Skip to content
Extraits de code Groupes Projets
raman.py 11,1 ko
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Roisin's avatar
    Nicolas Roisin a validé
    import numpy as np
    import matplotlib.pyplot as plt
    import scipy.signal
    import file_handling
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
    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
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
        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]))
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
        else :
            lamb=np.roots([1,-tr,-0.5*(tr2-tr**2),-det])
        return np.sqrt(lamb+w0**2)
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
    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
        """
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
        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
    
    Nicolas Roisin's avatar
    Nicolas Roisin a validé
    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