:py:mod:`autodeer` ================== .. py:module:: autodeer Subpackages ----------- .. toctree:: :titlesonly: :maxdepth: 0 gui/index.rst hardware/index.rst Submodules ---------- .. toctree:: :titlesonly: :maxdepth: 1 DEER_analysis/index.rst FieldSweep/index.rst Logging/index.rst Relaxation/index.rst ResPro/index.rst TwoD_Experiment/index.rst _version/index.rst classes/index.rst colors/index.rst criteria/index.rst dataset/index.rst pulses/index.rst reporter/index.rst sequences/index.rst tools/index.rst utils/index.rst Package Contents ---------------- Classes ~~~~~~~ .. autoapisummary:: autodeer.FieldSweepAnalysis autodeer.ResonatorProfileAnalysis autodeer.Sequence autodeer.CarrPurcellAnalysis autodeer.ReptimeAnalysis autodeer.RefocusedEcho2DAnalysis autodeer.Parameter autodeer.Interface autodeer.Parameter autodeer.Pulse autodeer.Detection autodeer.Delay autodeer.RectPulse autodeer.Sequence autodeer.DEERSequence autodeer.HahnEchoSequence autodeer.T2RelaxationSequence autodeer.FieldSweepSequence autodeer.ReptimeScan autodeer.CarrPurcellSequence autodeer.RefocusedEcho2DSequence autodeer.ResonatorProfileSequence autodeer.TWTProfileSequence autodeer.Parameter autodeer.Pulse autodeer.Detection autodeer.Delay autodeer.RectPulse autodeer.GaussianPulse autodeer.FrequencySweptPulse autodeer.HSPulse autodeer.ChirpPulse autodeer.SincPulse autodeer.Pulse autodeer.Detection autodeer.Parameter autodeer.Interface autodeer.Sequence autodeer.DEERSequence autodeer.EPRAccessor autodeer.Reporter Functions ~~~~~~~~~ .. autoapisummary:: autodeer.eprload autodeer.build_table autodeer.sop autodeer.transpose_dict_of_list autodeer.transpose_list_of_dicts autodeer.save_file autodeer.autoEPRDecoder autodeer.gcd autodeer.val_in_us autodeer.val_in_ns autodeer.round_step autodeer.optimise_spectra_position autodeer.detect_ESEEM autodeer.plot_1Drelax autodeer.build_table autodeer.autoEPRDecoder autodeer.build_table autodeer.sop autodeer.autoEPRDecoder autodeer.build_default_pulses autodeer.autoEPRDecoder autodeer.get_all_axes autodeer.get_all_fixed_param autodeer.create_dataset_from_sequence autodeer.create_dataset_from_axes autodeer.create_dataset_from_bruker autodeer.combo_figure Attributes ~~~~~~~~~~ .. autoapisummary:: autodeer.__version__ autodeer.cmap autodeer.primary_colors .. py:data:: __version__ :value: "'0.8'" .. py:function:: eprload(path, experiment = None, type = None, **kwargs) A general versions of eprload :Parameters: **path** : str The file path of the data that should be loaded. **experiment** : str, optional _description_, by default None **type** : str, optional _description_, by default None :Returns: xarray.Dataarray _description_ :Raises: ValueError _description_ RuntimeError _description_ .. !! processed by numpydoc !! .. py:function:: build_table(source, params, params_widths) .. py:function:: sop(spins, comps) Spin Operator Matricies. This function is ported from EasySpin (https://easyspin.org/easyspin/documentation/sop.html) References: +++++++++++ [1] Stefan Stoll, Arthur Schweiger EasySpin, a comprehensive software package for spectral simulation and analysis in EPR J. Magn. Reson. 178(1), 42-55 (2006) [2] Stefan Stoll, R. David Britt General and efficient simulation of pulse EPR spectra Phys. Chem. Chem. Phys. 11, 6614-6625 (2009) :Parameters: **spins** : list A list of each spin and its spin qunatum number **comps** : str The type of spin operator matrix to create. Options are: x,y,z,+,-,e .. !! processed by numpydoc !! .. py:function:: transpose_dict_of_list(d) Turns a dictionary of lists into a list of dictionaries. .. !! processed by numpydoc !! .. py:function:: transpose_list_of_dicts(d) Turns a list of dictionaries into a dictionary of lists. .. !! processed by numpydoc !! .. py:function:: save_file(path, str) .. py:function:: autoEPRDecoder(dct) .. py:function:: gcd(values) Generates the greatest common dividor on a list of floats :Parameters: **values** : list _description_ .. !! processed by numpydoc !! .. py:function:: val_in_us(Param, axis=True) Returns the value or axis of a parameter in microseconds :Parameters: **Param** : autodeer.Parameter The parameter to be converted :Returns: float or numpy.ndarray .. .. !! processed by numpydoc !! .. py:function:: val_in_ns(Param) Returns the value or axis of a parameter in nanoseconds :Parameters: **Param** : autodeer.Parameter The parameter to be converted :Returns: float or numpy.ndarray .. .. !! processed by numpydoc !! .. py:function:: round_step(value, step) .. py:class:: FieldSweepAnalysis(dataset) Analysis and calculation of FieldSweep Experiment. :Parameters: **dataset** : xarray.Dataarray _description_ .. !! processed by numpydoc !! .. py:attribute:: data .. py:method:: find_max() Calculates the maximum field :Returns: float Max field .. !! processed by numpydoc !! .. py:method:: calc_gyro(LO = None) Calculates the gyromagnetic ratio for a given frequency :Parameters: **det_frq** : float The detection frequency for the field sweep. :Returns: float The gyromagnetic ratio in G/GHz. .. !! processed by numpydoc !! .. py:method:: calc_noise_level(SNR_target=30) .. py:method:: smooth(*args, **kwargs) Generates a smoothed version of the data using a 1D smoothing spline. :Returns: np.ndarray The smoothed data. .. !! processed by numpydoc !! .. py:method:: fit(spintype='N', **kwargs) .. py:method:: plot(norm = True, axis = 'field', axs=None, fig=None) Generate a field sweep plot :Parameters: **norm** : bool, optional Nomarlisation of the plot to a maximum of 1, by default True **axis** : str, optional plot field sweep on either the "field" axis or "freq" axis :Returns: Matplotlib.Figure matplotlib figure .. !! processed by numpydoc !! .. py:class:: ResonatorProfileAnalysis(dataset, f_lims=(32, 36)) Analysis and calculation of resonator profiles. :Parameters: **dataset** : xr.xarray The dataset containing the nutations. It must have both a 'LO' axis and a 'pulse0_tp' axis. **f_lims** : tuple, optional The frequency limits of the resonator profile, by default (33,35) .. !! processed by numpydoc !! .. py:attribute:: dataset .. py:attribute:: n_files .. py:attribute:: t .. py:attribute:: f_lims .. py:method:: process_nutations(noisedensity = None, threshold = 2, nfft = 1000) Uses a power series to extract the resonator profile. :Parameters: **noisedensity** : tuple, optional If not given the first trace is assumed to be so far off resonance that it is just noise. **nfft: int, optional** The length of the fft to be used, zero padded if requred, default is 1000. **threshold: int, optional** The multiples above the noise a single must be to not be excluded, default is 2. :Returns: prof_data: np.ndarray The resonator profile, give in nutation frequency (GHz) prof_frqs: np.ndarray The frequency axis in GHz .. !! processed by numpydoc !! .. py:method:: _process_fit(R_limit=0.5) .. py:method:: fit(f_diff_threshold=2, cores=1, multi_mode=False, fc_guess=None) Fit the resonator profile with a sum of lorentzians. :Parameters: **f_diff_threshold** : float, optional The difference between two peaks at which they will be merged into one, by default 0.03 .. !! processed by numpydoc !! .. py:method:: plot(fieldsweep=None, axs=None, fig=None) plot. :Parameters: **fieldsweep** : FieldSweepAnalysis, optional Overlays the FieldSweep if provided, by default None **axs** : matplotlib.Axes, optional Axes to plot on, by default None **fig** : matplotlib.Figure, optional Figure to plot on, by default None :Returns: Matplotlib.Figure matplotlib figure object .. !! processed by numpydoc !! .. py:function:: optimise_spectra_position(resonator_profile, fieldsweep, verbosity=0) .. py:class:: Sequence(*, name, B, LO, reptime, averages, shots, **kwargs) Represents an experimental pulse sequence. Represents an experimental pulse sequence. :Parameters: **name** : str The name of this pulse sequence **B** : float The magnetic field for this sequence in Gauss. **LO** : float The central frequency of this sequence. I.e. The frequnecy at which a zero offset pulse is at. **reptime** : float The shot repetition time in us. **averages** : int The number of scans to be accumulated. **shots** : itn The number of shots per point. .. !! processed by numpydoc !! .. py:property:: seqtable_steps .. py:attribute:: pulses :value: '[]' .. py:attribute:: num_pulses .. py:attribute:: axes_uuid :value: '[]' .. py:attribute:: reduce_uuid :value: '[]' .. py:attribute:: LO .. py:attribute:: averages .. py:attribute:: shots .. py:attribute:: name .. py:attribute:: progTable .. py:method:: plot() .. py:method:: plot_pulse_exc(FieldSweep=None, ResonatorProfile=None) .. py:method:: addPulse(pulse) Adds a pulse to the next position in the sequence. :Parameters: **pulse** : Pulse The object describing the pulse. .. !! processed by numpydoc !! .. py:method:: _estimate_time() Calculates the estimated experiment time in seconds. .. !! processed by numpydoc !! .. py:method:: _buildPhaseCycle() .. py:method:: evolution(params, reduce=[]) .. py:method:: shift_detfreq_to_zero() .. py:method:: isPulseFocused() Is the sequence expressed to contain only pulses and no delays? .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Is the sequence expressed to contain both pulses and delays? .. !! processed by numpydoc !! .. py:method:: convert(*, reduce=True) Converts the current sequence to either pulse focused or delay focused depending on the current state :Parameters: **reduce** : bool, optional Reduce to the smallest number of objects, by default True .. !! processed by numpydoc !! .. py:method:: _convert_to_delay() .. py:method:: _convert_to_pulses() .. py:method:: _checkRect() Checks if all the pulses in the sequence are rectangular. .. !! processed by numpydoc !! .. py:method:: __str__() .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the sequence to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load an object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Sequence The Sequence loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: CarrPurcellAnalysis(dataset, sequence = None) Analysis and calculation of Carr Purcell decay. :Parameters: **dataset** _description_ .. !! processed by numpydoc !! .. py:attribute:: dataset .. py:attribute:: data .. py:method:: fit(type = 'mono') Fit the experimental CP decay :Parameters: **type** : str, optional Either a mono or double exponential decay model, by default "mono" .. !! processed by numpydoc !! .. py:method:: plot(norm = True, axs=None, fig=None) Plot the carr purcell decay with fit, if avaliable. :Parameters: **norm** : bool, optional Normalise the fit to a maximum of 1, by default True :Returns: Figure The figure. .. !! processed by numpydoc !! .. py:method:: check_decay(level=0.05) Checks that the data has decayed by over 5% in the entire length and less than 5% in the first 30% of the data. :Parameters: **level** : float, optional The level to check the decay, by default 0.05 :Returns: int 0 if both conditions are met, 1 if the decay is less than 5% in the first 30% of the data, and -1 if the decay is less than 5% in the entire length. .. !! processed by numpydoc !! .. py:method:: find_optimal(SNR_target, target_time, target_step, averages=None) Calculate the optimal inter pulse delay for a given total measurment time. :Parameters: **SNR_target: float,** The Signal to Noise ratio target. **target_time** : float The target time in hours **target_shrt** : float The shot repettition time of target in seconds **target_step: float** The target step size in ns. **averages** : int, optional The total number of shots taken, by default None. If None, the number of shots will be calculated from the dataset. :Returns: float The calculated optimal time in us .. !! processed by numpydoc !! .. py:class:: ReptimeAnalysis(dataset, sequence = None) Analysis and calculation of Reptime based saturation recovery. :Parameters: **dataset** The dataset to be analyzed. **sequence** : Sequence, optional The sequence object describing the experiment. (not currently used) .. !! processed by numpydoc !! .. py:attribute:: axis .. py:attribute:: seq .. py:method:: fit(**kwargs) .. py:method:: plot(axs=None, fig=None) .. py:method:: calc_optimal_reptime(recovery=0.9) .. py:function:: detect_ESEEM(dataset, type='deuteron', threshold=1.5) Detect if the dataset is an ESEEM experiment. :Parameters: **dataset** : xr.DataArray The dataset to be analyzed. **type** : str, optional The type of ESEEM experiment, either deuteron or proton, by default 'deuteron' **threshold** : float, optional The SNR threshold for detection, by default 1.5 :Returns: bool True if ESEEM is detected, False if not. .. !! processed by numpydoc !! .. py:data:: cmap :value: "['#D95B6F', '#42A399']" .. py:function:: plot_1Drelax(*args, fig=None, axs=None, cmap=cmap) Create a superimposed plot of relaxation data and fits. :Parameters: **args** : ad.Analysis The 1D relaxation data to be plotted. **fig** : Figure, optional The figure to plot to, by default None **axs** : Axes, optional The axes to plot to, by default None **cmap** : list, optional The color map to use, by default ad.cmap .. !! processed by numpydoc !! .. py:class:: RefocusedEcho2DAnalysis(dataset, sequence = None) Analysis and calculation of Refocused Echo 2D data. :Parameters: **dataset** The dataset to be analyzed. **sequence** : Sequence, optional The sequence object describing the experiment. (not currently used) .. !! processed by numpydoc !! .. py:attribute:: axis :value: '[]' .. py:attribute:: dataset .. py:attribute:: data .. py:method:: _smooth(elements=3) Used SVD to smooth the 2D data. :Parameters: **elements** : int, optional The number of elements to use in the smoothing, by default 3 :Returns: np.ndarray The smoothed data. .. !! processed by numpydoc !! .. py:method:: plot2D(contour=True, smooth=False, norm='Normal', axs=None, fig=None) Create a 2D plot of the 2D relaxation data. :Parameters: **contour** : bool, optional Plot the contour of the data, by default True **norm** : str, optional Normalise the data, by default 'Normal'. Options are 'Normal' and 'tau2'. With 'tau2' normalisation, the data is normalised to the maximum of each row. **axs** : Axes, optional The axes to plot to, by default None **fig** : Figure, optional The figure to plot to, by default None .. !! processed by numpydoc !! .. py:method:: plot1D(axs=None, fig=None) Create a 1D plot of the 2D relaxation data. :Parameters: **axs** : Axes, optional The axes to plot to, by default None **fig** : Figure, optional The figure to plot to, by default None .. !! processed by numpydoc !! .. py:method:: find_optimal(type, SNR_target, target_time, target_step, averages=None) Calculate the optimal inter pulse delay for a given total measurment time, using either 4pulse or 5pulse data. :Parameters: **type** : str The type of data to use, either '4pDEER' or '5pDEER' **SNR_target** : float The Signal to Noise ratio target. **target_time** : float The target time in hours **target_step: float** The target step size in ns. **averages** : int, optional The total number of shots taken, by default None. If None, the number of shots will be calculated from the dataset. :Returns: tau1: float The calculated optimal tau1 in us tau2: float The calculated optimal tau2 in us .. !! processed by numpydoc !! .. py:method:: optimal_tau1(tau2=None) .. py:class:: Parameter(name, value, unit='', description='', virtual=False, **kwargs) Represents a sequence or pulse parameter. A general parameter. :Parameters: **name** : str The parameter name **value** : float or int The parameter value, eithe initial or static **unit** : str, optional The unit of parameter, by default None. Leave as None if unitless. **description** : str, optional A brief description of the parameter, by default None **axis** : np.ndarray, optional The difference from the intial value for each position in a dynamic axis. Can be n-dimensional, by default None. **ax_id** : list, optional .. **virtual: bool, optional** A virtual paramter is only used to vary other parameters, it is not varied itself and will not be directly passed to a spectrometer. This parameter is **never** inherited. By default, False :Attributes: **progressive** : bool Is the parameter used in any progression or is it constant **prog** : dict A dict containing progressive programs for this parameter. This list has two elements. 1) The axis_id"s and 2) the "axis" of values. .. rubric:: Examples Creating a static parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") ``` Creating a dynamic parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter", axis=np.arange(0,10,1), axis_id=0) ``` Adding a parameter and a number: ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") Par2 = Par1 + 2 .. !! processed by numpydoc !! .. py:property:: dim .. py:attribute:: name .. py:attribute:: unit .. py:attribute:: description .. py:attribute:: virtual .. py:attribute:: axis :value: '[]' .. py:attribute:: ax_id :value: '[]' .. py:method:: add_axis(axis_id, axis) .. py:method:: get_axis() .. py:method:: remove_dynamic() .. py:method:: is_static() .. py:method:: __eq__(__o) .. py:method:: __add__(__o) .. py:method:: __sub__(__o) .. py:method:: __mul__(__o) .. py:method:: __rmul__(__o) .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the parameter to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dict) :staticmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Parameter object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Parameter The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Interface(log=None) Represents the interface connection from autoEPR to the spectrometer. .. !! processed by numpydoc !! .. py:attribute:: pulses .. py:attribute:: savefolder .. py:attribute:: savename :value: "''" .. py:attribute:: resonator :value: 'None' .. py:method:: connect() .. py:method:: acquire_dataset(data) Acquires the dataset. .. !! processed by numpydoc !! .. py:method:: launch(sequence, savename) Launches the experiment and initialises autosaving. :Parameters: **sequence** : Sequence The sequence to be launched **savename** : str The savename for this measurement. A timestamp will be added to the value. .. !! processed by numpydoc !! .. py:method:: isrunning() .. py:method:: terminate() Terminates the experiment immediately. .. !! processed by numpydoc !! .. py:method:: terminate_at(criterion, test_interval=2, keep_running=True, verbosity=0, autosave=True) Terminates the experiment upon a specific condition being satisified. :Parameters: **criterion** : _type_ The criteria to be tested. **test_interval** : int, optional How often should the criteria be tested in minutes, by default 10. **keep_running** : bool, optional If True, an error will not be raised if the experiment finishes before the criteria is met, by default True. **verbosity** : int, optional The verbosity level, by default 0. **autosave** : bool, optional If True, the data will be autosaved, by default True. .. !! processed by numpydoc !! .. py:class:: Parameter(name, value, unit='', description='', virtual=False, **kwargs) Represents a sequence or pulse parameter. A general parameter. :Parameters: **name** : str The parameter name **value** : float or int The parameter value, eithe initial or static **unit** : str, optional The unit of parameter, by default None. Leave as None if unitless. **description** : str, optional A brief description of the parameter, by default None **axis** : np.ndarray, optional The difference from the intial value for each position in a dynamic axis. Can be n-dimensional, by default None. **ax_id** : list, optional .. **virtual: bool, optional** A virtual paramter is only used to vary other parameters, it is not varied itself and will not be directly passed to a spectrometer. This parameter is **never** inherited. By default, False :Attributes: **progressive** : bool Is the parameter used in any progression or is it constant **prog** : dict A dict containing progressive programs for this parameter. This list has two elements. 1) The axis_id"s and 2) the "axis" of values. .. rubric:: Examples Creating a static parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") ``` Creating a dynamic parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter", axis=np.arange(0,10,1), axis_id=0) ``` Adding a parameter and a number: ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") Par2 = Par1 + 2 .. !! processed by numpydoc !! .. py:property:: dim .. py:attribute:: name .. py:attribute:: unit .. py:attribute:: description .. py:attribute:: virtual .. py:attribute:: axis :value: '[]' .. py:attribute:: ax_id :value: '[]' .. py:method:: add_axis(axis_id, axis) .. py:method:: get_axis() .. py:method:: remove_dynamic() .. py:method:: is_static() .. py:method:: __eq__(__o) .. py:method:: __add__(__o) .. py:method:: __sub__(__o) .. py:method:: __mul__(__o) .. py:method:: __rmul__(__o) .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the parameter to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dict) :staticmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Parameter object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Parameter The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Pulse(*, tp, t=None, scale=None, flipangle=None, pcyc=[0], name=None, **kwargs) Represents a general experimental pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: bandwidth .. py:property:: amp_factor The B1 amplitude factor (nutation frequency) for the pulse in GHz .. !! processed by numpydoc !! .. py:attribute:: name .. py:attribute:: Progression :value: 'False' .. py:method:: _addPhaseCycle(phases, detections=None) Adds a phase cycle to the pulse sequence. Args: phases (list): List of phases to add to the phase cycle. detections (list, optional): List of detection signs. Defaults to None. If None then all cycles are summed. Returns: None .. !! processed by numpydoc !! .. py:method:: _buildFMAM(func, ax=None) Builds the amplitude modulation (AM) and frequency modulation (FM) of a given function. Args: func: A function that takes in an array of values and returns two arrays, representing the AM and FM of the function. Returns: Two arrays representing the AM and FM of the function. .. !! processed by numpydoc !! .. py:method:: build_shape(ax=None) .. py:method:: build_table() Builds a table of variables, axes, and UUIDs for all non-static Parameters in the object. Returns: dict: A dictionary containing the following keys: "Variable", "axis", and "uuid". The values for each key are lists of the corresponding values for each non-static Parameter. .. !! processed by numpydoc !! .. py:method:: is_static() Check if all parameters in the pulse object are static. Returns: bool: True if all parameters are static, False otherwise. .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Does the pulse contain a specified time, `t`? If so then it is not delay focused. .. !! processed by numpydoc !! .. py:method:: isPulseFocused() Does the pulse contain a specified time, `t`? If so then it is delay focused. .. !! processed by numpydoc !! .. py:method:: plot(pad=1000) Plots the time domain representation of this pulse. :Parameters: **pad** : int, optional The number of zeros to pad the data with, by default 1000 .. !! processed by numpydoc !! .. py:method:: _calc_fft(pad=10000) .. py:method:: exciteprofile(freqs=None, resonator=None) Excitation profile Generates the exciatation profiles for this pulse. This function is ported from EasySpin (https://easyspin.org/easyspin/documentation/sop.html) [1-2], and based upon the method from Gunnar Jeschke, Stefan Pribitzer and Andrin Doll[3]. References: +++++++++++ [1] Stefan Stoll, Arthur Schweiger EasySpin, a comprehensive software package for spectral simulation and analysis in EPR J. Magn. Reson. 178(1), 42-55 (2006) [2] Stefan Stoll, R. David Britt General and efficient simulation of pulse EPR spectra Phys. Chem. Chem. Phys. 11, 6614-6625 (2009) [3] Jeschke, G., Pribitzer, S. & DollA. Coherence Transfer by Passage Pulses in Electron Paramagnetic Resonance Spectroscopy. J. Phys. Chem. B 119, 13570-13582 (2015) :Parameters: **freqs: np.ndarray, optional** The frequency axis. Caution: A larger number of points will linearly increase computation time. **resonator: ad.ResonatorProfile, optional** .. :Returns: Mx: np.ndarray The magentisation in the X direction. My: np.ndarray The magentisation in the Y direction. Mz: np.ndarray The magentisation in the Z direction. .. !! processed by numpydoc !! .. py:method:: plot_fft() .. py:method:: _pcyc_str() .. py:method:: __str__() .. py:method:: copy(clear=False, **kwargs) Creates a deep-copy of the pulse. I.e. Every parameter object is re-created at another memory space. Parameter can be chaged at this stage by adding them as keyword- arguments (kwargs). :Returns: Pulse A deep copy of the pulse .. !! processed by numpydoc !! .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the Pulse to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Pulse object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Pulse The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Detection(*, tp, t=None, freq=0, **kwargs) Bases: :py:obj:`Pulse` Represents a detection pulse. A general detection pulse. :Parameters: **tp** : float The **total** time of the detection event. The detection event will be symetrical about the centre time. **t** : float, optional The **centre** time of the detection event **freq: float, optional** The detection frequency, not all spectrometer support this functionality, by default 0 MHz .. !! processed by numpydoc !! .. py:attribute:: scale :value: 'None' .. py:attribute:: freq .. py:attribute:: pcyc :value: 'None' .. py:class:: Delay(*, tp, t=None) Bases: :py:obj:`Pulse` DEPRECATION WARNING: THIS WILL BE REMOVED SOON. Represents a inter-pulse delay pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:attribute:: tp .. py:attribute:: pcyc :value: 'None' .. py:attribute:: scale :value: 'None' .. py:class:: RectPulse(tp=16, freq=0, t=None, flipangle=None, **kwargs) Bases: :py:obj:`Pulse` Represents a rectangular monochromatic pulse. :Parameters: **tp** : flaot, optional Pulse Length in ns, by default 16 **freq** : float,optional Frequency in MHz, by default 0 **t** : float, optional Time position in ns, by default None **flipangle** : _type_, optional The flip angle in radians, by default None .. !! processed by numpydoc !! .. py:attribute:: freq .. py:method:: func(ax) .. py:function:: build_table(source, params, params_widths) .. py:function:: autoEPRDecoder(dct) .. py:class:: Sequence(*, name, B, LO, reptime, averages, shots, **kwargs) Represents an experimental pulse sequence. Represents an experimental pulse sequence. :Parameters: **name** : str The name of this pulse sequence **B** : float The magnetic field for this sequence in Gauss. **LO** : float The central frequency of this sequence. I.e. The frequnecy at which a zero offset pulse is at. **reptime** : float The shot repetition time in us. **averages** : int The number of scans to be accumulated. **shots** : itn The number of shots per point. .. !! processed by numpydoc !! .. py:property:: seqtable_steps .. py:attribute:: pulses :value: '[]' .. py:attribute:: num_pulses .. py:attribute:: axes_uuid :value: '[]' .. py:attribute:: reduce_uuid :value: '[]' .. py:attribute:: LO .. py:attribute:: averages .. py:attribute:: shots .. py:attribute:: name .. py:attribute:: progTable .. py:method:: plot() .. py:method:: plot_pulse_exc(FieldSweep=None, ResonatorProfile=None) .. py:method:: addPulse(pulse) Adds a pulse to the next position in the sequence. :Parameters: **pulse** : Pulse The object describing the pulse. .. !! processed by numpydoc !! .. py:method:: _estimate_time() Calculates the estimated experiment time in seconds. .. !! processed by numpydoc !! .. py:method:: _buildPhaseCycle() .. py:method:: evolution(params, reduce=[]) .. py:method:: shift_detfreq_to_zero() .. py:method:: isPulseFocused() Is the sequence expressed to contain only pulses and no delays? .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Is the sequence expressed to contain both pulses and delays? .. !! processed by numpydoc !! .. py:method:: convert(*, reduce=True) Converts the current sequence to either pulse focused or delay focused depending on the current state :Parameters: **reduce** : bool, optional Reduce to the smallest number of objects, by default True .. !! processed by numpydoc !! .. py:method:: _convert_to_delay() .. py:method:: _convert_to_pulses() .. py:method:: _checkRect() Checks if all the pulses in the sequence are rectangular. .. !! processed by numpydoc !! .. py:method:: __str__() .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the sequence to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load an object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Sequence The Sequence loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: DEERSequence(*, tau1, tau2, tau3=None, tau4=None, dt, B, LO, reptime, averages, shots, ESEEM_avg=None, **kwargs) Bases: :py:obj:`Sequence` Represents a DEER/PELDOR sequence. Build a DEER sequence using rectangular pulses :Parameters: **tau1** : int or float The first interpulse delay in us **tau2** : int or float The second interpulse delay in us **dt** : int or float The time step for DEER measurment in ns **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point **tau3** : int or float, optional The delay between the first static pump pulse in 5-pulse DEER and the 1st refocusing pulse in us, by default None. If the value is None then a 4-pulse sequence is created, otherwise a 5-pulse. **ESEEM_avg: str** Selecting the ESEEM averaging required. ESEEM averaging works by introducing small stepping in the first tau delay and averaging across them all. Options: * `proton` - 8 small steps of 8ns * `deuteron` - 8 small steps of 16ns * None - default .. !! processed by numpydoc !! .. py:attribute:: name :value: "'DEERSequence'" .. py:attribute:: tau1us .. py:attribute:: tau1 .. py:attribute:: tau2 .. py:attribute:: dt .. py:attribute:: deadtime :value: '200' .. py:attribute:: ESEEM :value: 'False' .. py:method:: add_ESEEM_avg(type=None) .. py:method:: three_pulse(tp=16) Build a four pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: four_pulse(tp=16, relaxation=False) Build a four pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: five_pulse(tp=16, relaxation=False, re_step=50, re_dim=100) Build a five pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: seven_pulse(tp=16, relaxation=False) Build a seven pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: nDEER_CP(n, tp=16, relaxation=False, pcyc='Normal') Generate an nDEER sequence. The sum of tau1 and tau2 is used as total trace length. :Parameters: **n** : int The number of refocusing pulses **tp** : int, optional _description_, by default 16 **relaxation** : bool, optional _description_, by default False **pcyc: str, optional** Normal: Phases cycles pump and observer pulses, no DC cycle NormalDC: Phases cycles pump and observer pulses, DC cycle Obs: Phases cycles observer pulses, no DC cycle ObsDC: Phases cycles and observer pulses, DC cycle .. !! processed by numpydoc !! .. py:method:: select_pcyc(option) Choose which DEER phase you would like. .. |xp| replace:: x\ :sub:`p` .. table:: :width: 150 :widths: 10 10 10 5 30 30 5 +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | Phase cycle | Short Code | Sequence | Steps | Pulse Phase Cycle | Remaining Echoes | Ref. | +===========================+=============+================+========+===========================+=============================+============+ | (x)x|xp|x | DC | ALL | 2 | [+(+x)-(-x)] | PE12rp, SE(PE12)p3, PE12rpr3| | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | (x)[|xp|]x | 8step_3p | 3 pulse | 8 | [+(+x)-(-x)] | | | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | x[x][|xp|]x | 16step_4p | 4 pulse | 16 | [+(+x)-(+y)+(-x)-(-y)] | | [1] | +---------------------------+-------------+----------------+--------+ +-----------------------------+------------+ | x|xp|[x][|xp|]x | 16step_5p | 5 pulse | 16 | [+(+x)+(+y)+(-x)+(-y)] | PEp02r3,b PE1p0r2r3b | [1] | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | x[x]|xp|(x)(|xp|)(|xp|)x | 32step_7p | 7 pulse | 32 | | | [1] | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ :Parameters: **option** : str The short code of the phase cycle. See table above. .. !! processed by numpydoc !! .. py:method:: simulate() .. py:class:: HahnEchoSequence(*, B, LO, reptime, averages, shots, **kwargs) Bases: :py:obj:`Sequence` Represents a Hahn-Echo sequence. Build a Hahn-Echo sequence using either rectangular pulses or specified pulses. By default no progression is added to this sequence. :Parameters: **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point .. !! processed by numpydoc !! .. py:attribute:: name :value: "'HahnEchoSequence'" .. py:class:: T2RelaxationSequence(*, B, LO, reptime, averages, shots, step=40, dim=200, **kwargs) Bases: :py:obj:`HahnEchoSequence` Represents a T2 relaxation sequence. A Hahn Echo where the interpulse delay increases Build a Hahn-Echo sequence using either rectangular pulses or specified pulses. By default no progression is added to this sequence. :Parameters: **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point .. !! processed by numpydoc !! .. py:attribute:: tau .. py:attribute:: name :value: "'T2RelaxationSequence'" .. py:class:: FieldSweepSequence(*, B, LO, Bwidth, reptime, averages, shots, **kwargs) Bases: :py:obj:`HahnEchoSequence` Represents a Field Sweep (EDFS) sequence. Build a Field Sweep (EDFS) sequence using either rectangular pulses or specified pulses. :Parameters: **B** : int or float The B0 field, in Guass **Bwidth: int or float** The width of the field sweep, in Gauss **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point .. !! processed by numpydoc !! .. py:attribute:: name :value: "'FieldSweepSequence'" .. py:attribute:: B .. py:class:: ReptimeScan(*, B, LO, reptime, reptime_max, averages, shots, **kwargs) Bases: :py:obj:`HahnEchoSequence` Represents a reptime scan of a Hahn Echo Sequence. A Hahn echo sequence is perfomed with the shot repetition time increasing.1 :Parameters: **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime: float** The default reptime, this is used for tuning pulses etc... **reptime_max** : np.ndarray The maximum shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point .. !! processed by numpydoc !! .. py:attribute:: min_reptime :value: '20' .. py:attribute:: dim :value: '100' .. py:attribute:: step .. py:attribute:: reptime .. py:attribute:: name :value: "'ReptimeScan'" .. py:class:: CarrPurcellSequence(*, B, LO, reptime, averages, shots, tau, n, dim=100, **kwargs) Bases: :py:obj:`Sequence` Represents a Carr-Purcell sequence. Build a Carr-Purcell dynamical decoupling sequence using either rectangular pulses or specified pulses. :Parameters: **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point **tau** : int The maximum total sequence length in us **n** : int The number refocusing pulses **dim** : int The number of points in the X axis .. !! processed by numpydoc !! .. py:attribute:: name :value: "'CarrPurcellSequence'" .. py:attribute:: tau .. py:attribute:: n .. py:attribute:: dim .. py:method:: _build_sequence() .. py:class:: RefocusedEcho2DSequence(*, B, LO, reptime, averages, shots, tau, dim=100, **kwargs) Bases: :py:obj:`Sequence` Represents a 2D Refocused-echo Sequence. Build a 2D Refocused-echo sequence using either rectangular pulses or specified pulses. :Parameters: **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point **tau** : int The maximum total sequence length in us **dim: int** The number of points in both the X and Y axis .. !! processed by numpydoc !! .. py:attribute:: name :value: "'RefocusedEcho2D'" .. py:attribute:: tau_init :value: '400' .. py:attribute:: dt .. py:attribute:: tau1 .. py:attribute:: tau2 .. py:method:: _build_sequence() .. py:class:: ResonatorProfileSequence(*, B, LO, reptime, averages, shots, fwidth=0.3, **kwargs) Bases: :py:obj:`Sequence` Builds nutation based Resonator Profile sequence. Build a resonator profile nutation sequence using either rectangular pulses or specified pulses. :Parameters: **B** : int or float The B0 field, in Guass **Bwidth: int or float** The width of the field sweep, in Gauss **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point **fwidth: float** The frequency width of the resonator profile in GHz, by default 0.3GHz **tau1: float** The delay between the nutating pulse and the Hahn Echo, by default 2000 ns **tau2: float** The interpulse delay in the Hahn Echo, by default 500 ns .. !! processed by numpydoc !! .. py:attribute:: name :value: "'ResonatorProfileSequence'" .. py:attribute:: gyro .. py:attribute:: fwidth .. py:method:: _build_sequence() .. py:class:: TWTProfileSequence(*, B, LO, reptime, averages=1, shots=100, **kwargs) Bases: :py:obj:`Sequence` Builds TWT based Resonator Profile sequence. Represents an experimental pulse sequence. :Parameters: **name** : str The name of this pulse sequence **B** : float The magnetic field for this sequence in Gauss. **LO** : float The central frequency of this sequence. I.e. The frequnecy at which a zero offset pulse is at. **reptime** : float The shot repetition time in us. **averages** : int The number of scans to be accumulated. **shots** : itn The number of shots per point. .. !! processed by numpydoc !! .. py:attribute:: name :value: "'TWTProfileSequence'" .. py:method:: _build_sequence() .. py:class:: Parameter(name, value, unit='', description='', virtual=False, **kwargs) Represents a sequence or pulse parameter. A general parameter. :Parameters: **name** : str The parameter name **value** : float or int The parameter value, eithe initial or static **unit** : str, optional The unit of parameter, by default None. Leave as None if unitless. **description** : str, optional A brief description of the parameter, by default None **axis** : np.ndarray, optional The difference from the intial value for each position in a dynamic axis. Can be n-dimensional, by default None. **ax_id** : list, optional .. **virtual: bool, optional** A virtual paramter is only used to vary other parameters, it is not varied itself and will not be directly passed to a spectrometer. This parameter is **never** inherited. By default, False :Attributes: **progressive** : bool Is the parameter used in any progression or is it constant **prog** : dict A dict containing progressive programs for this parameter. This list has two elements. 1) The axis_id"s and 2) the "axis" of values. .. rubric:: Examples Creating a static parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") ``` Creating a dynamic parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter", axis=np.arange(0,10,1), axis_id=0) ``` Adding a parameter and a number: ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") Par2 = Par1 + 2 .. !! processed by numpydoc !! .. py:property:: dim .. py:attribute:: name .. py:attribute:: unit .. py:attribute:: description .. py:attribute:: virtual .. py:attribute:: axis :value: '[]' .. py:attribute:: ax_id :value: '[]' .. py:method:: add_axis(axis_id, axis) .. py:method:: get_axis() .. py:method:: remove_dynamic() .. py:method:: is_static() .. py:method:: __eq__(__o) .. py:method:: __add__(__o) .. py:method:: __sub__(__o) .. py:method:: __mul__(__o) .. py:method:: __rmul__(__o) .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the parameter to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dict) :staticmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Parameter object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Parameter The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:function:: build_table(source, params, params_widths) .. py:function:: sop(spins, comps) Spin Operator Matricies. This function is ported from EasySpin (https://easyspin.org/easyspin/documentation/sop.html) References: +++++++++++ [1] Stefan Stoll, Arthur Schweiger EasySpin, a comprehensive software package for spectral simulation and analysis in EPR J. Magn. Reson. 178(1), 42-55 (2006) [2] Stefan Stoll, R. David Britt General and efficient simulation of pulse EPR spectra Phys. Chem. Chem. Phys. 11, 6614-6625 (2009) :Parameters: **spins** : list A list of each spin and its spin qunatum number **comps** : str The type of spin operator matrix to create. Options are: x,y,z,+,-,e .. !! processed by numpydoc !! .. py:function:: autoEPRDecoder(dct) .. py:class:: Pulse(*, tp, t=None, scale=None, flipangle=None, pcyc=[0], name=None, **kwargs) Represents a general experimental pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: bandwidth .. py:property:: amp_factor The B1 amplitude factor (nutation frequency) for the pulse in GHz .. !! processed by numpydoc !! .. py:attribute:: name .. py:attribute:: Progression :value: 'False' .. py:method:: _addPhaseCycle(phases, detections=None) Adds a phase cycle to the pulse sequence. Args: phases (list): List of phases to add to the phase cycle. detections (list, optional): List of detection signs. Defaults to None. If None then all cycles are summed. Returns: None .. !! processed by numpydoc !! .. py:method:: _buildFMAM(func, ax=None) Builds the amplitude modulation (AM) and frequency modulation (FM) of a given function. Args: func: A function that takes in an array of values and returns two arrays, representing the AM and FM of the function. Returns: Two arrays representing the AM and FM of the function. .. !! processed by numpydoc !! .. py:method:: build_shape(ax=None) .. py:method:: build_table() Builds a table of variables, axes, and UUIDs for all non-static Parameters in the object. Returns: dict: A dictionary containing the following keys: "Variable", "axis", and "uuid". The values for each key are lists of the corresponding values for each non-static Parameter. .. !! processed by numpydoc !! .. py:method:: is_static() Check if all parameters in the pulse object are static. Returns: bool: True if all parameters are static, False otherwise. .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Does the pulse contain a specified time, `t`? If so then it is not delay focused. .. !! processed by numpydoc !! .. py:method:: isPulseFocused() Does the pulse contain a specified time, `t`? If so then it is delay focused. .. !! processed by numpydoc !! .. py:method:: plot(pad=1000) Plots the time domain representation of this pulse. :Parameters: **pad** : int, optional The number of zeros to pad the data with, by default 1000 .. !! processed by numpydoc !! .. py:method:: _calc_fft(pad=10000) .. py:method:: exciteprofile(freqs=None, resonator=None) Excitation profile Generates the exciatation profiles for this pulse. This function is ported from EasySpin (https://easyspin.org/easyspin/documentation/sop.html) [1-2], and based upon the method from Gunnar Jeschke, Stefan Pribitzer and Andrin Doll[3]. References: +++++++++++ [1] Stefan Stoll, Arthur Schweiger EasySpin, a comprehensive software package for spectral simulation and analysis in EPR J. Magn. Reson. 178(1), 42-55 (2006) [2] Stefan Stoll, R. David Britt General and efficient simulation of pulse EPR spectra Phys. Chem. Chem. Phys. 11, 6614-6625 (2009) [3] Jeschke, G., Pribitzer, S. & DollA. Coherence Transfer by Passage Pulses in Electron Paramagnetic Resonance Spectroscopy. J. Phys. Chem. B 119, 13570-13582 (2015) :Parameters: **freqs: np.ndarray, optional** The frequency axis. Caution: A larger number of points will linearly increase computation time. **resonator: ad.ResonatorProfile, optional** .. :Returns: Mx: np.ndarray The magentisation in the X direction. My: np.ndarray The magentisation in the Y direction. Mz: np.ndarray The magentisation in the Z direction. .. !! processed by numpydoc !! .. py:method:: plot_fft() .. py:method:: _pcyc_str() .. py:method:: __str__() .. py:method:: copy(clear=False, **kwargs) Creates a deep-copy of the pulse. I.e. Every parameter object is re-created at another memory space. Parameter can be chaged at this stage by adding them as keyword- arguments (kwargs). :Returns: Pulse A deep copy of the pulse .. !! processed by numpydoc !! .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the Pulse to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Pulse object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Pulse The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Detection(*, tp, t=None, freq=0, **kwargs) Bases: :py:obj:`Pulse` Represents a detection pulse. A general detection pulse. :Parameters: **tp** : float The **total** time of the detection event. The detection event will be symetrical about the centre time. **t** : float, optional The **centre** time of the detection event **freq: float, optional** The detection frequency, not all spectrometer support this functionality, by default 0 MHz .. !! processed by numpydoc !! .. py:attribute:: scale :value: 'None' .. py:attribute:: freq .. py:attribute:: pcyc :value: 'None' .. py:class:: Delay(*, tp, t=None) Bases: :py:obj:`Pulse` DEPRECATION WARNING: THIS WILL BE REMOVED SOON. Represents a inter-pulse delay pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:attribute:: tp .. py:attribute:: pcyc :value: 'None' .. py:attribute:: scale :value: 'None' .. py:class:: RectPulse(tp=16, freq=0, t=None, flipangle=None, **kwargs) Bases: :py:obj:`Pulse` Represents a rectangular monochromatic pulse. :Parameters: **tp** : flaot, optional Pulse Length in ns, by default 16 **freq** : float,optional Frequency in MHz, by default 0 **t** : float, optional Time position in ns, by default None **flipangle** : _type_, optional The flip angle in radians, by default None .. !! processed by numpydoc !! .. py:attribute:: freq .. py:method:: func(ax) .. py:class:: GaussianPulse(*, tp=32, FWHM=16, freq=0, **kwargs) Bases: :py:obj:`Pulse` Represents a Gaussian monochromatic pulse. Represents a Gaussian monochromatic pulse. :Parameters: **tp** : float Pulse length in ns, by default 128 **FWHM** : float, The full width at half maximum of the pulse **freq** : float, optional The frequency of the pulse, by default 0 .. !! processed by numpydoc !! .. py:attribute:: freq .. py:attribute:: FWHM .. py:method:: func(ax) .. py:class:: FrequencySweptPulse(*, tp, t=None, scale=None, flipangle=None, pcyc=[0], name=None, **kwargs) Bases: :py:obj:`Pulse` A general parent class for Frequency Swept Pulses. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: Qcrit The critical Q factor for the pulse. .. !! processed by numpydoc !! .. py:property:: sweeprate :abstractmethod: The sweep rate of the pulse in GHz/ns .. !! processed by numpydoc !! .. py:property:: amp_factor The B1 amplitude factor (nutation frequency) for the pulse in GHz .. !! processed by numpydoc !! .. py:class:: HSPulse(*, tp=128, order1=1, order2=6, beta=20, **kwargs) Bases: :py:obj:`FrequencySweptPulse` Represents a hyperboilc secant frequency-swept pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: sweeprate The sweep rate of the pulse in GHz/ns .. !! processed by numpydoc !! .. py:attribute:: order1 .. py:attribute:: order2 .. py:attribute:: beta .. py:method:: func(ax) .. py:class:: ChirpPulse(*, tp=128, **kwargs) Bases: :py:obj:`FrequencySweptPulse` Represents a linear frequency-swept pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: sweeprate The sweep rate of the pulse in GHz/ns .. !! processed by numpydoc !! .. py:method:: func(ax) .. py:class:: SincPulse(*, tp=128, freq=0, order=6, window=None, **kwargs) Bases: :py:obj:`Pulse` Represents a general experimental pulse. Represents a sinc shaped monochromatic pulse. :Parameters: **tp** : int Pulse length in ns, by default 128 **freq** : int, optional The frequency of the pulse, by default 0 **order** : int, optional The order of this sinc function, by default 6 **window** : _type_, optional The window function, by default None .. !! processed by numpydoc !! .. py:attribute:: freq .. py:attribute:: order .. py:attribute:: window .. py:method:: func(ax) .. py:function:: build_default_pulses(AWG=True, SPFU=False, tp=12) .. py:function:: autoEPRDecoder(dct) .. py:class:: Pulse(*, tp, t=None, scale=None, flipangle=None, pcyc=[0], name=None, **kwargs) Represents a general experimental pulse. The class for a general pulse. :Parameters: **tp** : float The pulse length in ns. **scale** : float The arbitary experimental pulse amplitude, 0-1. **t** : float, optional The pulse start time in ns. .. !! processed by numpydoc !! .. py:property:: bandwidth .. py:property:: amp_factor The B1 amplitude factor (nutation frequency) for the pulse in GHz .. !! processed by numpydoc !! .. py:attribute:: name .. py:attribute:: Progression :value: 'False' .. py:method:: _addPhaseCycle(phases, detections=None) Adds a phase cycle to the pulse sequence. Args: phases (list): List of phases to add to the phase cycle. detections (list, optional): List of detection signs. Defaults to None. If None then all cycles are summed. Returns: None .. !! processed by numpydoc !! .. py:method:: _buildFMAM(func, ax=None) Builds the amplitude modulation (AM) and frequency modulation (FM) of a given function. Args: func: A function that takes in an array of values and returns two arrays, representing the AM and FM of the function. Returns: Two arrays representing the AM and FM of the function. .. !! processed by numpydoc !! .. py:method:: build_shape(ax=None) .. py:method:: build_table() Builds a table of variables, axes, and UUIDs for all non-static Parameters in the object. Returns: dict: A dictionary containing the following keys: "Variable", "axis", and "uuid". The values for each key are lists of the corresponding values for each non-static Parameter. .. !! processed by numpydoc !! .. py:method:: is_static() Check if all parameters in the pulse object are static. Returns: bool: True if all parameters are static, False otherwise. .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Does the pulse contain a specified time, `t`? If so then it is not delay focused. .. !! processed by numpydoc !! .. py:method:: isPulseFocused() Does the pulse contain a specified time, `t`? If so then it is delay focused. .. !! processed by numpydoc !! .. py:method:: plot(pad=1000) Plots the time domain representation of this pulse. :Parameters: **pad** : int, optional The number of zeros to pad the data with, by default 1000 .. !! processed by numpydoc !! .. py:method:: _calc_fft(pad=10000) .. py:method:: exciteprofile(freqs=None, resonator=None) Excitation profile Generates the exciatation profiles for this pulse. This function is ported from EasySpin (https://easyspin.org/easyspin/documentation/sop.html) [1-2], and based upon the method from Gunnar Jeschke, Stefan Pribitzer and Andrin Doll[3]. References: +++++++++++ [1] Stefan Stoll, Arthur Schweiger EasySpin, a comprehensive software package for spectral simulation and analysis in EPR J. Magn. Reson. 178(1), 42-55 (2006) [2] Stefan Stoll, R. David Britt General and efficient simulation of pulse EPR spectra Phys. Chem. Chem. Phys. 11, 6614-6625 (2009) [3] Jeschke, G., Pribitzer, S. & DollA. Coherence Transfer by Passage Pulses in Electron Paramagnetic Resonance Spectroscopy. J. Phys. Chem. B 119, 13570-13582 (2015) :Parameters: **freqs: np.ndarray, optional** The frequency axis. Caution: A larger number of points will linearly increase computation time. **resonator: ad.ResonatorProfile, optional** .. :Returns: Mx: np.ndarray The magentisation in the X direction. My: np.ndarray The magentisation in the Y direction. Mz: np.ndarray The magentisation in the Z direction. .. !! processed by numpydoc !! .. py:method:: plot_fft() .. py:method:: _pcyc_str() .. py:method:: __str__() .. py:method:: copy(clear=False, **kwargs) Creates a deep-copy of the pulse. I.e. Every parameter object is re-created at another memory space. Parameter can be chaged at this stage by adding them as keyword- arguments (kwargs). :Returns: Pulse A deep copy of the pulse .. !! processed by numpydoc !! .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the Pulse to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Pulse object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Pulse The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Detection(*, tp, t=None, freq=0, **kwargs) Bases: :py:obj:`Pulse` Represents a detection pulse. A general detection pulse. :Parameters: **tp** : float The **total** time of the detection event. The detection event will be symetrical about the centre time. **t** : float, optional The **centre** time of the detection event **freq: float, optional** The detection frequency, not all spectrometer support this functionality, by default 0 MHz .. !! processed by numpydoc !! .. py:attribute:: scale :value: 'None' .. py:attribute:: freq .. py:attribute:: pcyc :value: 'None' .. py:class:: Parameter(name, value, unit='', description='', virtual=False, **kwargs) Represents a sequence or pulse parameter. A general parameter. :Parameters: **name** : str The parameter name **value** : float or int The parameter value, eithe initial or static **unit** : str, optional The unit of parameter, by default None. Leave as None if unitless. **description** : str, optional A brief description of the parameter, by default None **axis** : np.ndarray, optional The difference from the intial value for each position in a dynamic axis. Can be n-dimensional, by default None. **ax_id** : list, optional .. **virtual: bool, optional** A virtual paramter is only used to vary other parameters, it is not varied itself and will not be directly passed to a spectrometer. This parameter is **never** inherited. By default, False :Attributes: **progressive** : bool Is the parameter used in any progression or is it constant **prog** : dict A dict containing progressive programs for this parameter. This list has two elements. 1) The axis_id"s and 2) the "axis" of values. .. rubric:: Examples Creating a static parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") ``` Creating a dynamic parameter ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter", axis=np.arange(0,10,1), axis_id=0) ``` Adding a parameter and a number: ``` Par1 = Parameter( name="Par1", value=10, unit="us", description="The first parameter") Par2 = Par1 + 2 .. !! processed by numpydoc !! .. py:property:: dim .. py:attribute:: name .. py:attribute:: unit .. py:attribute:: description .. py:attribute:: virtual .. py:attribute:: axis :value: '[]' .. py:attribute:: ax_id :value: '[]' .. py:method:: add_axis(axis_id, axis) .. py:method:: get_axis() .. py:method:: remove_dynamic() .. py:method:: is_static() .. py:method:: __eq__(__o) .. py:method:: __add__(__o) .. py:method:: __sub__(__o) .. py:method:: __mul__(__o) .. py:method:: __rmul__(__o) .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the parameter to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dict) :staticmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load a Parameter object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Parameter The Pulse loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: Interface(log=None) Represents the interface connection from autoEPR to the spectrometer. .. !! processed by numpydoc !! .. py:attribute:: pulses .. py:attribute:: savefolder .. py:attribute:: savename :value: "''" .. py:attribute:: resonator :value: 'None' .. py:method:: connect() .. py:method:: acquire_dataset(data) Acquires the dataset. .. !! processed by numpydoc !! .. py:method:: launch(sequence, savename) Launches the experiment and initialises autosaving. :Parameters: **sequence** : Sequence The sequence to be launched **savename** : str The savename for this measurement. A timestamp will be added to the value. .. !! processed by numpydoc !! .. py:method:: isrunning() .. py:method:: terminate() Terminates the experiment immediately. .. !! processed by numpydoc !! .. py:method:: terminate_at(criterion, test_interval=2, keep_running=True, verbosity=0, autosave=True) Terminates the experiment upon a specific condition being satisified. :Parameters: **criterion** : _type_ The criteria to be tested. **test_interval** : int, optional How often should the criteria be tested in minutes, by default 10. **keep_running** : bool, optional If True, an error will not be raised if the experiment finishes before the criteria is met, by default True. **verbosity** : int, optional The verbosity level, by default 0. **autosave** : bool, optional If True, the data will be autosaved, by default True. .. !! processed by numpydoc !! .. py:class:: Sequence(*, name, B, LO, reptime, averages, shots, **kwargs) Represents an experimental pulse sequence. Represents an experimental pulse sequence. :Parameters: **name** : str The name of this pulse sequence **B** : float The magnetic field for this sequence in Gauss. **LO** : float The central frequency of this sequence. I.e. The frequnecy at which a zero offset pulse is at. **reptime** : float The shot repetition time in us. **averages** : int The number of scans to be accumulated. **shots** : itn The number of shots per point. .. !! processed by numpydoc !! .. py:property:: seqtable_steps .. py:attribute:: pulses :value: '[]' .. py:attribute:: num_pulses .. py:attribute:: axes_uuid :value: '[]' .. py:attribute:: reduce_uuid :value: '[]' .. py:attribute:: LO .. py:attribute:: averages .. py:attribute:: shots .. py:attribute:: name .. py:attribute:: progTable .. py:method:: plot() .. py:method:: plot_pulse_exc(FieldSweep=None, ResonatorProfile=None) .. py:method:: addPulse(pulse) Adds a pulse to the next position in the sequence. :Parameters: **pulse** : Pulse The object describing the pulse. .. !! processed by numpydoc !! .. py:method:: _estimate_time() Calculates the estimated experiment time in seconds. .. !! processed by numpydoc !! .. py:method:: _buildPhaseCycle() .. py:method:: evolution(params, reduce=[]) .. py:method:: shift_detfreq_to_zero() .. py:method:: isPulseFocused() Is the sequence expressed to contain only pulses and no delays? .. !! processed by numpydoc !! .. py:method:: isDelayFocused() Is the sequence expressed to contain both pulses and delays? .. !! processed by numpydoc !! .. py:method:: convert(*, reduce=True) Converts the current sequence to either pulse focused or delay focused depending on the current state :Parameters: **reduce** : bool, optional Reduce to the smallest number of objects, by default True .. !! processed by numpydoc !! .. py:method:: _convert_to_delay() .. py:method:: _convert_to_pulses() .. py:method:: _checkRect() Checks if all the pulses in the sequence are rectangular. .. !! processed by numpydoc !! .. py:method:: __str__() .. py:method:: copy() .. py:method:: _to_dict() .. py:method:: _to_json() .. py:method:: save(filename) Save the sequence to a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: None .. :Raises: TypeError If the object cannot be serialized to JSON. .. !! processed by numpydoc !! .. py:method:: _from_dict(dct) :classmethod: .. py:method:: _from_json(JSONstring) :classmethod: .. py:method:: load(filename) :classmethod: Load an object from a JSON file. :Parameters: **filename** : str Path to the JSON file. :Returns: **obj** : Sequence The Sequence loaded from the JSON file. :Raises: FileNotFoundError If the file does not exist. .. !! processed by numpydoc !! .. py:class:: DEERSequence(*, tau1, tau2, tau3=None, tau4=None, dt, B, LO, reptime, averages, shots, ESEEM_avg=None, **kwargs) Bases: :py:obj:`Sequence` Represents a DEER/PELDOR sequence. Build a DEER sequence using rectangular pulses :Parameters: **tau1** : int or float The first interpulse delay in us **tau2** : int or float The second interpulse delay in us **dt** : int or float The time step for DEER measurment in ns **B** : int or float The B0 field, in Guass **LO** : int or float The LO frequency in GHz **reptime** : _type_ The shot repetition time in us **averages** : int The number of scans. **shots** : int The number of shots per point **tau3** : int or float, optional The delay between the first static pump pulse in 5-pulse DEER and the 1st refocusing pulse in us, by default None. If the value is None then a 4-pulse sequence is created, otherwise a 5-pulse. **ESEEM_avg: str** Selecting the ESEEM averaging required. ESEEM averaging works by introducing small stepping in the first tau delay and averaging across them all. Options: * `proton` - 8 small steps of 8ns * `deuteron` - 8 small steps of 16ns * None - default .. !! processed by numpydoc !! .. py:attribute:: name :value: "'DEERSequence'" .. py:attribute:: tau1us .. py:attribute:: tau1 .. py:attribute:: tau2 .. py:attribute:: dt .. py:attribute:: deadtime :value: '200' .. py:attribute:: ESEEM :value: 'False' .. py:method:: add_ESEEM_avg(type=None) .. py:method:: three_pulse(tp=16) Build a four pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: four_pulse(tp=16, relaxation=False) Build a four pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: five_pulse(tp=16, relaxation=False, re_step=50, re_dim=100) Build a five pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: seven_pulse(tp=16, relaxation=False) Build a seven pulse DEER sequence. :Parameters: **tp** : float Length of default RectPulse in ns, by default 16ns. .. !! processed by numpydoc !! .. py:method:: nDEER_CP(n, tp=16, relaxation=False, pcyc='Normal') Generate an nDEER sequence. The sum of tau1 and tau2 is used as total trace length. :Parameters: **n** : int The number of refocusing pulses **tp** : int, optional _description_, by default 16 **relaxation** : bool, optional _description_, by default False **pcyc: str, optional** Normal: Phases cycles pump and observer pulses, no DC cycle NormalDC: Phases cycles pump and observer pulses, DC cycle Obs: Phases cycles observer pulses, no DC cycle ObsDC: Phases cycles and observer pulses, DC cycle .. !! processed by numpydoc !! .. py:method:: select_pcyc(option) Choose which DEER phase you would like. .. |xp| replace:: x\ :sub:`p` .. table:: :width: 150 :widths: 10 10 10 5 30 30 5 +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | Phase cycle | Short Code | Sequence | Steps | Pulse Phase Cycle | Remaining Echoes | Ref. | +===========================+=============+================+========+===========================+=============================+============+ | (x)x|xp|x | DC | ALL | 2 | [+(+x)-(-x)] | PE12rp, SE(PE12)p3, PE12rpr3| | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | (x)[|xp|]x | 8step_3p | 3 pulse | 8 | [+(+x)-(-x)] | | | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | x[x][|xp|]x | 16step_4p | 4 pulse | 16 | [+(+x)-(+y)+(-x)-(-y)] | | [1] | +---------------------------+-------------+----------------+--------+ +-----------------------------+------------+ | x|xp|[x][|xp|]x | 16step_5p | 5 pulse | 16 | [+(+x)+(+y)+(-x)+(-y)] | PEp02r3,b PE1p0r2r3b | [1] | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ | x[x]|xp|(x)(|xp|)(|xp|)x | 32step_7p | 7 pulse | 32 | | | [1] | +---------------------------+-------------+----------------+--------+---------------------------+-----------------------------+------------+ :Parameters: **option** : str The short code of the phase cycle. See table above. .. !! processed by numpydoc !! .. py:method:: simulate() .. py:function:: get_all_axes(sequence) .. py:function:: get_all_fixed_param(sequence) .. py:function:: create_dataset_from_sequence(data, sequence, extra_params={}) .. py:function:: create_dataset_from_axes(data, axes, params = None, axes_labels=None) .. py:function:: create_dataset_from_bruker(filepath) .. py:class:: EPRAccessor(xarray_obj) .. py:property:: correctphase .. py:property:: normalise .. py:property:: correctphasefull .. py:property:: SNR .. py:property:: fft .. py:property:: sequence .. py:attribute:: _obj .. py:method:: save(filename, type='netCDF') .. py:class:: Reporter(filepath, pagesize='A4') .. py:attribute:: pdf .. py:attribute:: story .. py:attribute:: frame .. py:attribute:: template .. py:method:: header(canvas, doc) .. py:method:: footer(canvas, doc) .. py:method:: _build() .. py:method:: add_title(key, title) .. py:method:: add_new_section(key, title) .. py:method:: add_text(key, text, title=None) .. py:method:: add_code_block(key, code, title=None) .. py:method:: add_figure(key, figure, title=None) .. py:method:: add_space(key, height=5) .. py:method:: add_page_break(key) .. py:method:: add_table(key, lists) Generates a table as a reportlab flowable from a list of lists .. !! processed by numpydoc !! .. py:function:: combo_figure(EDFS, respro, pulses, relaxation, init_deer, long_deer, title=None) Creates a 2x2 summary figure. - The top left plot is the EDFS and resonator profile, overlapped with the optimised pulses. - The top right plot is the relaxation data and fits. - The bottom left plot is the initial DEER data and fits. - The bottom right plot is the final DEER data and fits. :Parameters: **EDFS: ad.FieldSweepAnalysis** The Echo-Detected Field Sweep analysis. **respro: ad.ResonatorProfileAnalysis** The resonator profile analysis **pulses: dict** A dictionary containing the optimised pulses. **relaxation: list** A list containing the relaxation data and fits. **init_deer: deerlab.FitResult** The initial DEER data and fits. **long_deer: deerlab.FitResult** The final DEER data and fits. **title: str, optional** The title of the figure, by default None .. !! processed by numpydoc !! .. py:data:: primary_colors :value: "['#D95B6F', '#42A399', '#E1AE38']"