Newer
Older
import numpy as np
import matplotlib.pyplot as plt
import scipy.signal
import file_handling
def phonon_deformation_silicon(strain_matrix,p,q,r,sort=False,w0=None):
""" Function to calculate the Raman shift from an arbitrary strain tensor using Phonon Deformation Potential (PDP) theory
args:
- strain_matrix (3x3 matrix) : the strain tensor
- p (scalar) : the first phonon deformation potential
- q (scalar) : the second phonon deformation potential.
- r (scalar) : the third phonon deformation potential
- sort (boolean) : if true, sort the phonon modes from lowest to highest energy
- w0 (scalar) : reference energy at zero strain, 520.7 cm-1 for silicon
return:
- an array of three elements with the energy of the three phonon modes (LO, TO1, and TO2).
"""
if w0==None:
w0=520.7 # in cm-1
p=p*w0**2
q=q*w0**2
r=r*w0**2
exx=strain_matrix[0,0]
eyy=strain_matrix[1,1]
ezz=strain_matrix[2,2]
eyz=strain_matrix[1,2]
exz=strain_matrix[0,2]
exy=strain_matrix[0,1]
ezy=strain_matrix[2,1]
ezx=strain_matrix[2,0]
eyx=strain_matrix[1,0]
P=np.array([[p*exx+q*(eyy+ezz),2*r*exy,2*r*exz],
[2*r*eyx,p*eyy+q*(ezz+exx),2*r*eyz],
[2*r*ezx,2*r*ezy,p*ezz+q*(eyy+exx)]])
det=np.linalg.det(P)
tr=np.trace(P)
tr2=np.trace(P.dot(P))
if sort :
lamb=np.sort(np.roots([1,-tr,-0.5*(tr2-tr**2),-det]))
else :
lamb=np.roots([1,-tr,-0.5*(tr2-tr**2),-det])
return np.sqrt(lamb+w0**2)
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def find_peaks(x,y,height=None, threshold=None, distance=None, width=None):
""" Function to find peaks in the Raman spectrum
args:
- x (array) : an array
- y (array) : the signal with peaks with the same dimension as x
- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
return:
- (positions, heights, widths) : an array of three elements with the positions, the heights and the widths of the peaks
"""
dx=(np.max(x)-np.max(y))/len(x)
distance_index=int(np.round(distance/dx))
peaks_index,properties=scipy.signal.find_peaks(y,height=height, threshold=threshold, distance=distance_index, width=width)
return x[peaks_index],properties["peak_heights"],properties["widths"]
def plot_with_peaks(x,y,ax=None,height=None, threshold=None, distance=None, width=None,*ax_kwargs,**plot_kwargs):
""" Function to plot the Raman spectrum with the peaks indicated
args:
- x (array) : an array for the energy of the Raman spectrum
- y (array) : the Raman signal with peaks with the same dimension as x
- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
- *ax_kwargs : this method also takes any keyword argument for the Figure.add_sublot() function such as xlabel, ylabel, xticks, yticks, xlim, ylim, xscale, yscale, ...
- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
return:
- fig, ax : the Figure and Axes object created if None is specified for ax
"""
if ax==None:
fig=plt.figure()
ax=fig.add_subplot(*ax_kwargs)
ax.plot(x,y,**plot_kwargs)
position, heights, width=find_peaks(x,y,height=height, threshold=threshold, distance=distance, width=width)
ax.plot(position,height,marker="o",ls="",color="k")
for i in range(len(height)):
ax.plot([position[i],position[i]],[0,height[i]],marker="",ls="--",color="k")
ax.text(position[i],1.2*height[i],"%.2f cm$^{-1}$"%position[i],ha="center",va="bottom",rotation="vertical")
if ax==None:
return fig, ax
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def plot_from_file(file_path,ax=None,with_peaks=False,height=None, threshold=None, distance=None, width=None,*ax_kwargs,**plot_kwargs):
""" Function to plot the Raman spectrum with the peaks indicated
args:
- file_path (string) : the file to read
- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
- *ax_kwargs : this method also takes any keyword argument for the Figure.add_sublot() function such as xlabel, ylabel, xticks, yticks, xlim, ylim, xscale, yscale, ...
- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
return:
- fig, ax : the Figure and Axes object created if None is specified for ax
"""
data=file_handling.read_file(file_path,comments="#",delimiter=None)
x=data[:,0]
y=data[:,0]
if ax==None:
fig=plt.figure()
ax=fig.add_subplot(*ax_kwargs)
if with_peaks:
plot_with_peaks(x,y,ax=ax,height=height, threshold=threshold, distance=distance, width=width,**plot_kwargs)
else:
ax.plot(x,y,*ax_kwargs)
if ax==None:
return fig, ax
def plot_from_multiple_files(file_paths,with_peaks=False,height=None, threshold=None, distance=None, width=None,*ax_kwargs,**plot_kwargs):
""" Function to plot the Raman spectrum with the peaks indicated
args:
- file_paths (list of string) : lis of the names for the files to read
- ax (Axes) : the axes of the subplot in which plotting the Raman signal and peaks
- height (None, scalar or 2-element sequence) : required height of peaks. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required height.
- threshold (None, scalar or 2-element sequence) : required threshold of peaks, the vertical distance to its neighboring samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required threshold.
- distance (scalar) : Required minimal horizontal distance in samples between neighbouring peaks. The distance should be higher than the step between two adjacents points from x. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
- width (None, scalar or 2-element sequence) : required width of peaks in samples. Either a number, None, an array matching x or a 2-element sequence of the former. The first element is always interpreted as the minimal and the second, if supplied, as the maximal required width.
- *ax_kwargs : this method also takes any keyword argument for the Figure.add_sublot() function such as xlabel, ylabel, xticks, yticks, xlim, ylim, xscale, yscale, ...
- **plot_kwargs : this method also takes any keyword argument for the Axes.plot() function such as linewidth, linestyle, marker, markersize, color, markeredgecolor, zorder, alpha, label, clip_on, ...
return:
- fig, ax : the Figure and a list with the axes object created
"""
n_plot=len(file_paths)
fig,ax=plt.subplots(n_plot,1,sharex=True,figsize=(5,n_plot*2))
for i in range(n_plot):
ax[i].spines.right.set_visible(False)
ax[i].spines.top.set_visible(False)
ax[i].spines.bottom.set_visible(False)
plot_from_file(file_paths[i],ax=ax[i],with_peaks=with_peaks,height=height, threshold=threshold, distance=distance, width=width,*ax_kwargs,**plot_kwargs)
return fig, ax