Using via the Python API#

The API provides the ability to interact with cavcalc in a Python environment, whilst being similar in its usage to invoking the program via the CLI. Most use-cases will just require calling the single-function interface, calculate(), and then accessing properties and methods of the resulting output object; see output for details on these objects.

Given the similarity with the CLI in the workflow for computing parameters, we will not provide a wide range of examples on this page; you should refer to those given on the Using via the command line page, whilst noting that each CLI command would just be replaced with a calculate() call. You can also find several API examples in the section of the same name in the calculate() documentation itself.

The following imports are used for any examples on this page:

import cavcalc as cc
import matplotlib.pyplot as plt
import numpy as np

# This configures the matplotlib rcParams for the session
# to use the style-sheet provided by cavcalc
cc.configure("cavcalc")

A simple reference example#

To get us started, here is a simple use-case via the API for reference:

out = cc.calculate(L="23cm", Rc="25cm")
print(out)
Given:
	Cavity length = 23 cm

	Radius of curvature of both mirrors = 25 cm

	Wavelength of beam = 1064 nm

Computed:
	FSR = 651722734.7826086 Hz
	Mode separation frequency = 309247630.6687703 Hz

	Position of beam waist (from first mirror) = 0.115 m

	Radius of beam at mirrors = 0.2795483285659775 mm
	Radius of beam at waist = 0.2054252290303631 mm

	Stability g-factor of cavity = 0.006399999999999993
	Stability g-factor of both mirrors = 0.07999999999999996

	Round-trip Gouy phase = 170.82286852842833 deg

	Divergence angle = 0.09446266946261173 deg

As you can see, by simply printing the return type of calculate(), we can view the computed values in an identical manner to invoking cavcalc via the CLI.

Accessing results#

The out object from above is of type MultiOutput, as our calculate() call was performed with no targets specified. We can access any of the results from this object using a dict-like interface:

# Check which cavity properties were computed
print(out.results.keys())

# Get the TargetParameter object for one of the computed properties; in
# this case, the beam radius at the mirrors:
print(out['w'])
# and if you want the Quantity object itself:
w_q = out['w'].value
print(w_q)
# Quantity.m gives us the magnitude of the quantity
print(w_q.m)

# We can also inspect the values of the parameters used to compute the
# results --- this can be useful when working with a loaded cavcalc Output object
print(out.given['L'])
dict_keys(['FSR', 'gs', 'z0', 'div', 'g', 'w0', 'modesep', 'w', 'gouy'])
Radius of beam at mirrors = 0.2795483285659775 mm
0.2795483285659775 millimeter
0.2795483285659775
Cavity length = 23 cm

The type of the value returned from a MultiOutput mapping is always a TargetParameter, so you should refer to the associated documentation for details on all the properties and methods of this object. Similarly, the values of the out.given dict will always be ArgParameter instances.

When computing a single target, the return type of calculate() will be a SingleOutput object. One can also craft an instance of this from a MultiOutput object using the MultiOutput.as_single() method. Using the example from above:

# This will be a SingleOutput object
gouy_out = out.as_single("gouy")

# and get the TargetParameter result simply via:
print(gouy_out.result)
Round-trip Gouy phase = 170.82286852842833 deg
Handling Quantity objects

As we saw above, all physical results (and given arguments) are ultimately stored as pint.Quantity objects — consisting of the numeric value itself, as well as the associated units of this value. Here a few tips are provided for working with these objects; refer to the Pint Documentation for a more thorough and complete overview.

Instantiating

One should never try to use Quantity objects from different Pint unit-registries. When you import cavcalc, a unit-registry is constructed and cached for you — accessible via cc.ureg (where cc is the module alias as above). This is the registry that you should use if you want to interact with Pint directly during any workflows which involve cavcalc.

A convenient short-hand alias for the associated Quantity type can be accessed via cc.Q_. Here are a couple of examples of this:

l = cc.Q_("12cm") # distance of 12 cm
# can also multiply value with a Unit to make a Quantity, e.g.:
l2 = 12 * cc.ureg.cm
assert l == l2

div = cc.Q_("40 mdeg") # angle of 40 milli-degrees

out = cc.calculate(L=l, div=div)
assert all(isinstance(res.value, cc.Q_) for res in out.results.values())

There are several ways of constructing quantities, including with composite units and combining other quantities together. Again, see the Pint documentation for more examples.

Converting

Quantities can be converted using the to method:

print(out['w'].value.to('um'))
print(out['FSR'].value.to('GHz'))
print(out['gouy'].value.to('rad'))
486.9307843333742 micrometer
1.2491352416666668 gigahertz
0.3445232553811186 radian

One can also use the results / given arguments from an output in another calculate() call. For example, we can verify that we get the same cavity geometry as the first example on this page when re-using the computed Gouy phase from earlier:

out = cc.calculate(L="23cm", Rc="25cm")
print(cc.calculate(L=out.given["L"], gouy=out["gouy"]))
Given:
	Cavity length = 23 cm

	Round-trip Gouy phase = 170.82286852842833 deg

	Wavelength of beam = 1064 nm

Computed:
	FSR = 651722734.7826086 Hz
	Mode separation frequency = 309247630.6687703 Hz

	Position of beam waist (from first mirror) = 0.115 m

	Radius of curvature of both mirrors = 0.25000000000000006 m

	Radius of beam at mirrors = 0.2795483285659775 mm
	Radius of beam at waist = 0.2054252290303631 mm

	Stability g-factor of cavity = 0.006400000000000018
	Stability g-factor of both mirrors = 0.08000000000000011

	Divergence angle = 0.09446266946261171 deg

Using the configure function#

An advantage of using the API, versus the CLI, is the ability to temporarily override units for parameters without needing to create or modify cavcalc.ini config files. We can do this via the use of the configure() function, which can be used both regularly and through a with block. The recommended way to use it, for overriding units, is the latter; as this ensures that any unit overrides are temporary.

We can take the example from the Using via the command line page, where we showed how to use config files, and instead use the API:

# Temporarily override any beam-size, RoC, distance, and frequency category units
with cc.configure(beamsizes="um", rocs="mm", distances="mm", frequencies="GHz"):
    print(cc.calculate(L=56, Rc1=25.5, Rc2=35))
Given:
	Cavity length = 56 mm

	Radius of curvature of first mirror = 25.5 mm
	Radius of curvature of second mirror = 35 mm

	Wavelength of beam = 1064 nm

Computed:
	FSR = 2.676718375 GHz
	Mode separation frequency = 0.47731829070785287 GHz

	Position of beam waist (from first mirror) = 22.834951456310677 mm

	Radius of beam at first mirror = 158.99728556011118 µm
	Radius of beam at second mirror = 224.48840499807176 µm
	Radius of beam at waist = 51.401072623419914 µm

	Stability g-factor of cavity = 0.7176470588235291
	Stability g-factor of first mirror = -1.1960784313725488
	Stability g-factor of second mirror = -0.5999999999999999

	Round-trip Gouy phase = 295.80401051536586 deg

	Divergence angle = 0.3775164852670658 deg

This, of course, also applies when using data-ranges, e.g:

# Temporarily override units for the cavity length, and FSR
with cc.configure(L="km", fsr="kHz"):
    cc.calculate("FSR", L=np.linspace(4, 40, 200)).plot();
../_images/module_9_0.png

Note, as we saw near the start of this page, configure() takes a single positional argument: plt_style. This allows you to use a matplotlib style-sheet for configuring plotting styles; again this can be done temporarily, with the matplotlib.rcParams reset back to their previous state on exit from a with block where this is done. By using "cavcalc" for this argument, as we did earlier, the style-sheet provided by this package is used; resulting in plots of the same style as those generated via the CLI.