Configurations¶
The use of bruker_control
requires an experimental configuration file held inside a JSON
format. These were created as a means of doing the
following:
Create files that act as documentation which precisely describe the exact parameters used for an experiment for every subject
Have a reproducible experiment that can be executed using completed configuration files
Have a standard set of parameters for performing experiments with the system that is flexible for several use cases and simpler to modify and add to
Avoid generating copies of Arduino sketches at runtime as occured in the first iterations of running headfixed behavior experiments
Have a file format that can be programmatically accessed when running analysis scripts or searching for particular experiments
Have templates that can be easily called upon and updated programatically at runtime without requiring user input
Many of these fields were present in the initial Arduino and MATLAB code, but the Arduino scripts had these values hard coded into the sketch itself. Having a configuration file allows for there to be just one sketch for each team/project as needed that can stand ready for a session without needing to reupload a new sketch in between running individual animals.
Example Project Config: Behavior¶
Below is an example of what such a configuration looks like:
{"beh_metadata": {
"totalNumberOfTrials": 60,
"startingReward": 3,
"maxSequentialReward": null,
"maxSequentialPunish": 3,
"punishTone": 2000,
"rewardTone": 9000,
"USDeliveryTime_Sucrose": 200,
"USDeliveryTime_Air": 100,
"USConsumptionTime_Sucrose": 3000,
"vacuum" : true,
"ITIJitter": true,
"baseITI": null,
"minITI": 15,
"maxITI": 30,
"toneJitter": false,
"baseTone": 3,
"minTone": null,
"maxTone": null,
"catchTrials": true,
"numCatchReward": 3,
"numCatchPunish": 2,
"catchOffset" : 0.25,
"percentPunish": 0.25,
"stim": true,
"shutterOnly": false,
"stimFrequency": 20,
"stimPulseTime": 5,
"stimLambda": 590,
"stimDeliveryTime_PreCS": 1000,
"stimDeliveryTime_Total": 5000,
"stimStartPosition": 20,
"numStimReward": 5,
"numStimPunish": 5,
"numStimAlone": 3,
"yoked": false,
"trialArray": {},
"ITIArray": {},
"toneArray": {},
"LEDArray": {},
"dropped_frames": {}
},
"zstack_metadata": {
"zstack": true,
"stack_number": 3,
"zdelta": 25.0,
"zstep": 1.0
},
"weight_check": true
}
Config Values Key: Behavior Metadata¶
Many of the fields were written as to be self explanatory. Below you can find an explainer for each field:
totalNumberOfTrials: Total number of trials for an experiment
startingReward: Total number of sucrose trials to deliver in the beginnin
maxSequentialReward: Maximum number of reward trials to allow in a row
maxSequentialPunish: Maximum number of punishment trials to allow in a row
punishTone: Tone in Hertz (Hz) to play through a speaker for the subject
rewardTone: Tone in Hertz (Hz) to play through a speaker for the subject
USDeliveryTime_Sucrose: Time in milliseconds (ms) to open sucrose solenoid
USDeliveryTime_Air: Time in milliseconds (ms) to open the air solenoid
USConsumptionTime_Sucrose: Time in milliseconds (ms) to allow subject to consume sucrose droplet
vacuum: Whether or not a vacuum is enabled for use in the experiment. Either
True
orFalse
ITIJitter: Whether or not to have jitter in inter-trial-interval (ITI) timings
baseITI: Inter-trial-interval (ITI) to use if no
ITIJitter
isFalse
minITI: Minimum inter-trial-interval (ITI) value in seconds. Defines lower bound for sampling ITI values
maxITI: Maximum inter-trial-interval (ITI) value in seconds. Defines upper bound for sampling ITI values
toneJitter: Whether or not to have jitter in the duration of tones that are played for the subject. Either
True
orFalse
baseTone: Time to play tone in seconds (s) for subject if
toneJitter
isFalse
.minTone: Minimum time to play tone in seconds (s). Defines lower bound for sampling tone values
maxTone: Maximum time to play tone in seconds (s). Defines upper bound for sampling tone values
catchTrials: Whether or not to have catch trials occur during an experiment. Either
True
orFalse
numCatchReward: Number of reward catch trials to present to the subject
numCatchPunish: Number of punish catch trials to present to the subject
catchOffset: Where in the
trialArray
catch trials should be presented. This is defined as the proportion of remaining trials that should be eligible for delivering catch trials.percentPunish: The proportion of trials that will be punishment trials.
stim: Whether or not to have stimulation trials occur during an experiment. Currently only valid for whole field LED stimulation.
shutterOnly: Whether or not the stimulation trials did not activate LED and only activated PMT shutters.
stimFrequency: Frequency of stimulation in Hertz (Hz) that the whole field LED will perform
stimLambda: Wavelength of stimulating LED in nanometers (nm). This is assumed to be constant for a given project and is for documentation purposes alone
stimDeliveryTime_PreCS: Time in milliseconds (ms) to start LED output before presentation of conditioned stimulus
stimDeliveryTime_Total: Total time in milliseconds (ms) that the LED ouptut will be delivered. This is assumed to be constant for a given project and is for documentation purposes alone.
stimStartPosition:
1-Indexed
position where LED stimulation should begin.trial_utils.py
will decrement this by 1 so it is0-indexed
for Python/Arduino iterations.numStimReward: Number of trials to give LED stimulation with a reward
numStimPunish: Number of trials to give LED stimulation with a punishment
numStimAlone: Number of trials to give LED stimulation alone
yoked: (NEW) Whether or not to generate/check for
yoked
trial settingstrialArray: Array of integers for trials that the Arduino will iterate through. Valid numbers are 0-6
ITIArray: Array of inter-trial-intervals (ITIs) that the Arduino will iterate through
toneArray: Array of tone durations to deliver to the subject
LEDArray: Array of times for delivering LED stimulation. Calculated by
trial_utils.py
by taking the ITI for the appropriate trial and subtracting thestimDeliveryTime_PreCS
valuedropped_frames: List of video frames that are dropped when transferring data from the Genie Nano to the computer during an experiment. Packet loss is rare, but has occured previously.
Config Values Key: Trial Types¶
Currently accessible trial types in bruker_control are entirely designed around one behavior paradigm: the delivery of sucrose or an airpuff to the headfixed subject. Perhaps in the future a library like Autopilot could be used to dynamically generate trials using the library’s powerful framework. We create base trial types around these and then have additional trial types we build off them:
LED optogenetic stimulation trials with airpuff and sucrose presented
LED only trials: Trials where no stimuli are presented but the LED is triggered to stimulate neurons
Catch trials: trials where only the tone (or conditioned stimulus) is presented and the associated airpuff or sucrose (unconditioned stimulus) is not
When building the trial arrays, each trial type is associated with a specific number. The key for these numbers is:
0: Airpuff
1: Sucrose
2: Airpuff Catch
3: Sucrose Catch
4: Airpuff LED
5: Sucrose LED
6: LED Only
Config Values Key: Z-Stack Metadata¶
If users want to have a z-stack performed for their imaging session before the experiment, they can use this metadata to define parameters used for imaging.
zstack: Whether or not to perform a z-stack for a given recording
stack_number: Number of z-stacks to perform
zdelta: Distance in micrometers (um) to move above and below the selected imaging plane for the z-stack.
zstep: Distance in micrometeres (um) the scope will move between images.
Config Values Key: Miscellaneous¶
Some users need to make sure a weight has been recorded for the subject being imaged. To ensure that users remember to have weights recorded for their mice, there’s an option to perform a weight check. If the weight check fails, the experiment won’t go forward. It is likely that this will be removed in the near future.
Complete Configuration File¶
This is an example of what a completed configuration file looks like after an experiment is completed (from a real experiment!):
{
"beh_metadata": {
"totalNumberOfTrials": 60,
"startingReward": 3,
"maxSequentialReward": null,
"maxSequentialPunish": 3,
"punishTone": 2000,
"rewardTone": 9000,
"USDeliveryTime_Sucrose": 200,
"USDeliveryTime_Air": 100,
"USConsumptionTime_Sucrose": 1000,
"USDelay": 2000,
"vacuum": true,
"ITIJitter": true,
"baseITI": null,
"minITI": 25,
"maxITI": 30,
"toneJitter": false,
"baseTone": 3,
"minTone": null,
"maxTone": null,
"catchTrials": true,
"numCatchReward": 3,
"numCatchPunish": 2,
"catchOffset": 0.25,
"percentPunish": 0.25,
"stim": true,
"shutter_only": false,
"stimFrequency": 20,
"stimPulseTime": 5,
"stimLambda": 590,
"stimDeliveryTime_PreCS": 6000,
"stimDeliveryTime_Total": 5000,
"stimStartPosition": 20,
"numStimReward": 5,
"numStimPunish": 5,
"numStimAlone": 3,
"yoked": false,
"trialArray": [
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
6,
6,
4,
5,
4,
5,
5,
4,
4,
4,
5,
5,
6,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
3,
1,
1,
0,
2,
3,
2,
1,
1,
0,
3,
1,
1,
1,
1
],
"ITIArray": [
29480,
29582,
25763,
25851,
25784,
27231,
27803,
26458,
28338,
27721,
29685,
26766,
27797,
27750,
26832,
27437,
27762,
26503,
29295,
28137,
28762,
26795,
25739,
29311,
27552,
25838,
28862,
27459,
28341,
28575,
26141,
29665,
27975,
29316,
25065,
26304,
25210,
28299,
25331,
28878,
26094,
27875,
28720,
26682,
29879,
25739,
25534,
28427,
29739,
26514,
26915,
26121,
26061,
28227,
29269,
29778,
28466,
29169,
25100,
27282
],
"toneArray": [
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000,
3000
],
"LEDArray": [
22762,
20795,
19739,
23311,
21552,
19838,
22862,
21459,
22341,
22575,
20141,
23665,
21975
],
"dropped_frames": []
},
"zstack_metadata": {
"zstack": true,
"stack_number": 1,
"zdelta": 25.0,
"zstep": 1.0
},
"weight_check": false
}
Example Subject Metadata¶
In an effort to make metadata about the subject programmatically available for use in generating Neurodata Without Borders compliant datasets as well as programmatically update laser power and wavelength for instances where z-stacks required multiple wavelengths for imaging different fluorophores. Below is an example of what the subject metdata looks like:
# Subject Metadata used for grabbing information
# Jeremy Delahanty, Tye Lab Februrary 2022
# This was generated by taking all available fields labmembers had stored
# in their surgery logs and joining it with NWB metadata fields.
subject_id: "A000"
subject_alias: "best-mouse"
ear_tag:
l_ear: true
r_ear: false
ear_notch:
l_ear: false
r_ear: false
# Cage IDs MUST be the barcode for the cage
cage_id: 0123456
# Cage Alias is whatever the experimenter likes to refer the cage as
cage_alias: "cage-alias"
# Date of birth in YYYMMDD format
dob: "20220205"
# Descriptions
description: "Mouse Description"
genotype: "HET DAT Cre"
sex: "M"
species: "Mus Musculus"
strain: "C57BL/6J"
# Surgeries are organized by date
surgery:
"20210924":
surgeon: "Jeremy Delahanty"
start_time: "10:00"
end_time: "11:00"
stereotax: "Delta"
anesthetic: "Isoflurane"
skull_position:
bregma: -0.02
lambda: -0.02
level_left: -0.01
level_right: -0.01
headplate:
num_screws: 1
skull_hashing: true
grin_implant:
target: "mPFC"
hemisphere: "R"
type: "Proview"
dims: [1, 4]
supplier: "Inscopix"
ap: 1.90
ml: 0.45
dv: -2.18
angle: null
notes: "None"
brain_injections:
gcamp:
target: "mPFC"
hemisphere: "R"
virus: "AAV8"
promoter: "promoter"
opsin: null
fluorophore: "jGCaMP7f"
fluorophore_excitation_lambda: 482.5
fluorophore_emission_lambda: 513.0
supplier: "The Salk Institute for Biological Studies"
description: "Calcium Sensitive Green Fluorescent Indicator"
lot: null
ap: 1.90
ml: 0.45
dv: -2.20
angle: null
# Volume in nL
volume: 300
# Rate in nL/min
rate: 100.0
# Bevel Direction: Away from you is 0 degrees
bevel: 90
chr:
target: "VTA"
hemisphere: "R"
virus: "AAV8"
promoter: "hSyn"
cre: "FLEX"
flp: null
opsin: "chrimsonR"
opsin_excitation_lambda: 100.0
fluorophore: "tdTomato"
fluorophore_excitation_lambda: 482.5
fluorophore_emission_lambda: 581.0
supplier: "Supplier"
description: "description"
lot: null
ap: -3.30
ml: 0.35
dv: -4.05
angle: null
# Volume in nL
volume: 700.0
# Rate in nL/min
rate: 100.0
# Bevel Direction
bevel: 180
analgesics:
buprinex:
route: "IP"
location: "abdomen"
# Dosages are in mg/kg
dose: 1.0
# Volumes here in mL
volume: 2.0
lidocaine:
route: "SQ"
location: "scalp"
dose: null
volume: 0.5
loxicam:
route: "IP"
location: "abdomen"
# Dosages are in mg/kg
dose: 5.0
volume: 0.5
fluids:
ringers:
route: "IP"
location: "abdomen"
percent: 20.0
volume: 1.0
status:
alive: true
time_of_death: null
death_notes: null
Not every project has this metadata available and no project is required to have it to use the system. Only some of these fields are used by bruker_control
while
a majority of them are used for NWB compliance. bruker_control
does not currently implement NWB files at runtime as it did previously. The module nwb_utils.py
may be reimplemented in the future.
There is currently only 1 field that is used by bruker_control
:
fluorophore_excition_lambda: Wavelength in nanometers (nm) that the injected indicator uses for imaging. Value is multiplied by 2 at runtime to change the laser wavelength
The remaining fields are used for documentation of the subject and NWB compliance.
Example Subject Metadata: Weights¶
The NWB standard asks for weights to be recorded for a given recording. While they’re not required, users typically are weighing subjects before imaging sessions.
In order to programatically add weights to the NWB File and access them later, a weights file was added to store subjects’ measurements. The files are very simple and consist
of date/weight pairs. The date format is stored as YYYYMMDD
as with all other dates stored in this system. Weights are stored in kilograms (kg) per the NWB standard’s
documentation.
"20211104": 0.0268
"20211111": 0.0260
"20211118": 0.0273
"20211125": 0.0250
"20211202": 0.0279
"20211209": 0.0247
"20211214": 0.0279