ENLIGHTEN
Cross-platform desktop GUI for Wasatch Photonics spectrometers
Loading...
Searching...
No Matches
enlighten.timing.BatchCollection.BatchCollection Class Reference

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
 

Detailed Description

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.

History

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.

Process Mode

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.

Multispec

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.

Untimed Collections (Fast-Batch [#516])

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]".

Laser Control

There are four use-cases:

  • MANUAL: means the user is manually controlling the laser (if there is one), so don't worry about it
  • BATCH: turn the laser on at the beginning of a batch (count 0), off at the end (measurement_count)
  • SPECTRUM: turn the laser on at the beginning of a measurement (each count), off after.
  • AUTO-RAMAN: use the standard ENLIGHTEN Auto-Raman feature to generate one or more an optimized measurements at each batch cycle

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.

Dark

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.

Constructor & Destructor Documentation

◆ __init__()

enlighten.timing.BatchCollection.BatchCollection.__init__ ( self,
ctl )

Member Function Documentation

◆ complete_batch()

enlighten.timing.BatchCollection.BatchCollection.complete_batch ( self)

◆ generate_export_filename()

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.

◆ init_from_config()

enlighten.timing.BatchCollection.BatchCollection.init_from_config ( self)

◆ process()

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.

◆ save_complete()

enlighten.timing.BatchCollection.BatchCollection.save_complete ( self)

A VCRControls "step_save" event has completed (or we just manually saved a TakeMany Fast-Batch Measurement).

◆ start_batch()

enlighten.timing.BatchCollection.BatchCollection.start_batch ( self)

◆ start_batch_post_dark()

enlighten.timing.BatchCollection.BatchCollection.start_batch_post_dark ( self)

◆ start_collection()

enlighten.timing.BatchCollection.BatchCollection.start_collection ( self)

Someone clicked the "Start Collection" button in VCRButtons.

◆ stop()

enlighten.timing.BatchCollection.BatchCollection.stop ( self)

◆ tick_measurement()

enlighten.timing.BatchCollection.BatchCollection.tick_measurement ( self)

At each tick of the Batch timer, initiate a Step And Save event.

◆ update_explanation()

enlighten.timing.BatchCollection.BatchCollection.update_explanation ( self)

Generates the ToolTip on "Explain This.".

◆ update_from_widgets()

enlighten.timing.BatchCollection.BatchCollection.update_from_widgets ( self)

◆ update_suffix()

enlighten.timing.BatchCollection.BatchCollection.update_suffix ( self)

◆ vcr_stop()

enlighten.timing.BatchCollection.BatchCollection.vcr_stop ( self)

Member Data Documentation

◆ batch_count

enlighten.timing.BatchCollection.BatchCollection.batch_count = self.spinbox_batch_count.value()

◆ batch_period_sec

enlighten.timing.BatchCollection.BatchCollection.batch_period_sec = self.spinbox_batch_period_sec.value()

◆ cb_clear_before_batch

enlighten.timing.BatchCollection.BatchCollection.cb_clear_before_batch = cfu.checkBox_BatchCollection_clear_before_batch

◆ cb_dark_before_batch

enlighten.timing.BatchCollection.BatchCollection.cb_dark_before_batch = cfu.checkBox_BatchCollection_dark_before_batch

◆ cb_enabled

enlighten.timing.BatchCollection.BatchCollection.cb_enabled = cfu.checkBox_BatchCollection_enabled

◆ cb_export_after_batch

enlighten.timing.BatchCollection.BatchCollection.cb_export_after_batch = cfu.checkBox_BatchCollection_export_after_batch

◆ clear_before_batch

bool enlighten.timing.BatchCollection.BatchCollection.clear_before_batch = False

◆ collection_start_time

enlighten.timing.BatchCollection.BatchCollection.collection_start_time = None

◆ collection_timeout

enlighten.timing.BatchCollection.BatchCollection.collection_timeout = self.collection_start_time + datetime.timedelta(seconds=self.spinbox_collection_timeout.value())

◆ ctl

enlighten.timing.BatchCollection.BatchCollection.ctl = ctl

◆ current_batch_count

enlighten.timing.BatchCollection.BatchCollection.current_batch_count = 1

◆ current_batch_start_time

enlighten.timing.BatchCollection.BatchCollection.current_batch_start_time = None

◆ current_measurement_count

enlighten.timing.BatchCollection.BatchCollection.current_measurement_count = 1

◆ dark_before_batch

bool enlighten.timing.BatchCollection.BatchCollection.dark_before_batch = False

◆ enabled

enlighten.timing.BatchCollection.BatchCollection.enabled = self.cb_enabled.isChecked()

◆ export_after_batch

bool enlighten.timing.BatchCollection.BatchCollection.export_after_batch = False

◆ first_tick

bool enlighten.timing.BatchCollection.BatchCollection.first_tick = True

◆ laser_mode

enlighten.timing.BatchCollection.BatchCollection.laser_mode = "manual"

◆ laser_warmup_ms

enlighten.timing.BatchCollection.BatchCollection.laser_warmup_ms = int(self.spinbox_laser_warmup_ms.value())

◆ lb_explain

enlighten.timing.BatchCollection.BatchCollection.lb_explain = cfu.label_BatchCollection_explain

◆ measurement_count

enlighten.timing.BatchCollection.BatchCollection.measurement_count = self.spinbox_measurement_count.value()

◆ measurement_period_ms

enlighten.timing.BatchCollection.BatchCollection.measurement_period_ms = self.spinbox_measurement_period_ms.value()

◆ next_batch_start_time

enlighten.timing.BatchCollection.BatchCollection.next_batch_start_time = None

◆ next_tick_start_time

enlighten.timing.BatchCollection.BatchCollection.next_tick_start_time = None

◆ rb_laser_auto_raman

enlighten.timing.BatchCollection.BatchCollection.rb_laser_auto_raman = cfu.radioButton_BatchCollection_laser_auto_raman

◆ rb_laser_batch

enlighten.timing.BatchCollection.BatchCollection.rb_laser_batch = cfu.radioButton_BatchCollection_laser_batch

◆ rb_laser_manual

enlighten.timing.BatchCollection.BatchCollection.rb_laser_manual = cfu.radioButton_BatchCollection_laser_manual

◆ rb_laser_spectrum

enlighten.timing.BatchCollection.BatchCollection.rb_laser_spectrum = cfu.radioButton_BatchCollection_laser_spectrum

◆ running

bool enlighten.timing.BatchCollection.BatchCollection.running = False

◆ save_complete

enlighten.timing.BatchCollection.BatchCollection.save_complete = True)

◆ save_count_by_device_id

dict enlighten.timing.BatchCollection.BatchCollection.save_count_by_device_id = {}

◆ spinbox_batch_count

enlighten.timing.BatchCollection.BatchCollection.spinbox_batch_count = cfu.spinBox_BatchCollection_batch_count

◆ spinbox_batch_period_sec

enlighten.timing.BatchCollection.BatchCollection.spinbox_batch_period_sec = cfu.spinBox_BatchCollection_batch_period_sec

◆ spinbox_collection_timeout

enlighten.timing.BatchCollection.BatchCollection.spinbox_collection_timeout = cfu.spinBox_BatchCollection_collection_timeout

◆ spinbox_laser_warmup_ms

enlighten.timing.BatchCollection.BatchCollection.spinbox_laser_warmup_ms = cfu.spinBox_BatchCollection_laser_warmup_ms

◆ spinbox_measurement_count

enlighten.timing.BatchCollection.BatchCollection.spinbox_measurement_count = cfu.spinBox_BatchCollection_measurement_count

◆ spinbox_measurement_period_ms

enlighten.timing.BatchCollection.BatchCollection.spinbox_measurement_period_ms = cfu.spinBox_BatchCollection_measurement_period_ms

◆ start_batch

enlighten.timing.BatchCollection.BatchCollection.start_batch

◆ start_collection

enlighten.timing.BatchCollection.BatchCollection.start_collection = self

◆ take_one_template

enlighten.timing.BatchCollection.BatchCollection.take_one_template = None

◆ tick_measurement

enlighten.timing.BatchCollection.BatchCollection.tick_measurement

◆ timer_batch

enlighten.timing.BatchCollection.BatchCollection.timer_batch = QtCore.QTimer()

◆ timer_measurement

enlighten.timing.BatchCollection.BatchCollection.timer_measurement = QtCore.QTimer()

◆ update_from_widgets

enlighten.timing.BatchCollection.BatchCollection.update_from_widgets

◆ vcr_stop

enlighten.timing.BatchCollection.BatchCollection.vcr_stop = None

The documentation for this class was generated from the following file: