It is assumed you are familiar with basics of the library. If not - see "Tutorial on basic topics".
import pymice as pm
import glob
pm.getTutorialData(quiet=True)
dataFiles = glob.glob('C57_AB/*.zip')
Visit objects returned by .getVisits()
method are not ordered by default, which means they might be in a random order. In an extremal case the order may be different for every call of the method!
Of course it is possible to sort the returned list, however it is also possible to have it already ordered by attribute(s) indicated by the order
parameter of the method.
To have the list ordered by one attribute pass the name of the attribute as the order
parameter.
ml = pm.Loader('C57_AB/2012-08-28 15.33.58.zip')
visits = ml.getVisits(order='Start')
for visit in visits[:5]:
print visit.Start
Since some attributes (e.g. .Animal
) are objects with their own attributes, it is also possible to have the list sorted by such "nested" attributes (e.g. .Animal.Name
).
visits = ml.getVisits(order='Animal.Name')
for visit in visits[::500]:
print visit.Animal.Name
It is possible to have visits ordered firstly by one attibute, then by another one (and so on) by passing a sequence of attribute names as order
parameter.
visits = ml.getVisits(order=('Cage', 'Corner'))
for visit in visits[::500]:
print visit.Cage, visit.Corner
Usually only a subset of recorded visits is meaningful for certain analysis. The library provides methods for selection of such subsets.
It is common to analyse visits of cetrain animal.
To select visits of a particular mouse pass its name as the mice
parameter of .getVisits()
method.
visits = ml.getVisits(mice='C57 A 1')
print len(visits)
print visits[321].Animal
The mice
parameter accepts also multiple names.
visits = ml.getVisits(mice=['C57 A 1', 'C57 A 2'])
visitorNames = [v.Animal.Name for v in visits]
for mouse in set(visitorNames):
print '%s: %d visits' % (mouse, visitorNames.count(mouse))
Analyses are very often focused on a certain time period (e.g. phase of experiment phase).
To select visits before or after particular time you can use (respectively) start
and end
parameters of getVisits()
method.
In the example visits started between 15:00 (inclusive) and 16:00 (exclusive) 28th August 2012 are being selected. The time is given as Eastern European Time (EET).
from datetime import datetime
import pytz
EET = pytz.timezone('Etc/GMT-2')
timeFrom = datetime(2012, 8, 28, 15, 0, tzinfo=EET)
timeTo = datetime(2012, 8, 28, 16, 0, tzinfo=EET)
visits = ml.getVisits(start=timeFrom, end=timeTo)
print min(v.Start for v in visits)
print max(v.Start for v in visits)
It is rather inconvenient to have starts and ends of time periods hardcoded in the source code. It would be much more convenient to have the time periods defined in a configuration file.
To aid that purpose library provides ExperimentTimeline
class for loading such files. The class inherits from both ConfigParser.RawConfigParser
class of The Python Standard Library and matplotlib.ticker.Formatter
class of matplotlib library.
The format of the file is an adaptation of INI format. To be more specific, it is the format supported by the ConfigParser
module of The Python Standard Library.
Every section of the file describes a time period with following properties:
start
- a start time of the period in YYYY-MM-DD HH:MM
or YYYY-MM-DD HH:MM:SS
format,end
- an end time of the period in YYYY-MM-DD HH:MM
or YYYY-MM-DD HH:MM:SS
format,tzinfo
- a name of timezone used by start
and end
property (it has to be recognizable by timezone
function of the pytz
module).A configuration file might look like this:
[SA 1 dark]
start = 2012-08-28 13:00
end = 2012-08-29 01:00
tzinfo = Etc/GMT-2
[SA 1 light]
start = 2012-08-29 01:00
end = 2012-08-29 13:00
tzinfo = Etc/GMT-2
To load a configuration file pass a path to it to the class constructor. Then you will be able to list defined time period (with .sections()
method) and get their boundaries (with .getTime()
method).
timeline = pm.Timeline('C57_AB/timeline.ini')
for timePeriod in timeline.sections():
start, end = timeline.getTimeBounds(timePeriod)
print "%s:\t%s - %s" % (timePeriod, start, end)
To get boundaries of a minimal time period covering several time periods defined in the config file pass a collection of their names as a parameter of .getTime()
method.
start, end = timeline.getTimeBounds(['Place Pref 1 dark',
'Place Pref 3 light'])
print '%s - %s' % (start, end)
You might want to verify whether every time period defined in the file is defined as it was supposed to be. A simplest way for that is screening the file with the plotPhases()
function of the pymice.debug
module.
IPython Notebook notes:
%matplotlib inline
is a directive of IPython Notebook necessary to display the image,_
intercepts a matplotlib.figure.Figure instance returned by the function in order not to display the image twice.%matplotlib inline
import pymice.debug as pmd
_ = pmd.plotPhases(timeline)
ml = pm.Loader('C57_AB/2012-08-28 15.33.58.zip', getNp=False)
visits = ml.getVisits(order=('Start', 'End'))
visit = visits[4]
print visit.Nosepokes
No log, environment nor hardware events data are loaded unless the loader is explicitely told to do so.
print ml.getLog()
print ml.getEnvironment()
print ml.getHardwareEvents()
ml = pm.Loader('C57_AB/2012-08-28 15.33.58.zip', getLog=True, getHw=True, getEnv=True)
print len(ml.getLog())
print len(ml.getEnvironment())
print len(ml.getHardwareEvents())
It is important to be sure the data you are going to analyse are valid. For that purpose log analysis is necessary.
Log analysis is being performed by a DataValidator
object with a collection of log analyzers given as arguments of its constructor.
Instances of LickometerLogAnalyzer
class checks log for lickometer problems while PresenceLogAnalyzer
- for presence of unidentified animal.
Remember that for log analysis log data must be loaded (getLog
flag of constructors od Loader
and Merger
objects must be set to True
).
loaders = [pm.Loader(filename, getLog=True) for filename in dataFiles]
mm = pm.Merger(*loaders, getLog=True)
dataValidator = pm.DataValidator(pm.LickometerLogAnalyzer(),
pm.PresenceLogAnalyzer())
validatorReport = dataValidator(mm)
After the analysis is performed, you can use TestMiceData
objects to check, if there is no problem with data in a period of interest (POI).
The POI in the example is defined as a period from first to last registration (obtained with getStart()
and getEnd()
methods).
start = mm.getStart()
end = mm.getEnd()
interval = (start, end)
strInterval = '(from %s to %s)' % interval
noLickometerProblems = pm.FailureInspector('Lickometer')
noPresenceProblems = pm.FailureInspector('Presence')
if noLickometerProblems(validatorReport, interval):
print "lickometer ok " + strInterval
else:
print "lickometer problem " + strInterval
if noPresenceProblems(validatorReport, interval):
print "presences ok " + strInterval
else:
print "unknown mice presence problem " + strInterval