brainspy.processors.hardware.drivers.ni package#
Module contents#
National Instruments related drivers.
Submodules#
brainspy.processors.hardware.drivers.ni.channels module#
This file contains a set of functions that are used to initialise the channels used to specify the connection between the National Instrument devices and the electrodes of DNPU hardware devices. It supports to declare channels for one or more DNPU hardware devices simultaneously.
- brainspy.processors.hardware.drivers.ni.channels.add_uniquely(original_list, value)[source]#
Adds a value to a list if the value does not exist already in that list.
- Parameters:
original_list (list) – List against which the value that wants to be inserted will be compared.
value (any) – Value that wants to be added to the list.
- Returns:
original_list – The original list containing the specified value just once.
- Return type:
list
- brainspy.processors.hardware.drivers.ni.channels.concatenate_voltage_ranges(voltage_ranges: list | ndarray)[source]#
It creates a single array of voltage ranges, as defined in the activation_voltage_ranges flag of the driver’s configs files. It is meant for cases where the PCB supports writing to more than one DNPU hardware device simultaneously, in order to concatenate all input voltage ranges for all activation electrodes into a single numpy array.
- Parameters:
voltage_ranges (np.array or list) – The maximum and minimum voltage values that the National Instrument device will be allowed to send through the activation electrodes of a particular DNPU hardware device.
- Returns:
result – A numpy array with the concatenation of several voltage ranges from more than one DNPU hardware device, in cases where the PCB supports writing to more than one DNPU hardware device simultaneously.
- Return type:
np.array # or list
- brainspy.processors.hardware.drivers.ni.channels.get_mask(configs: dict)[source]#
This method retrieves a list of the masks for the channels from a configuration dictionary and transforms it into a numpy array. If the key does not exist in the dictionary returns None. The mask is used to deactivate some of the channels in PCBs that support reading from more than one DNPU hardware device simultaneously.
- Parameters:
configs (Configurations of the driver. There is only one key needed to operate in this function:) –
1. activation_channel_mask: Optional[list] A list of zeroes and ones, representing each of the channels that go to the activation electrodes of a particular DNPU. The list should have a length of (activation_electrode_no). Each zero in the list will be a deactivated channel, each one in the list will be an activated channel.
E.g., for an 8 electrode hardware DNPU with 7 activation electrodes: activation_channel_mask = [0,1,1,1,1,1,1] will act as if the first electrode does not exist.
- Returns:
result – Mask used to deactivate some of the channels in numpy format.
- Return type:
None or np.array
- brainspy.processors.hardware.drivers.ni.channels.init_activation_channels(configs, activation_channel_list=[])[source]#
Method to retrieve all the activation channel lists from more than one hardware DNPU devices, in cases where the PCB supports writing to more than one DNPU hardware device simultaneously.
- Parameters:
configs (dict) –
Configurations of the driver. There is only one key needed to operate this function: 1. activation_channels: list List of physical channels of the National Instruments device from which the input of a hardware DNPU will be read. The length of the list is the same as the number of activation electrodes.
2. activation_instrument: str Name of the instrument that is used for writing the input of a hardware DNPU.
- Returns:
ractivation_channel_list (list)
A list containing all the activation channels currently registered in the list.
- brainspy.processors.hardware.drivers.ni.channels.init_channel_data(configs)[source]#
It creates a single array of voltage ranges, as defined in the activation_voltage_ranges flag of the driver’s configs files. It is meant for cases where the PCB supports writing to more than one DNPU hardware device simultaneously, in order to concatenate all input voltage ranges for all activation electrodes into a single numpy array.
- Parameters:
configs –
Dictionary containing information about the instruments setup. The dictionary contains the following keys: 1. instruments_setup: 1.1 multiple_devices: boolean Whether if the configurations contain the configurations of reading from a single DNPU hardware device or multiple DNPU hardware devices.
1.2 trigger_source: str For synchronisation purposes, sending data for the activation voltages on one NI Task can trigger the readout device of another NI Task. In these cases, the trigger source name should be specified in the configs. This is only applicable for CDAQ to CDAQ setups (with or without real-time rack). E.g., cDAQ1/segment1 - More information at: https://nidaqmx-python.readthedocs.io/en/latest/start_trigger.html
A. The reminder of the keys work as follows. If the attribute multiple_devices is set to False, the following configurations apply:
A.1 activation_instrument: str The name of the National Instument device used for writing the data into the activation electrodes of the hardware DNPU device. (e.g., cDAQ1Mod2)
A.2 activation_channels: list A list containing the physical ao channels of the National Instrument device that will be used for writing the data into the activation electrodes of the hardware DNPU device. (e.g., [6,0,7,5,2,4,3])
A.3 activation_voltage_ranges: list The maximum and minimum voltage values that the National Instrument device will be allowed to sent through the activation electrodes of a particular DNPU hardware device. The shape is (activation_electrode_no,2) where the second dimension stands for minimum and maximum of the range, respectively. E.g,: [[-1.2,0.7],[-1.2,0.7],[-1.2,0.7],[-1.2,0.7],[-1.2,0.7],[-1.2,0.7],[-1.2,0.7]]
A.4 activation_channel_mask: list A list of zeroes and ones, representing each of the channels that go to the activationelectrodes of a particular DNPU. The list should have a length of (activation_electrode_no). Each zero in the list will be a deactivated channel, each one in the list will be an activated channel. E.g., [0,0,0,0,0,0,0]
A.5 readout_instrument: str Name of the instrument that is used for reading the output of a hardware DNPU. E.g., cDAQ1Mod4
A.6 readout_channels: list List of physical channels of the National Instruments device from which the output of a hardware DNPU will be read. The length of the list is the same as the number of readout electrodes.
- Returns:
result – A numpy array with the concatenation of several voltage ranges from more than one DNPU hardware device, in cases where the PCB supports writing to more than one DNPU hardware device simultaneously.
- Return type:
np.array
- brainspy.processors.hardware.drivers.ni.channels.init_readout_channels(configs: dict, readout_channel_list: list = [])[source]#
Method to retrieve all the readout channel lists from more than one hardware DNPU devices, in cases where the PCB supports reading from more than one DNPU hardware device simultaneously.
- Parameters:
configs (dict) –
Configurations of the driver. There is only one key needed to operate this function:
1. readout_channels: list List of physical channels of the National Instruments device from which the output of a hardware DNPU will be read. The length of the list is the same as the number of readout electrodes.
2. readout_instrument: str Name of the instrument that is used for reading the output of a hardware DNPU.
- Returns:
readout_channel_list – A list containing all the readout channels currently registered in the list.
- Return type:
list
- brainspy.processors.hardware.drivers.ni.channels.is_device_name(key)[source]#
Checks if a configuration key from the instruments_setup configuration dictionary contains the name of a DNPU device, in the case of having a PCB with multiple DNPU devices (multiple_devices = True).
- Parameters:
key (str) – Configuration key to be checked against being a device name.
- Returns:
Whether if the configuration key is a device name
- Return type:
bool
brainspy.processors.hardware.drivers.ni.setup module#
File containing the generic class for creating a driver of national instruments
- class brainspy.processors.hardware.drivers.ni.setup.NationalInstrumentsSetup(configs)[source]#
Bases:
object- average_point_difference(data)[source]#
A difference between the activation sampling frequency (DAC) and the readout sampling frequency (ADC) can cause the read data to have a longer shape than the data that was written. This method averages all the points that were read per point that was written. The averaging is only applied if there is a difference between write and read data of more than one point, and if configs[‘instruments_setup’][‘average_io_point_difference’] is set to True.
- Parameters:
data (np.array) – Processed output data in numpy format, with two dimensions (channel_no, read_point_no), and with the amplification correction factor applied.
- Returns:
Array with an averaged point difference, when applicable.
- Return type:
np.array
- calculate_io_points(points_to_write: int)[source]#
Calculates the number of points to be written and read depending on which setup (cdaq_to_cdaq or cdaq_to_nidaq) is being used.
cdaq_to_nidaq setups require an extra offset of zero points, to give some time to the reading instrument. These points are depending on the point difference due to the different sampling frequencies between the reading and writing devices. The offset should be added to both writing and reading instruments. Default offset values are added in the __init__ of the nidaq class.
cdaq_to_cdaq setups measure an extra point by default. The extra offset should only be added to the reading point number. This is always only a point, regardless of the sampling frequencies of reading and writing devices.
- Parameters:
points_to_write (int) – Raw number of points that needs to be written. It is used to calculate the reading point number and the writing point number, depending on the offset required by each setup type.
- Returns:
points_to_write – The raw number of points that was passed as input of the method.
- Return type:
int
- disable_os_signals()[source]#
Disables the OS signals by removing the signal HandlerRoutine in the the win32 OS or ignoring the signal incase of other processors.
- enable_os_signals()[source]#
Enables the OS signals by adding an a signal HandlerRoutine to support read/write in both linux and windows in Windows and Linux operating systems.
- forward_numpy()[source]#
The forward function computes output numpy values from input numpy array. This is done to enable compatibility of the the model which is an nn.Module with numpy. This function will be overriden by the specific implementation in the CDAQ TO CDAQ or CDAQ TO NIDAQ setup.
- get_amplification_value()[source]#
To get the amplification value from the data provided in the configuratons dictionary
- Returns:
amplification value
- Return type:
int
- init_configs(configs)[source]#
To initialise the configurations of the setup. Note - The configurations dictionary contains a “max_ramping_time_seconds” key whose value should be chosen carefully because steep values may damage the device.
- Parameters:
configs (dict) – Configurations to be initialised. Described in the __init__ method of this class.
- init_sampling_configs(configs)[source]#
Initialises configuration related to sampling. It saves the variable io_point_difference, which is calculated dividing the readout_sampling_frequency by the activation_sampling_frequency. It asserts that the remainder of this division between frequencies is zero. It raises a warning related to resolution loss if the activation_sampling_frequency is higher than half of the readout_sampling_frequency.
- Parameters:
configs (dict) – A dictionary containing at least the following keys: 1. instruments_setup: 1.1 readout_sampling_frequency: Frequency at which the ADC will sample. 1.2 activation_sampling_frequency: Frequency at which the DAC will sample.
- init_semaphore()[source]#
Initializes the semaphore that will manage the main thread by synchronsing it with the read/write of data.
- init_tasks(configs)[source]#
Initializes the tasks driver and voltage ranges based on the configurations.
- Parameters:
configs (dict) – configurations of the model as a python dictionary
- is_hardware()[source]#
Method to indicate whether this is a hardware processor. Returns True.
- Returns:
True
- Return type:
bool
- os_signal_handler(signum, frame=None)[source]#
Used to handle the termination of the read task in such a way that enables the last read call to the drivers to finish, and adequately closing the NI tasks afterwards. A handler for a particular signal, once set, remains installed until it is explicitly reset.
More information can be found at: https://docs.python.org/3/library/signal.html
- Parameters:
signum (int) – The signal number.
frame (int, optional) – The current stack frame, by default None.
- process_output_data(data)[source]#
Processes the output data. Also the PCB connected to the DNPU hardware does a uses an operational amplifier to amplify the current, and transforms the current into voltage to do the reading. For this, the output gets amplified. An amplification correction factor is applied in software, in order to obtain the real current value again. This is done using the configs[‘driver’][‘amplification’] value. The function creates a numpy array from a list, ensuring it has dimensions (channel_no, read_point_no) and multiplies it by the amplification of the device.
- Parameters:
data (list) – output data
- Returns:
Processed output data in numpy format, with two dimensions (channel_no, read_point_no), and with the amplification correction factor applied.
- Return type:
np.array
- read_data(y)[source]#
Initializes the semaphore to read data from the device if the data cannot be read, a signal is sent to the signal handler which blocks the calling thread and closes the nidaqmx tasks
- Parameters:
y (np.array) – Input data to be sent to the device. The data should have a shape of: (device_input_channel_no, data_point_no) Where device_input_channel_no is typically the number of activation electrodes of the DNPU.
- Returns:
Output data that has been read from the device when receiving the input y.
- Return type:
list
- read_security_checks(y)[source]#
This method reads the security checks from the input data, and makes sure that the input voltage does not go above certain threshhold.
- Parameters:
y (np.array) – It represents the input data as matrix where the shape is defined by the “number of inputs to the device” times “input points that you want to input to the device”.
- set_io_configs(points_to_write: int, timeout: float | None = None)[source]#
Calculates and sets the I/O configuration variables related to the number of points the signal that is going to be writing and reading. This is only performed if there is a change with respect to the last number of points that were write/read. The calculation includes:
1. last_points_to_write_val: Number of points that were sent in the previos write attempt.
2. offsetted_points_to_write: Number of points with to be written with an extra offset that depends on the setup type. For cdaq, the default offset is 1 point, for nidaq, it is calculated from the sampling frequency.
3. set_sampling_frequencies: Sets the sampling frequencies of the activation and readout instruments.
timeout: Specifies the timeout for reading. Read below for more information.
5. points_to_read: Number of points that will be read given the number of points that are written and the activation/readout frequency relationship.
- Parameters:
points_to_write (int) – Number of points to be written.
timeout (float) – Specifies the amount of time in seconds to wait for samples to become available. If the time elapses, the method returns an error and any samples read before the timeout elapsed. The default timeout is 10 seconds. If you set timeout to nidaqmx.constants.WAIT_INFINITELY, the method waits indefinitely. If you set timeout to 0, the method tries once to read the requested samples and returns an error if it is unable to. By default, None, which calculates the timeout based on the frequency.
- set_timeout(timeout=None)[source]#
Updates the internal timeout value that will be used when reading the data.
- Parameters:
timeout (int, optional) – Specifies the amount of time in seconds to wait for samples to become available. If the time elapses, the method returns an error and any samples read before the timeout elapsed. The default timeout is 10 seconds. If you set timeout to nidaqmx.constants.WAIT_INFINITELY, the method waits indefinitely. If you set timeout to 0, the method tries once to read the requested samples and returns an error if it is unable to. By default, None.
brainspy.processors.hardware.drivers.ni.tasks module#
This file contains drivers to handle nidaqmx.Tasks on different environments, that include regular National Instrument racks or National Instrument real-time racks.
Both drivers work seamlessly, they declare the following nidaqmx.Task instances: 1. activation_task: It handles sending signals to the (DNPU) device through electrodes declared as activation electrodes.
2. readout_task: It handles reading signlas comming out from the (DNPU) device from electrodes declared as readout electrodes.
Both nidaqmx.Task instances will declare a channel per electrode, and in the case of the cdaq to nidaq connection, they will also declare an extra synchronization channel. It can alo be used to set the shape variables according to the requiremnets.
- class brainspy.processors.hardware.drivers.ni.tasks.IOTasksManager(configs)[source]#
Bases:
objectClass to initialise and handle the “nidaqmx.Task”s required for brains-py drivers.
More information about NI tasks can be found at: https://nidaqmx-python.readthedocs.io/en/latest/task.html
- add_synchronisation_channels(readout_instrument, activation_instrument, activation_channel_no=7, readout_channel_no=7)[source]#
The method is used to add a synchronized activation and readout channel to the device when using cdaq to nidaq devices. Activation channels send signals to the activation electrodes while an additional synchronisation channel is created to communicate with the nidaq readout module. A spike is sent through this synchronisation channel to make the nidaq and the cdaq write and read syncrhonously.
- Parameters:
readout_instrument (str) – Name of the instrument from which the read will be performed on the readout electrodes.
activation_instrument (str) – Name of the instrument writing signals to the activation electrodes.
activation_channel_no (int, optional) – Channel through which voltages will be sent for activating the device (with both data inputs and control voltages), by default 7.
readout_channel_no (int, optional) – Channel for reading the output current values, by default 7.
- close_tasks()[source]#
Close all the task on this device - both activation and readout tasks by deleting them. Note - This method is different from the stop_tasks() method which only stops the current tasks temporarily.
- init_activation_channels(channel_names, voltage_ranges=None)[source]#
Initialises the activation channels connected to the activation electrodes of the device. These are being sent as list of voltage values and channel names which are the start values for device.
- Parameters:
channel_names (list) – List of the names of the activation channels
voltage_ranges (Optional[list] or numpy.ndarray) – List/numpy.ndarray of maximum and minimum voltage ranges that will be allowed to be sent through each channel. The dimension of the list should be (channel_no,2) where the second dimension stands for min and max values of the range, respectively. When set to None, there will be no specific limitations on what can be sent through the device. This could potentially cause damages to the device. By default is None.
- init_readout_channels(readout_channels)[source]#
Initializes the readout channels corresponding to the readout electrodes of the device. The range of the readout channels depends on setup and on the feedback resistance produced.
- Parameters:
readout_channels (list[str]) – List containing all the readout channels of the device.
- init_tasks(configs)[source]#
To Initialize the tasks on the device based on the configurations dictionary provided. the method initializes the activation and readout tasks from the device by setting the voltage ranges and choosing the instruments that have been specified.
- Parameters:
configs (dict) –
Configs dictionary for the device model
The configs should have the following keys:
1. sampling_frequency: int The average number of samples to be obtained in one second, when transforming the signal from analogue to digital.
2. amplification: float The output current (nA) of the device is converted by the readout hardware to voltage (V), because it is easier to do the readout of the device in voltages. This output signal in nA is amplified by the hardware when doing this current to voltage conversion, as larger signals are easier to detect. In order to obtain the real current (nA) output of the device, the conversion is automatically corrected in software by multiplying by the amplification value again.
The amplification value depends on the feedback resistance of each of the setups. Below, there is a guide of the amplification value needed for each of the setups:
Setup 1 - Darwin: Variable amplification levels: A: 1000 Amplification Feedback resistance: 1 MOhm
B: 100 Amplification Feedback resistance 10 MOhms
C: 10 Amplification Feedback resistance: 100 MOhms
D: 1 Amplification Feedback resistance 1 GOhm
Setup 2 - Pinky: - PCB 1 (6 converters with): A. Amplification 10 Feedback resistance 100 MOhm
B. PCB 2 (6 converters with): Amplification 100 tims 10 mOhm Feedback resistance
Setup 3 - Brains: Amplfication 28.5 Feedback resistance, 33.3 MOhm
Setup 4 - Switch: (Information to be completed) If no correction is desired, the amplification can be set to 1.
instruments_setup:
3.1 multiple_devices: boolean False will initialise the drivers to read from a single hardware DNPU. True, will enable to read from more than one DNPU device at the same time.
3.2 activation_instrument: str Name of the activation instrument as observed in the NI Max software. E.g., cDAQ1Mod3
3.3 activation_channels: list Channels through which voltages will be sent for activating the device (both data inputs and control voltage electrodes). The channels can be checked in the schematic of the DNPU device. E.g., [8,10,13,11,7,12,14]
3.4 activation_voltage_ranges: list Minimum and maximum voltage for the activation electrodes. E.g., [[-1.2, 0.6], [-1.2, 0.6], [-1.2, 0.6], [-1.2, 0.6], [-1.2, 0.6], [-0.7, 0.3], [-0.7, 0.3]]
3.5 readout_instrument: str Name of the readout instrument as observed in the NI Max software. E.g., cDAQ1Mod4
3.6 readout_channels: [2] list Channels for reading the output current values. The channels can be checked in the schematic of the DNPU device.
3.7 trigger_source: str For synchronisation purposes, sending data for the activation voltages on one NI Task can trigger the readout device of another NI Task. In these cases,the trigger source name should be specified in the configs. This is only applicable for CDAQ to CDAQ setups (with or without real-time rack). E.g., cDAQ1/segment1 More information at https://nidaqmx-python.readthedocs.io/en/latest/start_trigger.html
4. plateau_length: float - Length of the plateau that is being sent through the forward call of the HardwareProcessor slope_length : float - Length of the slopes in the waveforms sent to the device through the drivers
- Returns:
list of voltage ranges
- Return type:
list
- read(number_of_samples_per_channel, timeout=None)[source]#
Reads samples from the task or virtual channels you specify. This read method is dynamic, and is capable of inferring an appropriate return type based on these factors: - The channel type of the task. - The number of channels to read. - The number of samples per channel. The data type of the samples returned is independently determined by the channel type of the task. For digital input measurements, the data type of the samples returned is determined by the line grouping format of the digital lines. If the line grouping format is set to “one channel for all lines”, the data type of the samples returned is int. If the line grouping format is set to “one channel per line”, the data type of the samples returned is boolean. If you do not set the number of samples per channel, this method assumes one sample was requested. This method then returns either a scalar (1 channel to read) or a list (N channels to read).
If you set the number of samples per channel to ANY value (even 1), this method assumes multiple samples were requested. This method then returns either a list (1 channel to read) or a list of lists (N channels to read).
Original documentation from: https://nidaqmx-python.readthedocs.io/en/latest/task.html
- Parameters:
number_of_samples_per_channel (int) – Specifies the number of samples to read. If this input is not set, assumes samples to read is 1. Conversely, if this input is set, assumes there are multiple samples to read. If you set this input to nidaqmx.constants. READ_ALL_AVAILABLE, NI-DAQmx determines how many samples to read based on if the task acquires samples continuously or acquires a finite number of samples. If the task acquires samples continuously and you set this input to nidaqmx.constants.READ_ALL_AVAILABLE, this method reads all the samples currently available in the buffer. If the task acquires a finite number of samples and you set this input to nidaqmx.constants.READ_ALL_AVAILABLE, the method waits for the task to acquire all requested samples, then reads those samples. If you set the “read_all_avail_samp” property to True, the method reads the samples currently available in the buffer and does not wait for the task to acquire all requested samples.
timeout (Optional[float]) – Specifies the amount of time in seconds to wait for samples to become available. If the time elapses, the method returns an error and any samples read before the timeout elapsed. The default timeout is 10 seconds. If you set timeout to nidaqmx.constants.WAIT_INFINITELY, the method waits indefinitely. If you set timeout to 0, the method tries once to read the requested samples and returns an error if it is unable to.
- Returns:
The samples requested in the form of a scalar, a list, or a list of lists. See method docstring for more info. NI-DAQmx scales the data to the units of the measurement, including any custom scaling you apply to the channels. Use a DAQmx Create Channel method to specify these units.
- Return type:
list
- set_sampling_frequencies(activation_sampling_frequency: int, readout_sampling_frequency: int, points_to_write: int, points_to_read: int)[source]#
Sets the sampling frequency for the activation and readout tasks. The activation task is in charge to send signals from the computer to the NI module, and the readout task is in charge of reading signals from the NI module.
- Parameters:
activation_sampling_frequency (int) – The number of samples that the activation task will obtain in one second.
readout_sampling_frequency (int) – The number of samples that the readout task will obtain in one second.
points_to_write (int) – Number of points that will be written.
points_to_read (int) – Number of points that are expected to be read given the number of points to be written, and the activation and readout frequencies.
- start_trigger(trigger_source)[source]#
To synchronise cdaq to cdaq modules a start trigger can be set, in such a way that when a write operation is done, a read operation is triggered.
More information can be found in: https://nidaqmx-python.readthedocs.io/en/latest/start_trigger.html
- Parameters:
trigger_source (str) – Source trigger name. It can be found on the NI max program. Click on the device rack inside devices and interfaces, and then click on the Device Routes tab.
- stop_tasks()[source]#
To stop the all tasks on this device namely - the activation tasks and the readout tasks to and from the device.
- write(y, auto_start)[source]#
This method writes samples to the task or virtual channels specified in the tasks of the tasks driver. It also catches DaqError exceptions. It supports automatic start of tasks. This write method is dynamic, and is capable of accepting the samples to write in the various forms for most operations:
Scalar: Single sample for 1 channel. List/1D numpy.ndarray: Multiple samples for 1 channel or 1 sample for multiple channels. List of lists/2D numpy.ndarray: Multiple samples for multiple channels.
The data type of the samples passed in must be appropriate for the channel type of the task.
For counter output pulse operations, this write method only accepts samples in these forms:
Scalar CtrFreq, CtrTime, CtrTick (from nidaqmx.types): Single sample for 1 channel. List of CtrFreq, CtrTime, CtrTick (from nidaqmx.types): Multiple samples for 1 channel or 1 sample for multiple channels.
If the task uses on-demand timing, this method returns only after the device generates all samples. On-demand is the default timing type if you do not use the timing property on the task to configure a sample timing type. If the task uses any timing type other than on- demand, this method returns immediately and does not wait for the device to generate all samples. Your application must determine if the task is done to ensure that the device generated all samples.
Both of these tasks occur simulataneously and are synchronized. The tasks will start automatically if the “auto_start” option is set to True in the configuration dictionary used to intialize this device.
- Parameters:
y (np.array) – Contains the samples to be written to the activation task.
auto_start (Bool) – True to enable auto-start from nidaqmx drivers. False to start the tasks immediately after writing.