Using scorevideo_lib to transfer lights-on marks into behavior logs
Written by Chris Skalnik on May 23rd, 2019
These instructions were written by Christopher Skalnik while working under Beau Alward in the Fernald Lab at Stanford University.
Copyright © 2019 Stanford University, All rights reserved. Note that this work is NOT released under the same license as the rest of the site.
Let’s say that we have these types of behavior logs:
Full Scoring Logs: Records every behavior observed over the 30-minute period we analyze. These behaviors are the ones we will measure and analyze. These logs come from the morning and afternoon, and they have names like:
050118_OD1030618_TA23_Dyad_Afternoon.wmv_CS.txt
050118_OD1030618_TA23_Dyad_Morning.wmv_CS.txt
We sometimes call these videos “trims,” “trimmed,” or “spliced.”
log052318_OD1030618_OC4C_Dyad_#.avi_CS.txt
where #
can be either a
1
, for the first video recorded of that subject that day, or a 2
for the second video. These logs do not necessarily cover the full
video because we usually stop scoring once we see and score that first
behavior. The times in these logs are the ones we use when making the
full scoring logs. These logs are for the un-trimmed videos.LIGHTS ON
behavior and have names like
log052318_OD1030618_OC4C_Dyad_#.avi_CS_LIGHTSON.txt
, where again #
can be either a 1
or a 2
to signify the first or second video. The
2
is possible because sometimes the first video is so short that it
is dark throughout the video.We want to use
behaviorcode
or
behaviorcodeAuto
to
statistically analyze the behavior and latency data, but these scripts
don’t know how to handle lights-on information being in a separate log
file that starts at a different time than the full scoring log.
Therefore, we need to add a LIGHTS ON
mark (in the MARKS
section) to
the full scoring log with a negative frame number and timestamp to
accurately reflect when the lights came on relative to the behaviors in
the full scoring log. We can use
scorevideo_lib
to do this!
Download scorevideo_lib from
here. Make sure
to note which release you use! If you prefer, you can also use git
to
clone the repository like this:
$ git clone https://github.com/U8NWXD/scorevideo_lib.git
$ cd scorevideo_lib
$ git checkout v0.4.1-beta
Note that you probably want to use the most recent release by
changing v0.4.1-beta
to the release you want. You should use a
release and not just the master
branch because master
may
represent work in progress that is not yet ready for use.
For the rest of this guide, I will start my paths with
scorevideo_lib
to refer to the root folder of the repository.
Project Interpreter
under Project
in the left sidebar,
choosing to add a virtual environment, and finally choosing to create
a new virtual environment.Activate the virtual environment by opening a new terminal from the bottom of your PyCharm window. Then install dependencies by running
$ pip install -r requirements.txt
scorevideo_lib/fm_behaviors.txt
to
scorevideo_lib/scorevideo_lib/fm_behaviors.txt
. This comes from
another quirk of how Python searches for and loads files, and this
step may not be needed later if I fix this bug.scorevideo_lib/scorevideo_lib/work/
. This will
be your work directory (not your working directory).Into your work directory, copy the following:
Note that any leading log
prefixing the log filenames is ignored.
Also note that you should only include relevant files. Any extra
files, such as first aggression logs that don’t have associated full
scoring logs, will trigger errors. Similarly, all relevant files
must be included. In the next step you will specify which files
precisely are required, but any missing files will also trigger
errors.
In scorevideo_lib/scorevideo_lib/transfer_lights_on_marks.py
, find
the code that looks like this:
# Specify regular expressions that identify logs required for every partition
PART_REQUIRED = [ExpectedFile(["_Morning."], ["_LIGHTSON.txt"]),
ExpectedFile(["_1."], ["_LIGHTSON.txt"])]
# Specify regular expressions that identify logs optional for every partition
PART_OPTIONAL = [ExpectedFile(["_2."], ["_LIGHTSON.txt"]),
ExpectedFile(["_LIGHTSON.txt"])]
# Any files in partitions not matching any of the above throw errors
These lines specify which files are required. To explain this, we
first need some background on how scorevideo_lib matches up log
files. It uses a function get_partitions
in the
transfer_lights_on_marks.py
file to split the log file names into
equivalence partitions where every partition is composed of log files
whose names are “equal,” where “equal” means that the logs are for
the same fish on the same day. This equality is determined by the
same_fish_and_day
function in the transfer_lights_on_marks.py
script.
Once the partitions have been created, scorevideo_lib validates
them using the PART_REQUIRED
and PART_OPTIONAL
constants.
PART_REQUIRED
is a list ExpectedFile
objects, each of which
describes a file. You can see the documentation
here.
In short, the first argument to ExpectedFile
is a list of strings
that are expected to present in the file name, and the second
argument is a list of strings that are expected to not be present
in the file name. Any file name that matches both criteria “matches”
the ExpectedFile
object. scorevideo_lib checks that each partition
has exactly one file that matches each ExpectedFile
in
PART_REQUIRED
and no files that match no ExpectedFile
objects in
the union of PART_REQUIRED
and PART_OPTIONAL
. In other words, the
files described in PART_REQUIRED
are mandatory, while the files
described in PART_OPTIONAL
are allowable but not required.
Note that the script also uses a
name_filter
function to filter out files that don’t look like logs and afternoon
full scoring logs.
In my case, I used
# Specify regular expressions that identify logs required for every partition
PART_REQUIRED = [ExpectedFile(["_Morning."], ["_LIGHTSON.txt"]),
ExpectedFile(["_1."], ["_LIGHTSON.txt"]),
ExpectedFile(["_LIGHTSON.txt"])]
# Specify regular expressions that identify logs optional for every partition
PART_OPTIONAL = [ExpectedFile(["_2."], ["_LIGHTSON.txt"]),
]
# Any files in partitions not matching any of the above throw errors
This requires a morning full scoring log, a first aggression log for video 1, and a lights on log. A first aggression log for video 2 is optional.
You are now ready to transfer the marks. Within PyCharm, run the
scorevideo_lib/scorevideo_lib/transfer_lights_on_marks.py
script by
clicking the green triangle in the upper right of the window.
If this fails, you might need to set the working directory to
scorevideo_lib/scorevideo_lib
in PyCharm by choosing to
Edit Configurations
from the drop-down menu to the left of the green
triangle.
When scorevideo_lib finishes, you should now see LIGHTS ON
marks with
negative frame numbers and timestamps in the full scoring logs. Now
you’re ready to analyze them!
The behaviors that count as the first behavior are stored in
fm_behaviors.txt
in the scorevideo_lib
repository. ↩