Usage¶
A set of trials are run through the SerialController.py
script. At
the windows command prompt cd to the root directory of the
behaviour_box repository.
When the program runs the first thing it does is make a new folder to
save the logs in. The base of the new directory can be specified by
--datapath
and the new folder is always the current date is in the
format YYMMDD.
In addition it also creates two files, a raw log file which stores all
time stamped communications sent and received by the program, and a csv
file which contains the same data in tabulated form. The name pattern
for the csv is {ID}_{date}_000.csv
where ID is given with the
-ID
argument and date is in the format YYMMDD.
Note
It is important to note that the data files will be appended to each time the program is run over the course of the day, unless a new ID is specified.
Next the program checks the serial port specified by the --port
argument. By default, if no port is specified the program will search
the available ports for any Arduino that is plugged in. If more than
one Arduino is available it will print a warning, followed by a list
of Arduino ports. It will then select the first arduino.
On Windows the serial ports are specified by COMx
where
x
is some integer. If no communications are found the program
will exit.
Note
If you always have the Arduino detected on the same port
you can adjust the default value of the port
variable to avoid setting
this flag each run, see Adjusting Default Arguments. This strategy applies to
all the variables that might remain invariant between sessions.
When the connection has been established the program first transmits a number of configuration variables to the arduino, such as the lick threshold, and timing information. These can be updated online later, but it saves time to avoid sending them on each trial if they are unchanged.
The program then begins to loop through the trials
variable, which
is an iterable list of the stimulus durations. On each loop the program
tells the Arduino what duration to play, and whether or not to reward a
lick.
At this point the program sends the START
message to the Arduino and
the trial begins. As the trial runs the program monitors the Arduino
status messages as they come in.
At the end of the trial the program collects all the status messages and
formats them into a Pandas DataFrame, which is then saved into
{ID}_{date}_000.csv
Interactive Options¶
The Python wrapper was written to allow for limited interaction with the Arduino while a trial was being run without the need to touch the source code and recompile. With animal experimentation in mind it was decided that it would be best to avoid editing the control code during a run. The Arduino exposes a number of relevant variables to the Serial Communications port, which the Python wrapper reads and writes to.
Pressing any key (except for SPACE
or Enter
) while the SerialComms.py
script is running will pause the program loop. Pressing Enter
or SPACE
will resume the program.
In addition a subset of relevant variables can be modified using key presses outlined in the following table.
key | option |
---|---|
H |
This menu |
P |
Punish |
< /
> |
increase / decrease the lick threshold |
? |
show threshold |
[ /
] |
increase / decrease the minimum number of licks required to get a reward |
\ |
show lickcount |
tab |
toggle mode |
: /
" |
increase / decrease the time prior to a stimulus in which a lick will end the trial |
L |
show noLick period |
( /
) |
increase / decrease the duration of a trial |
T |
show trial duration period |
Y |
toggle timeout (requires punish to take effect) |
Adjusting Default Arguments¶
The default parameters to the Python Script are all set in the file
utilities\args.py
. The file looks something like this:
import argparse
# create the argument parsing object
p = argparse.ArgumentParser(description="This program"
"controls the Arduino"
"and reads from it too"
)
# construct a dictionary of program parameters
kwargs = {
("-i", "--ID", ) : {
'default' : "_",
'help' : "identifier for this animal/run",
},
.
.
.
("--port", ) : {
'default' : None,
'type' : str,
'help' : "port that the Arduino is connected to",
},
}
# load the argument parser with the parameters specified
for k, v in kwargs.iteritems():
p.add_argument(*k, **v)
# read the command line arguments
args = p.parse_args()
Each of the parameters that can be supplied as arguments to the Python Script
are defined in the kwargs
dictionary in this file. Supplying a new value to
the 'default'
key of any of these parameters will set the value that the
program loads with if no value for that parameter has been supplied at the
command line.
For example, here the Arduino is always located on the port "COM5"
,
therefore the args.py file is modified as follows:
import argparse
# create the argument parsing object
p = argparse.ArgumentParser(description="This program"
"controls the Arduino"
"and reads from it too"
)
# construct a dictionary of program parameters
kwargs = {
("-i", "--ID", ) : {
'default' : "_",
'help' : "identifier for this animal/run",
},
.
.
.
("--port", ) : {
'default' : "COM5",
'type' : str,
'help' : "port that the Arduino is connected to",
},
}
# load the argument parser with the parameters specified
for k, v in kwargs.iteritems():
p.add_argument(*k, **v)
# read the command line arguments
args = p.parse_args()