finesse.analysis.actions package
Submodules
finesse.analysis.actions.axes module
Axes Actions such as xaxis, noaxais, etc.
- class finesse.analysis.actions.axes.Noxaxis(pre_step=None, post_step=None, name='noxaxis')
Bases:
Sweep
- class finesse.analysis.actions.axes.X2axis(parameter1, mode1, start1, stop1, steps1, parameter2, mode2, start2, stop2, steps2, relative=False, *, pre_step=None, post_step=None, name='x2axis')
Bases:
XNaxis
- class finesse.analysis.actions.axes.X3axis(parameter1, mode1, start1, stop1, steps1, parameter2, mode2, start2, stop2, steps2, parameter3, mode3, start3, stop3, steps3, relative=False, *, pre_step=None, post_step=None, name='x3axis')
Bases:
XNaxis
finesse.analysis.actions.base module
Base level Actions utilities and classes.
- class finesse.analysis.actions.base.Action(name, analysis_state_manager=False)
Bases:
objectBase class for all actions
- property analysis_state_manager
- get_requests(model)
- property name
- class finesse.analysis.actions.base.AnalysisState(model, name='AnalysisState', parent=None, simulation_type=None, simulation_options=None)
Bases:
TreeNode- property action_workspaces
Actions can use their id, id(self), to generate a key to store simulation specific data and reuse it each time run is called.
- apply(action)
- build_model(changing_params, extra_input_nodes, extra_output_nodes)
- finished()
- property model
- property previous_solution
- property sim
- finesse.analysis.actions.base.convert_str_to_parameter(model, attr)
Converts names component.parameter or component to a parameter object. Will return default parameter when component name is given.
Parameters
- modelModel
Model object to look for parameter in
- attr[str | Parameter]
String value for the name of an element or a parameters full name. If a Parameter is given its full name will be used to grab the equivalent parameter in this Model.
Returns
- parameter
The equivalent Parameter object for the attr provided
- finesse.analysis.actions.base.request_dict_reduction(A, B)
finesse.analysis.actions.beam module
Collection of Actions that involve beam tracing.
- class finesse.analysis.actions.beam.ABCD(name='abcd', **kwargs)
Bases:
ActionComputation of an ABCD matrix over a path.
See
compute_abcd()for details.
- class finesse.analysis.actions.beam.BeamTrace(name='beam_trace', **kwargs)
Bases:
ActionFull beam tracing on a complete model.
See
Model.beam_trace()for details.
- class finesse.analysis.actions.beam.PropagateAstigmaticBeam(name='astig_propagation', **kwargs)
Bases:
ActionPropagation of a beam, in both planes, through a given path.
See
Model.propagate_beam_astig()for details.
- class finesse.analysis.actions.beam.PropagateBeam(name='propagation', **kwargs)
Bases:
ActionPropagation of a beam, in a single plane, through a given path.
See
Model.propagate_beam()for details.
finesse.analysis.actions.dc module
- class finesse.analysis.actions.dc.DCFields(*, name='dcfields')
Bases:
ActionAn action that saves the DC (carrier) fields at all nodes, frequencies, and higher order modes for the current state of the simulation.
Parameters
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.dc.DCFieldsSolutions
Bases:
BaseSolutionContains the result of a
DCFieldsaction. The returned fields are the internal description of the carrier are all nodes, modes, and frequencies. Fields are defined as P=|E|^2.Attributes
- homslist
The Hermite-Gaussian higher order mode indices at each node, of each frequency.
- nodestuple[str]
Name of nodes the fields were extracted at
- frequenciesarray_like[dtype=float]
Values of the optical frequencies at each node
- fieldsarray_like
Field data array with shape [nodes, frequencies, HOMs.shape[0]]
Notes
The fields attribute will contain all the required information with its ordering defined by the nodes, frequencies, and homs array. For easier indexing you can access the solution directly with node names.
Select all the frequencies and modes at l1.p1.i: >>> sol[‘l1.p1.i’]
Select all the first modes at all frequencies and modes at l1.p1.i: >>> sol[‘l1.p1.i’, :, 0]
Select all the frequencies and modes at two nodes: >>> sol[(‘l1.p1.i’, ‘l1.p1.o’)]
The same nodes can be selected directly with the OpticalNodes: >>> sol[(model.l1.p1.i, model.l1.p1.o)]
Select all the HG02 modes at every node and frequency >>> sol[:, :, sol.homs.index([0, 2]))]
Select all the HG02 modes at every output node and every frequency >>> idx = np.array([node.split(“.”)[-1] == “o” for node in sol.nodes]) >>> sol[idx, :, sol.homs.index([0, 2])]
The frequency and mode selection must be a slice or an array of integer or boolean values.
- fields = None
- frequencies = None
- homs = None
- nodes = None
- selector(key)
finesse.analysis.actions.debug module
- class finesse.analysis.actions.debug.Debug(name='Debug')
Bases:
ActionAn action that will start an IPython debug shell.
To access the current model use state.model.
- class finesse.analysis.actions.debug.SaveMatrix(*, name='savematrix')
Bases:
ActionAn action that will save the current state of the matrix being used by the simulation.
Not something that should be used lightly in loops or multiple times in a large simulation. Using this in something like a full LIGO model with many HOMs and sidebands will quickly fill up memory.
- class finesse.analysis.actions.debug.SaveMatrixSolution
Bases:
BaseSolutionAttributes
- carriercoo_matrix
A Scipy coo_matrix of the carrier simulation matrix. None if the matrix was not available.
- signalcoo_matrix
A Scipy coo_matrix of the signal simulation matrix. None if the matrix was not available.
finesse.analysis.actions.folder module
Folder Action.
- class finesse.analysis.actions.folder.Folder(name, action, solution)
Bases:
ActionA Folder action collects a new solution every time the action is called.
An example of this is the ‘post step’ for the xaxis. A folder action is made called post_step and is passed to a function which will do it multiple times. After each step the specificed action is called and its solution will be added to the folder.
finesse.analysis.actions.locks module
Lock Actions.
- class finesse.analysis.actions.locks.DragLocks(*locks, parameters, stop_points, relative=False, method='proportional', scale_factor=1, num_steps=11, never_optimize_phase=None, exception_on_fail=True, max_recursions=5, max_iterations=1000, display_progress=False, show_progress_bar=False, name='drag locks')
Bases:
ActionAn action that incrementally changes model parameter values, reaching lock at each step, until lock is reached at the desired final parameter values.
Parameters
- *lockslist, optional
A list of locks to use in each
finesse.analysis.actions.locks.RunLocksstep. Acts like the *locks parameter infinesse.analysis.actions.locks.RunLocks: if not provided, all locks in model are used.- parameterslist
A list of strings. Each element should correspond to a parameter in the model.
- stop_pointslist
The final parameter values that locks move towards incrementally.
- relativeboolean
If true, stop_points are relative to the initial parameter values.
- max_recursionsint
The number of times that the step size is allowed to decreased by a factor of ten when locks fail.
- methodstr, either “newton” or “proportional”
The method to use in each locking step.
- scale_factorfloat
Factor by which to multiply all DOF changes. Should be set below 1 if it is desired to minimize overshooting.
- num_stepsint
Number of steps to calculate, starting at the initial point and ending at the stop point.
- never_optimize_phaseboolean
Deprecated: When true, never optimize readout phases. When false, phases will be optimized anytime the previous step required more than 10 iterations.
- exception_on_failboolean
When true, raise exception if max_recursions is surpassed.
- max_iterationsint
The maximum number of locking steps in each execution of RunLocks. If surpassed, step size is decreased.
- display_progressboolean
When true, displays the status of the lock dragging.
- namestr
Name of the action.
- class finesse.analysis.actions.locks.RunLocks(*locks, method='proportional', scale_factor=1, sensing_matrix=None, max_iterations=10000, display_progress=False, optimize_phase=None, d_dof_phase=1e-09, set_gains=True, d_dof_gain=1e-09, exception_on_fail=True, no_warning=False, pre_step=None, show_progress_bar=None, name='run locks')
Bases:
ActionAn action that iteratively moves the system to lock. Currently, lock error signals must be readouts, not detectors, for use in this action.
Parameters
- *lockslist, optional
A list of locks to use in each RunLocks step. If not provided, all locks in model are used.
- methodstr, either “newton” or “proportional”
Which method to use in the locking iterations.
- scale_factorfloat
Factor by which to multiply all DOF changes. Should be set below 1 if it is desired to minimize overshooting.
- sensing_matrixSensingMatrixSolution or None
Sensing matrix of gains used in locking, of the type that would be returned by state.apply(SensingMatrixDC(lock_dof_names, readout_names) If None, the sensing matrix is recalculated. Recommended to be None except when locking multiple times in a row, e.g. with DragLocks.
- max_iterationsint
The maximum number of locking steps in each execution of RunLocks.
- display_progressboolean
When true, displays the status of the error signals during locking iterations.
- optimize_phaseboolean
Deprecated: Use an action like OptimiseRFReadoutPhaseDC instead.
- d_dof_phasefloat
Step size to use when optimizing the demodulation phase for each error signal/DOF pair.
- set_gainsboolean
Only applies if method is “proportional”. If true, sets the gains for each error signal/DOF pair. If false, uses pre-set gains.
- d_dof_gainfloat
Step size to use when calculating the gain for every pair of error signals and DOFs.
- exception_on_failboolean
When true, raise exception if maximum iterations are surpassed.
- no_warningboolean
When true, don’t even raise a warning if maximum iterations are reached. Recommended to be false unless repeatedly testing locking.
- pre_step
Action Action to apply on each step of the lock
- show_progress_barboolean
Will enable the progress bar when true.
- namestr
Name of the action.
- complete_pbar()
- init_pbar(locks)
- update_pbar()
- update_pbar_lock(lock_name, is_locked)
- class finesse.analysis.actions.locks.RunLocksSolution(*args, **kwargs)
Bases:
BaseSolutionSolution from applying the
RunLocksaction.Attributes
- itersint
Number of steps lock has required
- max_iterationsint
Maximum number of iterations this lock can do
- error_signalsarray_like
error signals during locking steps, shape [num_locks, max_iterations]
- control_signalsarray_like
Control signals during locking steps, shape [num_locks, max_iterations]
- lock_namestuple[str]
Names of locks being controlled, shape [num_locks]
- feedback_namestuple[str]
Names of feedback for each lock, shape [num_locks]
- feedback_namestuple[str]
Names of error signals for each lock, shape [num_locks]
- finalarrary_like
Final control signals, shape [num_locks]
- sensing_matrixSensingMatrixSolution, optional
The sensing matrix used when running the locks with Newton’s method.
- plot(ax=None)
Plots how the error signals vary during this lock attempt.
Parameters
- axMatplotlib.Axes, optional
Axes to plot on, if no current axis is set then a new one is generated
- plot_control_signals(ax=None)
Plots how the controls signals vary during this lock attempt. If 0 gaps will be shown when no change has been made to that degree of freedom for that step (As it was within the locks accuracy setting).
Parameters
- axMatplotlib.Axes, optional
Axes to plot on, if no current axis is set then a new one is generated
- class finesse.analysis.actions.locks.SetLockGains(*locks, d_dof_gain=1e-10, gain_scale=1, name='set gains', optimize_phase=None, verbose=False)
Bases:
ActionAn action that computes the optimal lock gains using the sensing matrix found with
SensingMatrixDC. This action computes the error signal gradient for each lock with respect to its drive and sets the gain as -gain_scale/sensing.Parameters
- *lockslist, optional
A list of locks for which to set the gain. If none provided, all enabled locks in model are used. Disabled locks that are explicitly listed will have their gains set.
- d_dof_gainfloat, optional
Step size to use when calculating the gain for each error signal/DOF pair.
- gain_scalefloat, optional
Extra gain scaling factor applied to the gain calculation: -gain_scale/sensing In multiple lock models where the locks are cross coupled using a gain_scale < 1 can improve the stability of the locking algorithm to stop excessively large steps.
- optimize_phasebool, optional,
Deprecated feature: Use
OptimiseRFReadoutPhaseDCinstead- namestr
Name of the action.
- verbosebool
If True this will print the name of the enabled locks and their gains.
finesse.analysis.actions.lti module
Collection of Actions that deal linear time invariant (LTI) modelling tasks.
- class finesse.analysis.actions.lti.FrequencyResponse(f, inputs, outputs, *, open_loop=False, name='frequency_response')
Bases:
ActionComputes the frequency response of a signal injected at various nodes to compute transfer functions to multiple output nodes. Inputs and outputs should be electrical or mechanical nodes. It does this in an efficient way by using the same model and solving for multiple RHS input vectors.
This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each input node to some readout output. The shape of the output matrix is:
[frequencies, inputs, outputs]
To inject into optical nodes please see
FrequencyResponse2andFrequencyResponse3. To readout optical nodes please seeFrequencyResponse3andFrequencyResponse4.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[str or Element]
Mechanical or electrical node to inject signal at
- outputsiterable[str or Element]
Mechanical or electrical nodes to measure output at
- open_loopbool, optional
Computes open loop transfer functions if the system has closed
- namestr, optional
Solution name
Examples
Here we measure a set of transfer functions from DARM and CARM to four readouts for a particular model,
>>> sol = model.run(FrequencyResponse(np.geomspace(0.1, 50000, 100), ... ('DARM', 'CARM'), ... ('AS.DC', 'AS45.I', 'AS45.Q', 'REFL9.I'), ... ))
Single inputs and outputs can also be specified
>>> model.run(FrequencyResponse(np.geomspace(0.1, 50000, 100), 'DARM', AS.DC'))
The transfer functions can then be accessed like a 2D array by name, the ordering of inputs to outputs does not matter.
>>> sol['DARM'] # DARM to all outputs >>> sol['DARM', 'AS.DC'] # DARM to AS.DC >>> sol['DARM', ('AS.DC', 'AS45.I')] >>> sol['AS.DC'] # All inputs to AS.DC readout
- class finesse.analysis.actions.lti.FrequencyResponse2(f, inputs, outputs, *, name='frequency_response2')
Bases:
ActionComputes the frequency response of a signal injected at an optical port at a particular optical frequency. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse2you specify optical input nodes and a signal output node.This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each HOM at a particular frequency and optical node to some readout output. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into mechanical and electrical nodes please see
FrequencyResponseandFrequencyResponse4. To readout optical nodes please seeFrequencyResponse3andFrequencyResponse4.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to inject at. A symbolic refence to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- outputsiterable[str or Element]
Mechanical or electrical (signal)nodes to measure output to
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> import finesse >>> from finesse.analysis.actions import FrequencyResponse2 >>> model = finesse.script.parse(''' ... l l1 ... bs bs1 R=1 T=0 xbeta=1e-6 ybeta=1e-9 ... readout_dc A ... link(l1, bs1, A) ... fsig(1) ... modes(maxtem=1) ... gauss g1 l1.p1.o w=1m Rc=inf ... ''') >>> sol = model.run( ... FrequencyResponse2( ... [1, 10, 100], ... [ ... ('bs1.p2.o', +model.fsig.f.ref), ... ('bs1.p2.o', -model.fsig.f.ref) ... ], ... ['A.DC'] ... ) ... )
- class finesse.analysis.actions.lti.FrequencyResponse3(f, inputs, outputs, *, name='frequency_response3')
Bases:
ActionComputes the frequency response of a signal injected at an optical port at a particular optical frequency. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse3you specify optical input nodes and optical output nodes.This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each HOM at a particular frequency and optical node to some other optical node and frequency. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into mechanical and electrical nodes please see
FrequencyResponseandFrequencyResponse4. To readout mechanical and electrical nodes please seeFrequencyResponseandFrequencyResponse2.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to inject at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- outputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to measure output at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> import finesse >>> from finesse.analysis.actions import FrequencyResponse3 >>> model = finesse.script.parse(''' ... l l1 ... bs bs1 R=1 T=0 xbeta=1e-6 ybeta=1e-9 ... readout_dc A ... link(l1, bs1, A) ... fsig(1) ... modes(maxtem=1) ... gauss g1 l1.p1.o w=1m Rc=inf ... ''') >>> sol = model.run( ... FrequencyResponse3( ... [1, 10, 100], ... [ ... ('bs1.p2.o', +model.fsig.f.ref), ... ('bs1.p2.o', -model.fsig.f.ref) ... ], ... [ ... ('A.p1.i', +model.fsig.f.ref), ... ('A.p1.i', -model.fsig.f.ref) ... ] ... ) ... )
- class finesse.analysis.actions.lti.FrequencyResponse4(f, inputs, outputs, *, name='frequency_response4')
Bases:
ActionComputes the frequency response of a signal injected at an electrical or mechanical port. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse4you specify signal input nodes and optical output nodes.This action does not alter the model state. This action will ignore any currently defined signal generator elements in the model.
Produces an output transfer matrix from each signal node to each HOM at a particular frequency and optical node. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into optical nodes please see
FrequencyResponse2andFrequencyResponse3. To readout mechanical and electrical nodes please seeFrequencyResponseandFrequencyResponse2.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[str or Element]
Mechanical or electrical node to inject signal at
- outputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to measure output at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> sol = model.run( ... FrequencyResponse( ... [1, 10, 100], ... [model.ETM.mech.z], ... [ ... (model.ITM.p2.o, +model.fsig.f.ref), ... (model.ITM.p2.o, -model.fsig.f.ref) ... ] ... ) ... )
- class finesse.analysis.actions.lti.FrequencyResponseSolution
Bases:
BaseSolutionA solution from running a
FrequencyResponseaction on a model. This solution contains the frequency vector and potentially multiple input and output transfer function matrix.Attributes
- farray_like
Frequency vector [Hz]
- inputsarray_like
The input names injected into for this analysis
- outputsarray_like
The output names read out for this analysis
- outarrray_like[dtype=np.complex128]
A matrix of transfer functions for each input to every output over the array of frequencies requested. Depending on which frequency response action was run will decide what shape this output matrix actually is. The shape of out is dependent on the analysis done:
FrequencyResponse - (N_f, N_outputs, N_inputs)
FrequencyResponse2 - (N_f, N_outputs, N_inputs, N_hom)
FrequencyResponse3 - (N_f, N_outputs, N_inputs, N_hom, N_hom)
FrequencyResponse4 - (N_f, N_outputs, N_inputs, N_hom)
- typetype
Type of FrequencyResponse that was used to generate this solution
Examples
Note that the name indexing below is only available when used with the
FrequencyResponseaction, the other frequency-response actions must be accessed using the out attribute.Results from a FrequencyResponseSolution can be retrieved in two ways, first through the FrequencyResponseSolution.out array or by name using [outputs, inputs]. As an example we will create a fake solution:
>>> from finesse.analysis.actions.lti import FrequencyResponseSolution >>> sol = FrequencyResponseSolution("name") >>> sol.inputs = ("A", "B", "C") >>> sol.outputs = ("D", "E", "F", "G") >>> sol.out = np.random.rand(3, len(sol.outputs), len(sol.inputs))
The names will map to those provided in the FrequencyResponse action you called to generate the solution.
The following will work to select single transfer functions between some input and output by name:
>>> sol["D", "A"] # Select A -> D >>> sol["D", "C"] # Select C -> D >>> sol["F", "C"] # Select C -> F
Transfer function matrices can be extracted by providing multiple
>>> sol["F", ("C", "A")] >>> sol[("F", "G"), ("C", "A")]
Slicing can also be used:
>>> sol["D", :] # Select all inputs to "D" >>> sol["D", ::2] # Select every other input to "D" >>> sol[:, "B"] # Select "B" to all outputs >>> sol[1:, "B"] # Select "B" to all but the first output
- outputs_inputs_indices(outputs: List[str], inputs: List[str], *, reversed: bool = False) Tuple[int, int]
Returns the indices to use for selecting certain inputs and outputs from the out attribute of this solution object.
Parameters
- outputsList[str]
List of names of outputs, see outputs attribute for options
- inputsList[str]
List of names of inputs, see inputs attribute for options
- reversedbool, optional
Should not be used by the user, this is an internal flag used for checking if the reverse case should be tried, ie. inputs specified first rather than outputs. This is for backwards compatibility before FrequencyResponse was fixed.
Returns
- output_index, input_index
Indices for the outputs and inputs
Raises
- KeyError
Raised when no input or output name can be found.
- plot(*inputs, axs=None, max_width=12, show_unity=False, **kwargs)
Plot all transfer functions on a NxM grid with a max_width.
Parameters
- inputs*,
Names of inputs for each subplot
- axs_type_, optional
Matplotlib axes to draw on
- max_widthint, optional
Maximum number of subplots in width
- show_unitybool, optional
Plot a line where unity is
Returns
- figure, axes
Matplotlib figure and axes to plot on
- plot_inputs(*inputs, axs=None, max_width=12, show_unity=False, **kwargs)
Plot all transfer functions on a NxM grid with a max_width.
Parameters
- inputs*,
Names of inputs for each subplot
- axs_type_, optional
Matplotlib axes to draw on
- max_widthint, optional
Maximum number of subplots in width
- show_unitybool, optional
Plot a line where unity is
Returns
- figure, axes
Matplotlib figure and axes to plot on
- plot_outputs(*outputs, axs=None, max_width=12, **kwargs)
Plot all transfer functions on a NxM grid with a max_width.
Parameters
- outputs*,
Names of outputs for each subplot
- axs_type_, optional
Matplotlib axes to draw on
- max_widthint, optional
Maximum number of subplots in width
- show_unitybool, optional
Plot a line where unity is
Returns
- figure, axes
Matplotlib figure and axes to plot on
finesse.analysis.actions.noise module
Actions to compute noise projections and budgets.
- class finesse.analysis.actions.noise.NoiseProjection(f, *output_nodes, scaling=None, name='loop')
Bases:
Action
- class finesse.analysis.actions.noise.NoiseProjectionSolution
Bases:
BaseSolution- plot(self, *args, show=True, **kwargs)
Plot solution(s).
If the solution contains child solutions, they are plotted in order. Solutions without plot arguments are skipped. Positional arguments passed to this method are assumed to be
dictand are unpacked into calls to each child’s plot method. Global arguments to be passed to all plot methods can be specified directly as keyword arguments. Duplicate arguments specified in a positional argumentdictionariestake precendence over global arguments.Parameters
- show
bool, optional Show the figures.
Other Parameters
- *args
Sequence of
dictto use as parameters for the call to each child solution’s plot method.- **kwargs
Keyword arguments supported by the child solution(s).
Notes
If the Nth solution contains no plot method, it still consumes the Nth positional argument passed to this method.
- show
finesse.analysis.actions.operator module
Operator based Actions to extract operators and perform operator based analyes, such as calculating eigenmodes.
- class finesse.analysis.actions.operator.Eigenmodes(cavity: Cavity, frequency, *, name='eigenmodes')
Bases:
ActionFor a given Cavity defined in a model, this action will compute the roundtrip operator and calculate the eigen-values and -vectors of the cavity. This will not give correct solutions for coupled cavities as these need to include additional effects.
This can be used to determine what modes combination of modes are resonating in a cavity and the required tuning to make that mode resonate.
Parameters
- class finesse.analysis.actions.operator.EigenmodesSolution
Bases:
BaseSolutionContains the result of an Eigenmodes action. The start node is defined by the Cavity starting point.
Attributes
- connectionstuple((Node, Node))
Node connections used in the round trip propagator
- roundtrip_matrixarray
Combined round trip matrix operator for the cavity
- matriceslist[array]
A list of operators for each connection
- eigvalues, eigvectorsarray, array
Eigen values and vectors of the round trip matrix
- cavity_planewave_lossfloat
Round trip loss for a planewave
- homsarray_like
Array of HOMs used in the model at the time this was computed
- loss(remove_planewave_loss=False)
Computes the round trip loss of all the eigenmodes of the cavity. Eigenmodes are ordered by loss. Lowest loss may not be the fundamental mode.
Parameters
- remove_planewave_lossbool, optional
Whether to remove the roundtrip loss a plane wave would experience to see the loss induced from HOM effects.
Returns
- indexarray_like
Indicies of ordering for the eigvalues and eigvectors of this solution
- lossarray_like
Roundtrip loss of modes
- plot_field(mode_idx, *, x=None, y=None, samples=100, scale=3, ax=None, colorbar=True, **kwargs)
Plots a 2D optical field for one of the eigenmodes.
x and y dimensions can be specified if required, otherwise it will return an area of scale times the spot sizes. When x and y are provided scale and samples will not do anything.
Parameters
- mode_idxint
index of the mode to plot
- x, yndarray, optional
Specify x and y coordinates to plot beam
- samplesint, optional
Number of sample points to use in x and y
- scalefloat, optional
Number of sample points to use in x and y
- axAxis, optional
A Matplotlib axis to put the image on. If None, a new figure will be made.
- colorbarbool
When True the colorbar will be added
- **kwargs
Extra keyword arguments will be passed to the pcolormesh plotting function.
- plot_phase(scale=None, ax=None, **kwargs)
Plots the eigenmode phases.
Parameters
- scalefloat
Scale of scatter point size
- axMatplotlib.Axis, optional
The axis to plot on to, if None a new figure is made
- **kwargs
Keyword arguments passed to matplotlib.pyplot.scatter for styling trace
- plot_roundtrip_loss(remove_planewave_loss=False, ax=None, **kwargs)
Plots the roundtrip loss of the cavity for each eigenmode.
Parameters
- remove_planewave_lossbool, optional
If True, remove the loss a planewave would experience to just see the effects from higher order modes.
- axMatplotlib.Axis, optional
The axis to plot on to, if None a new figure is made
- **kwargs
Keyword arguments passed to matplotlib.pyplot.semilogy for styling trace
- class finesse.analysis.actions.operator.Operator(start_node, end_node, via=None, frequency=0, *, name='operator')
Bases:
ActionThis action can be used to extract operators out from a simulation for external use. The operators are defined by a path in the network between two nodes (via some other if more direction is required).
The model.path method can be used to test which nodes are traversed before using this to extract operators if needed.
Parameters
- start_nodestr
Start node name
- end_nodestr
End node name
- viastr, optional
Via node to use to specify a path with multiple options
- frequencyfloat, optional
Optical carrier or signal frequency to use for calculating the operators
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.operator.OperatorSolution
Bases:
BaseSolution- operator: ndarray
Contains solution to the Operator action. The main result is the operator attribute which describes the operator taking the field from start to end node.
Attributes
- connections[(Node, Node)]
A list of node pairs describing the connections traversed to compute this operator
- operatorndarray(ndim=2, dtype=complex)
The operator describing the propagation from start to end node.
finesse.analysis.actions.optimisation module
Collection of Actions that deal linear time invariant (LTI) modelling tasks.
- class finesse.analysis.actions.optimisation.Maximize(detector, parameter, name='maximize', *args, **kwargs)
Bases:
OptimizeAn action that maximizes some detector output by applying some feedback to multiple targets in a model. Extra keyword arguments are passed on to the Scipy method:
This action offers a simplified interface that allows an optimization to be done during a simulation. By default the the Nelder-Mead optimization method is used but can be overridden. The user should read the Scipy documentation to determine which options should be used which are method dependant.
Notes
Default optimizer used is nelder-mead. To set the absolute and relative error targets use (From the scipy documentation: https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html)
- xatolfloat, optional
Absolute error in xopt between iterations that is acceptable for convergence. Defaults to 1e-4.
- fatolfloat, optional
Absolute error in func(xopt) between iterations that is acceptable for convergence. Defaults to 1e-4.
These can be set as keyword arguments to the action.
Parameters
- detectorstr
The name of the detector output to maximize / minimize.
- parameter[
Parameter| str | tuple] The parameter or name of the parameter to optimize, or a tuple of parameters when using multiple targets to optimize over.
- boundslist, optional
A pair of (lower, upper) bounds on the parameter value. Requires a method that uses bounds.
- offsetfloat, optional
An offset applied to the detector output when optimizing, defaults to 0.
- kindstr, optional
Either ‘max’ for maximization or ‘min’ for minimization, defaults to ‘max’.
- max_iterationsint, optional
Maximum number of solver iterations, defaults to 10000.
- methodstr, optional
Optimisation method to use, see Scipy documentation for options.
- namestr, optional
The name of this action, defaults to ‘maximize’.
- update_mapsbool, optional
If you are changing some parameter or variable that a Map depends on then setting this flag to True will recompute the Map data for each iteration of the optimiser.
- pre_stepAction, optional
Action to run on each step of the optimisation.
- kwargs
Optional parameters passed to the Scipy optimisation routine as the options input. See Scipy method documentation to determine what is available.
Examples
Simple example that maximizes the power in a coupled cavity solution by moving multiple mirrors
model = finesse.Model() model.parse(''' l l1 P=1 m m1 R=0.98 T=0.02 phi=10 m m2 R=0.99 T=0.01 m m3 R=1 T=0 phi=-20 link(l1, m1, m2, m3) pd P m3.p1.i ''') sol = model.run("maximize(P, [m1.phi, m3.phi], xatol=1e-7)") print(sol.result)
- class finesse.analysis.actions.optimisation.Minimize(detector, parameter, name='minimize', *args, **kwargs)
Bases:
OptimizeAn action that minimizes some detector output by applying some feedback to multiple targets in a model. Extra keyword arguments are passed on to the Scipy method:
This action offers a simplified interface that allows an optimization to be done during a simulation. By default the the Nelder-Mead optimization method is used but can be overridden. The user should read the Scipy documentation to determine which options should be used which are method dependant.
Notes
Default optimizer used is nelder-mead. To set the absolute and relative error targets use (From the scipy documentation: https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html)
- xatolfloat, optional
Absolute error in xopt between iterations that is acceptable for convergence. Defaults to 1e-4.
- fatolfloat, optional
Absolute error in func(xopt) between iterations that is acceptable for convergence. Defaults to 1e-4.
These can be set as keyword arguments to the action.
Parameters
- detectorstr
The name of the detector output to maximize / minimize.
- parameter[
Parameter| str | tuple] The parameter or name of the parameter to optimize, or a tuple of parameters when using multiple targets to optimize over.
- boundslist, optional
A pair of (lower, upper) bounds on the parameter value. Requires a method that uses bounds.
- offsetfloat, optional
An offset applied to the detector output when optimizing, defaults to 0.
- kindstr, optional
Either ‘max’ for maximization or ‘min’ for minimization, defaults to ‘max’.
- max_iterationsint, optional
Maximum number of solver iterations, defaults to 10000.
- methodstr, optional
Optimisation method to use, see Scipy documentation for options.
- namestr, optional
The name of this action, defaults to ‘maximize’.
- update_mapsbool, optional
If you are changing some parameter or variable that a Map depends on then setting this flag to True will recompute the Map data for each iteration of the optimiser.
- pre_stepAction, optional
Action to run on each step of the optimisation.
- kwargs
Optional parameters passed to the Scipy optimisation routine as the options input. See Scipy method documentation to determine what is available.
Examples
Simple example that minimizes some measured power by feeding back to the laser power
model = finesse.Model() model.parse(''' l l1 P=1 pd P l1.p1.o ''') sol = model.run("minimize(P, l1.P)") print(sol.result)
- exception finesse.analysis.actions.optimisation.OptimizationWarning
Bases:
RuntimeWarning
- class finesse.analysis.actions.optimisation.Optimize(detector, parameters, bounds=None, offset=0, kind='max', max_iterations=10000, tol=None, verbose=False, method='nelder-mead', opfunc=None, update_maps=False, pre_step=None, name='optimize', **kwargs)
Bases:
Action- property parameter_names
- class finesse.analysis.actions.optimisation.OptimizeSolution(*args, **kwargs)
Bases:
BaseSolutionSolution for an optimization action.
Attributes
- resultscipy.optimize.optimize.OptimizeResult
Result from the scipy optimization method that contains the results and some extra data about the process and any errors that might happen.
- parameters[Parameter | tuple]
Name or names of parameters that were optimized over
- x[numeric | ndarray]
The final minimized values for the parameters requested.
finesse.analysis.actions.parallel module
Parallel Action.
- class finesse.analysis.actions.parallel.ParallelSolution
Bases:
BaseSolution
finesse.analysis.actions.pseudolock module
- class finesse.analysis.actions.pseudolock.PseudoLockCavity(cavity, *, mode=None, lowest_loss=False, feedback=None, name='pseudo_lock_cavity')
Bases:
ActionAn action that locks a cavity defined by a Cavity element to a specific mode without using any radio-frequency sensing scheme. This will only work on simple cavities that are not coupled in any way. You can specify whether to try and lock to a particular HG mode with the mode=[n,m] keyword argument, or just pick the lowest loss mode, lowest_loss=True.
Parameters
- cavityCavity
Cavity element describing some Fabry-Perot like optical cavity
- mode(n, m), optional
HG mode to try and lock to, default is [0,0]
- lowest_lossbool, optional
Select the eigenmode which has the lowest loss, most likely the fundamental mode of the cavity. Using lowest loss will override the mode selection.
- feedbackParameter optional
If None the required cavity tuning to lock to the calculated mode will be determined from the cavity objects source node element, and the relevant phi parameter will be used. Alternatively you can specify which tuning parameter is used instead. Which should be a phi of some mirror in the cavity or a DegreeOfFreedom which controls the cavity length.
- namestr, optional
Name of the solution generated by this action
Examples
A Fabry-Perot based on aLIGO cavities:
>>> import finesse >>> model = finesse.Model() >>> model.parse(''' ... l l1 P=1 ... m ITM T=0.014 L=0 Rc=-1945 ... s sARM ITM.p2 ETM.p1 L=3994 ... m ETM R=1 L=0 Rc=2145 ... link(l1, ITM) ... cav arm ETM.p1.o ... modes(maxtem=1) ... ''')
The cavity source node is on the ETM so the pseudo-lock will use that node and component phi parameter to feedback to. In this case the ETM.phi will be corrected to match the ITM.phi which will make the HG00 resonant.
>>> model.ITM.phi = 0 >>> model.ETM.phi = 10 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 0.0 degrees 0.0 degrees
>>> model.ITM.phi = 10 >>> model.ETM.phi = 0 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 10.0 degrees 10.0 degrees
This lock will also handle any misalignments, mismatches, or maps applied to the cavity.
>>> model.ITM.xbeta = 5e-8 >>> model.ITM.phi = 11 >>> model.ETM.phi = 0 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 11.0 degrees 10.984168676865762 degrees
We can also lock to other HG modes:
>>> sol = model.run("series(pseudo_lock_cavity(arm, mode=[1,0]), noxaxis())") >>> print(model.ITM.phi, model.ETM.phi) >>> print(model.homs) >>> print(sol['noxaxis']['Ecirc']) 11.0 degrees 28.663091273523214 degrees [[0 0] [1 0] [0 1]] [-0.16465261-0.11468501j 0.41262682-0.27112167j 0. +0.j ]
- class finesse.analysis.actions.pseudolock.PseudoLockCavitySolution
Bases:
BaseSolutionSolution to the
PseudoLockCavityaction.Attributes
- operator
OperatorSolution Solution of the operator action that is used to compute the roundtrip operator in the cavity
- warray_like
2D Eigenvector array
- varray_like
1D Eigenvalue array
- v_idxint
Index of the eigenmode being locked to
- phasefloat
Phase in degrees of the eigenmode that is being locked to. This is what is used to set the operating point of the cavity
- cavitystr
Which cavity is being locked
- lowest_lossbool
If False, the target mode attribute is used. Otherwise
- modearray_like
[n, m] target mode to try and lock to
- operator
- class finesse.analysis.actions.pseudolock.PseudoLockDRFPMI(frequency=0, *, apply_tunings=True, name='operator_lock')
Bases:
ActionPseudo-locking is attempting to find an operating point for a LIGO like model without needing to use RF sidebands and readouts. Although it is not physically accurate it does provide a useful tool for analysing detectors from a more theoretical basis. This generates a
PseudoLockDRFPMISolutionsolution containing various operators and results.This action is hardcoded to work with a LIGO like model. Mirrors should be named with ITMX, ETMX, PRM, etc.
This currently action only really works for finding the lock points for the PRC, SRC, XARM, and YARM – which all have defined cavity roundtrips which allow eigendecomposition of roundtrip operators. The eigenvectors describe the HOM mix for each resonant mode in a cavity and the eigenvalues the roundtrip phase and loss of the mode. This code looks for eigenvectors with the largest HG00 content and then uses the eigenvalues to compute what cavity tunings need to make this mode resonant.
The corner is the most complicated here as the PRC and SRC are coupled via the beamsplitter. The eigendecomposition is performed on the 2x2 operator matrix for the PRC, SRC, and the coupling matrices between them. When the coupling is small the results are the same as performing the decomposition on each SRC and PRC separately.
Note that the only degree of freedom that this does not handle currently is MICH. MICH is awkward because it is not a cavity. It is essentially the beamsplitter position that makes the anti-symmetric port dark.
Parameters
- frequencyfloat, optional
Frequency to use for calculating the operators
- apply_tuningsbool, optional
When True the action will modify the model tunings
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.pseudolock.PseudoLockDRFPMISolution
Bases:
BaseSolutionTODO: needs updating for all the various attributes this stores.
- plot_PRC_SRC_eigenvectors()
finesse.analysis.actions.random module
Random collection of Actions that do no warrant a separate module.
- class finesse.analysis.actions.random.Change(change_dict=None, *, relative=False, name='change', **kwargs)
Bases:
ActionChanges a model Parameter to some value during an analysis.
Parameters
- change_dictdict, optional
Dictionary of parameter:value pairs to change.
- relativebool, optional
Whether to increment from the parameters current value or not
- namestr, optional
Name of action
- **kwargs
Alternative method to specify parameter:value pairs to change
Examples
A simple change of a parameter between running two noxaxis analyses:
>>> model = finesse.script.parse("l L1 P=1") >>> model.run('series(noxaxis(), change(L1.P=2), noxaxis())')
Or increment from the current value: >>> model.run(‘series(noxaxis(), change(L1.P=1, relative=True), noxaxis())’)
- property change_kwargs
- class finesse.analysis.actions.random.Execute(do_fn, parameters=None, name='execute')
Bases:
ActionAn action that will execute the function passed to it when it is run.
Parameters
- do_fnfunction
A function that takes an AnalysisState, and the name of the Exec action as its only arguments. If this function returns a
finesse.solutions.base.BaseSolutionobject then it will be added to the simulations solution to return to the user.- parameterslist, optional
A list of parameters that will be changed by do_fn, if any.
- namestr
The name to give this action.
Examples
A simple function to execute might use a pattern such as this, which generates a Solution that is returned back to the user.
>>> from finesse.solutions import SimpleSolution >>> def my_action(state, name): ... sol = SimpleSolution(name) ... return sol
The
finesse.solutions.simple.SimpleSolutionobject is just an object you can store anything you want in. You can extract any state information about the simulation or model and store it here. This allows you to probe and store details that might not be available as a detector, for example.
- class finesse.analysis.actions.random.MakeTransparent(surfaces, name='make transparent')
Bases:
ActionAction to make all provided surfaces transparent. Simply sets the reflectivity to zero and transmitivity to one.
Parameters
- surfaceslist
A list of surface component names to be made transparent.
- class finesse.analysis.actions.random.PrintModel(name='print_model')
Bases:
ActionAn action that prints the model object being currently used to run actions.
- class finesse.analysis.actions.random.PrintModelAttr(*args, eval=True, prefix='')
Bases:
ActionPrints an attribute of the model being currently used.
Parameters
- *args(str,)
Strings input for the attribute to print
- evalbool, optional
When True symbolic expressions will be evaluated before printing. Defaults to True.
- prefixstr, optional
Optional string to print before the attributes
Examples
You can print the current value of parameters and such using:
>>> PrintModelAttr("m1.R", "bs.phi")
- class finesse.analysis.actions.random.SaveModelAttrSolution
Bases:
BaseSolutionAttributes
- valuesdict
Dictionary of model attribute values
- class finesse.analysis.actions.random.Scale(scales: dict, **kwargs)
Bases:
ActionAction for scaling simulation outputs by some fixed amount. Included for compatibility with legacy Finesse code. New users should apply any desired scalings manually from Python.
Parameters
- detectorsdict
A dictionary of detector name: scaling factor mappings.
finesse.analysis.actions.sensing module
Collection of Actions that deal with sensing tasks such as computing sensing matrices, optimising RF readouts, etc.
- class finesse.analysis.actions.sensing.CheckLinearity(*locks, num_points=10, plot_results=True, xlim=None, name='run locks')
Bases:
ActionAn action that shows the relationships between all DOFs and all error signals, to check whether they are related linearly. Plotted for DOFs starting at their initial values and up until their initial values + 2*gain*intial error signal.
Parameters
- *lockslist, optional
A list of locks to use in each
finesse.analysis.actions.locks.RunLocksstep. Acts like *locks parameter infinesse.analysis.actions.locks.RunLocks: if not provided, all locks in model are used.- num_pointsint
Number of points to plot in the DOF range.
- plot_resultsboolean
Whether or not to plot results (requires matplotlib)
- xlimlist or None
Defines (half of) the range of DOF values over which to plot the error signals. If not specified, gains are used to find a useful range of DOF values to plot over.
- namestr
Name of the action.
- class finesse.analysis.actions.sensing.CheckLinearitySolution(*args, **kwargs)
Bases:
BaseSolution
- class finesse.analysis.actions.sensing.GetErrorSignals(*locks, name='get error signals')
Bases:
ActionAn action that quickly calculates the current error signals for all or a subset of locks in a model.
Parameters
- *lockslist, optional
A list of lock names to compute the error signals for. If not provided, all locks in model are used.
- namestr
Name of the action.
- class finesse.analysis.actions.sensing.GetErrorSignalsSolution(*args, **kwargs)
Bases:
BaseSolution
- class finesse.analysis.actions.sensing.OptimiseRFReadoutPhaseDC(*args, d_dof=1e-10, name='optimise_demod_phases_dc')
Bases:
ActionThis optimises the demodulation phase of
ReadoutRFelements relative to someDegreeOfFreedomor drivenParameterin the model. The phases are optimised by calculating the DC response of the readouts. ThisActionchanges the state of the model by varying the readout demodulation phases. If no arguments are given it will try to automatically optimise any lock element in the model that is using an RF readout with respect to the lock feedback parameter.Parameters
- args
Pairs of
DegreeOfFreedomorParameterandReadoutRFelements, or pairs of their names. If none are provided OptimiseRFReadoutPhaseDC will automatically search forLockelements which haveReadoutRFerror signal and optimise them.- d_doffloat, optional
A small offset applied to the DOFs to compute the gradients of the error signals
Examples
Take a typicaly Pound-Drever-Hall lock of a cavity. Here is some KatScript to setup such a model:
>>> import finesse >>> from finesse.analysis.actions import OptimiseRFReadoutPhaseDC >>> >>> model = finesse.Model() >>> model.parse(''' >>> l l1 >>> mod mod1 10M 0.1 mod_type=pm >>> readout_rf PD f=mod1.f phase=33 output_detectors=True optical_node=m1.p1.o >>> m m1 R=0.99 T=0.01 >>> m m2 R=1 T=0 >>> link(l1, mod1, m1, 1, m2) >>> lock cav_lock PD_I m2.phi 0.01 1e-3 >>> ''')
We have defined a lock above using the I quadrature RF demodulation and feeding back to the m2 mirror position. We can optimise this demodulation phase by running. Here we manually provied which drives and readouts to use:
>>> sol = model.run(OptimiseRFReadoutPhaseDC("m2.phi", 'PD_I')) >>> print(sol.phases) {'PD': 181.3535303754581} >>> print(model.PD.phase) 181.3535303754581
Alternatively, PD_Q could also be optimised for above. You can also just optimise all locks that are using RF readouts by providing no arguments:
>>> sol = model.run(OptimiseRFReadoutPhaseDC()) >>> print(sol.phases) {'PD': 181.3535303754581}
To tell what was optimised, see the sol.phases dictionary.
- class finesse.analysis.actions.sensing.OptimiseRFReadoutPhaseDCSolution
Bases:
BaseSolution
- class finesse.analysis.actions.sensing.SensingMatrixAC(dofs, readouts, f=0.001, name='sensing_matrix_ac')
Bases:
ActionComputes the sensing matrix elements for various degrees of freedom and readouts that should be present in the model. The solution object for this action then contains all the information on the sensing matrix. This can be plotted in polar coordinates, displayed in a table, or directly accessed.
The sensing gain is computed by calculating the gradient of each readout signal, which means it is a DC measurement. This will not include any suspension or radiation pressure effects.
This action does not modify the states model.
Parameters
- dofsiterable[str]
String names of degrees of freedom
- readoutsiterable[str]
String names of readouts
- ffloat
Frequency to measure sensing matrix at
- class finesse.analysis.actions.sensing.SensingMatrixDC(dofs, readouts, d_dof=1e-09, name='sensing_matrix_dc')
Bases:
ActionComputes the sensing matrix elements for various degrees of freedom and readouts that should be present in the model. The solution object for this action then contains all the information on the sensing matrix. This can be plotted in polar coordinates, displayed in a table, or directly accessed.
The sensing gain is computed by calculating the gradient of each readout signal, which means it is a DC measurement. This will not include any suspension or radiation pressure effects.
This action does not modify the states model.
Parameters
- dofsiterable[str]
String names of degrees of freedom
- readoutsiterable[str]
String names of readouts
- d_doffloat, optional
Small step used to compute derivative
- class finesse.analysis.actions.sensing.SensingMatrixSolution
Bases:
BaseSolutionSensing matrix solution.
The raw sensing matrix information can be accessed using the SensingMatrixSolution.out member. This is a complex-valued array with dimensions (DOFs, Readouts), which are accessible via SensingMatrixSolution.dofs and SensingMatrixSolution.readouts.
A table can be printed using
SensingMatrixSolution.display().Polar plot can be generated using
SensingMatrixSolution.plot()Printing
SensingMatrixSolutionwill show an ASCII table of the data.- display(dofs=None, readouts=None, tablefmt='pandas', numfmt='{:.2G}', highlight=None, highlight_color='#808080')
Displays a HTML table of the sensing matrix, optionally highlighting the largest absolute value for each readout or dof.
Notes
Only works when called from an IPython environment with the display method available. Pandas is required for highlighting.
Parameters
- dofsiterable[str], optional
Names of degrees of freedom to show, defaults to all if None
- readoutsiterable[str], optional
Names of readouts to show, defaults to all if None
- tablefmtstr, optional
Either ‘pandas’ for pandas formatting, or anything else to use finesse.utilities.tables.Table. Defaults to ‘pandas’ if available.
- numfmtstr or func or array, optional
Either a function to format numbers or a formatting string. The function must return a string. Can also be an array with one option per row, column or cell. Defaults to ‘{:.2G}’.
- highlightstr or None, optional
Either ‘dof’ to highlight the readout that gives the largest output for each dof, or ‘readout’ to highlight the dof for which each readout gives the largest output. Defaults to None (no highlighting).
- highlight_colorstr, optional
Color to highlight the maximum values with. Pandas is required for this to have an effect. Defaults to pale orange.
- matrix_data(dofs=None, readouts=None)
Generates a sensing matrix table.
Parameters
- dofsiterable[str], optional
Names of degrees of freedom to show, defaults to all if None
- readoutsiterable[str], optional
Names of readouts to show, defaults to all if None
Returns
matrix : 2D numpy array, complex dofs : list of
strreadouts: list ofstr
- plot(self, *args, show=True, **kwargs)
Plot solution(s).
If the solution contains child solutions, they are plotted in order. Solutions without plot arguments are skipped. Positional arguments passed to this method are assumed to be
dictand are unpacked into calls to each child’s plot method. Global arguments to be passed to all plot methods can be specified directly as keyword arguments. Duplicate arguments specified in a positional argumentdictionariestake precendence over global arguments.Parameters
- show
bool, optional Show the figures.
Other Parameters
- *args
Sequence of
dictto use as parameters for the call to each child solution’s plot method.- **kwargs
Keyword arguments supported by the child solution(s).
Notes
If the Nth solution contains no plot method, it still consumes the Nth positional argument passed to this method.
- show
- finesse.analysis.actions.sensing.get_readout_workspace(readouts, output, readout_workspaces)
Return the readout workspaces for a particular readout’s quadrature outputs.
Parameters
- readoutsiterable
ReadoutRFelements- outputstr
Quadrature output to try and select, ‘I’, ‘Q’, ‘DC’
- readout_workspacesdict
Workspaces of the readouts in the simulation
finesse.analysis.actions.series module
Serial Action.
- class finesse.analysis.actions.series.For(param, values, *actions)
Bases:
ActionAn action changes a parameter value and runs a set of actions for each value in the array. Essentially the same as Series combined with Change. The parameter value is not reset to its original value once this action has finished.
Generates a
ForSolutionoutput when run.Examples
A simple example printing some a varied laser power output.
>>> import finesse >>> model = finesse.Model() >>> model.parse(''' ... l l1 ... pd P l1.p1.o ... ''') >>> sol = model.run('for(l1.P, [0, 1, 2, 3], print(l1.P))') 0.0 W 1.0 W 2.0 W 3.0 W >>> print(sol.values) [0, 1, 2, 3]
Parameters
- paramstr|Parameter
Parameter to change in the model
- valuesarray_like
Array of values to use for the parameter
- *actionstuple(Action)
Actions to run for each parameter value.
- class finesse.analysis.actions.series.ForSolution
Bases:
BaseSolutionSolution generated by a For Action.
Attributes
- parameterobject | str
Model parameter that was varied by the For action
- valuesarray_like
Array of values that were iterated over
Examples
A simple example printing some a varied laser power output:
>>> import finesse >>> model = finesse.Model() >>> model.parse(''' ... l l1 ... pd P l1.p1.o ... ''') >>> sol = model.run('for(l1.P, [0, 1, 2, 3], print(l1.P))') 0.0 W 1.0 W 2.0 W 3.0 W >>> print(sol.values) [0, 1, 2, 3]
- class finesse.analysis.actions.series.Series(*actions, flatten=True, name=None)
Bases:
ActionA sequential series of actions to apply during a simulation.
Parameters
- actions
Action A collection of Actions to run in series
- flattenbool
When True, each action will be stored in the top level of the solution tree. When False, each action will be a child of the previous solution generated.
- namestr
Optional name for the solution generated by these actions
- actions
- class finesse.analysis.actions.series.SeriesSolution
Bases:
BaseSolutionSeriesSolution is a solution object that contains the results from running the requested actions by a
Series. You can see what solutions are contained by printing this object or by inspecting thechildrenattribute.
finesse.analysis.actions.squeezing module
Collection of actions to perform analysis on squeezing.
- class finesse.analysis.actions.squeezing.AntiSqueezing(f, squeezer, readout, *, signal=None, name='antisqueezing')
Bases:
ActionComputes the amount of anti-squeezing at an output from a squeezing element.
Notes
This will only works in cases where the HG00 is squeezed and is used after a filtering component, like a cavity to select only the HG00. The calculation does not use the usual internal quantum noise solver in Finesse. Instead it computes how much loss and rotation from a squeezer happens by calculating the upper and lower sideband transfer functions from the squeezer to some readout. From this the relevant squeezing outputs can be calculated.
Parameters
- farray_like
Signal frequencies to compute the anti-squeezing over
- squeezerstr
Name of squeezing component
- readoutstr
Name of readout port to compute squeezing at
- signalstr
Name of signal drive to calculate a the signal transfer function of. This is returned in sol.signal and can be used to scale the noise into equivalent units of some signal.
- property f
- class finesse.analysis.actions.squeezing.AntiSqueezingSolution
Bases:
BaseSolution
finesse.analysis.actions.sweep module
Sweep Action.
- class finesse.analysis.actions.sweep.Sweep(*args, pre_step=None, post_step=None, reset_parameter=True, name='sweep')
Bases:
ActionAn action that sweeps N number of parameters through the values in N arrays.
Parameters
- args[Parameter, str], array, boolean
Expects 3 arguments per axis. The first is a full name of a Parameter or a Parameter object. The second is an array of values to step this parameter over, and lastly a boolean value to say whether this is a relative step from the parameters initial value.
- pre_stepAction, optional
An action to perform before the step is computed
- post_stepAction, optional
An action to perform after the step is computed
- reset_parameterboolean, optional
When true this action will reset the all the parameters it changed to the values before it ran.
- namestr
Name of the action, used to find the solution in the final output.
finesse.analysis.actions.temporary module
Temporary actions allow for temporary state changes to perform some chosen set of actions with, then returning to the original state.
- class finesse.analysis.actions.temporary.Temporary(temp_action, *actions)
Bases:
ActionMake the first action in a series of actions temporary, i.e. restore its parameters after the rest of the actions are complete.
- class finesse.analysis.actions.temporary.TemporaryParameters(action, *, include=None, exclude=None)
Bases:
ActionAn action that will revert any changed parameters back to their values before this action was called. Options exist to include or exclude certain Parameters from this reversion. This action does not generate any Solution.
Parameters
- action
finesse.analysis.actions.base.Action Action to perform followed by reverting requested Parameters in the model
- include[iterable|str], optional
Parameters that should be included.
If a single string is given it can be a Unix file style wildcard (See
fnmatch). A value of None means everything is included.If an iterable is provided it must be a list of names or Parameter objects.
- exclude[iterable|str], optional
Parameters that should not be included.
If a single string is given it can be a Unix file style wildcard (See
fnmatch). A value of None means nothing is excluded.If an iterable is provided it must be a list of names or Parameter objects.
- action
- finesse.analysis.actions.temporary.temporary(action)
Converts an action into a temporary action.
This function takes a target action, and returns an action that takes multiple actions as arguments. When the returned action is run, it will first run the target action, then all actions passed to it, then restore the changes made by the target action, e.g.
temporary(Change({'m1.phi': 10}))( Xaxis(l1.P, 'lin', 0, 10, 100) )
will first set the parameter m1.phi to 10, then run a sweep of l1.P, then restore m1.phi to its previous value.
Parameters
- actionAction
The action to make temporary.
Returns
- action
An action that temporarily applies the passed action when run.
finesse.analysis.actions.utils module
- finesse.analysis.actions.utils.elements_to_name(x)
Module contents
- class finesse.analysis.actions.ABCD(name='abcd', **kwargs)
Bases:
ActionComputation of an ABCD matrix over a path.
See
compute_abcd()for details.
- class finesse.analysis.actions.Action(name, analysis_state_manager=False)
Bases:
objectBase class for all actions
- property analysis_state_manager
- get_requests(model)
- property name
- class finesse.analysis.actions.AntiSqueezing(f, squeezer, readout, *, signal=None, name='antisqueezing')
Bases:
ActionComputes the amount of anti-squeezing at an output from a squeezing element.
Notes
This will only works in cases where the HG00 is squeezed and is used after a filtering component, like a cavity to select only the HG00. The calculation does not use the usual internal quantum noise solver in Finesse. Instead it computes how much loss and rotation from a squeezer happens by calculating the upper and lower sideband transfer functions from the squeezer to some readout. From this the relevant squeezing outputs can be calculated.
Parameters
- farray_like
Signal frequencies to compute the anti-squeezing over
- squeezerstr
Name of squeezing component
- readoutstr
Name of readout port to compute squeezing at
- signalstr
Name of signal drive to calculate a the signal transfer function of. This is returned in sol.signal and can be used to scale the noise into equivalent units of some signal.
- property f
- class finesse.analysis.actions.BeamTrace(name='beam_trace', **kwargs)
Bases:
ActionFull beam tracing on a complete model.
See
Model.beam_trace()for details.
- class finesse.analysis.actions.Change(change_dict=None, *, relative=False, name='change', **kwargs)
Bases:
ActionChanges a model Parameter to some value during an analysis.
Parameters
- change_dictdict, optional
Dictionary of parameter:value pairs to change.
- relativebool, optional
Whether to increment from the parameters current value or not
- namestr, optional
Name of action
- **kwargs
Alternative method to specify parameter:value pairs to change
Examples
A simple change of a parameter between running two noxaxis analyses:
>>> model = finesse.script.parse("l L1 P=1") >>> model.run('series(noxaxis(), change(L1.P=2), noxaxis())')
Or increment from the current value: >>> model.run(‘series(noxaxis(), change(L1.P=1, relative=True), noxaxis())’)
- property change_kwargs
- class finesse.analysis.actions.CheckLinearity(*locks, num_points=10, plot_results=True, xlim=None, name='run locks')
Bases:
ActionAn action that shows the relationships between all DOFs and all error signals, to check whether they are related linearly. Plotted for DOFs starting at their initial values and up until their initial values + 2*gain*intial error signal.
Parameters
- *lockslist, optional
A list of locks to use in each
finesse.analysis.actions.locks.RunLocksstep. Acts like *locks parameter infinesse.analysis.actions.locks.RunLocks: if not provided, all locks in model are used.- num_pointsint
Number of points to plot in the DOF range.
- plot_resultsboolean
Whether or not to plot results (requires matplotlib)
- xlimlist or None
Defines (half of) the range of DOF values over which to plot the error signals. If not specified, gains are used to find a useful range of DOF values to plot over.
- namestr
Name of the action.
- class finesse.analysis.actions.DCFields(*, name='dcfields')
Bases:
ActionAn action that saves the DC (carrier) fields at all nodes, frequencies, and higher order modes for the current state of the simulation.
Parameters
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.Debug(name='Debug')
Bases:
ActionAn action that will start an IPython debug shell.
To access the current model use state.model.
- class finesse.analysis.actions.DragLocks(*locks, parameters, stop_points, relative=False, method='proportional', scale_factor=1, num_steps=11, never_optimize_phase=None, exception_on_fail=True, max_recursions=5, max_iterations=1000, display_progress=False, show_progress_bar=False, name='drag locks')
Bases:
ActionAn action that incrementally changes model parameter values, reaching lock at each step, until lock is reached at the desired final parameter values.
Parameters
- *lockslist, optional
A list of locks to use in each
finesse.analysis.actions.locks.RunLocksstep. Acts like the *locks parameter infinesse.analysis.actions.locks.RunLocks: if not provided, all locks in model are used.- parameterslist
A list of strings. Each element should correspond to a parameter in the model.
- stop_pointslist
The final parameter values that locks move towards incrementally.
- relativeboolean
If true, stop_points are relative to the initial parameter values.
- max_recursionsint
The number of times that the step size is allowed to decreased by a factor of ten when locks fail.
- methodstr, either “newton” or “proportional”
The method to use in each locking step.
- scale_factorfloat
Factor by which to multiply all DOF changes. Should be set below 1 if it is desired to minimize overshooting.
- num_stepsint
Number of steps to calculate, starting at the initial point and ending at the stop point.
- never_optimize_phaseboolean
Deprecated: When true, never optimize readout phases. When false, phases will be optimized anytime the previous step required more than 10 iterations.
- exception_on_failboolean
When true, raise exception if max_recursions is surpassed.
- max_iterationsint
The maximum number of locking steps in each execution of RunLocks. If surpassed, step size is decreased.
- display_progressboolean
When true, displays the status of the lock dragging.
- namestr
Name of the action.
- class finesse.analysis.actions.Eigenmodes(cavity: Cavity, frequency, *, name='eigenmodes')
Bases:
ActionFor a given Cavity defined in a model, this action will compute the roundtrip operator and calculate the eigen-values and -vectors of the cavity. This will not give correct solutions for coupled cavities as these need to include additional effects.
This can be used to determine what modes combination of modes are resonating in a cavity and the required tuning to make that mode resonate.
Parameters
- class finesse.analysis.actions.Execute(do_fn, parameters=None, name='execute')
Bases:
ActionAn action that will execute the function passed to it when it is run.
Parameters
- do_fnfunction
A function that takes an AnalysisState, and the name of the Exec action as its only arguments. If this function returns a
finesse.solutions.base.BaseSolutionobject then it will be added to the simulations solution to return to the user.- parameterslist, optional
A list of parameters that will be changed by do_fn, if any.
- namestr
The name to give this action.
Examples
A simple function to execute might use a pattern such as this, which generates a Solution that is returned back to the user.
>>> from finesse.solutions import SimpleSolution >>> def my_action(state, name): ... sol = SimpleSolution(name) ... return sol
The
finesse.solutions.simple.SimpleSolutionobject is just an object you can store anything you want in. You can extract any state information about the simulation or model and store it here. This allows you to probe and store details that might not be available as a detector, for example.
- class finesse.analysis.actions.For(param, values, *actions)
Bases:
ActionAn action changes a parameter value and runs a set of actions for each value in the array. Essentially the same as Series combined with Change. The parameter value is not reset to its original value once this action has finished.
Generates a
ForSolutionoutput when run.Examples
A simple example printing some a varied laser power output.
>>> import finesse >>> model = finesse.Model() >>> model.parse(''' ... l l1 ... pd P l1.p1.o ... ''') >>> sol = model.run('for(l1.P, [0, 1, 2, 3], print(l1.P))') 0.0 W 1.0 W 2.0 W 3.0 W >>> print(sol.values) [0, 1, 2, 3]
Parameters
- paramstr|Parameter
Parameter to change in the model
- valuesarray_like
Array of values to use for the parameter
- *actionstuple(Action)
Actions to run for each parameter value.
- class finesse.analysis.actions.FrequencyResponse(f, inputs, outputs, *, open_loop=False, name='frequency_response')
Bases:
ActionComputes the frequency response of a signal injected at various nodes to compute transfer functions to multiple output nodes. Inputs and outputs should be electrical or mechanical nodes. It does this in an efficient way by using the same model and solving for multiple RHS input vectors.
This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each input node to some readout output. The shape of the output matrix is:
[frequencies, inputs, outputs]
To inject into optical nodes please see
FrequencyResponse2andFrequencyResponse3. To readout optical nodes please seeFrequencyResponse3andFrequencyResponse4.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[str or Element]
Mechanical or electrical node to inject signal at
- outputsiterable[str or Element]
Mechanical or electrical nodes to measure output at
- open_loopbool, optional
Computes open loop transfer functions if the system has closed
- namestr, optional
Solution name
Examples
Here we measure a set of transfer functions from DARM and CARM to four readouts for a particular model,
>>> sol = model.run(FrequencyResponse(np.geomspace(0.1, 50000, 100), ... ('DARM', 'CARM'), ... ('AS.DC', 'AS45.I', 'AS45.Q', 'REFL9.I'), ... ))
Single inputs and outputs can also be specified
>>> model.run(FrequencyResponse(np.geomspace(0.1, 50000, 100), 'DARM', AS.DC'))
The transfer functions can then be accessed like a 2D array by name, the ordering of inputs to outputs does not matter.
>>> sol['DARM'] # DARM to all outputs >>> sol['DARM', 'AS.DC'] # DARM to AS.DC >>> sol['DARM', ('AS.DC', 'AS45.I')] >>> sol['AS.DC'] # All inputs to AS.DC readout
- class finesse.analysis.actions.FrequencyResponse2(f, inputs, outputs, *, name='frequency_response2')
Bases:
ActionComputes the frequency response of a signal injected at an optical port at a particular optical frequency. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse2you specify optical input nodes and a signal output node.This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each HOM at a particular frequency and optical node to some readout output. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into mechanical and electrical nodes please see
FrequencyResponseandFrequencyResponse4. To readout optical nodes please seeFrequencyResponse3andFrequencyResponse4.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to inject at. A symbolic refence to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- outputsiterable[str or Element]
Mechanical or electrical (signal)nodes to measure output to
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> import finesse >>> from finesse.analysis.actions import FrequencyResponse2 >>> model = finesse.script.parse(''' ... l l1 ... bs bs1 R=1 T=0 xbeta=1e-6 ybeta=1e-9 ... readout_dc A ... link(l1, bs1, A) ... fsig(1) ... modes(maxtem=1) ... gauss g1 l1.p1.o w=1m Rc=inf ... ''') >>> sol = model.run( ... FrequencyResponse2( ... [1, 10, 100], ... [ ... ('bs1.p2.o', +model.fsig.f.ref), ... ('bs1.p2.o', -model.fsig.f.ref) ... ], ... ['A.DC'] ... ) ... )
- class finesse.analysis.actions.FrequencyResponse3(f, inputs, outputs, *, name='frequency_response3')
Bases:
ActionComputes the frequency response of a signal injected at an optical port at a particular optical frequency. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse3you specify optical input nodes and optical output nodes.This action does not alter the model state. This action will ignore any currently definied signal generator elements in the model.
Produces an output transfer matrix from each HOM at a particular frequency and optical node to some other optical node and frequency. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into mechanical and electrical nodes please see
FrequencyResponseandFrequencyResponse4. To readout mechanical and electrical nodes please seeFrequencyResponseandFrequencyResponse2.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to inject at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- outputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to measure output at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> import finesse >>> from finesse.analysis.actions import FrequencyResponse3 >>> model = finesse.script.parse(''' ... l l1 ... bs bs1 R=1 T=0 xbeta=1e-6 ybeta=1e-9 ... readout_dc A ... link(l1, bs1, A) ... fsig(1) ... modes(maxtem=1) ... gauss g1 l1.p1.o w=1m Rc=inf ... ''') >>> sol = model.run( ... FrequencyResponse3( ... [1, 10, 100], ... [ ... ('bs1.p2.o', +model.fsig.f.ref), ... ('bs1.p2.o', -model.fsig.f.ref) ... ], ... [ ... ('A.p1.i', +model.fsig.f.ref), ... ('A.p1.i', -model.fsig.f.ref) ... ] ... ) ... )
- class finesse.analysis.actions.FrequencyResponse4(f, inputs, outputs, *, name='frequency_response4')
Bases:
ActionComputes the frequency response of a signal injected at an electrical or mechanical port. This differs from
FrequencyResponsein the way the inputs and outputs are prescribed. ForFrequencyResponse4you specify signal input nodes and optical output nodes.This action does not alter the model state. This action will ignore any currently defined signal generator elements in the model.
Produces an output transfer matrix from each signal node to each HOM at a particular frequency and optical node. The shape of the output matrix is:
[frequencies, outputs, inputs, HOMs]
It should be noted that when exciting a lower signal sideband frequency it will actually return the operator for propagating the conjugate of the lower sideband. This is because FINESSE is internally solving for the conjugate of the lower sideband to linearise non-linear optical effects.
To inject into optical nodes please see
FrequencyResponse2andFrequencyResponse3. To readout mechanical and electrical nodes please seeFrequencyResponseandFrequencyResponse2.Parameters
- farray, double
Frequencies to compute the transfer functions over
- inputsiterable[str or Element]
Mechanical or electrical node to inject signal at
- outputsiterable[tuple[str or Node, Frequency]]
Optical node and frequency tuple to measure output at. A symbolic reference to the model’s fsig.f parameter should always be used when defining a frequency to look at.
- namestr, optional
Solution name
Examples
It is advisable to use always use a reference to the symbolic reference to the signal frequency model.fsig.f.ref instead of a fixed number incase it changes. This action will look for an initial frequency bin of X Hz to track during the frequency response analysis. A symbolic reference will always ensure the right bin is used, in cases such as looking at RF signal sidebands, 10e6+model.fsig.f.ref and 10e6-model.fsig.f.ref will always look at the upper and lower signal sideband around the +10MHz sideband.
>>> sol = model.run( ... FrequencyResponse( ... [1, 10, 100], ... [model.ETM.mech.z], ... [ ... (model.ITM.p2.o, +model.fsig.f.ref), ... (model.ITM.p2.o, -model.fsig.f.ref) ... ] ... ) ... )
- class finesse.analysis.actions.GetErrorSignals(*locks, name='get error signals')
Bases:
ActionAn action that quickly calculates the current error signals for all or a subset of locks in a model.
Parameters
- *lockslist, optional
A list of lock names to compute the error signals for. If not provided, all locks in model are used.
- namestr
Name of the action.
- class finesse.analysis.actions.Maximize(detector, parameter, name='maximize', *args, **kwargs)
Bases:
OptimizeAn action that maximizes some detector output by applying some feedback to multiple targets in a model. Extra keyword arguments are passed on to the Scipy method:
This action offers a simplified interface that allows an optimization to be done during a simulation. By default the the Nelder-Mead optimization method is used but can be overridden. The user should read the Scipy documentation to determine which options should be used which are method dependant.
Notes
Default optimizer used is nelder-mead. To set the absolute and relative error targets use (From the scipy documentation: https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html)
- xatolfloat, optional
Absolute error in xopt between iterations that is acceptable for convergence. Defaults to 1e-4.
- fatolfloat, optional
Absolute error in func(xopt) between iterations that is acceptable for convergence. Defaults to 1e-4.
These can be set as keyword arguments to the action.
Parameters
- detectorstr
The name of the detector output to maximize / minimize.
- parameter[
Parameter| str | tuple] The parameter or name of the parameter to optimize, or a tuple of parameters when using multiple targets to optimize over.
- boundslist, optional
A pair of (lower, upper) bounds on the parameter value. Requires a method that uses bounds.
- offsetfloat, optional
An offset applied to the detector output when optimizing, defaults to 0.
- kindstr, optional
Either ‘max’ for maximization or ‘min’ for minimization, defaults to ‘max’.
- max_iterationsint, optional
Maximum number of solver iterations, defaults to 10000.
- methodstr, optional
Optimisation method to use, see Scipy documentation for options.
- namestr, optional
The name of this action, defaults to ‘maximize’.
- update_mapsbool, optional
If you are changing some parameter or variable that a Map depends on then setting this flag to True will recompute the Map data for each iteration of the optimiser.
- pre_stepAction, optional
Action to run on each step of the optimisation.
- kwargs
Optional parameters passed to the Scipy optimisation routine as the options input. See Scipy method documentation to determine what is available.
Examples
Simple example that maximizes the power in a coupled cavity solution by moving multiple mirrors
model = finesse.Model() model.parse(''' l l1 P=1 m m1 R=0.98 T=0.02 phi=10 m m2 R=0.99 T=0.01 m m3 R=1 T=0 phi=-20 link(l1, m1, m2, m3) pd P m3.p1.i ''') sol = model.run("maximize(P, [m1.phi, m3.phi], xatol=1e-7)") print(sol.result)
- class finesse.analysis.actions.Minimize(detector, parameter, name='minimize', *args, **kwargs)
Bases:
OptimizeAn action that minimizes some detector output by applying some feedback to multiple targets in a model. Extra keyword arguments are passed on to the Scipy method:
This action offers a simplified interface that allows an optimization to be done during a simulation. By default the the Nelder-Mead optimization method is used but can be overridden. The user should read the Scipy documentation to determine which options should be used which are method dependant.
Notes
Default optimizer used is nelder-mead. To set the absolute and relative error targets use (From the scipy documentation: https://docs.scipy.org/doc/scipy/reference/optimize.minimize-neldermead.html)
- xatolfloat, optional
Absolute error in xopt between iterations that is acceptable for convergence. Defaults to 1e-4.
- fatolfloat, optional
Absolute error in func(xopt) between iterations that is acceptable for convergence. Defaults to 1e-4.
These can be set as keyword arguments to the action.
Parameters
- detectorstr
The name of the detector output to maximize / minimize.
- parameter[
Parameter| str | tuple] The parameter or name of the parameter to optimize, or a tuple of parameters when using multiple targets to optimize over.
- boundslist, optional
A pair of (lower, upper) bounds on the parameter value. Requires a method that uses bounds.
- offsetfloat, optional
An offset applied to the detector output when optimizing, defaults to 0.
- kindstr, optional
Either ‘max’ for maximization or ‘min’ for minimization, defaults to ‘max’.
- max_iterationsint, optional
Maximum number of solver iterations, defaults to 10000.
- methodstr, optional
Optimisation method to use, see Scipy documentation for options.
- namestr, optional
The name of this action, defaults to ‘maximize’.
- update_mapsbool, optional
If you are changing some parameter or variable that a Map depends on then setting this flag to True will recompute the Map data for each iteration of the optimiser.
- pre_stepAction, optional
Action to run on each step of the optimisation.
- kwargs
Optional parameters passed to the Scipy optimisation routine as the options input. See Scipy method documentation to determine what is available.
Examples
Simple example that minimizes some measured power by feeding back to the laser power
model = finesse.Model() model.parse(''' l l1 P=1 pd P l1.p1.o ''') sol = model.run("minimize(P, l1.P)") print(sol.result)
- class finesse.analysis.actions.NoiseProjection(f, *output_nodes, scaling=None, name='loop')
Bases:
Action
- class finesse.analysis.actions.Operator(start_node, end_node, via=None, frequency=0, *, name='operator')
Bases:
ActionThis action can be used to extract operators out from a simulation for external use. The operators are defined by a path in the network between two nodes (via some other if more direction is required).
The model.path method can be used to test which nodes are traversed before using this to extract operators if needed.
Parameters
- start_nodestr
Start node name
- end_nodestr
End node name
- viastr, optional
Via node to use to specify a path with multiple options
- frequencyfloat, optional
Optical carrier or signal frequency to use for calculating the operators
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.OptimiseRFReadoutPhaseDC(*args, d_dof=1e-10, name='optimise_demod_phases_dc')
Bases:
ActionThis optimises the demodulation phase of
ReadoutRFelements relative to someDegreeOfFreedomor drivenParameterin the model. The phases are optimised by calculating the DC response of the readouts. ThisActionchanges the state of the model by varying the readout demodulation phases. If no arguments are given it will try to automatically optimise any lock element in the model that is using an RF readout with respect to the lock feedback parameter.Parameters
- args
Pairs of
DegreeOfFreedomorParameterandReadoutRFelements, or pairs of their names. If none are provided OptimiseRFReadoutPhaseDC will automatically search forLockelements which haveReadoutRFerror signal and optimise them.- d_doffloat, optional
A small offset applied to the DOFs to compute the gradients of the error signals
Examples
Take a typicaly Pound-Drever-Hall lock of a cavity. Here is some KatScript to setup such a model:
>>> import finesse >>> from finesse.analysis.actions import OptimiseRFReadoutPhaseDC >>> >>> model = finesse.Model() >>> model.parse(''' >>> l l1 >>> mod mod1 10M 0.1 mod_type=pm >>> readout_rf PD f=mod1.f phase=33 output_detectors=True optical_node=m1.p1.o >>> m m1 R=0.99 T=0.01 >>> m m2 R=1 T=0 >>> link(l1, mod1, m1, 1, m2) >>> lock cav_lock PD_I m2.phi 0.01 1e-3 >>> ''')
We have defined a lock above using the I quadrature RF demodulation and feeding back to the m2 mirror position. We can optimise this demodulation phase by running. Here we manually provied which drives and readouts to use:
>>> sol = model.run(OptimiseRFReadoutPhaseDC("m2.phi", 'PD_I')) >>> print(sol.phases) {'PD': 181.3535303754581} >>> print(model.PD.phase) 181.3535303754581
Alternatively, PD_Q could also be optimised for above. You can also just optimise all locks that are using RF readouts by providing no arguments:
>>> sol = model.run(OptimiseRFReadoutPhaseDC()) >>> print(sol.phases) {'PD': 181.3535303754581}
To tell what was optimised, see the sol.phases dictionary.
- class finesse.analysis.actions.Optimize(detector, parameters, bounds=None, offset=0, kind='max', max_iterations=10000, tol=None, verbose=False, method='nelder-mead', opfunc=None, update_maps=False, pre_step=None, name='optimize', **kwargs)
Bases:
Action- property parameter_names
- class finesse.analysis.actions.PrintModel(name='print_model')
Bases:
ActionAn action that prints the model object being currently used to run actions.
- class finesse.analysis.actions.PrintModelAttr(*args, eval=True, prefix='')
Bases:
ActionPrints an attribute of the model being currently used.
Parameters
- *args(str,)
Strings input for the attribute to print
- evalbool, optional
When True symbolic expressions will be evaluated before printing. Defaults to True.
- prefixstr, optional
Optional string to print before the attributes
Examples
You can print the current value of parameters and such using:
>>> PrintModelAttr("m1.R", "bs.phi")
- class finesse.analysis.actions.PropagateAstigmaticBeam(name='astig_propagation', **kwargs)
Bases:
ActionPropagation of a beam, in both planes, through a given path.
See
Model.propagate_beam_astig()for details.
- class finesse.analysis.actions.PropagateBeam(name='propagation', **kwargs)
Bases:
ActionPropagation of a beam, in a single plane, through a given path.
See
Model.propagate_beam()for details.
- class finesse.analysis.actions.PseudoLockCavity(cavity, *, mode=None, lowest_loss=False, feedback=None, name='pseudo_lock_cavity')
Bases:
ActionAn action that locks a cavity defined by a Cavity element to a specific mode without using any radio-frequency sensing scheme. This will only work on simple cavities that are not coupled in any way. You can specify whether to try and lock to a particular HG mode with the mode=[n,m] keyword argument, or just pick the lowest loss mode, lowest_loss=True.
Parameters
- cavityCavity
Cavity element describing some Fabry-Perot like optical cavity
- mode(n, m), optional
HG mode to try and lock to, default is [0,0]
- lowest_lossbool, optional
Select the eigenmode which has the lowest loss, most likely the fundamental mode of the cavity. Using lowest loss will override the mode selection.
- feedbackParameter optional
If None the required cavity tuning to lock to the calculated mode will be determined from the cavity objects source node element, and the relevant phi parameter will be used. Alternatively you can specify which tuning parameter is used instead. Which should be a phi of some mirror in the cavity or a DegreeOfFreedom which controls the cavity length.
- namestr, optional
Name of the solution generated by this action
Examples
A Fabry-Perot based on aLIGO cavities:
>>> import finesse >>> model = finesse.Model() >>> model.parse(''' ... l l1 P=1 ... m ITM T=0.014 L=0 Rc=-1945 ... s sARM ITM.p2 ETM.p1 L=3994 ... m ETM R=1 L=0 Rc=2145 ... link(l1, ITM) ... cav arm ETM.p1.o ... modes(maxtem=1) ... ''')
The cavity source node is on the ETM so the pseudo-lock will use that node and component phi parameter to feedback to. In this case the ETM.phi will be corrected to match the ITM.phi which will make the HG00 resonant.
>>> model.ITM.phi = 0 >>> model.ETM.phi = 10 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 0.0 degrees 0.0 degrees
>>> model.ITM.phi = 10 >>> model.ETM.phi = 0 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 10.0 degrees 10.0 degrees
This lock will also handle any misalignments, mismatches, or maps applied to the cavity.
>>> model.ITM.xbeta = 5e-8 >>> model.ITM.phi = 11 >>> model.ETM.phi = 0 >>> model.run("pseudo_lock_cavity(arm)") >>> print(model.ITM.phi, model.ETM.phi) 11.0 degrees 10.984168676865762 degrees
We can also lock to other HG modes:
>>> sol = model.run("series(pseudo_lock_cavity(arm, mode=[1,0]), noxaxis())") >>> print(model.ITM.phi, model.ETM.phi) >>> print(model.homs) >>> print(sol['noxaxis']['Ecirc']) 11.0 degrees 28.663091273523214 degrees [[0 0] [1 0] [0 1]] [-0.16465261-0.11468501j 0.41262682-0.27112167j 0. +0.j ]
- class finesse.analysis.actions.PseudoLockDRFPMI(frequency=0, *, apply_tunings=True, name='operator_lock')
Bases:
ActionPseudo-locking is attempting to find an operating point for a LIGO like model without needing to use RF sidebands and readouts. Although it is not physically accurate it does provide a useful tool for analysing detectors from a more theoretical basis. This generates a
PseudoLockDRFPMISolutionsolution containing various operators and results.This action is hardcoded to work with a LIGO like model. Mirrors should be named with ITMX, ETMX, PRM, etc.
This currently action only really works for finding the lock points for the PRC, SRC, XARM, and YARM – which all have defined cavity roundtrips which allow eigendecomposition of roundtrip operators. The eigenvectors describe the HOM mix for each resonant mode in a cavity and the eigenvalues the roundtrip phase and loss of the mode. This code looks for eigenvectors with the largest HG00 content and then uses the eigenvalues to compute what cavity tunings need to make this mode resonant.
The corner is the most complicated here as the PRC and SRC are coupled via the beamsplitter. The eigendecomposition is performed on the 2x2 operator matrix for the PRC, SRC, and the coupling matrices between them. When the coupling is small the results are the same as performing the decomposition on each SRC and PRC separately.
Note that the only degree of freedom that this does not handle currently is MICH. MICH is awkward because it is not a cavity. It is essentially the beamsplitter position that makes the anti-symmetric port dark.
Parameters
- frequencyfloat, optional
Frequency to use for calculating the operators
- apply_tuningsbool, optional
When True the action will modify the model tunings
- namestr, optional
Name of the solution generated by this action
- class finesse.analysis.actions.RunLocks(*locks, method='proportional', scale_factor=1, sensing_matrix=None, max_iterations=10000, display_progress=False, optimize_phase=None, d_dof_phase=1e-09, set_gains=True, d_dof_gain=1e-09, exception_on_fail=True, no_warning=False, pre_step=None, show_progress_bar=None, name='run locks')
Bases:
ActionAn action that iteratively moves the system to lock. Currently, lock error signals must be readouts, not detectors, for use in this action.
Parameters
- *lockslist, optional
A list of locks to use in each RunLocks step. If not provided, all locks in model are used.
- methodstr, either “newton” or “proportional”
Which method to use in the locking iterations.
- scale_factorfloat
Factor by which to multiply all DOF changes. Should be set below 1 if it is desired to minimize overshooting.
- sensing_matrixSensingMatrixSolution or None
Sensing matrix of gains used in locking, of the type that would be returned by state.apply(SensingMatrixDC(lock_dof_names, readout_names) If None, the sensing matrix is recalculated. Recommended to be None except when locking multiple times in a row, e.g. with DragLocks.
- max_iterationsint
The maximum number of locking steps in each execution of RunLocks.
- display_progressboolean
When true, displays the status of the error signals during locking iterations.
- optimize_phaseboolean
Deprecated: Use an action like OptimiseRFReadoutPhaseDC instead.
- d_dof_phasefloat
Step size to use when optimizing the demodulation phase for each error signal/DOF pair.
- set_gainsboolean
Only applies if method is “proportional”. If true, sets the gains for each error signal/DOF pair. If false, uses pre-set gains.
- d_dof_gainfloat
Step size to use when calculating the gain for every pair of error signals and DOFs.
- exception_on_failboolean
When true, raise exception if maximum iterations are surpassed.
- no_warningboolean
When true, don’t even raise a warning if maximum iterations are reached. Recommended to be false unless repeatedly testing locking.
- pre_step
Action Action to apply on each step of the lock
- show_progress_barboolean
Will enable the progress bar when true.
- namestr
Name of the action.
- complete_pbar()
- init_pbar(locks)
- update_pbar()
- update_pbar_lock(lock_name, is_locked)
- class finesse.analysis.actions.SensingMatrixAC(dofs, readouts, f=0.001, name='sensing_matrix_ac')
Bases:
ActionComputes the sensing matrix elements for various degrees of freedom and readouts that should be present in the model. The solution object for this action then contains all the information on the sensing matrix. This can be plotted in polar coordinates, displayed in a table, or directly accessed.
The sensing gain is computed by calculating the gradient of each readout signal, which means it is a DC measurement. This will not include any suspension or radiation pressure effects.
This action does not modify the states model.
Parameters
- dofsiterable[str]
String names of degrees of freedom
- readoutsiterable[str]
String names of readouts
- ffloat
Frequency to measure sensing matrix at
- class finesse.analysis.actions.SensingMatrixDC(dofs, readouts, d_dof=1e-09, name='sensing_matrix_dc')
Bases:
ActionComputes the sensing matrix elements for various degrees of freedom and readouts that should be present in the model. The solution object for this action then contains all the information on the sensing matrix. This can be plotted in polar coordinates, displayed in a table, or directly accessed.
The sensing gain is computed by calculating the gradient of each readout signal, which means it is a DC measurement. This will not include any suspension or radiation pressure effects.
This action does not modify the states model.
Parameters
- dofsiterable[str]
String names of degrees of freedom
- readoutsiterable[str]
String names of readouts
- d_doffloat, optional
Small step used to compute derivative
- class finesse.analysis.actions.Series(*actions, flatten=True, name=None)
Bases:
ActionA sequential series of actions to apply during a simulation.
Parameters
- actions
Action A collection of Actions to run in series
- flattenbool
When True, each action will be stored in the top level of the solution tree. When False, each action will be a child of the previous solution generated.
- namestr
Optional name for the solution generated by these actions
- actions
- class finesse.analysis.actions.SetLockGains(*locks, d_dof_gain=1e-10, gain_scale=1, name='set gains', optimize_phase=None, verbose=False)
Bases:
ActionAn action that computes the optimal lock gains using the sensing matrix found with
SensingMatrixDC. This action computes the error signal gradient for each lock with respect to its drive and sets the gain as -gain_scale/sensing.Parameters
- *lockslist, optional
A list of locks for which to set the gain. If none provided, all enabled locks in model are used. Disabled locks that are explicitly listed will have their gains set.
- d_dof_gainfloat, optional
Step size to use when calculating the gain for each error signal/DOF pair.
- gain_scalefloat, optional
Extra gain scaling factor applied to the gain calculation: -gain_scale/sensing In multiple lock models where the locks are cross coupled using a gain_scale < 1 can improve the stability of the locking algorithm to stop excessively large steps.
- optimize_phasebool, optional,
Deprecated feature: Use
OptimiseRFReadoutPhaseDCinstead- namestr
Name of the action.
- verbosebool
If True this will print the name of the enabled locks and their gains.
- class finesse.analysis.actions.Sweep(*args, pre_step=None, post_step=None, reset_parameter=True, name='sweep')
Bases:
ActionAn action that sweeps N number of parameters through the values in N arrays.
Parameters
- args[Parameter, str], array, boolean
Expects 3 arguments per axis. The first is a full name of a Parameter or a Parameter object. The second is an array of values to step this parameter over, and lastly a boolean value to say whether this is a relative step from the parameters initial value.
- pre_stepAction, optional
An action to perform before the step is computed
- post_stepAction, optional
An action to perform after the step is computed
- reset_parameterboolean, optional
When true this action will reset the all the parameters it changed to the values before it ran.
- namestr
Name of the action, used to find the solution in the final output.
- class finesse.analysis.actions.Temporary(temp_action, *actions)
Bases:
ActionMake the first action in a series of actions temporary, i.e. restore its parameters after the rest of the actions are complete.
- class finesse.analysis.actions.TemporaryParameters(action, *, include=None, exclude=None)
Bases:
ActionAn action that will revert any changed parameters back to their values before this action was called. Options exist to include or exclude certain Parameters from this reversion. This action does not generate any Solution.
Parameters
- action
finesse.analysis.actions.base.Action Action to perform followed by reverting requested Parameters in the model
- include[iterable|str], optional
Parameters that should be included.
If a single string is given it can be a Unix file style wildcard (See
fnmatch). A value of None means everything is included.If an iterable is provided it must be a list of names or Parameter objects.
- exclude[iterable|str], optional
Parameters that should not be included.
If a single string is given it can be a Unix file style wildcard (See
fnmatch). A value of None means nothing is excluded.If an iterable is provided it must be a list of names or Parameter objects.
- action
- class finesse.analysis.actions.UpdateMaps(name='update_maps', *args, **kwargs)
Bases:
ActionUpdate any maps that might be changing in the simulation.
- class finesse.analysis.actions.X2axis(parameter1, mode1, start1, stop1, steps1, parameter2, mode2, start2, stop2, steps2, relative=False, *, pre_step=None, post_step=None, name='x2axis')
Bases:
XNaxis