Package: matisse-controller
matisse-controllerA Python package to control the Matisse 2 TS laser for the University of Washington's Optical Spintronics and Sensing Lab.Requirements: Python 3.7+, NI VISA, PyVISA, pySerial, SciPy, matplotlib, PyQt5Tested on Windows 7 and 10 (x64).ContentsInstallationUsageAPI DocumentationChangelogTerminologyPickled DataGUI OptionsDevelopmentContributingLicenseInstallation$ pip install matisse-controllerIf you plan on using PLE features with Andor instruments, copy the required DLL files from the Andor SDK into[package install dir]/shamrock_ple/lib(see the README in that directory for more details)UsageTo launch the GUI, connect the Matisse and a supported wavemeter, and then run:$ matisse-controllerThe GUI uses a Python API to control the Matisse. If you're writing a Python program, just import the subpackages
that contain the APIs you want. Thematissesubpackage contains Matisse-related components, theconfigsubpackage
contains configuration functionality, etc.To configure the behavior of the program using a GUI, click the 'Configuration' menu option from the main GUI, or run:$ matisse-configHovering over most fields in this configuration dialog will reveal tooltips with more information about what the options do.API DocumentationAPI documentation for this project can be found athttps://lucis-fluxum.github.io/matisse-controller/docs.ChangelogThe changelog for this project can be found athttps://lucis-fluxum.github.io/matisse-controller/CHANGELOG.TerminologyThere are a few important bits of terminology that may be confusing:Thetarget wavelengthis the wavelength that is explicitly set (via Set > Wavelength), but if no target wavelength is
given, the current measured wavelength is considered to be the target wavelength instead.Auto-stabilizationorstabilizationin this case refers to constantly checking and scanning the device up and down to
keep the wavelength at a particular value.Thestabilization piezosare the reference cell, the piezo etalon, and the slow piezo.Scanningmay refer to the act of moving a motor back and forth to locate an optimal position, or the act of adjusting the
reference cell and stabilization piezos to adjust the wavelength.Pickled DataPLE data from this application is stored in text files as a list of counts separated by newlines, as well as a.picklefile, which is an efficient form of binary storage that Python uses to serialize objects.To load the data from a .pickle file:importpicklewithopen('file_name_here.pickle','rb')asdata_file:data=pickle.load(data_file)GUI OptionsConsoleClear Log: clear the log windowClose All Plots: close any birefringent filter or thin etalon scan plot windows that may be openConfiguration: open a dialog that allows you to customize all configurable optionsReset: reset everything, or individual components (like Matisse motors, Matisse piezos, or PLE tasks)Restart: close and re-open the GUI, reinitialize everything. Good for when things go wrong.SetWavelength: set the laser wavlength to a given valueBiFi Approx. Wavelength: move the birefringent filter to an approximate wavelengthBiFi Motor Position: set the position of the birefringent filterThin Etalon Motor Position: set the position of the thin etalonPiezo Etalon Position: set the position of the piezo etalonSlow Piezo Position: set the position of the slow piezoRefCell Position: set the position of the reference cellScanBirefringent Filter: perform a scan of the birefringent filter, choosing the location with maximum diode powerThin Etalon: perform a scan of the thin etalon, choosing the mode closest to the target wavelengthScan Device Up: slowly increase the wavelength by scanning the stabilization piezos and the thin etalon togetherScan Device Down: slowly decrease the wavelength by scanning the stabilization piezos and the thin etalon togetherStop Scanning Device: stop scanning the stabilization piezos and the thin etalonStabilizationToggle Control Loop: toggle individual control loops of Matisse componentsToggle Lock Laser: toggle execution of a thread that attempts to lock the laser to the target wavelengthSet Recommended Fast Pz Setpoint: measure the reference cell transmission spectrum, and set the fast piezo setpointToggle Auto Stabilization: toggle execution of a thread that scans the device up or down to keep the wavelength at
the target valueShamrockStart PLE Scan: open a dialog to set parameters of a PLE scan, and perform the scan, saving acquired data in text
files separated by wavelength, and also a .pickle file containing all the dataStart PLE Analysis: open a dialog to load a .pickle file of a PLE scan, and integrate the counts for each laser
wavelength used in the scan. Opens a plot of integrated counts vs. laser wavelength afterwards. You can also load
background data that you'd like to be subtracted from the acquisition data.View PLE Analysis: plot the data in a .pickle file representing the analysis of a particular PLE scanView Single Acquisition: plot a file containing data from the CCD, or acquire a single image from the CCD. This
feature does not wait for the CCD to reach a particular temperature.DevelopmentAfter checking out the repo, runpipenv install --devto install dependencies. Using a virtual environment is
recommended.To install this package onto your local machine, runpip install -e ..Useful documentation:PyVISA,pySerial,SciPy,matplotlib,Qt 5Adding features to the Matisse classThe standard way of interacting with the Matisse outside of the existing API is to use theMatisse.querymethod. The
Matisse implements several commands that run asynchronously, like motor movements, so if you want to run these
synchronously, you must do it on your own (like checking the motor status until it's idle again).Long-running tasks should be executed in a thread that can be started and gracefully stopped from the Matisse class.
Currently, fetching a measurement from the wavemeter is a relatively expensive process, so avoid doing this too much if
possible.Adding another wavemeterCurrently I've only implemented an interface for the WaveMaster, but any class will do, as long as it implements theget_raw_valueandget_wavelengthmethods. Theget_raw_valuemethod should return a value representing exactly
what is seen on the wavemeter display (this might not be a measurement), and theget_wavelengthmethod should always
return a floating-point number representing the latest measurement from the wavemeter. The WaveMaster implementation
blocks the thread until a value is returned from the instrument. Additionally, please ensure any code you write that
communicates with instruments is thread-safe.Adding features to the GUILogging and UI updates should have top priority, so take care not to block the UI thread. Here's the process I use:Add a menu action undersetup_menusand connect it to a Qt slot undersetup_slots, to be executed on the main
thread later.Do UI updates in this slot, if you need a long-running task that also updates the UI, use a subclass of QThread with a
slot (see LoggingThread, StatusUpdateThread for examples).For long-running tasks that do not need access to the UI, submit a runnable object to the ControlApplication's
instance of ThreadPoolExecutor. Hold a reference to the Future it gives you and calladd_done_callbackon it, passing
inmatisse_controller.gui.utils.raise_error_from_futureif you want to log errors from that thread. For an example of
a method that runs tasks one-by-one on the Matisse, seeControlApplication.run_matisse_task.Adding another PLE procedureCurrently I've only implemented a PLE scan for the Andor Shamrock 750. If you'd like to implement your own PLE procedure,
create a separate Python package with a class that has the methodsstart_ple_scan,stop_ple_scan, andanalyze_ple_data. It's up to you to implement the scanning logic for your particular spectrometer and CCD setup.
Modify the Matisse class__init__method to use your chosen wavemeter and an instance of your PLE scanning class.ContributingBug reports and pull requests are welcome on GitHub athttps://github.com/lucis-fluxum/matisse-controller.LicenseThe package is available as open source under the terms of theMIT License.