Command Line Interfaces

This module provides click-based Command-Line Interface (CLI) scripts that allow accessing all user-facing features from this library through the terminal.

sl-crc

Calculates the CRC32-XFER checksum for the input string.

sl-crc [OPTIONS]

Options

-i, --input_string <input_string>

The string to calculate the CRC checksum for.

sl-devices

Displays information about all Zaber devices available through USB ports of the host-system.

sl-devices [OPTIONS]

Options

-e, --errors

Determines whether to display errors encountered when connecting to evaluated serial ports.

Default:

False

sl-maintain

Exposes a terminal interface to interact with the water delivery solenoid valve and the running wheel break.

This CLI command is primarily designed to fill, empty, check, and, if necessary, recalibrate the solenoid valve used to deliver water to animals during training and experiment runtimes. Also, it is capable of locking or unlocking the wheel breaks, which is helpful when cleaning the wheel (after each session) and maintaining the wrap around the wheel surface (weekly to monthly).

sl-maintain [OPTIONS]

sl-lick-train

Runs the lick training session for the specified animal and project combination.

Lick training is the first phase of preparing the animal to run experiment runtimes in the lab, and is usually carried out over the first two days of head-fixed training. Primarily, this training is designed to teach the animal to operate the lick-port and associate licking at the port with water delivery.

sl-lick-train [OPTIONS]

Options

-u, --user <user>

Required The ID of the user supervising the training session.

-p, --project <project>

Required The name of the project to which the trained animal belongs.

-a, --animal <animal>

Required The ID of the animal undergoing the lick training session.

-w, --animal_weight <animal_weight>

Required The weight of the animal, in grams, at the beginning of the training session.

-min, --minimum_delay <minimum_delay>

The minimum number of seconds that has to pass between two consecutive reward deliveries during training.

Default:

6

-max, --maximum_delay <maximum_delay>

The maximum number of seconds that can pass between two consecutive reward deliveries during training.

Default:

18

-v, --maximum_volume <maximum_volume>

The maximum volume of water, in milliliters, that can be delivered during training.

Default:

1.0

-t, --maximum_time <maximum_time>

The maximum time to run the training, in minutes.

Default:

20

-ur, --unconsumed_rewards <unconsumed_rewards>

The maximum number of rewards that can be delivered without the animal consuming them, before reward delivery is paused. Set to 0 to disable enforcing reward consumption.

Default:

1

-r, --restore_parameters

Determines whether to load and use the same training parameters as used during the previous lick training session of the target animal.

Default:

False

sl-run-train

Runs the run training session for the specified animal and project combination.

Run training is the second phase of preparing the animal to run experiment runtimes in the lab, and is usually carried out over the five days following the lick training sessions. Primarily, this training is designed to teach the animal how to run the wheel treadmill while being head-fixed and associate getting water rewards with running on the treadmill. Over the course of training, the task requirements are adjusted to ensure the animal performs as many laps as possible during experiment sessions lasting ~60 minutes.

sl-run-train [OPTIONS]

Options

-u, --user <user>

Required The ID of the user supervising the training session.

-p, --project <project>

Required The name of the project to which the trained animal belongs.

-a, --animal <animal>

Required The name of the animal undergoing the run training session.

-w, --animal_weight <animal_weight>

Required The weight of the animal, in grams, at the beginning of the training session.

-is, --initial_speed <initial_speed>

The initial speed, in centimeters per second, the animal must maintain to obtain water rewards.

Default:

0.4

-id, --initial_duration <initial_duration>

The initial duration, in seconds, the animal must maintain above-threshold running speed to obtain water rewards.

Default:

0.4

-it, --increase_threshold <increase_threshold>

The volume of water delivered to the animal, in milliliters, after which the speed and duration thresholds are increased by the specified step-sizes. This is used to make the training progressively harder for the animal over the course of the training session.

Default:

0.1

-ss, --speed_step <speed_step>

The amount, in centimeters per second, to increase the speed threshold each time the animal receives the volume of water specified by the ‘increase-threshold’ parameter.

Default:

0.05

-ds, --duration_step <duration_step>

The amount, in seconds, to increase the duration threshold each time the animal receives the volume of water specified by the ‘increase-threshold’ parameter.

Default:

0.05

-v, --maximum_volume <maximum_volume>

The maximum volume of water, in milliliters, that can be delivered during training.

Default:

1.0

-t, --maximum_time <maximum_time>

The maximum time to run the training, in minutes.

Default:

20

-ur, --unconsumed_rewards <unconsumed_rewards>

The maximum number of rewards that can be delivered without the animal consuming them, before reward delivery is paused. Set to 0 to disable enforcing reward consumption.

Default:

1

-mit, --maximum_idle_time <maximum_idle_time>

The maximum time, in seconds, the animal is allowed to maintain speed that is below the speed threshold, tostill be rewarded. Set to 0 to disable allowing the animal to temporarily dip below running speed threshold.

Default:

0.3

-r, --restore_parameters

Determines whether to load and use the same training parameters as used during the previous lick training session of the target animal.

Default:

False

sl-experiment

Runs the requested experiment session for the specified animal and project combination.

Experiment runtimes are carried out after the lick and run training sessions Unlike training session commands, this command can be used to run different experiments. Each experiment runtime is configured via the user-defined configuration .yaml file, which should be stored inside the ‘configuration’ folder of the target project. The experiments are discovered by name, allowing a single project to have multiple different experiments. To create a new experiment configuration, use the ‘sl-create-experiment’ CLI command.

sl-experiment [OPTIONS]

Options

-u, --user <user>

Required The ID of the user supervising the experiment session.

-p, --project <project>

Required The name of the project to which the trained animal belongs.

-e, --experiment <experiment>

Required The name of the experiment to carry out during runtime.

-a, --animal <animal>

Required The name of the animal undergoing the experiment session.

-w, --animal_weight <animal_weight>

Required The weight of the animal, in grams, at the beginning of the experiment session.

sl-check-window

Runs the cranial window and surgery quality checking session for the specified animal and project combination.

Before the animals are fully inducted (included) into a project, the quality of the surgical intervention (craniotomy and window implantation) is checked to ensure the animal will produce high-quality scientific data. As part of this process, various parameters of the Mesoscope-VR data acquisition system are also calibrated to best suit the animal. This command aggregates all steps necessary to verify and record the quality of the animal’s window and to generate customized Mesoscope-VR parameters for the animal.

sl-check-window [OPTIONS]

Options

-p, --project <project>

Required The name of the project to which the trained animal belongs.

-a, --animal <animal>

Required The name of the animal undergoing the experiment session.

sl-preprocess

Preprocesses the target session’s data.

This command aggregates all session data on the VRPC, compresses the data to optimize it for network transmission and storage, and transfers the data to the NAS and the BioHPC cluster. It automatically skips already completed processing stages as necessary to optimize runtime performance.

Primarily, this command is intended to retry or resume failed or interrupted preprocessing runtimes. Preprocessing should be carried out immediately after data acquisition to optimize the acquired data for long-term storage and distribute it to the NAS and the BioHPC cluster for further processing and storage.

sl-preprocess [OPTIONS]

Options

-sp, --session-path <session_path>

Required The path to the session directory to preprocess.

sl-purge

Removes all redundant data directories for ALL projects from the ScanImagePC and the VRPC.

Redundant data purging is now executed automatically as part of data preprocessing. This command is primarily maintained as a fall-back option if automated data purging fails for any reason. Data purging should be carried out at least weekly to remove no longer necessary data from the PCs used during data acquisition.

sl-purge [OPTIONS]

Mesoscope-VR Acquisition System

This package stores the data acquisition and preprocessing assets used by the Mesoscope_VR data acquisition system. It exposes the APIs that allow interfacing with the Mesoscope-VR system to acquire new experiment data, train animals, and preprocess already acquired data.

class sl_experiment.mesoscope_vr.CRCCalculator

Bases: object

A CRC32-XFER checksum calculator that works with raw bytes or pythonic strings.

This utility class exposes methods that generate CRC checksum labels and bytes objects, which are primarily used by Zaber binding classes to verify that Zaber devices have been configured to work with the binding interface exposed by this library.

_calculator

Stores the configured Calculator class object used to calculate the checksums.

bytes_checksum(data)

Calculates the CRC32-XFER checksum for the input bytes.

While the class is primarily designed for generating CRC-checksums for strings, this method can be used to checksum any bytes-converted object.

Parameters:

data (bytes) – The bytes-converted data to calculate the CRC checksum for.

Return type:

int

Returns:

The integer CRC32-XFER checksum.

string_checksum(string)

Calculates the CRC32-XFER checksum for the input string.

The input strings are first converted to bytes using ASCII protocol. The checksum is then calculated on the resultant bytes-object.

Parameters:

string (str) – The string for which to calculate the CRC checksum.

Return type:

int

Returns:

The integer CRC32-XFER checksum.

sl_experiment.mesoscope_vr.discover_zaber_devices(silence_errors=True)

Scans all available serial ports and displays information about connected Zaber devices.

Parameters:

silence_errors (bool, default: True) – Determines whether to display encountered errors. By default, when the discovery process runs into an error, it labels the error port as having no devices and suppresses the error. Enabling this flag will also print encountered error messages, which may be desirable for debugging purposes.

Return type:

None

sl_experiment.mesoscope_vr.experiment_logic(experimenter, project_name, experiment_name, animal_id, animal_weight)

Encapsulates the logic used to run experiments via the Mesoscope-VR system.

This function can be used to execute any valid experiment using the Mesoscope-VR system. Each experiment should be broken into one or more experiment states (phases), such as ‘baseline’, ‘task’ and ‘cooldown’. Furthermore, each experiment state can use one or more VR system states. Currently, the VR system has two states: rest (1) and run (2). The states are used to broadly configure the Mesoscope-VR system, and they determine which systems are active and what data is collected (see library ReadMe for more details on VR states).

Primarily, this function is concerned with iterating over the states stored inside the experiment_state_sequence tuple. Each experiment and VR state combination is maintained for the requested duration of seconds. Once all states have been executed, the experiment runtime ends. Under this design pattern, each experiment is conceptualized as a sequence of states.

Notes

During experiment runtimes, the task logic and the Virtual Reality world are resolved via the Unity game engine. This function itself does not resolve the task logic, it is only concerned with iterating over experiment states, controlling the VR system, and monitoring user command issued via keyboard.

Similar to all other runtime functions, this function contains all necessary bindings to set up, execute, and terminate an experiment runtime. Custom projects should implement a cli that calls this function with project-specific parameters.

Parameters:
  • experimenter (str) – The id of the experimenter conducting the experiment.

  • project_name (str) – The name of the project for which the experiment is conducted.

  • experiment_name (str) – The name or ID of the experiment to be conducted.

  • animal_id (str) – The numeric ID of the animal participating in the experiment.

  • animal_weight (float) – The weight of the animal, in grams, at the beginning of the experiment session.

Return type:

None

sl_experiment.mesoscope_vr.lick_training_logic(experimenter, project_name, animal_id, animal_weight, minimum_reward_delay=6, maximum_reward_delay=18, maximum_water_volume=1.0, maximum_training_time=20, maximum_unconsumed_rewards=1, load_previous_parameters=False)

Encapsulates the logic used to train animals to operate the lick port.

The lick training consists of delivering randomly spaced 5 uL water rewards via the solenoid valve to teach the animal that water comes out of the lick port. Each reward is delivered after a pseudorandom delay. Reward delay sequence is generated before training runtime by sampling a uniform distribution that ranges from ‘minimum_reward_delay’ to ‘maximum_reward_delay’. The training continues either until the valve delivers the ‘maximum_water_volume’ in milliliters or until the ‘maximum_training_time’ in minutes is reached, whichever comes first.

Parameters:
  • experimenter (str) – The ID (net-ID) of the experimenter conducting the training.

  • project_name (str) – The name of the project to which the trained animal belongs.

  • animal_id (str) – The numeric ID of the animal being trained.

  • animal_weight (float) – The weight of the animal, in grams, at the beginning of the training session.

  • minimum_reward_delay (int, default: 6) – The minimum time, in seconds, that has to pass between delivering two consecutive rewards.

  • maximum_reward_delay (int, default: 18) – The maximum time, in seconds, that can pass between delivering two consecutive rewards.

  • maximum_water_volume (float, default: 1.0) – The maximum volume of water, in milliliters, that can be delivered during this runtime.

  • maximum_training_time (int, default: 20) – The maximum time, in minutes, to run the training.

  • maximum_unconsumed_rewards (int, default: 1) – The maximum number of rewards that can be delivered without the animal consuming them, before reward delivery (but not the training!) pauses until the animal consumes available rewards. If this is set to a value below 1, the unconsumed reward limit will not be enforced. A value of 1 means the animal has to consume each reward before getting the next reward.

  • load_previous_parameters (bool, default: False) – Determines whether to override all input runtime-defining parameters with the parameters used during the previous session. If this is set to True, the function will ignore most input parameters and will instead load them from the cached session descriptor of the previous session. If the descriptor is not available, the function will fall back to using input parameters.

Return type:

None

sl_experiment.mesoscope_vr.maintenance_logic()

Encapsulates the logic used to maintain various components of the Mesoscope-VR system.

This runtime is primarily used to verify and, if necessary, recalibrate the water valve between training or experiment days and to maintain the surface material of the running wheel.

Return type:

None

sl_experiment.mesoscope_vr.preprocess_session_data(session_data)

Aggregates all data on VRPC, compresses it for efficient network transmission, safely transfers the data to the BioHPC server and the Synology NAS for long-term storage, and removes all local data copies.

This method should be called at the end of each training and experiment runtime to preprocess the data. Primarily, it prepares the data for further processing, moves it to appropriate long-term storage destinations, and keeps the VRPC and ScanImagePC filesystem free from clutter by removing redundant local data copies.

Parameters:

session_data (SessionData) – The SessionData instance for the processed session.

Return type:

None

sl_experiment.mesoscope_vr.purge_redundant_data()

Loops over ScanImagePC and VRPC directories that store training and experiment data and removes no longer necessary data caches.

This function searches the ScanImagePC and VRPC for no longer necessary directories and removes them from the respective systems. ScanImagePC directories are marked for deletion once they are safely copied to the VRPC. VRPC directories are marked for deletion once the data is safely copied to the BioHPC server. Both copying steps include verifying the integrity of the transferred data using xxHash-128 checksums.

Return type:

None

Notes

This is a service function intended to maintain the ScanImagePC and VRPC disk space. Once the data is moved to the BioHPC server and the NAS, it is generally safe to remove the copies stored on the ScanImagePC and VRPC.

Currently, this function does not discriminate between projects or animals. It will remove all data marked for deletion via the ubiquitin.bin markers.

sl_experiment.mesoscope_vr.run_training_logic(experimenter, project_name, animal_id, animal_weight, initial_speed_threshold=0.4, initial_duration_threshold=0.4, speed_increase_step=0.05, duration_increase_step=0.01, increase_threshold=0.1, maximum_water_volume=1.0, maximum_training_time=20, maximum_idle_time=0.5, maximum_unconsumed_rewards=1, load_previous_parameters=False)

Encapsulates the logic used to train animals to run on the wheel treadmill while being head-fixed.

The run training consists of making the animal run on the wheel with a desired speed, in centimeters per second, maintained for the desired duration of time, in seconds. Each time the animal satisfies the speed and duration thresholds, it receives 5 uL of water reward, and the speed and durations trackers reset for the next training ‘epoch’. Each time the animal receives ‘increase_threshold’ of water, the speed and duration thresholds increase to make the task progressively more challenging. The training continues either until the training time exceeds the ‘maximum_training_time’, or the animal receives the ‘maximum_water_volume’ of water, whichever happens earlier.

Notes

During runtime, it is possible to manually increase or decrease both thresholds via ‘ESC’ and arrow keys. The speed and duration thresholds are limited to a minimum of 0.1 cm/s and 0.05 s and a maximum of 20 cm/s and 20 s.

Parameters:
  • experimenter (str) – The id of the experimenter conducting the training.

  • project_name (str) – The name of the project to which the trained animal belongs.

  • animal_id (str) – The numeric ID of the animal being trained.

  • animal_weight (float) – The weight of the animal, in grams, at the beginning of the training session.

  • initial_speed_threshold (float, default: 0.4) – The initial running speed threshold, in centimeters per second, that the animal must maintain to receive water rewards.

  • initial_duration_threshold (float, default: 0.4) – The initial duration threshold, in seconds, that the animal must maintain above-threshold running speed to receive water rewards.

  • speed_increase_step (float, default: 0.05) – The step size, in centimeters per second, by which to increase the speed threshold each time the animal receives ‘increase_threshold’ milliliters of water.

  • duration_increase_step (float, default: 0.01) – The step size, in seconds, by which to increase the duration threshold each time the animal receives ‘increase_threshold’ milliliters of water.

  • increase_threshold (float, default: 0.1) – The volume of water received by the animal, in milliliters, after which the speed and duration thresholds are increased by one step. Note, the animal will at most get ‘maximum_water_volume’ of water, so this parameter effectively controls how many increases will be made during runtime, assuming the maximum training time is not reached.

  • maximum_water_volume (float, default: 1.0) – The maximum volume of water, in milliliters, that can be delivered during this runtime.

  • maximum_training_time (int, default: 20) – The maximum time, in minutes, to run the training.

  • maximum_idle_time (float, default: 0.5) – The maximum time, in seconds, the animal’s speed can be below the speed threshold to still receive water rewards. This parameter is designed to help animals with a distinct ‘step’ pattern to not lose water rewards due to taking many large steps, rather than continuously running at a stable speed. This parameter allows the speed to dip below the threshold for at most this number of seconds, for the ‘running epoch’ to not be interrupted.

  • maximum_unconsumed_rewards (int, default: 1) – The maximum number of rewards that can be delivered without the animal consuming them, before reward delivery (but not the training!) pauses until the animal consumes available rewards. If this is set to a value below 1, the unconsumed reward limit will not be enforced. A value of 1 means the animal has to consume all rewards before getting the next reward.

  • load_previous_parameters (bool, default: False) – Determines whether to override all input runtime-defining parameters with the parameters used during the previous session. If this is set to True, the function will ignore most input parameters and will instead load them from the cached session descriptor of the previous session. If the descriptor is not available, the function will fall back to using input parameters.

Return type:

None

sl_experiment.mesoscope_vr.window_checking_logic(project_name, animal_id)

Encapsulates the logic used to verify the surgery quality (cranial window) and generate the initial snapshot of the Mesoscope-VR system configuration for a newly added animal of the target project.

This function is used when new animals are added to the project, before any other training or experiment runtime. Primarily, it is used to verify that the surgery went as expected and the animal is fit for providing high-quality scientific data. As part of this process, the function also generates the snapshot of zaber motor positions and the mesoscope objective position to be reused by future sessions.

Notes

This function largely behaves similar to all other training and experiment session runtimes. However, it does not use most of the Mesoscope-VR components and does not make most of the runtime data files typically generated by other sessions. All window checking sessions are automatically marked as ‘incomplete’ and excluded from automated data processing.

Parameters:
  • project_name (str) – The name of the project to which the checked animal belongs.

  • animal_id (str) – The numeric ID of the animal whose cranial window is being checked.

Return type:

None

Shared Acquisition Tools And Assets

This package stores data acquisition and preprocessing assets shared by multiple data acquisition systems.

class sl_experiment.shared_components.BreakInterface(minimum_break_strength=43.2047, maximum_break_strength=1152.1246, object_diameter=15.0333, debug=False)

Bases: ModuleInterface

Interfaces with BreakModule instances running on Ataraxis MicroControllers.

BreakModule allows interfacing with a break to dynamically control the motion of break-coupled objects. The module is designed to send PWM signals that trigger Field-Effect-Transistor (FET) gated relay hardware to deliver voltage that variably engages the break. The module can be used to either fully engage or disengage the breaks or to output a PWM signal to engage the break with the desired strength.

Notes

The break will notify the PC about its initial state (Engaged or Disengaged) after setup.

This class is explicitly designed to work with an 8-bit Pulse Width Modulation (PWM) resolution. Specifically, it assumes that there are a total of 255 intervals covered by the whole PWM range when it calculates conversion factors to go from PWM levels to torque and force.

Parameters:
  • minimum_break_strength (float, default: 43.2047) – The minimum torque applied by the break in gram centimeter. This is the torque the break delivers at minimum voltage (break is disabled).

  • maximum_break_strength (float, default: 1152.1246) – The maximum torque applied by the break in gram centimeter. This is the torque the break delivers at maximum voltage (break is fully engaged).

  • object_diameter (float, default: 15.0333) – The diameter of the rotating object connected to the break, in centimeters. This is used to calculate the force at the end of the object associated with each torque level of the break.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_newton_per_gram_centimeter

Conversion factor from torque force in g cm to torque force in N cm.

_minimum_break_strength

The minimum torque the break delivers at minimum voltage (break is disabled) in N cm.

_maximum_break_strength

The maximum torque the break delivers at maximum voltage (break is fully engaged) in N cm.

_torque_per_pwm

Conversion factor from break pwm levels to breaking torque in N cm.

_force_per_pwm

Conversion factor from break pwm levels to breaking force in N at the edge of the object.

_debug

Stores the debug flag.

property force_per_pwm: float64

Returns the conversion factor to translate break pwm levels into breaking force in Newtons.

get_pwm_from_torque(target_torque_n_cm)

Converts the desired breaking torque in Newtons centimeter to the required PWM value (0-255) to be delivered to the break hardware by the BreakModule.

Use this method to convert the desired breaking torque into the PWM value that can be submitted to the BreakModule via the set_parameters() class method.

Parameters:

target_torque_n_cm (float) – Desired torque in Newtons centimeter at the edge of the object.

Return type:

uint8

Returns:

The byte PWM value that would generate the desired amount of torque.

Raises:

ValueError – If the input force is not within the valid range for the BreakModule.

initialize_remote_assets()

Not used.

Return type:

None

property maximum_break_strength: float64

Returns the maximum torque of the break in Newton centimeters.

property minimum_break_strength: float64

Returns the minimum torque of the break in Newton centimeters.

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

During debug runtime, dumps the data received from the module into the terminal.

Currently, this method only works with codes 52 (Engaged) and 53 (Disengaged).

Return type:

None

Notes

The method is not used during non-debug runtimes. If the interface runs in debug mode, make sure the console is enabled, as it is used to print received data into the terminal.

set_breaking_power()

Triggers the BreakModule to engage with the strength (torque) defined by the breaking_strength runtime parameter.

Unlike the toggle() method, this method allows precisely controlling the torque applied by the break. This is achieved by pulsing the break control pin at the PWM level specified by breaking_strength runtime parameter stored in BreakModule’s memory (on the microcontroller).

Return type:

None

Notes

This command switches the break to run in the variable strength mode and applies the current value of the breaking_strength parameter to the break, but it does not determine the breaking power. To adjust the power, use the set_parameters() class method to issue an updated breaking_strength value. By default, the break power is set to 50% (PWM value 128).

set_parameters(breaking_strength=np.uint8(255))

Changes the PC-addressable runtime parameters of the BreakModule instance.

Use this method to package and apply new PC-addressable parameters to the BreakModule instance managed by this Interface class.

Notes

Use set_breaking_power() command to apply the breaking-strength transmitted in this parameter message to the break. Until the command is called, the new breaking_strength will not be applied to the break hardware.

Parameters:

breaking_strength (uint8, default: np.uint8(255)) – The Pulse-Width-Modulation (PWM) value to use when the BreakModule delivers adjustable breaking power. Depending on this value, the breaking power can be adjusted from none (0) to maximum (255). Use get_pwm_from_force() to translate the desired breaking torque into the required PWM value.

Return type:

None

terminate_remote_assets()

Not used.

Return type:

None

toggle(state)

Triggers the BreakModule to be permanently engaged at maximum strength or permanently disengaged.

This command locks the BreakModule managed by this Interface into the desired state.

Notes

This command does NOT use the breaking_strength parameter and always uses either maximum or minimum breaking power. To set the break to a specific torque level, set the level via the set_parameters() method and then switch the break into the variable torque mode by using the set_breaking_power() method.

Parameters:

state (bool) – The desired state of the break. True means the break is engaged; False means the break is disengaged.

Return type:

None

property torque_per_pwm: float64

Returns the conversion factor to translate break pwm levels into breaking torque in Newton centimeters.

class sl_experiment.shared_components.EncoderInterface(encoder_ppr=8192, object_diameter=15.0333, cm_per_unity_unit=10.0, debug=False)

Bases: ModuleInterface

Interfaces with EncoderModule instances running on Ataraxis MicroControllers.

EncoderModule allows interfacing with quadrature encoders used to monitor the direction and magnitude of a connected object’s rotation. To achieve the highest resolution, the module relies on hardware interrupt pins to detect and handle the pulses sent by the two encoder channels.

Notes

This interface sends CW and CCW motion data to Unity via ‘LinearTreadmill/Data’ MQTT topic.

The default initial encoder readout is zero (no CW or CCW motion). The class instance is zeroed at communication initialization.

Parameters:
  • encoder_ppr (int, default: 8192) – The resolution of the managed quadrature encoder, in Pulses Per Revolution (PPR). This is the number of quadrature pulses the encoder emits per full 360-degree rotation. If this number is not known, provide a placeholder value and use the get_ppr () command to estimate the PPR using the index channel of the encoder.

  • object_diameter (float, default: 15.0333) – The diameter of the rotating object connected to the encoder, in centimeters. This is used to convert encoder pulses into rotated distance in cm.

  • cm_per_unity_unit (float, default: 10.0) – The length of each Unity ‘unit’ in centimeters. This is used to translate raw encoder pulses into Unity ‘units’ before sending the data to Unity.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_motion_topic

Stores the MQTT motion topic.

_ppr

Stores the resolution of the managed quadrature encoder.

_object_diameter

Stores the diameter of the object connected to the encoder.

_cm_per_pulse

Stores the conversion factor that translates encoder pulses into centimeters.

_unity_unit_per_pulse

Stores the conversion factor to translate encoder pulses into Unity units.

_communication

Stores the communication class used to send data to Unity over MQTT.

_debug

Stores the debug flag.

_distance_tracker

Stores the SharedMemoryArray that stores the absolute distance traveled by the animal since class initialization, in centimeters. Note, the distance does NOT account for the direction of travel. It is a monotonically incrementing count of traversed centimeters.

check_state(repetition_delay=np.uint32(200))

Returns the number of pulses accumulated by the EncoderModule since the last check or reset.

If there has been a significant change in the absolute count of pulses, reports the change and direction to the PC. It is highly advised to issue this command to repeat (recur) at a desired interval to continuously monitor the encoder state, rather than repeatedly calling it as a one-off command for best runtime efficiency.

This command allows continuously monitoring the rotation of the object connected to the encoder. It is designed to return the absolute raw count of pulses emitted by the encoder in response to the object ration. This allows avoiding floating-point arithmetic on the microcontroller and relies on the PC to convert pulses to standard units, such as centimeters. The specific conversion algorithm depends on the encoder and motion diameter.

Parameters:

repetition_delay (uint32, default: np.uint32(200)) – The time, in microseconds, to delay before repeating the command. If set to 0, the command will only run once.

Return type:

None

property cm_per_pulse: float64

Returns the conversion factor to translate raw encoder pulse count to distance moved in centimeters.

property distance_tracker: SharedMemoryArray

Returns the SharedMemoryArray that stores the total distance, in centimeters, traveled by the animal since runtime onset.

The distance is stored under index 0 of the tracker and uses the float64 datatype. Note, the distance does NOT account for the direction of travel. It is a monotonically incrementing count of traversed centimeters.

get_ppr()

Uses the index channel of the EncoderModule to estimate its Pulse-per-Revolution (PPR).

The PPR allows converting raw pulse counts the EncoderModule sends to the PC to accurate displacement in standard distance units, such as centimeters. This is a service command not intended to be used during most runtimes if the PPR is already known. It relies on the object tracked by the encoder completing up to 11 full revolutions and uses the index channel of the encoder to measure the number of pulses per each revolution.

Return type:

None

Notes

Make sure the evaluated encoder rotates at a slow and stead speed until this command completes. Similar to other service commands, it is designed to deadlock the controller until the command completes. Note, the EncoderModule does not provide the rotation, this needs to be done manually.

The direction of the rotation is not relevant for this command, as long as the object makes the full 360-degree revolution.

The command is optimized for the object to be rotated with a human hand at a steady rate, so it delays further index pin polling for 100 milliseconds each time the index pin is triggered. Therefore, if the object is moving too fast (or too slow), the command will not work as intended.

initialize_remote_assets()

Initializes the MQTTCommunication class and connects to the MQTT broker.

Also connects to the speed_tracker SharedMemoryArray and initializes the PrecisionTimer used in running speed calculation.

Return type:

None

property mqtt_topic: str

Returns the MQTT topic used to transfer motion data from the interface to Unity.

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

Processes incoming data in real time.

Motion data (codes 51 and 52) is converted into CW / CCW vectors, translated from pulses to Unity units, and is sent to Unity via MQTT. Encoder PPR data (code 53) is printed via console.

Also, keeps track of the total distance traveled by the animal since class initialization, relative to the initial position at runtime onset and updates the distance_tracker SharedMemoryArray.

Return type:

None

Notes

If debug mode is enabled, motion data is also converted to centimeters and printed via console.

reset_pulse_count()

Resets the EncoderModule pulse tracker to 0.

This command allows resetting the encoder without evaluating its current pulse count. Currently, this command is designed to only run once.

Return type:

None

set_parameters(report_ccw=np.True_, report_cw=np.True_, delta_threshold=np.uint32(10))

Changes the PC-addressable runtime parameters of the EncoderModule instance.

Use this method to package and apply new PC-addressable parameters to the EncoderModule instance managed by this Interface class.

Parameters:
  • report_ccw (bool | bool, default: np.True_) – Determines whether to report rotation in the CCW (positive) direction.

  • report_cw (bool | bool, default: np.True_) – Determines whether to report rotation in the CW (negative) direction.

  • delta_threshold (uint32 | int, default: np.uint32(10)) – The minimum number of pulses required for the motion to be reported. Depending on encoder resolution, this allows setting the ‘minimum rotation distance’ threshold for reporting. Note, if the change is 0 (the encoder readout did not change), it will not be reported, regardless of the value of this parameter. Sub-threshold motion will be aggregated (summed) across readouts until a significant overall change in position is reached to justify reporting it to the PC.

Return type:

None

terminate_remote_assets()

Destroys the MQTTCommunication class and disconnects from the speed_tracker SharedMemoryArray.

Return type:

None

class sl_experiment.shared_components.LickInterface(lick_threshold=1000, debug=False)

Bases: ModuleInterface

Interfaces with LickModule instances running on Ataraxis MicroControllers.

LickModule allows interfacing with conductive lick sensors used in the Sun Lab to detect mouse interaction with water dispensing tubes. The sensor works by sending a small direct current through the mouse, which is picked up by the sensor connected to the metal lick tube. When the mouse completes the circuit by making the contact with the tube, the sensor determines whether the resultant voltage matches the threshold expected for a tongue contact and, if so, notifies the PC about the contact.

Notes

The sensor is calibrated to work with very small currents that are not detectable by the animal, so it does not interfere with behavior during experiments. The sensor will, however, interfere with electrophysiological recordings.

The resolution of the sensor is high enough to distinguish licks from paw touches. By default, the microcontroller is configured in a way that will likely send both licks and non-lick interactions to the PC. Use the lick_threshold argument to provide a more exclusive lick threshold.

The interface automatically sends significant lick triggers to Unity via the “LickPort/” MQTT topic. This only includes the ‘onset’ triggers, the interface does not report voltage level reductions (associated with the end of the tongue-to-tube contact).

Parameters:
  • lick_threshold (int, default: 1000) – The threshold voltage, in raw analog units recorded by a 12-bit ADC, for detecting the tongue contact. Note, 12-bit ADC only supports values between 0 and 4095, so setting the threshold above 4095 will result in no licks being reported to Unity.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_sensor_topic

Stores the output MQTT topic.

_lick_threshold

The threshold voltage for detecting a tongue contact.

_volt_per_adc_unit

The conversion factor to translate the raw analog values recorded by the 12-bit ADC into voltage in Volts.

_communication

Stores the communication class used to send data to Unity over MQTT.

_debug

Stores the debug flag.

_lick_tracker

Stores the SharedMemoryArray that stores the current lick detection status and the total number of licks detected since class initialization.

_previous_readout_zero

Stores a boolean indicator of whether the previous voltage readout was a 0-value.

check_state(repetition_delay=np.uint32(0))

Returns the voltage signal detected by the analog pin monitored by the LickModule.

If there has been a significant change in the detected voltage level and the level is within the reporting thresholds, reports the change to the PC. It is highly advised to issue this command to repeat (recur) at a desired interval to continuously monitor the lick sensor state, rather than repeatedly calling it as a one-off command for best runtime efficiency.

This command allows continuously monitoring the mouse interaction with the lickport tube. It is designed to return the raw analog units, measured by a 3.3V ADC with 12-bit resolution. To avoid floating-point math, the value is returned as an unsigned 16-bit integer.

Parameters:
  • repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the

  • once. (command will only run)

Return type:

None

get_adc_units_from_volts(voltage)

Converts the input voltage to raw analog units of 12-bit Analog-to-Digital-Converter (ADC).

Use this method to determine the appropriate raw analog units for the threshold arguments of the set_parameters() method, based on the desired voltage thresholds.

Notes

This method assumes a 3.3V ADC with 12-bit resolution.

Parameters:

voltage (float) – The voltage to convert to raw analog units, in Volts.

Return type:

uint16

Returns:

The raw analog units of 12-bit ADC for the input voltage.

initialize_remote_assets()

Initializes the MQTTCommunication class, connects to the MQTT broker, and connects to the SharedMemoryArray used to communicate lick status to other processes.

Return type:

None

property lick_threshold: uint16

Returns the voltage threshold, in raw ADC units of a 12-bit Analog-to-Digital voltage converter that is interpreted as the mouse licking the sensor.

property lick_tracker: SharedMemoryArray

Returns the SharedMemoryArray that stores the total number of licks detected by the module since class initialization.

The count is stored under index 0 of the array as an uint64 value.

property mqtt_topic: str

Returns the MQTT topic used to transfer lick events from the interface to Unity.

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

Processes incoming data.

Lick data (code 51) comes in as a change in the voltage level detected by the sensor pin. This value is then evaluated against the _lick_threshold and if the value exceeds the threshold, a binary lick trigger is sent to Unity via MQTT. Additionally, the method increments the total lick count stored in the _lick_tracker each time an above-threshold voltage readout is received from the module.

Return type:

None

Notes

If the class runs in debug mode, this method sends all received lick sensor voltages to the terminal via console. Make sure the console is enabled before calling this method.

set_parameters(signal_threshold=np.uint16(200), delta_threshold=np.uint16(180), averaging_pool_size=np.uint8(30))

Changes the PC-addressable runtime parameters of the LickModule instance.

Use this method to package and apply new PC-addressable parameters to the LickModule instance managed by this Interface class.

Notes

All threshold parameters are inclusive! If you need help determining appropriate threshold levels for specific targeted voltages, use the get_adc_units_from_volts() method of the interface instance.

Parameters:
  • signal_threshold (uint16, default: np.uint16(200)) – The minimum voltage level, in raw analog units of 12-bit Analog-to-Digital-Converter (ADC), that needs to be reported to the PC. Setting this threshold to a number above zero allows high-pass filtering the incoming signals. Note, Signals below the threshold will be pulled to 0.

  • delta_threshold (uint16, default: np.uint16(180)) – The minimum value by which the signal has to change, relative to the previous check, for the change to be reported to the PC. Note, if the change is 0, the signal will not be reported to the PC, regardless of this parameter value.

  • averaging_pool_size (uint8, default: np.uint8(30)) – The number of analog pin readouts to average together when checking pin state. This is used to smooth the recorded values to avoid communication line noise. Teensy microcontrollers have built-in analog pin averaging, but we disable it by default and use this averaging method instead. It is recommended to set this value between 15 and 30 readouts.

Return type:

None

terminate_remote_assets()

Destroys the MQTTCommunication class and disconnects from the lick-tracker SharedMemoryArray.

Return type:

None

property volts_per_adc_unit: float64

Returns the conversion factor to translate the raw analog values recorded by the 12-bit ADC into voltage in Volts.

class sl_experiment.shared_components.ScreenInterface(initially_on, debug=False)

Bases: ModuleInterface

Interfaces with ScreenModule instances running on Ataraxis MicroControllers.

ScreenModule is specifically designed to interface with the HDMI converter boards used in Sun lab’s Virtual Reality setup. The ScreenModule communicates with the boards to toggle the screen displays on and off, without interfering with their setup on the host PC.

Notes

Since the current VR setup uses three screens, this implementation of ScreenModule is designed to interface with all three screens at the same time. In the future, the module may be refactored to allow addressing individual screens.

The physical wiring of the module also allows manual screen manipulation via the buttons on the control panel if the ScreenModule is not actively delivering a toggle pulse. However, changing the state of the screen manually is strongly discouraged, as it interferes with tracking the state of the screen via software.

Parameters:
  • initially_on (bool) – A boolean flag that communicates the initial state of the screen. This is used during log parsing to deduce the state of the screen after each toggle pulse and assumes the screens are only manipulated via this interface.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_initially_on

Stores the initial state of the screens.

_debug

Stores the debug flag.

initialize_remote_assets()

Not used.

Return type:

None

property initially_on: bool

Returns True if the screens were initially ON when the module interface was initialized, False otherwise.

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

If the class runs in the debug mode, dumps the received data into the terminal via console class.

This method is only used in the debug mode to print Screen toggle signal HIGH (On) and LOW (Off) phases.

Return type:

None

Notes

This method uses the console to print the data to the terminal. Make sure it is enabled before calling this method.

set_parameters(pulse_duration=np.uint32(1000000))

Changes the PC-addressable runtime parameters of the ScreenModule instance.

Use this method to package and apply new PC-addressable parameters to the ScreenModule instance managed by this Interface class.

Parameters:

pulse_duration (uint32, default: np.uint32(1000000)) – The duration, in microseconds, of each emitted screen toggle pulse HIGH phase. This is equivalent to the duration of the control panel POWER button press. The main criterion for this parameter is to be long enough for the converter board to register the press.

Return type:

None

terminate_remote_assets()

Not used.

Return type:

None

toggle()

Triggers the ScreenModule to briefly simulate pressing the POWER button of the scree control board.

This command is used to turn the connected display on or off. The new state of the display depends on the current state of the display when the command is issued. Since the displays can also be controlled manually (via the physical control board buttons), the state of the display can also be changed outside this interface, although it is highly advised to NOT change screen states manually.

Return type:

None

Notes

It is highly recommended to use this command to manipulate display states, as it ensures that display state changes are logged for further data analysis.

class sl_experiment.shared_components.SurgerySheet(project_name, animal_id, credentials_path, sheet_id)

Bases: object

Encapsulates the access to the target Google Sheet that contains shared lab surgery logs.

This class uses Google Sheets API to connect to and extract the data stored in the surgery log Google Sheet file. It functions as the central access point used to extract surgery data for each animal and project combination and save it as a .yaml file alongside other recorded training or experiment data.

The class is explicitly designed to work with the data of a single animal, which matches the case of how the class is used during data acquisition in the lab. It carries out all necessary checks at instantiation to ensure correct operation of all methods. Make sure the class is instantiated early in the session initialization hierarchy to abort the runtime if necessary.

Notes

This class is purpose-built to work with the specific surgery log format used in the Sun lab. If the target sheet or project tab layout does not conform to expectations, this class will likely not behave as intended.

Since version 2.0.0 this class is also used to write the Surgery Quality column value as the result of running the “window checking” session.

Parameters:
  • project_name (str) – The name of the project whose data should be parsed by the class instance. It is expected that the target sheet stores all Sun Lab projects as individual tabs.

  • animal_id (int) – The numeric ID of the animal whose data should be parsed by the class instance. It is expected that all animals use numeric IDs (either project-specific or unique across all projects) as ‘names’.

  • credentials_path (Path) – The path to the JSON file containing the service account credentials for accessing the Google Sheet.

  • sheet_id (str) – The ID of the Google Sheet containing the surgery data.

_project_name

Stores the target project name.

_animal_id

Stores the target animal ID.

_sheet_id

Stores the ID of the target Google Sheet.

_service

The Google Sheets API service instance used to fetch data from the target Google Sheet.

_headers

A dictionary that uses headers (column names) as keys and Google Sheet column names (A, B, etc.) as values. This dictionary stores all user-defined headers used by the target Google Sheet tab.

_animals

Stores all animal IDs (names) whose data is stored in the target Google Sheet tab.

Raises:

ValueError – If the sheet is not formatted correctly or does not contain expected data.

extract_animal_data()

Extracts the surgery data for the target animal and returns it as a SurgeryData object.

This method is used by all acquisition systems at the beginning of each data acquisition session to extract and cache the surgery intervention data of the processed animal.

Return type:

SurgeryData

Returns:

A fully configured SurgeryData instance that stores the extracted data.

update_surgery_quality(quality)

Updates the surgery quality value for the specified animal.

This method is used to write an integer value to the ‘Surgery Quality’ column for the specified animal. The value represents the quality assessment of the surgical intervention performed on the animal, typically made after the first pre-training imaging session (“window checking” session).

Parameters:

quality (int) – The integer value representing the surgery quality to be written. The value reflects the quality of the animal for scientific data acquisition: 0 means unusable, 1 means usable for testing (but not publications), 2 means publication-grade quality.

Return type:

None

class sl_experiment.shared_components.TTLInterface(module_id, report_pulses=False, debug=False)

Bases: ModuleInterface

Interfaces with TTLModule instances running on Ataraxis MicroControllers.

TTLModule facilitates exchanging Transistor-to-Transistor Logic (TTL) signals between various hardware systems, such as microcontrollers, cameras and recording devices. The module contains methods for both sending and receiving TTL pulses, but each TTLModule instance can only perform one of these functions at a time.

Notes

When the TTLModule is configured to output a signal, it will notify the PC about the initial signal state (HIGH or LOW) after setup.

Parameters:
  • module_id (uint8) – The unique byte-code identifier of the TTLModule instance. Since the mesoscope data acquisition pipeline uses multiple TTL modules on some microcontrollers, each instance running on the same microcontroller must have a unique identifier. The ID codes are not shared between AMC and other module types.

  • report_pulses (bool, default: False) – A boolean flag that determines whether the class should report detecting HIGH signals to other processes. This is intended exclusively for the mesoscope frame acquisition recorder to notify the central process whether the mesoscope start trigger has been successfully received and processed by ScanImage software.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_report_pulses

Stores the report pulses flag.

_debug

Stores the debug flag.

_pulse_tracker

When the class is initialized with the report_pulses flag, stores the SharedMemoryArray used to track how many pulses the class has recorded since initialization.

check_state(repetition_delay=np.uint32(0))

Checks the state of the TTL signal received by the TTLModule.

This command evaluates the state of the TTLModule’s input pin and, if it is different from the previous state, reports it to the PC. This approach ensures that the module only reports signal level shifts (edges), preserving communication bandwidth.

Parameters:

repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the command will only run once.

Return type:

None

initialize_remote_assets()

If the class is instructed to report detected HIGH incoming pulses, connects to the _pulse_tracker SharedMemoryArray.

Return type:

None

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

Processes incoming data when the class operates in debug or pulse reporting mode.

During debug runtimes, this method dumps all received data into the terminal via the console class. During pulse reporting runtimes, the class increments the _pulse_tracker array each time it encounters a HIGH TTL signal edge sent by the mesoscope to timestamp acquiring (scanning) a new frame.

Return type:

None

Notes

If the interface runs in debug mode, make sure the console is enabled, as it is used to print received data into the terminal.

property pulse_count: int

Returns the total number of received TTL pulses recorded by the class since initialization.

send_pulse(repetition_delay=np.uint32(0), noblock=True)

Triggers TTLModule to deliver a one-off or recurrent (repeating) digital TTL pulse.

This command is well-suited to carry out most forms of TTL communication, but it is adapted for comparatively low-frequency communication at 10-200 Hz. This is in contrast to PWM outputs capable of mHz or even Khz pulse oscillation frequencies.

Parameters:
  • repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the command will only run once. The exact repetition delay will be further affected by other modules managed by the same microcontroller and may not be perfectly accurate.

  • noblock (bool, default: True) – Determines whether the command should block the microcontroller while emitting the high phase of the pulse or not. Blocking ensures precise pulse duration, non-blocking allows the microcontroller to perform other operations while waiting, increasing its throughput.

Return type:

None

set_parameters(pulse_duration=np.uint32(10000), averaging_pool_size=np.uint8(0))

Changes the PC-addressable runtime parameters of the TTLModule instance.

Use this method to package and apply new PC-addressable parameters to the TTLModule instance managed by this Interface class.

Parameters:
  • pulse_duration (uint32, default: np.uint32(10000)) – The duration, in microseconds, of each emitted TTL pulse HIGH phase. This determines how long the TTL pin stays ON when emitting a pulse.

  • averaging_pool_size (uint8, default: np.uint8(0)) – The number of digital pin readouts to average together when checking pin state. This is used during the execution of the check_state () command to debounce the pin readout and acts in addition to any built-in debouncing.

Return type:

None

terminate_remote_assets()

If the class is instructed to report detected HIGH incoming pulses, disconnects from the _pulse_tracker SharedMemoryArray.

Return type:

None

toggle(state)

Triggers the TTLModule to continuously deliver a digital HIGH or LOW signal.

This command locks the TTLModule managed by this Interface into delivering the desired logical signal.

Parameters:

state (bool) – The signal to output. Set to True for HIGH and False for LOW.

Return type:

None

class sl_experiment.shared_components.TorqueInterface(baseline_voltage=2046, maximum_voltage=2750, sensor_capacity=720.0779, object_diameter=15.0333, debug=False)

Bases: ModuleInterface

Interfaces with TorqueModule instances running on Ataraxis MicroControllers.

TorqueModule interfaces with a differential torque sensor. The sensor uses differential coding in the millivolt range to communicate torque in the CW and the CCW direction. To convert and amplify the output of the torque sensor, it is wired to an AD620 microvolt amplifier instrument that converts the output signal into a single positive vector and amplifies its strength to Volts range.

The TorqueModule further refines the sensor data by ensuring that CCW and CW torque signals behave identically. Specifically, it adjusts the signal to scale from 0 to baseline proportionally to the detected torque, regardless of torque direction.

Notes

This interface receives torque as a positive uint16_t value from zero to at most 2046 raw analog units of 3.3v 12-bit ADC converter. The direction of the torque is reported by the event-code of the received message.

Parameters:
  • baseline_voltage (int, default: 2046) – The voltage level, in raw analog units measured by 3.3v ADC at 12-bit resolution after the AD620 amplifier, that corresponds to no (0) torque readout. Usually, for a 3.3v ADC, this would be around 2046 (the midpoint, ~1.65 V).

  • maximum_voltage (int, default: 2750) – The voltage level, in raw analog units measured by 3.3v ADC at 12-bit resolution after the AD620 amplifier, that corresponds to the absolute maximum torque detectable by the sensor. The best way to get this value is to measure the positive voltage level after applying the maximum CW (positive) torque. At most, this value can be 4095 (~3.3 V).

  • sensor_capacity (float, default: 720.0779) – The maximum torque detectable by the sensor, in grams centimeter (g cm).

  • object_diameter (float, default: 15.0333) – The diameter of the rotating object connected to the torque sensor, in centimeters. This is used to calculate the force at the edge of the object associated with the measured torque at the sensor.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_newton_per_gram_centimeter

Stores the hardcoded conversion factor from gram centimeter to Newton centimeter.

_capacity_in_newtons_cm

The maximum torque detectable by the sensor in Newtons centimeter.

_torque_per_adc_unit

The conversion factor to translate raw analog 3.3v 12-bit ADC values to torque in Newtons centimeter.

_force_per_adc_unit

The conversion factor to translate raw analog 3.3v 12-bit ADC values to force in Newtons.

_debug

Stores the debug flag.

check_state(repetition_delay=np.uint32(0))

Returns the torque signal detected by the analog pin monitored by the TorqueModule.

If there has been a significant change in the detected signal (voltage) level and the level is within the reporting thresholds, reports the change to the PC. It is highly advised to issue this command to repeat (recur) at a desired interval to continuously monitor the lick sensor state, rather than repeatedly calling it as a one-off command for best runtime efficiency.

This command allows continuously monitoring the CW and CCW torque experienced by the object connected to the torque sensor. It is designed to return the raw analog units, measured by a 3.3V ADC with 12-bit resolution. To avoid floating-point math, the value is returned as an unsigned 16-bit integer.

Notes

Due to how the torque signal is measured and processed, the returned value will always be between 0 and the baseline ADC value. For a 3.3V 12-bit ADC, this is between 0 and ~1.65 Volts.

Parameters:
  • repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the

  • once. (command will only run)

Return type:

None

property force_per_adc_unit: float64

Returns the conversion factor to translate the raw analog values recorded by the 12-bit ADC into force in Newtons.

get_adc_units_from_torque(target_torque)

Converts the input torque to raw analog units of 12-bit Analog-to-Digital-Converter (ADC).

Use this method to determine the appropriate raw analog units for the threshold arguments of the set_parameters() method.

Notes

This method assumes a 3.3V ADC with 12-bit resolution.

Parameters:

target_torque (float) – The target torque in Newton centimeter, to convert to an ADC threshold.

Return type:

uint16

Returns:

The raw analog units of 12-bit ADC for the input torque.

initialize_remote_assets()

Not used.

Return type:

None

parse_mqtt_command(topic, payload)

Not used.

Return type:

None

process_received_data(message)

If the class is initialized in debug mode, prints the received torque data to the terminal via console.

Return type:

None

In debug mode, this method parses incoming code 51 (CW torque) and code 52 (CCW torque) data and dumps it into

the terminal via console. If the class is not initialized in debug mode, this method does nothing.

Notes

Make sure the console is enabled before calling this method.

set_parameters(report_ccw=np.True_, report_cw=np.True_, signal_threshold=np.uint16(100), delta_threshold=np.uint16(70), averaging_pool_size=np.uint8(10))

Changes the PC-addressable runtime parameters of the TorqueModule instance.

Use this method to package and apply new PC-addressable parameters to the TorqueModule instance managed by this Interface class.

Notes

All threshold parameters are inclusive! If you need help determining appropriate threshold levels for specific targeted torque levels, use the get_adc_units_from_torque() method of the interface instance.

Parameters:
  • report_ccw (bool, default: np.True_) – Determines whether the sensor should report torque in the CounterClockwise (CCW) direction.

  • report_cw (bool, default: np.True_) – Determines whether the sensor should report torque in the Clockwise (CW) direction.

  • signal_threshold (uint16, default: np.uint16(100)) – The minimum torque level, in raw analog units of 12-bit Analog-to-Digital-Converter (ADC), that needs to be reported to the PC. Setting this threshold to a number above zero allows high-pass filtering the incoming signals. Note, Signals below the threshold will be pulled to 0.

  • delta_threshold (uint16, default: np.uint16(70)) – The minimum value by which the signal has to change, relative to the previous check, for the change to be reported to the PC. Note, if the change is 0, the signal will not be reported to the PC, regardless of this parameter value.

  • averaging_pool_size (uint8, default: np.uint8(10)) – The number of analog pin readouts to average together when checking pin state. This is used to smooth the recorded values to avoid communication line noise. Teensy microcontrollers have built-in analog pin averaging, but we disable it by default and use this averaging method instead. It is recommended to set this value between 15 and 30 readouts.

Return type:

None

terminate_remote_assets()

Not used.

Return type:

None

property torque_per_adc_unit: float64

Returns the conversion factor to translate the raw analog values recorded by the 12-bit ADC into torque in Newton centimeter.

class sl_experiment.shared_components.ValveInterface(valve_calibration_data, debug=False)

Bases: ModuleInterface

Interfaces with ValveModule instances running on Ataraxis MicroControllers.

ValveModule allows interfacing with a solenoid valve to controllably dispense precise volumes of fluid. The module is designed to send digital signals that trigger Field-Effect-Transistor (FET) gated relay hardware to deliver voltage that opens or closes the controlled valve. The module can be used to either permanently open or close the valve or to cycle opening and closing in a way that ensures a specific amount of fluid passes through the valve.

Notes

This interface comes pre-configured to receive valve pulse triggers from Unity via the “Gimbl/Reward/” topic.

The valve will notify the PC about its initial state (Open or Closed) after setup.

Our valve is statically configured to deliver audible tones when it is pulsed. This is used exclusively by the Pulse command, so the tone will not sound when the valve is activated during Calibration or Open commands. The default pulse duration is 100 ms, and this is primarily used to provide the animal with an auditory cue for the water reward.

Parameters:
  • valve_calibration_data (tuple[tuple[int | float, int | float], ...]) – A tuple of tuples that contains the data required to map pulse duration to delivered fluid volume. Each sub-tuple should contain the integer that specifies the pulse duration in microseconds and a float that specifies the delivered fluid volume in microliters. If you do not know this data, initialize the class using a placeholder calibration tuple and use the calibration() class method to collect this data using the ValveModule.

  • debug (bool, default: False) – A boolean flag that configures the interface to dump certain data received from the microcontroller into the terminal. This is used during debugging and system calibration and should be disabled for most runtimes.

_scale_coefficient

Stores the scale coefficient derived from the calibration data. We use the power law to fit the data, which results in better overall fit than using the linera equation.

_nonlinearity_exponent

The intercept of the valve calibration curve. This is used to account for the fact that some valves may have a minimum open time or dispensed fluid volume, which is captured by the intercept. This improves the precision of fluid-volume-to-valve-open-time conversions.

_calibration_cov

Stores the covariance matrix that describes the quality of fitting the calibration data using the power law. This is used to determine how well the valve performance is approximated by the power law.

_reward_topic

Stores the topic used by Unity to issue reward commands to the module.

_debug

Stores the debug flag.

_valve_tracker

Stores the SharedMemoryArray that tracks how many times the valve was opened and the total volume of water dispensed by the valve during runtime.

_previous_state

Tracks the previous valve state as Open (True) or Closed (False). This is used to accurately track delivered water volumes each time the valve opens and closes.

_cycle_timer

A PrecisionTimer instance initialized in the Communication process to track how long the valve stays open during cycling. This used together with the _previous_state to determine the volume of water delivered by the valve during runtime.

calibrate()

Triggers ValveModule to repeatedly pulse the valve using the duration defined by the pulse_duration runtime parameter.

This command is used to build the calibration map of the valve that matches pulse_duration to the volume of fluid dispensed during the time the valve is open. To do so, the command repeatedly pulses the valve to dispense a large volume of fluid which can be measured and averaged to get the volume of fluid delivered during each pulse. The number of pulses carried out during this command is specified by the calibration_count parameter, and the delay between pulses is specified by the calibration_delay parameter.

Return type:

None

Notes

When activated, this command will block in-place until the calibration cycle is completed. Currently, there is no way to interrupt the command, and it may take a prolonged period of time (minutes) to complete.

This command does not set any of the parameters involved in the calibration process. Make sure the parameters are submitted to the ValveModule’s hardware memory via the set_parameters() class method before running the calibration() command.

property calibration_covariance: ndarray[tuple[int, ...], dtype[float64]]

Returns the 2x2 covariance matrix associated with the power‐law calibration fit.

The covariance matrix contains the estimated variances of the calibration parameters on its diagonal (i.e., variance of the scale coefficient and the nonlinearity exponent) and the covariances between these parameters in its off-diagonal elements.

This information can be used to assess the uncertainty in the calibration.

Returns:

A NumPy array (2x2) representing the covariance matrix.

property delivered_volume: float

Returns the total volume of water, in microliters, delivered by the valve during the current runtime.

get_duration_from_volume(target_volume)

Converts the desired fluid volume in microliters to the valve pulse duration in microseconds that ValveModule will use to deliver that fluid volume.

Use this method to convert the desired fluid volume into the pulse_duration value that can be submitted to the ValveModule via the set_parameters() class method.

Parameters:

target_volume (float) – Desired fluid volume in microliters.

Raises:

ValueError – If the desired fluid volume is too small to be reliably dispensed by the valve, based on its calibration data.

Return type:

uint32

Returns:

The microsecond pulse duration that would be used to deliver the specified volume.

initialize_remote_assets()

Connects to the reward tracker SharedMemoryArray and initializes the cycle PrecisionTimer from the Communication process.

Return type:

None

property mqtt_topic: str

Returns the MQTT topic monitored by the module to receive reward commands from Unity.

property nonlinearity_exponent: float64

Returns the nonlinearity exponent (B) from the power‐law calibration.

In the calibration model, fluid_volume = A * (pulse_duration)^B, this exponent indicates the degree of nonlinearity in how the dispensed volume scales with the valve’s pulse duration. For example, an exponent of 1 would indicate a linear relationship.

parse_mqtt_command(topic, payload)

When called, this method statically sends a reward delivery command to the ValveModule instance.

Notes

The method does NOT evaluate the input message or topic. It is written to always send reward trigger commands when called. If future Sun lab pipelines need this method to evaluate the input message, the logic of the method needs to be rewritten.

Returning the command message is more efficient than using the input_queue interface in this particular case.

Return type:

OneOffModuleCommand

Returns:

The command message to be sent to the microcontroller.

process_received_data(message)

Processes incoming data.

Valve calibration events (code 54) are sent to the terminal via console regardless of the debug flag. If the class was initialized in the debug mode, Valve opening (code 52) and closing (code 53) codes are also sent to the terminal. Also, stores the total number of times the valve was opened under _reward_tracker index 0 and the total volume of water delivered during runtime under _reward_tracker index 1.

Note

Make sure the console is enabled before calling this method.

Return type:

None

property scale_coefficient: float64

Returns the scaling coefficient (A) from the power‐law calibration.

In the calibration model, fluid_volume = A * (pulse_duration)^B, this coefficient converts pulse duration (in microseconds) into the appropriate fluid volume (in microliters) when used together with the nonlinearity exponent.

send_pulse(repetition_delay=np.uint32(0), noblock=False)

Triggers ValveModule to deliver a precise amount of fluid by cycling opening and closing the valve once or repetitively (recurrently).

After calibration, this command allows delivering precise amounts of fluid with, depending on the used valve and relay hardware microliter or nanoliter precision. This command is optimized to change valve states at a comparatively low frequency in the 10-200 Hz range.

Notes

To ensure the accuracy of fluid delivery, it is recommended to run the valve in the blocking mode and, if possible, isolate it to a controller that is not busy with running other tasks.

Parameters:
  • repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the command will only run once. The exact repetition delay will be further affected by other modules managed by the same microcontroller and may not be perfectly accurate.

  • noblock (bool, default: False) – Determines whether the command should block the microcontroller while the valve is kept open or not. Blocking ensures precise pulse duration and dispensed fluid volume. Non-blocking allows the microcontroller to perform other operations while waiting, increasing its throughput.

Return type:

None

set_parameters(pulse_duration=np.uint32(35590), calibration_delay=np.uint32(200000), calibration_count=np.uint16(200), tone_duration=np.uint32(300000))

Changes the PC-addressable runtime parameters of the ValveModule instance.

Use this method to package and apply new PC-addressable parameters to the ValveModule instance managed by this Interface class.

Note

Default parameters are configured to support ‘reference’ calibration run. When calibrate() is called with these default parameters, the Valve should deliver ~5 uL of water, which is the value used during Sun lab experiments. If the reference calibration fails, you have to fully recalibrate the valve!

Parameters:
  • pulse_duration (uint32, default: np.uint32(35590)) – The time, in microseconds, the valve stays open when it is pulsed (opened and closed). This is used during the execution of the send_pulse() command to control the amount of dispensed fluid. Use the get_duration_from_volume() method to convert the desired fluid volume into the pulse_duration value.

  • calibration_delay (uint32, default: np.uint32(200000)) – The time, in microseconds, to wait between consecutive pulses during calibration. Calibration works by repeatedly pulsing the valve the requested number of times. Delaying after closing the valve (ending the pulse) ensures the valve hardware has enough time to respond to the inactivation phase before starting the next calibration cycle.

  • calibration_count (uint16, default: np.uint16(200)) – The number of times to pulse the valve during calibration. A number between 10 and 100 is enough for most use cases.

  • tone_duration (uint32, default: np.uint32(300000)) – The time, in microseconds, to sound the audible tone when the valve is pulsed. This is only used if the hardware ValveModule instance was provided with the TonePin argument at instantiation. If your use case involves emitting tones, make sure this value is higher than the pulse_duration value.

Return type:

None

terminate_remote_assets()

Disconnects from the reward tracker SharedMemoryArray.

Return type:

None

toggle(state)

Triggers the ValveModule to be permanently open or closed.

This command locks the ValveModule managed by this Interface into the desired state.

Parameters:

state (bool) – The desired state of the valve. True means the valve is open; False means the valve is closed.

Return type:

None

tone(repetition_delay=np.uint32(0), noblock=False)

Triggers ValveModule to an audible tone without changing the state of the managed valve.

This command will only work for ValveModules connected to a piezoelectric buzzer and configured to interface with the buzzer’s trigger pin. It allows emitting tones without water rewards, which is primarily used during training runtimes that pause delivering water when the animal is not consuming rewards.

Notes

While enforcing auditory tone durations is not as important as enforcing valve open times, this command runs in blocking mode by default to match the behavior of the tone-emitting valve pulse command.

Parameters:
  • repetition_delay (uint32, default: np.uint32(0)) – The time, in microseconds, to delay before repeating the command. If set to 0, the command will only run once. The exact repetition delay will be further affected by other modules managed by the same microcontroller and may not be perfectly accurate.

  • noblock (bool, default: False) – Determines whether the command should block the microcontroller while the tone is delivered or not. Blocking ensures precise tone duration. Non-blocking allows the microcontroller to perform other operations while waiting, increasing its throughput.

Return type:

None

property valve_tracker: SharedMemoryArray

Returns the SharedMemoryArray that stores the total number of valve pulses and the total volume of water delivered during the current runtime.

The number of valve pulses is stored under index 0, while the total delivered volume is stored under index 1. Both values are stored as a float64 datatype. The total delivered volume is given in microliters.

class sl_experiment.shared_components.WaterSheet(animal_id, session_date, credentials_path, sheet_id)

Bases: object

Encapsulates the access to the target Google Sheet that contains project water-restriction data.

This class uses Google Sheets API to connect to and update the data stored in the water restriction log Google Sheet file. It functions as the central access point used to update the water restriction data for each animal after training and experiment sessions. Primarily, this is used as a convenience feature that allows experimenters to synchronize runtime data with the Google Sheet tracker, instead of entering it manually.

The class is explicitly designed to work with the data of a single data acquisition session and animal, which matches the case of how the class is used during data acquisition in the lab. It carries out all necessary checks at instantiation to ensure correct operation of all methods. Make sure the class is instantiated early in the session initialization hierarchy to abort the runtime if necessary.

Notes

This class is purpose-built to work with the specific water restriction log format used in the Sun lab. If the target sheet layout does not conform to expectations, this class will likely not perform as intended.

In contrast to the surgery log, the water restriction log does not store project-specific information. While the general assumption is that each project uses a unique water restriction log file, the system also supports experimenters that use unique IDs for all mice, across all projects.

Parameters:
  • animal_id (int) – The ID of the animal whose data will be written by this class instance.

  • session_date (str) – The date of the session whose data will be written by this class instance. Date is used as the ‘id’ of each session in the format YYYY-MM-DD-HH-MM-SS-US, so setting this to session name (id) is the expected behavior.

  • credentials_path (Path) – The path to the JSON file containing the service account credentials for accessing the Google Sheet.

  • sheet_id (str) – The ID of the Google Sheet containing the water restriction data for the target project.

_sheet_id

Stores the ID of the target Google Sheet.

_service

The Google Sheets API service instance used to write data to the target Google Sheet.

_animals

Stores all animal IDs (names) whose data is stored in the target Google Sheet.

_headers

A dictionary that uses headers (column names) as keys and Google Sheet column names (A, B, etc.) as values. This dictionary stores all user-defined headers used by the target Google Sheet tab (animal tab).

_sheet_id_numeric

The numeric ID of the tab that stores the data for the managed animal. This is used to write the data to the target animal’s tab. _current_time: Stores the time (HH:MM) of the session. _session_row_index: Stores the index of the Google Sheet row where to write the managed session’s data.

Raises:

ValueError – If the sheet is not formatted correctly or does not contain expected data.

update_water_log(mouse_weight, water_ml, experimenter_id, session_type)

Updates the water restriction log for the managed animal’s training or experiment data.

This method is used at the end of each BehaviorTraining or MesoscopeExperiment runtime to update the water restriction log with the runtime data. Primarily, this is used to keep a record of behavior interventions and to streamline experimenter experience by automatically synchronizing the Google Sheet log with the data logged during runtime.

Notes

For this method to work as intended, the target water restriction log tab must be pre-filled with dates at least up to today’s data. The method searches the ‘date’ column for today’s date and uses it to determine which row of the table to update with data.

Parameters:
  • mouse_weight (float) – The weight of the mouse, in grams, at the beginning of the training or experiment session.

  • water_ml (float) – The combined volume of water, in milliliters, given to the animal automatically (during runtime) and manually (by the experimenter, after runtime).

  • experimenter_id (str) – The ID of the experimenter running the training or experiment session.

  • session_type (str) – The type of the training or experiment session. This is written to the ‘behavior’ column to describe the type of activity performed by the animal during runtime.

Return type:

None