|
ENLIGHTEN
Cross-platform desktop GUI for Wasatch Photonics spectrometers
|
This class encapsulates batch collection, which is the automated collection of a series of 'measurement_count' Step-And-Save events at a period of 'measurement_period_ms', captured to disk using the configured SaveOptions. More...
Public Member Functions | |
| __init__ (self, ctl) | |
| complete_batch (self) | |
| generate_export_filename (self, now) | |
| Tempting to render SaveOptions.label_template in here...not sure how that would fly with multiple spectrometers. | |
| init_from_config (self) | |
| process (self, pr, spec) | |
| This is similar to tick_measurement, except it's driven by Controller.process_reading when we're not using QTimers and are streaming multiple Readings from a single TakeOneRequest. | |
| save_complete (self) | |
| A VCRControls "step_save" event has completed (or we just manually saved a TakeMany Fast-Batch Measurement). | |
| start_batch (self) | |
| start_batch_post_dark (self) | |
| start_collection (self) | |
| Someone clicked the "Start Collection" button in VCRButtons. | |
| stop (self) | |
| tick_measurement (self) | |
| At each tick of the Batch timer, initiate a Step And Save event. | |
| update_explanation (self) | |
| Generates the ToolTip on "Explain This.". | |
| update_from_widgets (self) | |
| update_suffix (self) | |
| vcr_stop (self) | |
Public Attributes | |
| int | batch_count = self.spinbox_batch_count.value() |
| batch_period_sec = self.spinbox_batch_period_sec.value() | |
| cb_clear_before_batch = cfu.checkBox_BatchCollection_clear_before_batch | |
| cb_dark_before_batch = cfu.checkBox_BatchCollection_dark_before_batch | |
| cb_enabled = cfu.checkBox_BatchCollection_enabled | |
| cb_export_after_batch = cfu.checkBox_BatchCollection_export_after_batch | |
| bool | clear_before_batch = False |
| collection_start_time = None | |
| collection_timeout = self.collection_start_time + datetime.timedelta(seconds=self.spinbox_collection_timeout.value()) | |
| ctl = ctl | |
| int | current_batch_count = 1 |
| current_batch_start_time = None | |
| int | current_measurement_count = 1 |
| bool | dark_before_batch = False |
| enabled = self.cb_enabled.isChecked() | |
| bool | export_after_batch = False |
| bool | first_tick = True |
| str | laser_mode = "manual" |
| laser_warmup_ms = int(self.spinbox_laser_warmup_ms.value()) | |
| lb_explain = cfu.label_BatchCollection_explain | |
| measurement_count = self.spinbox_measurement_count.value() | |
| measurement_period_ms = self.spinbox_measurement_period_ms.value() | |
| next_batch_start_time = None | |
| next_tick_start_time = None | |
| rb_laser_auto_raman = cfu.radioButton_BatchCollection_laser_auto_raman | |
| rb_laser_batch = cfu.radioButton_BatchCollection_laser_batch | |
| rb_laser_manual = cfu.radioButton_BatchCollection_laser_manual | |
| rb_laser_spectrum = cfu.radioButton_BatchCollection_laser_spectrum | |
| bool | running = False |
| save_complete = True) | |
| dict | save_count_by_device_id = {} |
| spinbox_batch_count = cfu.spinBox_BatchCollection_batch_count | |
| spinbox_batch_period_sec = cfu.spinBox_BatchCollection_batch_period_sec | |
| spinbox_collection_timeout = cfu.spinBox_BatchCollection_collection_timeout | |
| spinbox_laser_warmup_ms = cfu.spinBox_BatchCollection_laser_warmup_ms | |
| spinbox_measurement_count = cfu.spinBox_BatchCollection_measurement_count | |
| spinbox_measurement_period_ms = cfu.spinBox_BatchCollection_measurement_period_ms | |
| start_batch | |
| start_collection = self | |
| take_one_template = None | |
| tick_measurement | |
| timer_batch = QtCore.QTimer() | |
| timer_measurement = QtCore.QTimer() | |
| update_from_widgets | |
| vcr_stop = None | |
This class encapsulates batch collection, which is the automated collection of a series of 'measurement_count' Step-And-Save events at a period of 'measurement_period_ms', captured to disk using the configured SaveOptions.
This sequence is normally triggered when the VCRControls' "Start Collection" button is clicked, and is implemented as a timed series of clicks to the VCRControls' "Step and Save" button.
VCRControls will be left Paused at the END of a Batch Collection, regardless of initial state.
Earlier implementations of BatchCollection left the spectrometer in free- running mode, and simply timed a sequence of "Save" events running in parallel to the ongoing stream of spectra continually rendered to the scope.
As a result, the beginning of acquisitions were not synchronized to the beginning of each batch "step", and the "save event" was not specifically tied to the END of an acquisition started within the step.
There were many things wrong with this approach, which are partially remedied by the new VCRControl's encapsulated "Step and Save" functionality.
Note that there is still a question of synchronization between when the software requests a spectrum (sends ACQUIRE to the microcontroller and FPGA), and when the commanded integration actually begins, due to the "free-running" modes internally implemented within the firmware to keep the detector pixels clear and the sensor in a ready state.
In so-called "process mode" (intended for 24/7 process line control systems), batches themselves can be indefinitely iterated if 'batch_count' is zero.
For process environments, the command-line switch –start-batch can initiate a continuous sequence of batches upon first spectrometer connection.
To be clear, the word "process" here has nothing to do with OS kernels or threads, and relates to continuous-measurement industrial environments.
The original concept was just to "collect X spectra in a row". The evolving concept is more like "at a period of Y ms, virtually click the 'Step and Save' button a total of X times".
Therefore, the number of spectrometers connected, and the individual integration times of those spectrometers, becomes irrelevant: the measurement_period_ms determines the interval between Step-and-Save events, and the and the number of events, rather than the number of spectra saved, is the count.
Some users don't wish to impose fixed timing, and just want to collect and save measurement_count spectra at the defined integration time.
Although this is the "easier" challenge than "clock ticked" collections, it has its own complications. For instance, if there are multiple spectrometers connected with different integration times in effect, and save_all_spectrometers is checked, the measurements will occur at different times, and the collections won't end together.
Therefore, if measurement_period_ms is ZERO, this class will not run any internal timers, but will simply collect "measurement_count" spectra from each contributing spectrometer.
This is still done via a "TakeOneRequest", but it's really more of a "TakeOne[Batch]" than "TakeOne[Reading]".
There are four use-cases:
The four modes are exposed in the configuration file as:
laser_mode = manual | batch | spectrum | auto-raman
If multiple spectrometers are connected, the laser commands (like acquisition triggers) are sent to each.
Note that laser_spectrum timing is implemented within Wasatch.PY, so that the laser on/off and timing can occur within the "spectrometer thread" during a single acquisition event. On the contrary, laser_batch is implemented here within BatchCollection.
It's clearly useful to be able to take a fresh dark at the start of each batch, and that has been implemented.
If you need a fresh dark before each measurement (not just each batch), then Auto-Raman mode is recommended.
| enlighten.timing.BatchCollection.BatchCollection.__init__ | ( | self, | |
| ctl ) |
| enlighten.timing.BatchCollection.BatchCollection.complete_batch | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.generate_export_filename | ( | self, | |
| now ) |
Tempting to render SaveOptions.label_template in here...not sure how that would fly with multiple spectrometers.
More to the point, label_template is rendered on individual Measurement objects, and the BatchCollection class, odd as it seems, doesn't actually have a reference to any of the Measurement objects it causes to be collected. They're all automated by raising step_save events in VCRControls, which doesn't itself hold any references so can't even send one back through the completion event. I don't think we can easily do this right now, perhaps for good reason.
| enlighten.timing.BatchCollection.BatchCollection.init_from_config | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.process | ( | self, | |
| pr, | |||
| spec ) |
This is similar to tick_measurement, except it's driven by Controller.process_reading when we're not using QTimers and are streaming multiple Readings from a single TakeOneRequest.
| enlighten.timing.BatchCollection.BatchCollection.save_complete | ( | self | ) |
A VCRControls "step_save" event has completed (or we just manually saved a TakeMany Fast-Batch Measurement).
| enlighten.timing.BatchCollection.BatchCollection.start_batch | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.start_batch_post_dark | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.start_collection | ( | self | ) |
Someone clicked the "Start Collection" button in VCRButtons.
| enlighten.timing.BatchCollection.BatchCollection.stop | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.tick_measurement | ( | self | ) |
At each tick of the Batch timer, initiate a Step And Save event.
| enlighten.timing.BatchCollection.BatchCollection.update_explanation | ( | self | ) |
Generates the ToolTip on "Explain This.".
| enlighten.timing.BatchCollection.BatchCollection.update_from_widgets | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.update_suffix | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.vcr_stop | ( | self | ) |
| enlighten.timing.BatchCollection.BatchCollection.batch_count = self.spinbox_batch_count.value() |
| enlighten.timing.BatchCollection.BatchCollection.batch_period_sec = self.spinbox_batch_period_sec.value() |
| enlighten.timing.BatchCollection.BatchCollection.cb_clear_before_batch = cfu.checkBox_BatchCollection_clear_before_batch |
| enlighten.timing.BatchCollection.BatchCollection.cb_dark_before_batch = cfu.checkBox_BatchCollection_dark_before_batch |
| enlighten.timing.BatchCollection.BatchCollection.cb_enabled = cfu.checkBox_BatchCollection_enabled |
| enlighten.timing.BatchCollection.BatchCollection.cb_export_after_batch = cfu.checkBox_BatchCollection_export_after_batch |
| bool enlighten.timing.BatchCollection.BatchCollection.clear_before_batch = False |
| enlighten.timing.BatchCollection.BatchCollection.collection_start_time = None |
| enlighten.timing.BatchCollection.BatchCollection.collection_timeout = self.collection_start_time + datetime.timedelta(seconds=self.spinbox_collection_timeout.value()) |
| enlighten.timing.BatchCollection.BatchCollection.ctl = ctl |
| enlighten.timing.BatchCollection.BatchCollection.current_batch_count = 1 |
| enlighten.timing.BatchCollection.BatchCollection.current_batch_start_time = None |
| enlighten.timing.BatchCollection.BatchCollection.current_measurement_count = 1 |
| bool enlighten.timing.BatchCollection.BatchCollection.dark_before_batch = False |
| enlighten.timing.BatchCollection.BatchCollection.enabled = self.cb_enabled.isChecked() |
| bool enlighten.timing.BatchCollection.BatchCollection.export_after_batch = False |
| bool enlighten.timing.BatchCollection.BatchCollection.first_tick = True |
| enlighten.timing.BatchCollection.BatchCollection.laser_mode = "manual" |
| enlighten.timing.BatchCollection.BatchCollection.laser_warmup_ms = int(self.spinbox_laser_warmup_ms.value()) |
| enlighten.timing.BatchCollection.BatchCollection.lb_explain = cfu.label_BatchCollection_explain |
| enlighten.timing.BatchCollection.BatchCollection.measurement_count = self.spinbox_measurement_count.value() |
| enlighten.timing.BatchCollection.BatchCollection.measurement_period_ms = self.spinbox_measurement_period_ms.value() |
| enlighten.timing.BatchCollection.BatchCollection.next_batch_start_time = None |
| enlighten.timing.BatchCollection.BatchCollection.next_tick_start_time = None |
| enlighten.timing.BatchCollection.BatchCollection.rb_laser_auto_raman = cfu.radioButton_BatchCollection_laser_auto_raman |
| enlighten.timing.BatchCollection.BatchCollection.rb_laser_batch = cfu.radioButton_BatchCollection_laser_batch |
| enlighten.timing.BatchCollection.BatchCollection.rb_laser_manual = cfu.radioButton_BatchCollection_laser_manual |
| enlighten.timing.BatchCollection.BatchCollection.rb_laser_spectrum = cfu.radioButton_BatchCollection_laser_spectrum |
| bool enlighten.timing.BatchCollection.BatchCollection.running = False |
| enlighten.timing.BatchCollection.BatchCollection.save_complete = True) |
| dict enlighten.timing.BatchCollection.BatchCollection.save_count_by_device_id = {} |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_batch_count = cfu.spinBox_BatchCollection_batch_count |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_batch_period_sec = cfu.spinBox_BatchCollection_batch_period_sec |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_collection_timeout = cfu.spinBox_BatchCollection_collection_timeout |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_laser_warmup_ms = cfu.spinBox_BatchCollection_laser_warmup_ms |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_measurement_count = cfu.spinBox_BatchCollection_measurement_count |
| enlighten.timing.BatchCollection.BatchCollection.spinbox_measurement_period_ms = cfu.spinBox_BatchCollection_measurement_period_ms |
| enlighten.timing.BatchCollection.BatchCollection.start_batch |
| enlighten.timing.BatchCollection.BatchCollection.start_collection = self |
| enlighten.timing.BatchCollection.BatchCollection.take_one_template = None |
| enlighten.timing.BatchCollection.BatchCollection.tick_measurement |
| enlighten.timing.BatchCollection.BatchCollection.timer_batch = QtCore.QTimer() |
| enlighten.timing.BatchCollection.BatchCollection.timer_measurement = QtCore.QTimer() |
| enlighten.timing.BatchCollection.BatchCollection.update_from_widgets |
| enlighten.timing.BatchCollection.BatchCollection.vcr_stop = None |