sda.io.loadspe ============== .. py:module:: sda.io.loadspe .. autoapi-nested-parse:: Load spectroscopic files. Original functions are taken from : http://people.seas.harvard.edu/~krussell/html-tutorial/_modules/winspec.html Fixed for Python 3 Added Imaging mode support Classes ------- .. autoapisummary:: sda.io.loadspe.SpecAnalyzer Functions --------- .. autoapisummary:: sda.io.loadspe.loadspe sda.io.loadspe.spe2im Module Contents --------------- .. py:function:: loadspe(fname, frames='all', flatten_1D=True, flatten_frames=True, verbose=True, warnings=True, unpack=False, return_info=False) Read in an SPE file and return the spectrum as a numpy array. usage: wavelength, luminescence = get_spectrum( spe_filename ). Type of winspec files read: 1D spectrum, 2D spectrum, 2D imaging :param fname: winspec file :type fname: :py:class:`str` :param frames: for images that contain more than 1 frame: if 'all', loads all the frames if an int, return a particular time frame Note that all frames can be loaded but only a few plotted or exported using frames='all' on import and the frames argument in get() function :type frames: :py:class:`int` or ``'all'`` :param flatten_1D: if ``True``, auto-flatten 1D arrays :type flatten_1D: :py:class:`boolean` :param flatten_frames: if ``True``, auto-flatten luminescence when there is one frame only :type flatten_frames: :py:class:`boolean` :param unpack: deprecated :type unpack: :py:class:`boolean` :param verbose: talk :type verbose: :py:class:`bool` :param warnings: Can be ``False``, ``True`` or ``2`` to display even more warnings (ex: if file format does not respect the suggested format. See Notes) :type warnings: :py:class:`bool` :param return_info: if True return spectrum conditions as read in spe file :type return_info: :py:class:`bool` :returns: * :py:class:`In imaging mode`, :py:class:`output is a (i,x,y) array` -- i: frame number x, y: 2D pixels luminescence value for frame i * **In spectrum mode, output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,x,y))`) -- wavelength: calibrated wavelength i: frame number x, y: 2D luminescence value for frame i * :py:class:`If flatten_1D option is activated (by default)` and :py:class:`data is detected` to :py:class:`be` * **1D-spectrum then output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,luminescence)) with:`) -- wavelength: calibrated wavelength i: frame number luminescence: 1D array luminescence value for frame i * :py:class:`If flatten_frames option is activated (by default)` and :py:class:`there is only one` * :py:class:`frame then output is (x,y) array with` -- x, y: 2D pixels luminescence value * :py:class:`If both flatten_1D` and :py:class:`flatten_frames are activated we obtain the following` * **output** (:py:class:`(wavelength`, :py:class:`luminescence)`) .. rubric:: Notes File naming convention: .. warning:: Winspec has a few limitations in how it stores metadata. In particular: - the number of software accumulations is the one that was chosen before the run. If the run was paused before all accumulations were completed then this number if wrong, and any averaging procedure using this number will result in errors. - Winspec cannot handle numbers greaters 32767 (2^8). Then it restarts from -32767. Comparing with filenames makes sure the number of onCCD accumulations is at least the same modulo something. To deal with this the SpecAnalyzer expects a naming convention for your filename. This way, it will cross-check that the names match with the metadata stored in the .spe file. The format is as follow: '[something]-gpe[gpe]-acc[acc]-[somethingelse].SPE' Where [gpe] and [acc] are the number of on CCD accumulations and software accumulations, respectively. So for instance:: 'spark_regime-gpe100000-acc100-.SPE' See :meth:`~sda.io.loadspe.SpecAnalyzer._read_param_from_filename` for more information .. seealso:: :class:`~sda.io.loadspe.SpecAnalyzer` .. py:function:: spe2im(fname, fout, frames='all', verbose=True, warnings=True) Convert Winspec file to image file. Supported format: BMP, EPS, JPG, JPEG, PDF, PNG, PPM. Only Tif can handle multiple frames Tif is exported in int16 to be readable by ImageJ :param fname: Winspec file :type fname: :py:class:`str` :param fout: Output file :type fout: :py:class:`str` :param frames: frames to export. 'all' by default :type frames: :py:class:`int`, :py:class:`list` of :py:class:`int`, or ``'all'`` .. py:class:: SpecAnalyzer(avgfunc=None, verbose=False, warnings=True, compare_with_filename=False) Machinery to batch process .spe files. :param avgfunc: function to get the real average intensity as a function of the number of on-chip accumulation. If None, then the one from Rusterholtz, 2012 is used (calibrated for the PIMax 2ns) :type avgfunc: :py:class:`function` :param spefilename: name of the SPE file to be read :type spefilename: :py:class:`str` :param verbose: print(debug statements (True) or not (False)) Can be 'all' to print every single detail :type verbose: :py:class:`boolean` :param warnings: print(warnings (True) or not (False)) :type warnings: :py:class:`boolean` :param compare_with_filename: if ``True``, analyze filename to extract accumulations, onCCD, gain, features and compare them with data stored in the file. See Notes :type compare_with_filename: :py:class:`boolean` :param verbose: talk :type verbose: :py:class:`bool` :param warnings: Can be ``False``, ``True`` or ``2`` to display even more warnings (ex: if file format does not respect the suggested format. See Notes) :type warnings: :py:class:`bool` .. rubric:: Notes File naming convention: .. warning:: Winspec has a few limitations in how it stores metadata. In particular: - the number of software accumulations is the one that was chosen before the run. If the run was paused before all accumulations were completed then this number if wrong, and any averaging procedure using this number will result in errors. - Winspec cannot handle numbers greaters 32767 (2^8). Then it restarts from -32767. Comparing with filenames makes sure the number of onCCD accumulations is at least the same modulo something. To deal with this the SpecAnalyzer expects a naming convention for your filename. This way, it will cross-check that the names match with the metadata stored in the .spe file. The format is as follow:: '[something]-gpe[gpe]-acc[acc]-[somethingelse].SPE' Where [gpe] and [acc] are the number of on CCD accumulations and software accumulations, respectively. So for instance:: 'spark_regime-gpe100000-acc100-.SPE' See :meth:`~sda.io.loadspe.SpecAnalyzer._read_param_from_filename` for more information .. rubric:: Examples How to use:: S = SpecAnalyzer() S.calibrate(theory,file1) S.load(winspec_file_1) S.average(winspec_file_1) S.export(file_out_1) S.load(winspec_file_2) S.average(winspec_file_2) S.export(file_out_2) etc. .. seealso:: :func:`~sda.io.loadspe.loadspe` .. py:attribute:: spedict :value: None .. py:attribute:: calibrated :value: False .. py:attribute:: absolute :value: False .. py:attribute:: avgfunc :value: None .. py:attribute:: verbose :value: False .. py:attribute:: warnings :value: True .. py:attribute:: data :value: None .. py:attribute:: wavelength :value: None .. py:attribute:: luminescence :value: None .. py:attribute:: xpixels :value: None .. py:attribute:: ypixels :value: None .. py:attribute:: dnfolder :value: None .. py:attribute:: dnfiles .. py:attribute:: mode :value: None .. py:attribute:: is1D :value: None .. py:attribute:: single_frame :value: None .. py:method:: is_2D() .. py:method:: load(fname, frames='all', mode_2D='auto') Read in an SPE file. :param fname: winspec file :type fname: :py:class:`str` :param unpack: if ``True``, returns a list instead of a matrix :type unpack: :py:class:`boolean` :param index: returns a time frame. (default: 0) :type index: :py:class:`int` :param all_frames: if ``True``, returns all the time frame (index is then unused) Default: ``'auto'`` :type all_frames: :py:class:`boolean`, or :py:class:``````'auto'``:py:class:```` :param mode_2D: if ``True``, returns 2D images as a 2D matrix. Default: ``'auto'`` :type mode_2D: :py:class:`boolean`, or :py:class:``````'auto'``:py:class:```` :returns: but stores content of file in SpecAnalyzer as 2D array (wavelength, luminescence) + metadata :rtype: :py:obj:`None` .. py:method:: get_info(filt=['data', 'XCALIB']) Get all infos, removing binary input and keys in filt. :param filt: spedict inputs to discard :type filt: :py:class:`list` of :py:class:`str` .. py:method:: calibrate(chk_w=True) Calibration factor: real data = measured / calibration factor. .. py:method:: loadtxt(f) Open with numpy loadtxt functions. Transpose if needed. .. py:method:: x_calibration(input_path) Calibrate the wavelength. If initial .spe file was recorded with a bad calibration in wavelength, since the data are recorder according to. pixel positions and that wavelengths are attributed at loading time, it is possible to correct it. For this, we need another .spe or .txt file matching the original file but with the correct calibration. This function updates the self.wavelength attribute of the SpecAnalyser object using the new calibration. :param input_path: path of file with new wavelength calibration :type input_path: :py:class:`str` :returns: but wavelength is calibrated :rtype: :py:obj:`None` .. rubric:: Examples s = SpecAnalyzer() s.load(data) s.x_calibration(self, path_to_calibration_file) .. py:method:: set_calibration(ftheory, fmeasured, bplot=True) Parameters. ---------- ftheory: str a text file fmeasured: str another text file (could have been obtained and exported with another SpecAnalyzer), or a Winspec file. Can be 1D or 2D. :param bplot: plot calibration? :type bplot: :py:class:`boolean` .. rubric:: Notes .. warning:: if importing a .SPE file directly, there is no way to remove the straylight. .. rubric:: Examples Determining 1D calfactor from 2D calfactor at a given wavelength With Im the measured intensity, I the theoretical one, C the calibration factor, i an y pixel index:: Im=Sum(Im_i) # assuming the camera vertical integration is linear I=Im/C=Sum(Im_i/C_i) --> C=Im/I=Sum(Im_i/I)=Sum(C_i) .. py:method:: set_dark_noise(folder) Choose the folder from which dark noise will be corrected. Folder contains text files (could have been obtained and exported with another SpecAnalyzer) whose name explicitely display the onCCD number. Store all dark noise files onCCD numbers in a dictionary for easy access .. py:method:: remove_dark_noise(matchCCD=False, force_CCD_averaged=False) To do before averaging!. Finds the dark noise measurement with the same amount of onCCD acc, and removes it. If there is no match, and matchCCD is not True, then proceed to a linear interpolation between the two closest values .. py:method:: remove_residual_background(percentile=50, bplot=False) .. py:method:: average(CCD=True, soft=True) Divide by number of accumulations, and effective number of CCD accumulation. See David Pai's 2008 PhD thesis p.40 for details. If no effective averaging function of CCD number is given, use Rusterholtz 2012 PhD thesis p. 73. Note: you may want to average separately over software first and onCCD then if you need to remove the software-averaged dark noise in between .. py:method:: average_CCD() Divide only by number of on CCD accumulations. See average function for more details. .. py:method:: average_software() Divide only by number of software accumulations. See average function for more details. .. py:method:: smooth_2D(kernel_dim=(11, 11), bplot=False) Smooth the luminescence with a moving average filter. The size of the averager filter is specified by kernel_dim (wavelengths,pixels). .. py:method:: integrate_wavelengths(wc, wmin, wmax, ftheory, fmeasured, bplot=False) To Do. .. py:method:: integrate_wavelengths_V2(wc, wmin, wmax) To Do. .. py:method:: integrate_wavelengths_auto(wc, treshold=0.15, smooth_param=2, bplot=False) To Do. .. py:method:: plot(frames='all', label='', fig=None, style='origin') Plot luminescence. If several frames, several figures are plot. :param frames: if 'all' plot all frames that have been loaded :type frames: :py:class:`int`, or ``'all'`` :param label: add label to plot :type label: :py:class:`str` :param fig: on which Figure to plot :type fig: :py:class:`int`, or :py:class:`str` :param style: which publib style to apply. Default 'origin' :type style: :py:class:`str` :returns: * :py:class:`Plot the chosen set. Intensity is normalized with minimum` and :py:class:`maximum` * :py:class:`value` of :py:class:`the set` .. py:method:: plot_options(frames='all', label='', fig=None, style='origin', abscissa_wl=False, show=False, lrange=None, scale=None, cmap='jet', mean=False, title='', div_factor=1) Plot luminescence. If several frames, several figures are plot. :param frames: if 'all' plot all frames that have been loaded :type frames: :py:class:`int`, or ``'all'`` :param label: add label to plot :type label: :py:class:`str` :param fig: on which Figure to plot :type fig: :py:class:`int`, or :py:class:`str` :param style: which publib style to apply. Default 'origin' :type style: :py:class:`str` :param abscissa_wl: if True, plot the abscissa axis in nm. Default is False :type abscissa_wl: :py:class:`bool` :param show: if True, show the image. Default is False. :type show: :py:class:`bool` :param lrange: minimale and maximale value of the scale :type lrange: :py:class:`list` of :py:class:`2 floats` :param scale: scale[0] = pixel corresponding to 0 mm along the horizontal axis scale[1] = ratio pixel/mm along the horizontal axis scale[2] = pixel corresponding to 0 mm along the vertical axis scale[3] = ratio pixel/mm along the vertical axis :type scale: :py:class:`list` of :py:class:`4 floats` :param cmap: set the colormap of the figure. Default is 'jet' :type cmap: :py:class:`string` :param mean: if True, plot the mean image (in case they are several frames). Default is False :type mean: :py:class:`bool` :returns: * :py:class:`Plot the chosen set. Intensity is normalized with minimum` and :py:class:`maximum` * :py:class:`value` of :py:class:`the set` .. py:method:: plot_Winspec(title='') Plot a 2D image the Winspec way, with side graphs. Note that has a reverse y axis by default. And Python stores data row-first so the image also has to be transposed. .. py:method:: get(frames='all', unpack=True, flatten_1D=True, flatten_frames=True, transpose=False) Return data (wavelength, luminescence). :param frames: give possibility to get only a few frames among the one already loaded :type frames: :py:class:`int`, :py:class:`list` of :py:class:`int` or ``'all'`` :param unpack: :type unpack: :py:class:`deprecated` :param flatten_1D: :type flatten_1D: :py:class:`boolean` :param flatten_frames: :type flatten_frames: :py:class:`boolean` :param transpose: :type transpose: :py:class:`boolean` :param force_array: if ``True``, results are returned under array form even in spectrum mode (if may require the luminance to be transposed) :type force_array: :py:class:`boolean` :returns: * :py:class:`In imaging mode`, :py:class:`output is a (i,x,y) array` -- i: frame number x, y: 2D pixels luminescence value for frame i * **In spectrum mode, output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,x,y))`) -- wavelength: calibrated wavelength i: frame number x, y: 2D luminescence value for frame i * :py:class:`If flatten_1D option is activated (by default)` and :py:class:`data is detected` to :py:class:`be` * **1D-spectrum then output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,luminescence)) with:`) -- wavelength: calibrated wavelength i: frame number luminescence: 1D array luminescence value for frame i * :py:class:`If flatten_frames option is activated (by default)` and :py:class:`there is only one` * :py:class:`frame then output is (x,y) array with` -- x, y: 2D pixels luminescence value * :py:class:`If both flatten_1D` and :py:class:`flatten_frames are activated we obtain the following` * **output** (:py:class:`(wavelength`, :py:class:`luminescence)`) .. py:method:: export_2D(filename, create_folders=True) Export data as a 257*1024 numpy array in text format. first line is the wavelengths. :param filename: file to save :type filename: :py:class:`str` :param create_folder: if ``True``, creates directories if needed :type create_folder: :py:class:`boolean` .. py:method:: export(filename, create_folders=True) Export data as a numpy array in text format. :param filename: file to save :type filename: :py:class:`str` :param create_folder: if ``True``, creates directories if needed :type create_folder: :py:class:`boolean` .. py:method:: write(fname, frames='all') Write data as an image format. If file format is not specified by the file extension, then ".tif" is used by default. If guessing the format from the file extension fails, a warning is raised and the image is saved as ".tif". Note that only the .tif format can be used to save a stack of images. If you choose another format, you have to choose one single frame only. :param filename: image can be: 'bmp','eps', 'jpg', 'jpeg', 'pdf','png', 'ppm' :type filename: :py:class:`str` :param frames: if not 'all' (default) only a subset is exported :type frames: :py:class:`int`, :py:class:`list` of :py:class:`int`, or ``'all'`` .. py:method:: check_param(gain=-1, onccd=-1, gate_width=-1, gate_delay=-1, verbose=True) Check acquisition parameters. Check that the acquisiton parameters filled in by the user in the function correspond to the metadata of the file. :param gain: Intensifier gain. The default is -1, the value is not checked :type gain: :py:class:`int`, *optional* :param onccd: number of on CCD accummulations. The default is -1, the value is not checked :type onccd: :py:class:`int`, *optional* :param gate_width: gate width in µs. The default is -1, the value is not checked :type gate_width: :py:class:`float`, *optional* :param gate_delay: gate delay in µs. The default is -1, the value is not checked :type gate_delay: :py:class:`float`, *optional* :param verbose: :type verbose: :py:class:`boolean`, *optional* :param write the value of: :type write the value of: :py:class:`gain`, :py:class:`onccd`, :py:class:`gate_width`, :py:class:`gate_delay. The default is True.` :rtype: :py:class:`True if the parameters correspond` to :py:class:`the metadata` .. py:method:: subtract(other, mode='by_frame') Subtract other to self. :param other: subtract other to self. :type other: :py:class:`SpecAnalyzer object` :param mode: subtract the mean 'frame' of other to self or subtract frame one by one i.e.: [self[1]-other[1], self[2]-other[2],..]. The default is 'by_frame'. :type mode: :py:class:`string`, *optional* :returns: **s** -- the resulting self-other. :rtype: :py:class:`SpecAnalyzer object` .. py:method:: flip_2Dimage(axis=2) .. py:method:: resize_roi(roi=None) Resize the ROI of all frames of the SpecAnalyzer object. Parameter ---------- roi : list, optional list of 4 int. The default is None. :rtype: :py:class:`None.` .. py:method:: binned(frames='all', flatten_1D=True, flatten_frames=True, transpose=True) Return data (wavelength, luminescence). :param frames: give possibility to get only a few frames among the one already loaded :type frames: :py:class:`int`, :py:class:`list` of :py:class:`int` or ``'all'`` :param unpack: :type unpack: :py:class:`deprecated` :param flatten_1D: :type flatten_1D: :py:class:`boolean` :param flatten_frames: :type flatten_frames: :py:class:`boolean` :param transpose: :type transpose: :py:class:`boolean` :param force_array: if ``True``, results are returned under array form even in spectrum mode (if may require the luminance to be transposed) :type force_array: :py:class:`boolean` :returns: * :py:class:`In imaging mode`, :py:class:`output is a (i,x,y) array` -- i: frame number x, y: 2D pixels luminescence value for frame i * **In spectrum mode, output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,x,y))`) -- wavelength: calibrated wavelength i: frame number x, y: 2D luminescence value for frame i * :py:class:`If flatten_1D option is activated (by default)` and :py:class:`data is detected` to :py:class:`be` * **1D-spectrum then output is a tuple** (:py:class:`(wavelength`, :py:class:`(i,luminescence)) with:`) -- wavelength: calibrated wavelength i: frame number luminescence: 1D array luminescence value for frame i * :py:class:`If flatten_frames option is activated (by default)` and :py:class:`there is only one` * :py:class:`frame then output is (x,y) array with` -- x, y: 2D pixels luminescence value * :py:class:`If both flatten_1D` and :py:class:`flatten_frames are activated we obtain the following` * **output** (:py:class:`(wavelength`, :py:class:`luminescence)`) .. py:method:: copy() .. py:method:: reverse()