kcl-bmeis / spectrumdevice Goto Github PK
View Code? Open in Web Editor NEWPython library for communicating with digitisers manufactured by Spectrum Instrumentation
License: MIT License
Python library for communicating with digitisers manufactured by Spectrum Instrumentation
License: MIT License
Recently implemented pulse gen and AWG functionality need examples and mention in the README
Following this guide.
Check works with 3.11
We're using polling mode for timestamp transfer, which is quite slow. Should have a look at using FIFO/DMA mode
SpectrumStarHub.set_enabled_channels()
does not work if the channels in the list provided are not in the numerical order
from the M2p-65xx AWG manual: "This mode allows the user to replay up to four additional digital channels that are synchronous and phase stable along with the analog data."
The digital waveform must be encoded in the analog samples like this:
def write_digital_waveform_to_bit_15_of_analog(
digital_waveform: NDArray[bool_], analog_waveform: NDArray[int16]
) -> NDArray[int16]:
if analog_waveform.shape != digital_waveform.shape:
raise ValueError("Analog and digital waveforms must have the same shape.")
analog_waveform &= ~1 # Clear the least significant bit
analog_waveform |= digital_waveform.astype(int16) # Set the least significant bit using bitwise OR
return analog_waveform
and then the mode enabled something like this:
analog_waveform = write_digital_waveform_to_bit_15_of_analog(digital_wfm, analog_wfm)
card.io_lines[0].set_mode(IOLineMode.SPCM_XMODE_DIGOUT)
card.io_lines[0].set_dig_out_settings(
DigOutIOLineModeSettings(
source_channel=DigOutSourceChannel.SPCM_XMODE_DIGOUTSRC_CH0,
source_bit=DigOutSourceBit.SPCM_XMODE_DIGOUTSRC_BIT15,
)
)
We need to support arbitrary waveform generators as well as digitisers. This will likely require some refactoring of the class hierarchy (and some renaming - SpectrumDevice will likely become SpectrumDigitiser, for example). This work will likely form the bulk of the version 1 release.
Refactoring was done in PR #29
Other card series like the M4i.22xx or M4i.44xx have a different step size for the SPC_MEMSIZE and SPC_POSTTRIGGER registers (32 samples for 22xx, 16 samples for 44xx).
The card type can be read from the SPC_PCITYP
register. This could be done in SpectrumCard.__init__()
. We'd then need a lookup table of step sizes for the different card types.
There's a bug in decode_status(). You can't instantiate a List
in that way.
Hi, I'm trying to install you package.
I'm usually use conda for create new envs, so I did it.
conda create -n myenv
conda activate myenv
Then
conda install -c conda-forge spectrumdevice -y
That does not return me any kind of error.
Then i follow your README with this 2 lines :
from spectrumdevice import SpectrumDigitiserCard
card_0 = SpectrumDigitiserCard(device_number=0)
Here i got an error :
ImportError: cannot import name 'SpectrumDigitiserCardconda' from 'spectrumdevice' (/miniconda/base/envs/envspectrum/lib/python3.11/site-packages/spectrumdevice/__init__.py)
Do i missed something ?
Register values constants required by #42 don't seem to be in the version of pyspcm we currently use. Update to new version provided by spec inst.
Many cards support on-board averaging. SPC_CARDMODE
needs to be set to one of the following values:
SPC_REC_STD_AVERAGE
for averaging in standard acquisition mode resulting in 32 bit dataSPC_REC_STD_AVERAGE_16BIT
for averaging in standard acquisition mode resulting in 16 bit data (8 bit cards only)SPC_REC_FIFO_AVERAGE
for averaging in FIFO acquisition mode resulting in 32 bit dataSPC_REC_FIFO_AVERAGE_16BIT
for averaging in FIFO acquisition mode resulting in 16 bit data (8 bit cards only)Then you set the number of averages by writing to the SPC_AVERAGES
register.
A spectrum acquisition card can provide trigger timestamps for each of its acquisitions. The device can be configured to provide the timestamps relative to the start of each acquisition, relative to an external trigger signal, or relative to a timestamp provided by the host PC. The timestamps are passed to the PC via the 'extra-FIFO' buffer.
In the first instance, it makes sense to configure a SpectrumCard
to return a system-clock timestamp with each acquisition, as this is likely the most commonly useful information.
The error handler in spectrum_wrapper/error_handler.py
currently only contains the descriptions of a few frequently encountered errors. Other errors are raised only by their Spectrum API error codes, and must be looked up in the Spectrum documentation.
As more errors are encountered while spectrumdevice
is used, those most likely to be encountered should be added to the error handler. This issue holds a list of those errors.
At some point, the whole error codes table from the spectrum documentation should probably be included in spectrumdevice
as a lookup table.
The card could receive enough trigger events in the mean time to overwrite the area just freed with new data, resulting in an inconsistent mix of old and new data being read. It would be better to first execute the “waveforms_in_columns = copy…” line, and after that mark the data as available again by calling “self.write_to_spectrum_device_register(SPC_DATA_AVAIL_CARD_LEN, num_available_bytes)”.
Test plan for testing on lab machine with drivers installed and hardware connected (before release).
pytest -v -m "not integration and not only_without_driver"
pytest -v -m "integration and not only_without_driver"
In tests/configuration.py
SINGLE_CARD_TEST_MODE = SpectrumTestMode.REAL_HARDWARE
STAR_HUB_TEST_MODE = SpectrumTestMode.REAL_HARDWARE
TEST_DEVICE_IP
equal to the device IP address shown in the Spectrum Control CentreTEST_DEVICE_NUMBER = 1
NUM_MODULES_PER_CARD = 2
NUM_CHANNELS_PER_MODULE = 4
NUM_CARDS_IN_STAR_HUB = 2
STAR_HUB_MASTER_CARD_INDEX = 1
ACQUISITION_LENGTH = 4096
Then:
pytest -v -m "not integration and not only_without_driver"
In tests/configuration.py
INTEGRATION_TEST_TRIGGER_SOURCE = TriggerSource.SPC_MASK_SOFTWARE
.Then:
pytest -v -m "integration and not only_without_driver"
Signal generator setup:
Connect signal generator to Netbox:
In tests/configuration.py
INTEGRATION_TEST_TRIGGER_SOURCE = TriggerSource.SPC_MASK_EXT0
.Then:
pytest -v -m "integration and not only_without_driver"
Manually run each of the example scripts in the example_scripts
directory, with the signal generator set up as for the Integration tests (with a signal generator) above. You will need to temporarily modify the if __name__ == '__main__':
of the scripts so that:
Then:
In tests/configuration.py
SINGLE_CARD_TEST_MODE = SpectrumTestMode.REAL_HARDWARE
TEST_DEVICE_IP = None
TEST_DEVICE_NUMBER = 0
NUM_MODULES_PER_CARD = 1
NUM_CHANNELS_PER_MODULE = 2
Then:
pytest -v -m "not star_hub and not integration and not only_without_driver"
Using the same configuration as above, and ensuring software triggering is selected in configuration.py:
pytest -v -m "not star_hub and integration and not only_without_driver"
Check Python 3.12 compatibility
The error message FIFO mode: coercing length to nearest ... kept showing up in my case, evenso I chose the proper acquisition_length_in_samples and pre_trigger_length_in_samples. I think the problem came from the _coerce_num_samples_if_fifo, so I modified it as follow:
def _coerce_num_samples_if_fifo(self, value: int) -> int:
if self.acquisition_mode == AcquisitionMode.SPC_REC_FIFO_MULTI:
if mod(value, get_memsize_step_size(self._model_number)) != 0:
logger.warning(
f"FIFO mode: coercing length to nearest {get_memsize_step_size(self._model_number)}" f" samples"
)
value = int(value - mod(value, get_memsize_step_size(self._model_number)))
return value
There are some unexpected failed tests when running the single card tests on hardware
There is an optional firmware feature for both AWGs and digitisers that enable the multipurpose IO lines to be used as pulse generators. From the manual:
"The module consists of four pulse generators, where each generator allows for (in)dependent generation of individual pulses, pulse trains or a continuous stream of pulses that can be output on a Multi-Pur- pose I/O Line, greatly enhancing the versatility of the XIO lines." [page 143].
Each IO line (AbstractSpectrumIOLine
in spectrumdevice
) has its own pulse generator. It is enabled by settings the SPCM_X0_MODE
, SPCM_X1_MODE
, SPCM_X2_MODE
, SPCM_X3_MODE
registers to SPCM_XMODE_PULSEGEN
. This must be configured before M2CMD_CARD_START
(or M2CMD_CARD_WRITESETUP
)
Hi,
Your package work near perfectly,
However, I'm encountering challenges while attempting to configure specific parameters:
Could you integrate those settings in AcquisitionSetting ?
Best regards
I'm using your package with a spectrum digitiser.
Can we obtain waveforms in integers (for exemple coded in 2**16 value) and not in mV ?
Implement an option for software averaging, for use with devices that do not support hardware averaging.
Hi Christian,
First of all, I like to thanks you for this great contribution, I recently started to use M2p.5946-x4 cards and found your code extremely useful.
For my application I would like to use as external trigger the main analog channel of the card. So I can display the channel I am triggering on.
In the manual p'103, they give some examples. I would like to do something like that:
trigger_settings = TriggerSettings(
trigger_sources=[TriggerSource.SPC_TMASK_CH0],
external_trigger_mode=ExternalTriggerMode.SPC_TM_POS,
external_trigger_level_in_mv=1000,
)
Is this option implemented in your code?
Thank you very much for your support.
Cheers,
Andy
The waveforms provided by spectrumdevice
currently contain raw ADC samples in LSB. They should be converted to voltages as follows:
"The Spectrum driver also contains a register that holds the value of the decimal value of the full scale representation of the installed ADC. This value should be used when converting ADC values (in LSB) into real-world voltage values, because this register also automatically takes any specialities into account, such as slightly reduced ADC resolution with reserved codes for gain/offset compensation.
Register: SPC_MIINST_MAXADCVALUE
Value: 1126
Description: Contains the decimal code (in LSB) of the ADC full scale value
In case of a board that uses an 8 bit ADC that provides the full ADC code (with- out reserving any bits) the returned value would be 128. The the peak value for a ±1.0 V input range would be 1.0 V (or 1000 mv).
When converting samples that contain any additional data such as for example additional digital channels or overrange bits, this extra information must be first masked out and a proper sign-extension must be per- formed, before these values can be used as a signed two’s complement value for above formulas."
There are some missing docstrings in the AWG and pulse gen classes
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.