Change Log
v2.0.3
Refactor of how we define ions and atoms. We now define a subclass of AtomFactory for each atom / ion definition. Pre-defined levels are now attributes of these classes. This change is partly motivated by making it easier to write species-agnostic code (makes it easier to write things like factory.S12 rather than having to access module-level attributes as well as the factory object).
v2.0
This version gives the atomic_physics API a much needed tidy up.
A major design goal for the tidy up was to make things more obvious for the user. This comes at the expense of some function names now being quite a bit more verbose, but that feels like a worthwhile price to pay for clarity!
Misc:
We now have a documentation build. Closes #32
States are now ordered in decreasing energy order, not increasing! This change allows the Pauli matrices to take on their customary meanings and signs, for example with \(\sigma_+\) being the raising operator and energies being represented by \(+\frac{1}{2}\omega\sigma_z\).
Formatting and linting moved from flake8 and black to ruff
CI now checks type annotations using pytype
Fix assorted type annotation and docstring bugs
Significantly expanded test coverage
Significantly expanded documentation
Added helper functions to convert between different polarization representations
Added a helper function to calculate the Rayleigh range of a beam
Added a new
polarizationsmodule for representing and manipulating polarizations.Added a new
RFDriveclass. This is a bit heavyweight for just calculating AC Zeeman shifts (which is all we use it for at present) but it is mainly intended for a future optical bloch equations solver.Added a simple
TwoStateAtomclass to help making simple tests and simulations.
Bug fixes:
Calculate derivatives properly in transition sensitivity calculations. Closes #24
Fix indexing in AC Zeeman shift calculation. Closes #78
Fix incorrect transition frequencies for calcium
API refactor:
Named tuples have been replaced with data classes
We no longer export classes at the module level. Replace import atomic_physics as ap with from atomic_physics.core import Atom
General push to avoid “partially constructed objects” - i.e. objects where we can’t set all the fields at construction time so rely on mutating them in non-obvious ways over the object’s lifetime. This makes the code easier to follow and removes the need for a bunch of checks to see if fields have been initialised.
General push to make variable and function names more explicit, even at the cost of increased verbosity (optimizing for least surprise not fewest keystrokes!). Closes #30
LevelDatanow only contains the atomic structure data; information about the energy-ordering of states is now in a separateLevelStatesobject.Atom.slicehas been renamed toAtom.get_slice_for_level. This avoids shadowing the name of a built-in python type.Atom.detuninghas been renamed toAtom.get_transition_frequency_for_states. This method supports an additionalrelativekeyword to calculate absolute transition frequencies. Closes #29Atom.indexhas been split intoget_states_for_M,get_state_for_F,get_state_for_MI_MJ. This avoids having one function which does lots of different jobs and has a return type which depends in non-obvious ways on the input parameters.Atom.levelhas been renamedget_level_for_stateadded a new
Atom.get_transition_for_levelshelper functionAtom.populationhas been removed as it wasn’t particularly usefulAtom.I0has been renamedAtom.get_saturation_intensityAtom.P0has been renamedintensity_to_powerLaser.qhas been renamed toLaser.polarizationLaser.Ihas been renamed toLaser.intensityAtom.Bhas been renamed toAtom.magnetic_fieldAtom.Ihas been renamed toAtom.nuclear_spinLaser.deltahas been renamed toLaser.detuningRateEquations.get_sponthas been renamed toRateEquations.get_spont_matrix.RateEquations.get_stimhas been renamed toRateEquations.get_stim_matrix.RateEquations.get_transitionshas been renamed toRateEquations.get_transitions_matrix.RateEquations.steady_statehas been renamed toRateEquations.get_steady_state_populations.RateEquations.get_steady_state_populationsnow only takes a transitions matrix as an input, not a transitions matrix or a set of lasers (supporting multiple input types saved a little boiler plate at the expense of making things complex/confusing).angular frequencies are denoted
wnotfMethods where we don’t care about the orderings of states / levels now take a tuple of states / levels rather than asking for an “upper” and “lower” one
The AC Zeeman shift code now takes a
RFDriveobjectPolarizations are new represented by Jones vectors rather than +-1 or 0. The old system was relatively easy once one understood it, but only worked for the simple case of rate equations. Anticipating doing more complex things like optical bloch equations, I’ve started moving us over to Jones vectors.
Add
operators.expectation_valuehelper method.Add
Atom.levelsfield.Add new
Atom.get_states_for_levelmethod.utils.field_insensitive_pointnow works with values ofFandM_Finstead of state indices.