|
Wasatch.PY
Python application driver for Wasatch Photonics spectrometers
|
A WasatchDevice encapsulates and wraps a Wasatch spectrometer in a blocking interface. More...
Public Member Functions | |
| __init__ (self, DeviceID device_id, Queue message_queue=None) | |
| acquire_data (self) | |
| acquire_spectrum (self) | |
| Generate one Reading from the spectrometer, including one optionally-averaged spectrum, device temperatures and other hardware status. | |
| acquire_spectrum_auto_raman (self) | |
| acquire_spectrum_standard (self) | |
| balance_acquisition (self, device=None, mode=None, intensity=45000, threshold=2500, pixel=None, max_integration_time_ms=5000, max_tries=20) | |
| change_setting (self, str setting, Any value, bool allow_immediate=True) | |
| Processes an incoming (setting, value) pair. | |
| connect (self) | |
| Attempt low level connection to the specified DeviceID. | |
| connect_feature_identification (self) | |
| Given a specified universal identifier, attempt to connect to the device using FID protocol. | |
| disconnect (self) | |
| handle_requests (self, list[SpectrometerRequest] requests) | |
| initialize_settings (self) | |
| monitor_memory (self) | |
| perform_optional_throwaways (self) | |
| It's unclear how many throwaways are really needed for a stable Raman spectrum, and whether they're really based on number of integrations (sensor stabilization) or time (laser warmup); I suspect both. | |
| process_commands (self) | |
| Process every entry on the incoming command (settings) queue, writing each to the device. | |
| take_one_averaged_reading (self, label=None) | |
Public Attributes | |
| auto_raman | |
| command_queue | |
| connected | |
| device_id | |
| hardware | |
| immediate_mode | |
| last_battery_percentage | |
| last_complete_acquisition | |
| last_memory_check | |
| lock | |
| message_queue | |
| process_f | |
| process_id | |
| session_reading_count | |
| settings | |
| sum_count | |
| Aggregate scan averaging. | |
| summed_spectra | |
| take_one_request | |
Public Attributes inherited from wasatch.InterfaceDevice.InterfaceDevice | |
| process_f | |
| remaining_throwaways | |
Protected Member Functions | |
| _init_process_funcs (self) | |
A WasatchDevice encapsulates and wraps a Wasatch spectrometer in a blocking interface.
It will normally wrap one of the following:
ENLIGHTEN does not instantiate WasatchDevices directly, but instead uses a WasatchDeviceWrapper to access a single WasatchDevice in a dedicated child thread. Other users of Wasatch.PY may of course instantiate a WasatchDevice directly.
| wasatch.WasatchDevice.WasatchDevice.__init__ | ( | self, | |
| DeviceID | device_id, | ||
| Queue | message_queue = None ) |
| device_id | a DeviceID instance OR string label thereof |
| message_queue | if provided, used to send status back to caller |
Reimplemented from wasatch.InterfaceDevice.InterfaceDevice.
|
protected |
| wasatch.WasatchDevice.WasatchDevice.acquire_data | ( | self | ) |
Process all enqueued settings, then read actual data (spectrum and temperatures) from the device. ENLIGHTEN calls this function via WrapperWorker.run(). @see Controller.acquire_reading
| wasatch.WasatchDevice.WasatchDevice.acquire_spectrum | ( | self | ) |
Generate one Reading from the spectrometer, including one optionally-averaged spectrum, device temperatures and other hardware status.
This is normally called by self.acquire_data when that function decides it is time to perform an acquisition.
IF the driver is in free-running mode, AND performing scan averaging, THEN scan averaging is NOT encapsulated within a single call to this function. Instead, we let ths spectrometer run in free-running mode, collecting individual spectra as per normal, and returning each "partial" readings while "building up" to the final averaged measurement.
That is to say, if scan averaging is set to 10, then this function will get called 10 times, as ticked by the regular free-running timers, before the fully averaged spectrum is returned. A total of 10 (not 11) spectra will be generated and sent upstream: the first 9 "partial" (unaveraged) reads, and the final 10th spectrum which will contain the average of all 10 measurements.
This gives the user-facing GUI an opportunity to update the "collected X-of-Y" readout on-screen, and potentially even graph the traces of in-process partial readings.
HOWEVER, this doesn't make as much sense if we're not in free-running mode, i.e. the subprocess has been slaved to explicit control by the Controller (likely a feature object like BatchCollection), and is collecting exactly those measurements we're being commanded, as they're commanded.
THEREFORE, if the driver IS NOT in free-running mode, then we ONLY return the final averaged spectrum as one atomic operation.
In this case, if scan averaging is set to 10, then A SINGLE CALL to this function will "block" while the full 10 measurements are made, and then a single, fully-averaged spectrum will be returned upstream.
| wasatch.WasatchDevice.WasatchDevice.acquire_spectrum_auto_raman | ( | self | ) |
@returns a Reading wrapped in a SpectrometerResponse
@todo fold-in a lot of the post-reading sensor measurements
(temperature, interlock etc) provided by acquire_spectrum_standard
| wasatch.WasatchDevice.WasatchDevice.acquire_spectrum_standard | ( | self | ) |
| wasatch.WasatchDevice.WasatchDevice.balance_acquisition | ( | self, | |
| device = None, | |||
| mode = None, | |||
| intensity = 45000, | |||
| threshold = 2500, | |||
| pixel = None, | |||
| max_integration_time_ms = 5000, | |||
| max_tries = 20 ) |
| wasatch.WasatchDevice.WasatchDevice.change_setting | ( | self, | |
| str | setting, | ||
| Any | value, | ||
| bool | allow_immediate = True ) |
Processes an incoming (setting, value) pair.
Some settings are processed internally within this function, if the functionality they are controlling is implemented by WasatchDevice. This includes scan averaging, and anything related to scan averaging (such as "take one" behavior).
Most tuples are queued to be sent downstream to the connected hardware (usually FeatureIdentificationDevice) at the start of the next acquisition.
Some hardware settings (those involving triggering or the laser) are sent downstream immediately, rather than waiting for the next "scheduled" settings update.
ENLIGHTEN commands to WasatchDeviceWrapper are sent here by WasatchDeviceWrapper.continuous_poll.
| setting | (Input) which setting to change |
| value | (Input) the new value of the setting (required, but can be None or "anything" for commands like "acquire" which don't use the argument). |
| allow_immediate |
| wasatch.WasatchDevice.WasatchDevice.connect | ( | self | ) |
Attempt low level connection to the specified DeviceID.
| wasatch.WasatchDevice.WasatchDevice.connect_feature_identification | ( | self | ) |
Given a specified universal identifier, attempt to connect to the device using FID protocol.
| wasatch.WasatchDevice.WasatchDevice.disconnect | ( | self | ) |
| wasatch.WasatchDevice.WasatchDevice.handle_requests | ( | self, | |
| list[SpectrometerRequest] | requests ) |
Reimplemented from wasatch.InterfaceDevice.InterfaceDevice.
| wasatch.WasatchDevice.WasatchDevice.initialize_settings | ( | self | ) |
| wasatch.WasatchDevice.WasatchDevice.monitor_memory | ( | self | ) |
| wasatch.WasatchDevice.WasatchDevice.perform_optional_throwaways | ( | self | ) |
It's unclear how many throwaways are really needed for a stable Raman spectrum, and whether they're really based on number of integrations (sensor stabilization) or time (laser warmup); I suspect both.
Also note the potential need for sensor warm-up, but I think that's handled inside FW.
Optimal would probably be something like "As many integrations as it takes to span 2sec, but not fewer than two."
These are NOT the same throwaways added to smooth spectra over changes to integration time and gain. These are separate throwaways potentially required when waking the sensor from sleep. However, I'm using the same mechanism for tracking (self.remaining_throwaways) for commonality.
| wasatch.WasatchDevice.WasatchDevice.process_commands | ( | self | ) |
Process every entry on the incoming command (settings) queue, writing each to the device.
Essentially this iterates through all the (setting, value) pairs we've received through change_setting() which have not yet been processed, and <– MZ: incomplete sentence
Note that WrapperWorker.run "de-dupes" commands on receipt from ENLIGHTEN, so the command stream arising from that source should already be optimized and minimal. Commands injected manually by calling WasatchDevice.change_setting() do not receive this treatment.
In the normal multithreaded (ENLIGHTEN) workflow, this function is called at the beginning of acquire_data, itself ticked regularly by WrapperWorker.run.
| wasatch.WasatchDevice.WasatchDevice.take_one_averaged_reading | ( | self, | |
| label = None ) |
Okay, let's talk about averaging. We only perform averaging as a blocking call in Wasatch.PY when given a TakeOneRequest with non-zero scans_to_average, typically from ENLIGHTEN's TakeOneFeature (perhaps via VCRControls.step, possibly with AutoRaman, or BatchCollection). Otherwise, normally this thread (the background thread owned by a WasatchDeviceWrapper object and running WrapperWorker.run) is in "free- running" mode, taking spectra just as fast as it can in an endless loop, feeding them back to the consumer (ENLIGHTEN) over a queue. To keep that pipeline "moving," generally we don't do heavy blocking operations down here in the background thread. The new AutoRaman feature makes increased using of scan averaging, and again kind of wants to be encapsulated down here. And by implication, all TakeOneRequests should really support encapsulated, atomic averaging. So the current design is that ATOMIC scans_to_average comes from TakeOneRequest, ENLIGHTEN-based averaging in SpectrometerState. @returns Reading on success, true or false on "stop processing" conditions
| wasatch.WasatchDevice.WasatchDevice.auto_raman |
| wasatch.WasatchDevice.WasatchDevice.command_queue |
| wasatch.WasatchDevice.WasatchDevice.connected |
| wasatch.WasatchDevice.WasatchDevice.device_id |
| wasatch.WasatchDevice.WasatchDevice.hardware |
| wasatch.WasatchDevice.WasatchDevice.immediate_mode |
| wasatch.WasatchDevice.WasatchDevice.last_battery_percentage |
| wasatch.WasatchDevice.WasatchDevice.last_complete_acquisition |
| wasatch.WasatchDevice.WasatchDevice.last_memory_check |
| wasatch.WasatchDevice.WasatchDevice.lock |
| wasatch.WasatchDevice.WasatchDevice.message_queue |
| wasatch.WasatchDevice.WasatchDevice.process_f |
| wasatch.WasatchDevice.WasatchDevice.process_id |
| wasatch.WasatchDevice.WasatchDevice.session_reading_count |
| wasatch.WasatchDevice.WasatchDevice.settings |
| wasatch.WasatchDevice.WasatchDevice.sum_count |
Aggregate scan averaging.
| wasatch.WasatchDevice.WasatchDevice.summed_spectra |
| wasatch.WasatchDevice.WasatchDevice.take_one_request |