diff --git a/src/example_scripts/connect_to_star_hub.py b/src/example_scripts/connect_to_star_hub.py deleted file mode 100644 index 1c23287..0000000 --- a/src/example_scripts/connect_to_star_hub.py +++ /dev/null @@ -1,43 +0,0 @@ -from spectrumdevice.devices.mocks import MockSpectrumDigitiserCard, MockSpectrumDigitiserStarHub -from spectrumdevice.devices.digitiser import SpectrumDigitiserCard -from spectrumdevice.devices.digitiser import SpectrumDigitiserStarHub -from spectrumdevice.settings import ModelNumber - - -def star_hub_example( - mock_mode: bool, num_cards: int, master_card_index: int, ip_address: str -) -> SpectrumDigitiserStarHub: - - if not mock_mode: - child_cards = [] - for n in range(num_cards): - # Connect to each card in the hub. - child_cards.append(SpectrumDigitiserCard(device_number=n, ip_address=ip_address)) - # Connect to the hub itself - return SpectrumDigitiserStarHub(device_number=0, child_cards=child_cards, master_card_index=master_card_index) - else: - mock_child_cards = [] - for n in range(num_cards): - # Create a mock device for each card in the hub - mock_child_cards.append( - MockSpectrumDigitiserCard( - device_number=n, - model=ModelNumber.TYP_M2P5966_X4, - mock_source_frame_rate_hz=10.0, # Mock devices need to be provided with a mock source frame rate - num_modules=2, # (For real devices, this and num_channels_per_module are read from the hardware). - num_channels_per_module=4, - ) - ) - # Create a mock hub containing the above devices - return MockSpectrumDigitiserStarHub( - device_number=0, child_cards=mock_child_cards, master_card_index=master_card_index - ) - - -if __name__ == "__main__": - hub = star_hub_example(mock_mode=False, num_cards=2, master_card_index=1, ip_address="169.254.13.35") - print(f"{hub} contains {len(hub.channels)} channels in total:") - for channel in hub.channels: - print(channel) - hub.reset() - hub.disconnect() diff --git a/src/example_scripts/finite_multi_fifo_mode.py b/src/example_scripts/finite_multi_fifo_mode.py index 8fc9f0b..b3970a5 100644 --- a/src/example_scripts/finite_multi_fifo_mode.py +++ b/src/example_scripts/finite_multi_fifo_mode.py @@ -55,7 +55,7 @@ def finite_multi_fifo_example( vertical_ranges_in_mv=[200], vertical_offsets_in_percent=[0], timestamping_enabled=True, - batch_size=5, + batch_size=batch_size, ) # Apply settings diff --git a/src/example_scripts/star_hub_example.py b/src/example_scripts/star_hub_example.py new file mode 100644 index 0000000..05042a7 --- /dev/null +++ b/src/example_scripts/star_hub_example.py @@ -0,0 +1,95 @@ +from matplotlib.pyplot import figure, title, plot, show + +from spectrumdevice.devices.mocks import MockSpectrumDigitiserCard, MockSpectrumDigitiserStarHub +from spectrumdevice.devices.digitiser import SpectrumDigitiserCard +from spectrumdevice.devices.digitiser import SpectrumDigitiserStarHub +from spectrumdevice.settings import ModelNumber, TriggerSettings, TriggerSource, ExternalTriggerMode, AcquisitionMode, \ + AcquisitionSettings + + +def connect_to_star_hub_example( + mock_mode: bool, num_cards: int, master_card_index: int, ip_address: str +) -> SpectrumDigitiserStarHub: + + if not mock_mode: + child_cards = [] + for n in range(num_cards): + # Connect to each card in the hub. + child_cards.append(SpectrumDigitiserCard(device_number=n, ip_address=ip_address)) + # Connect to the hub itself + return SpectrumDigitiserStarHub(device_number=0, child_cards=child_cards, master_card_index=master_card_index) + else: + mock_child_cards = [] + for n in range(num_cards): + # Create a mock device for each card in the hub + mock_child_cards.append( + MockSpectrumDigitiserCard( + device_number=n, + model=ModelNumber.TYP_M2P5966_X4, + mock_source_frame_rate_hz=10.0, # Mock devices need to be provided with a mock source frame rate + num_modules=2, # (For real devices, this and num_channels_per_module are read from the hardware). + num_channels_per_module=4, + ) + ) + # Create a mock hub containing the above devices + return MockSpectrumDigitiserStarHub( + device_number=0, child_cards=mock_child_cards, master_card_index=master_card_index + ) + + +if __name__ == "__main__": + + num_measurements = 5 + + hub = connect_to_star_hub_example(mock_mode=False, num_cards=2, master_card_index=1, ip_address="169.254.13.35") + + print(f"{hub} contains {len(hub.channels)} channels in total:") + for channel in hub.channels: + print(channel) + + # Trigger settings + trigger_settings = TriggerSettings( + trigger_sources=[TriggerSource.SPC_TMASK_EXT0], + external_trigger_mode=ExternalTriggerMode.SPC_TM_POS, + external_trigger_level_in_mv=1000, + ) + + # Acquisition settings + acquisition_settings = AcquisitionSettings( + acquisition_mode=AcquisitionMode.SPC_REC_FIFO_MULTI, + sample_rate_in_hz=40000000, + acquisition_length_in_samples=400, + pre_trigger_length_in_samples=0, + timeout_in_ms=1000, + enabled_channels=[0, 8], # at least 1 channel from each child card must be enabled + vertical_ranges_in_mv=[200], + vertical_offsets_in_percent=[0], + timestamping_enabled=True, + batch_size=5, + ) + + # Apply settings + hub.configure_trigger(trigger_settings) + hub.configure_acquisition(acquisition_settings) + + # Execute acquisition + measurements = hub.execute_finite_fifo_acquisition(num_measurements) + + # Plot waveforms + for n, measurement in enumerate(measurements): + figure() + title(f"Measurement {n}") + for wfm in measurement.waveforms: + plot(wfm) + + ts_format = "%Y-%m-%d %H:%M:%S.%f" + print(f"Completed {len(measurements)} measurements each containing {len(measurements[0].waveforms)} waveforms.") + print(f"Waveforms had the following shape: {measurements[0].waveforms[0].shape}") + print(f"and the following timestamps:") + for measurement in measurements: + print(measurement.timestamp.strftime(ts_format) if measurement.timestamp else "Timestamping disabled") + + hub.reset() + hub.disconnect() + + show() diff --git a/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py b/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py index 58de93f..635fe21 100644 --- a/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py +++ b/src/spectrumdevice/devices/digitiser/abstract_spectrum_digitiser.py @@ -31,7 +31,7 @@ def configure_acquisition(self, settings: AcquisitionSettings) -> None: if settings.batch_size > 1 and settings.acquisition_mode == AcquisitionMode.SPC_REC_STD_SINGLE: raise ValueError("In standard single mode, only 1 acquisition can be downloaded at a time.") self._acquisition_mode = settings.acquisition_mode - self._batch_size = settings.batch_size + self.set_batch_size(settings.batch_size) self.set_acquisition_mode(settings.acquisition_mode) self.set_sample_rate_in_hz(settings.sample_rate_in_hz) self.set_acquisition_length_in_samples(settings.acquisition_length_in_samples) @@ -101,14 +101,14 @@ def execute_finite_fifo_acquisition(self, num_measurements: int) -> List[Measure timestamp attribute, which (if timestamping was enabled in acquisition settings) contains the time at which the acquisition was triggered. """ - if (num_measurements % self._batch_size) != 0: + if (num_measurements % self.batch_size) != 0: raise ValueError( "Number of measurements in a finite FIFO acquisition must be a multiple of the " " batch size configured using AbstractSpectrumDigitiser.configure_acquisition()." ) self.execute_continuous_fifo_acquisition() measurements = [] - for _ in range(num_measurements // self._batch_size): + for _ in range(num_measurements // self.batch_size): measurements += [ Measurement(waveforms=frame, timestamp=self.get_timestamp()) for frame in self.get_waveforms() ] diff --git a/src/spectrumdevice/devices/digitiser/digitiser_card.py b/src/spectrumdevice/devices/digitiser/digitiser_card.py index 8855e82..77e3ce3 100644 --- a/src/spectrumdevice/devices/digitiser/digitiser_card.py +++ b/src/spectrumdevice/devices/digitiser/digitiser_card.py @@ -64,6 +64,7 @@ def __init__(self, device_number: int = 0, ip_address: Optional[str] = None): raise SpectrumCardIsNotADigitiser(self.type) self._acquisition_mode = self.acquisition_mode self._timestamper: Optional[Timestamper] = None + self._batch_size = 1 def _init_channels(self) -> Sequence[SpectrumDigitiserChannelInterface]: num_modules = self.read_spectrum_device_register(SPC_MIINST_MODULES) @@ -249,6 +250,13 @@ def set_acquisition_mode(self, mode: AcquisitionMode) -> None: mode (`AcquisitionMode`): The desired acquisition mode.""" self.write_to_spectrum_device_register(SPC_CARDMODE, mode.value) + @property + def batch_size(self) -> int: + return self._batch_size + + def set_batch_size(self, batch_size: int) -> None: + self._batch_size = batch_size + def define_transfer_buffer(self, buffer: Optional[Sequence[TransferBuffer]] = None) -> None: """Create or provide a `TransferBuffer` object for receiving acquired samples from the device. diff --git a/src/spectrumdevice/devices/digitiser/digitiser_interface.py b/src/spectrumdevice/devices/digitiser/digitiser_interface.py index 4f58edc..0940427 100644 --- a/src/spectrumdevice/devices/digitiser/digitiser_interface.py +++ b/src/spectrumdevice/devices/digitiser/digitiser_interface.py @@ -106,3 +106,12 @@ def acquisition_mode(self) -> AcquisitionMode: @abstractmethod def set_acquisition_mode(self, mode: AcquisitionMode) -> None: raise NotImplementedError() + + @property + @abstractmethod + def batch_size(self) -> int: + raise NotImplementedError() + + @abstractmethod + def set_batch_size(self, batch_size: int) -> None: + raise NotImplementedError() diff --git a/src/spectrumdevice/devices/digitiser/digitiser_star_hub.py b/src/spectrumdevice/devices/digitiser/digitiser_star_hub.py index 36d29fe..515ce39 100644 --- a/src/spectrumdevice/devices/digitiser/digitiser_star_hub.py +++ b/src/spectrumdevice/devices/digitiser/digitiser_star_hub.py @@ -96,7 +96,7 @@ def _get_waveforms(digitiser_card: SpectrumDigitiserCard) -> None: thread.join() waveform_sets_all_cards_ordered = [] - for n in range(self._batch_size): + for n in range(self.batch_size): waveforms_in_this_batch = [] for card in self._child_cards: waveforms_in_this_batch += card_ids_and_waveform_sets[str(card)][n] @@ -178,3 +178,14 @@ def set_acquisition_mode(self, mode: AcquisitionMode) -> None: mode (`AcquisitionMode`): The desired acquisition mode.""" for d in self._child_cards: cast(SpectrumDigitiserCard, d).set_acquisition_mode(mode) + + @property + def batch_size(self) -> int: + batch_sizes = [] + for d in self._child_cards: + batch_sizes.append(cast(SpectrumDigitiserCard, d).batch_size) + return check_settings_constant_across_devices(batch_sizes, __name__) + + def set_batch_size(self, batch_size: int) -> None: + for d in self._child_cards: + cast(SpectrumDigitiserCard, d).set_batch_size(batch_size) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index 837e5a8..0fd4bb1 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -5,7 +5,7 @@ import pytest from numpy import array, concatenate -from example_scripts.connect_to_star_hub import star_hub_example +from example_scripts.star_hub_example import connect_to_star_hub_example from example_scripts.continuous_averaging_fifo_mode import continuous_averaging_multi_fifo_example from example_scripts.continuous_multi_fifo_mode import continuous_multi_fifo_example from example_scripts.finite_multi_fifo_mode import finite_multi_fifo_example @@ -110,7 +110,7 @@ def setUp(self) -> None: self._star_hub_mock_mode = STAR_HUB_TEST_MODE == SpectrumTestMode.MOCK_HARDWARE def test_star_hub(self) -> None: - hub = star_hub_example( + hub = connect_to_star_hub_example( mock_mode=self._star_hub_mock_mode, num_cards=NUM_CARDS_IN_STAR_HUB, master_card_index=STAR_HUB_MASTER_CARD_INDEX,