diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..707d77d
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Run main",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/__main__2.py",
+ "console": "integratedTerminal"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AHF_BrainLight.py b/AHF_BrainLight/AHF_BrainLight.py
similarity index 94%
rename from AHF_BrainLight.py
rename to AHF_BrainLight/AHF_BrainLight.py
index b94ca12..57c6ac4 100644
--- a/AHF_BrainLight.py
+++ b/AHF_BrainLight/AHF_BrainLight.py
@@ -1,9 +1,12 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
from time import sleep
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_BrainLight(AHF_Base, metaclass = ABCMeta):
@@ -21,7 +24,7 @@ def config_user_get(starterDict = {}):
@abstractmethod
- def onForStim(self):
+ def onForStim(self):
"""
Runs when headFixing starts, illuminating the brain or whatever needs illuminating
"""
diff --git a/AHF_BrainLight_1GPIO.py b/AHF_BrainLight/AHF_BrainLight_1GPIO.py
similarity index 94%
rename from AHF_BrainLight_1GPIO.py
rename to AHF_BrainLight/AHF_BrainLight_1GPIO.py
index 35c3a79..b45454f 100644
--- a/AHF_BrainLight_1GPIO.py
+++ b/AHF_BrainLight/AHF_BrainLight_1GPIO.py
@@ -3,7 +3,7 @@
import RPi.GPIO as GPIO
from time import sleep
from _thread import start_new_thread
-from AHF_BrainLight import AHF_BrainLight
+from AHF_BrainLight.AHF_BrainLight import AHF_BrainLight
class AHF_BrainLight_1GPIO(AHF_BrainLight):
@@ -60,7 +60,7 @@ def offForStim(self):
super().offForStim()
if self.ledDelay > 0:
sleep(self.ledDelay)
- GPIO.output(self.ledPin, GPIO.LOW)
+ GPIO.output(self.ledPin, GPIO.LOW)
diff --git a/AHF_BrainLight/__init__.py b/AHF_BrainLight/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Camera.py b/AHF_Camera/AHF_Camera.py
similarity index 97%
rename from AHF_Camera.py
rename to AHF_Camera/AHF_Camera.py
index de2579b..6d14e40 100755
--- a/AHF_Camera.py
+++ b/AHF_Camera/AHF_Camera.py
@@ -1,9 +1,13 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
import os
import inspect
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Camera(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_Camera_PiCam.py b/AHF_Camera/AHF_Camera_PiCam.py
similarity index 95%
rename from AHF_Camera_PiCam.py
rename to AHF_Camera/AHF_Camera_PiCam.py
index f5399c4..4331d97 100755
--- a/AHF_Camera_PiCam.py
+++ b/AHF_Camera/AHF_Camera_PiCam.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_Camera import AHF_Camera
+from AHF_Camera.AHF_Camera import AHF_Camera
from picamera import PiCamera
import time
from datetime import datetime
@@ -182,19 +182,19 @@ def set_gain(self):
def capture(self, path, type, video_port =False):
self.piCam.capture(path, type, use_video_port=video_port)
- def start_recording(self, video_name_path):
+ def start_recording(self, video_name):
"""
Starts a video recording using the saved settings for format, quality, gain, etc.
A preview of the recording is always shown
- :param video_name_path: a full path to the file where the video will be stored. Always save to a file, not a PIL, for, example
+ :param video_name: Name of saved recording. Always save to a file, not a PIL, for, example
"""
- video_name = self.video_path+video_name_path
+ video_name_full = self.video_path+video_name
if self.AHFvideoFormat == 'rgb':
- self.piCam.start_recording(output=video_name, format=self.AHFvideoFormat)
+ self.piCam.start_recording(output=video_name_full, format=self.AHFvideoFormat)
else:
- self.piCam.start_recording(output=video_name, format = self.AHFvideoFormat, quality = self.AHFvideoQuality)
+ self.piCam.start_recording(output=video_name_full, format = self.AHFvideoFormat, quality = self.AHFvideoQuality)
self.piCam.start_preview(fullscreen = False, window= self.AHFpreview)
return
@@ -220,14 +220,13 @@ def stop_recording(self):
self.piCam.stop_preview()
return
- def timed_recording(self, video_name_path, recTime):
+ def timed_recording(self, recTime):
"""
Does a timed video recording using the PiCamera wait_recording function.
A preview of the recording is always shown
Control does not pass back to the calling function until the recording is finished
- :param video_name_path: a full path to the file where the video will be stored.
:param recTime: duration of the recorded video, in seconds
"""
if self.AHFvideoFormat == 'rgb':
diff --git a/AHF_Camera/AHF_Camera_PiStream.py b/AHF_Camera/AHF_Camera_PiStream.py
new file mode 100644
index 0000000..5e475ce
--- /dev/null
+++ b/AHF_Camera/AHF_Camera_PiStream.py
@@ -0,0 +1,235 @@
+#! /usr/bin/python3
+#-*-coding: utf-8 -*-
+
+from picamera.array import PiRGBArray
+from picamera import PiCamera
+import numpy as np
+import cv2
+import imutils
+from imutils.video import FPS
+import time
+from datetime import datetime
+import wiringpi as wpi
+import os
+import tables
+import csv
+import io
+from AHF_Camera.AHF_Camera import AHF_Camera
+from picamera import PiCamera
+from time import sleep
+from threading import Thread
+
+class AHF_Camera_PiStream(AHF_Camera):
+
+ @staticmethod
+ def about():
+ return 'uses picamera.PiCamera to run the standard Raspberry Pi camera, recording by frame'
+
+ @staticmethod
+ def config_user_get(starterDict = {}):
+ defaultFormat = 'hdf5'
+ defaultRes =(640,480)
+ defaultQuality = 20
+ defaultSensorMode = 4
+ defaultFrameRate = 30
+ defaultISO = 200
+ defaultShutterSpeed = 30000
+ defaultPath = '/home/Pi/Videos/'
+
+ # video path
+ video_path = starterDict.get('video_path', defaultPath)
+ tempInput = input('Set Video path for recording movies(currently ' + video_path + ') to :')
+ if tempInput != '':
+ video_path = tempInput
+ starterDict.update({'video_path' : video_path})
+ # videoFormat
+ videoFormat = starterDict.get('format', defaultFormat)
+ tempInput = input('Set Video format for recording movies(currently ' + videoFormat + ') to :')
+ if tempInput != '':
+ videoFormat = tempInput
+ starterDict.update({'format' : videoFormat})
+ # quality
+ quality = starterDict.get('quality', defaultQuality)
+ tempInput = input('Set Video quality for h264 movies, best=1, worst =40,0 for auto(currently ' + str(quality) + ') to :')
+ if tempInput != '':
+ quality = int(tempInput)
+ starterDict.update({'quality' : quality})
+ # resolution
+ resolution = starterDict.get('resolution', defaultRes)
+ tempInput = input('set X,Y resolution(currently {0}): '.format(resolution))
+ if tempInput != '':
+ resolution = tuple(int(x) for x in tempInput.split(','))
+ starterDict.update({'resolution' : resolution})
+ # framerate
+ frameRate = starterDict.get('framerate', defaultFrameRate)
+ tempInput = input('Set Frame rate in Hz of recorded movie(currently {0}): '.format(frameRate))
+ if tempInput != '':
+ frameRate = float(tempInput)
+ starterDict.update({'framerate' : frameRate})
+ # ISO
+ iso = starterDict.get('iso', defaultISO)
+ tempInput = input('Set ISO for video, or 0 to auto set gains(currently ' + str(iso) + ') to :')
+ if tempInput != '':
+ iso = int(tempInput)
+ starterDict.update({'iso' : iso})
+ # shutter speed
+ shutter_speed = starterDict.get('shutter_speed', defaultShutterSpeed)
+ tempInput = input('Set Shutter speed(in microseconds) for recorded video(currently ' + str(shutter_speed) + ') to :')
+ if tempInput != '':
+ shutter_speed= int(tempInput)
+ starterDict.update({'shutter_speed' : shutter_speed})
+ # Sensor mode
+ sensor_mode = starterDict.get('sensor_mode', defaultSensorMode)
+ tempInput = input('Set sensor mode for recording (currently ' + str(sensor_mode) + ') to :')
+ if tempInput != '':
+ sensor_mode= int(tempInput)
+ starterDict.update({'sensor_mode' : sensor_mode})
+ # preview window
+ previewWin = starterDict.get('previewWin',(0,0,640,480))
+ tempInput = input('Set video preview window, left, top, right, bottom,(currently ' + str(previewWin) + ') to :')
+ if tempInput != '':
+ previewWin = tuple(int(x) for x in tempInput.split(','))
+ starterDict.update({'previewWin' : previewWin})
+ # white balance
+ whiteBalance = starterDict.get('whiteBalance', False)
+ tempInput = input('Set white balancing for video, 1 for True, or 0 for False(currently ' + str(whiteBalance) + ') to :')
+ if tempInput !='':
+ tempInput = bool(int(tempInput))
+ starterDict.update({'whiteBalance' : whiteBalance})
+ # return already modified dictionary, needed when making a new dictionary
+ return starterDict
+
+
+ def setup(self):
+ # Set up text file and paths
+ self.data_path = self.settingsDict.get('data_path', '/home/Pi/Videos/closed_loop/')
+ # Create pi camera objecy
+ try:
+ self.piCam = PiCamera()
+ except Exception as anError:
+ print("Error initializing camera.." + str(anError))
+ raise anError
+ # set fields in Picamera
+ self.piCam.resolution = self.settingsDict.get('resolution',(640, 480))
+ self.piCam.framerate = self.settingsDict.get('framerate', 30)
+ self.piCam.iso = self.settingsDict.get('iso', 0)
+ self.piCam.shutter_speed = self.settingsDict.get('shutter_speed', 30000)
+ self.piCam.sensor_mode = self.settingsDict.get('sensor_mode', 4)
+ # turn off LED on camera
+ self.piCam.led = False
+
+ # set fields that are in AHF_Camera class
+ self.AHFvideoFormat = self.settingsDict.get('format', 'hdf5')
+ self.AHFvideoQuality = self.settingsDict.get('quality', 20)
+ self.AHFframerate= self.settingsDict.get('framerate', 30)
+ self.AHFpreview = self.settingsDict.get('previewWin',(0,0,640,480))
+ whiteBalance = self.settingsDict.get('whiteBalance', False)
+
+ # set gain
+ self.cfgDict = self.settingsDict.get('cfgDict', '')
+ if 'dff_history' in self.cfgDict:
+ while True:
+ if(self.piCam.analopiCg_gain>=7.0 and
+ self.piCam.analog_gain<=8.0 and
+ self.piCam.digital_gain>=1 and
+ self.piCam.digital_gain<=1.5):
+ self.piCam.exposure_mode='off'
+ print("ok")
+ break
+ else:
+ print('analog gain: ' + str(eval(str(self.piCam.analog_gain))))
+ print('digital gain: ' + str(eval(str(self.piCam.digital_gain))))
+
+
+ self.is_recording = False
+ self.stopped = False
+ self.rawCapture = PiRGBArray(self.piCam, size=self.resolution())
+
+ # Allow the camera to warmup
+ time.sleep(0.1)
+ print("done initializing!")
+ return
+
+ def resolution(self):
+ return self.piCam.resolution
+
+ def setdown(self):
+ """
+ Writes session end and closes log file
+ """
+ self.piCam.close()
+ pass
+
+
+ def update(self):
+ if self.data_path:
+ self.piCam.start_recording(self.data_path, format='rgb')
+ for f in self.stream:
+ start = time.time()
+ # grab the frame from the stream and clear the stream in
+ # preparation for the next frame
+ self.frame = f.array
+ self.rawCapture.seek(0)
+
+ # if the thread indicator variable is set, stop the thread
+ # and resource camera resources
+ if self.stopped:
+ self.stream.close()
+ if self.data_path:
+ self.piCam.stop_recording()
+ self.rawCapture.close()
+ self.piCam.close()
+ return
+ time.sleep(max(0.5/(self.piCam.framerate) - (time.time() - start), 0.0))
+
+
+ def start_recording(self):
+ """
+ """
+ self.start_preview()
+ self.is_recording = True
+ self.frame = None
+ t = Thread(target=self.update, args=())
+ t.daemon = True
+ t.start()
+ return self
+
+ def start_preview(self):
+ self.piCam.start_preview(fullscreen = False, window= self.AHFpreview)
+
+ def stop_preview(self):
+ self.piCam.stop_preview()
+
+ def stop_recording(self):
+ """
+ Stops a video recording previously started with start_recording.
+ """
+ if self.is_recording:
+ self.stopped = False
+ return
+
+ def hardwareTest(self):
+ """
+ Tests functionality, gives user a chance to change settings
+ """
+ while(True):
+ inputStr = input('p=display preview, r=record for 10 seconds, t= edit task settings, q= quit: ')
+ if inputStr == 'p':
+ print('Now displaying current output')
+ self.piCam.start_preview(fullscreen = False, window=self.AHFpreview)
+ result = input('Press any key to stop')
+ self.piCam.stop_preview()
+ elif inputStr == 'r':
+ print("Starting recording for 10 seconds")
+ self.start_recording()
+ time.sleep(10)
+ self.stop_recording()
+ elif inputStr == 't':
+ self.setdown()
+ self.settingsDict = self.config_user_get(self.settingsDict)
+ self.setup()
+ elif inputStr == 'q':
+ break
+ pass
+
+
diff --git a/AHF_Camera/__init__.py b/AHF_Camera/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_ClassAndDictUtils.py b/AHF_ClassAndDictUtils.py
index 87e1984..1fdef32 100755
--- a/AHF_ClassAndDictUtils.py
+++ b/AHF_ClassAndDictUtils.py
@@ -9,7 +9,7 @@
from collections import OrderedDict
import json
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
"""
methods for
@@ -21,7 +21,7 @@
##################################################################################
-def Class_from_file(nameTypeStr, nameStr):
+def Class_from_file(nameTypeStr, nameStr, dirName=''):
"""
Imports a module from a fileName(stripped of the .py) and returns the class
@@ -31,8 +31,8 @@ def Class_from_file(nameTypeStr, nameStr):
fileName = 'AHF_' + nameTypeStr
else:
fileName = 'AHF_' + nameTypeStr + '_' + nameStr
- module = __import__(fileName)
- return getattr(module, fileName)
+ module = __import__(dirName+'.'+fileName)
+ return getattr(getattr(module, fileName), fileName)
def Super_of_object(anObject):
@@ -66,7 +66,7 @@ def Subclass_from_user(aSuperClass):
for f in os.listdir(os.curdir):
try:
- moduleObj=__import__(f.rstrip('.py'))
+ moduleObj=__import__(f[:-3])
#print('module=' + str(moduleObj))
classObj = getattr(moduleObj, moduleObj.__name__)
#print(classObj)
@@ -107,8 +107,7 @@ def File_from_user(nameTypeStr, longName, typeSuffix, makeNew = False):
startStr = 'AHF_' + nameTypeStr + '_'
startlen = len(startStr)
endLn = len(typeSuffix)
- # print(os.listdir(os.curdir))
- for f in os.listdir(os.curdir):
+ for f in os.listdir(os.curdir + os.sep + 'AHF_'+nameTypeStr):
if f.startswith(startStr) and f.endswith(typeSuffix):
fname = f[startlen :-endLn]
if typeSuffix != '.py':
@@ -117,10 +116,10 @@ def File_from_user(nameTypeStr, longName, typeSuffix, makeNew = False):
#print(fname)
else:
try:
- moduleObj=__import__(f.rstrip(typeSuffix))
- print('module=' + str(moduleObj))
- classObj = getattr(moduleObj, moduleObj.__name__)
- print(classObj)
+ className = f[:-len(typeSuffix)]
+ moduleObj=__import__(startStr[:-1]+'.'+className)
+ #Going from two modules into one module and then into one class
+ classObj = getattr(getattr(moduleObj, className),className)
isAbstractClass = inspect.isabstract(classObj)
if isAbstractClass == False:
fileList.append(fname + ": " + classObj.about())
@@ -195,7 +194,7 @@ def Show_ordered_object(anObject, longName, isTaskConfig = False):
fields = sorted(inspect.getmembers(anObject))
# To simplify main menu, ignore the below classes. None of these have more
# one option.
- task_blacklist = ["BrainLightClass", "CameraClass", "LickDetectorClass", "ReaderClass", "SubjectsClass"]
+ task_blacklist = ["BrainLightClass", "LickDetectorClass", "ReaderClass", "SubjectsClass"]
for item in fields:
if not(inspect.isroutine(item [1]) or isinstance(item[1], AHF_Base) or item[0].startswith('_')):
if isTaskConfig and "Class" not in item[0] and "Dict" not in item[0]:
@@ -217,6 +216,8 @@ def Edit_Obj_fields(anObject, longName, isTaskConfig = False):
changes = False
while True:
showDict = Show_ordered_object(anObject, longName, isTaskConfig)
+ print('\n')
+ print('Make sure you check [DataLoggerDict] for database passwords and [SubjectsDict] for mouse config file names before proceeding')
inputStr = input('Enter number of setting to edit, or 0 to exit:')
try:
inputNum = int(inputStr)
@@ -236,7 +237,7 @@ def Edit_Obj_fields(anObject, longName, isTaskConfig = False):
if itemKey.endswith('Class') and(itemValue is None or isinstance(itemValue, ABCMeta)):
baseName = itemKey[:-5]
#newClassName = File_from_user(baseName, baseName, '.py')
- newClass = Class_from_file(baseName, File_from_user(baseName, baseName, '.py'))
+ newClass = Class_from_file(baseName, File_from_user(baseName, baseName, '.py'), 'AHF_'+baseName)
setattr(anObject, itemKey, newClass)
# new class needs new dict
dictName = baseName + 'Dict'
@@ -247,7 +248,7 @@ def Edit_Obj_fields(anObject, longName, isTaskConfig = False):
theClass = getattr(anObject, baseName + 'Class')
if theClass is None:
#newClassName = File_from_user(baseName, baseName, '.py')
- theClass = Class_from_file(baseName, File_from_user(baseName, baseName, '.py'))
+ theClass = Class_from_file(baseName, File_from_user(baseName, baseName, '.py'), 'AHF_'+baseName)
setattr(anObject, baseName + 'Class', theClass)
setattr(anObject, itemKey, theClass.config_user_get(itemValue))
elif type(itemValue) is str:
@@ -417,7 +418,7 @@ def Obj_fields_to_file(anObject, nameTypeStr, nameStr, typeSuffix, dir = ''):
fp.close()
uid = pwd.getpwnam('pi').pw_uid
gid = grp.getgrnam('pi').gr_gid
- os.chown(configFile, uid, gid) # we may run as root for pi PWM, so we need to expicitly set ownership
+ os.chown(dir+configFile, uid, gid) # we may run as root for pi PWM, so we need to expicitly set ownership
@@ -427,7 +428,7 @@ def File_to_obj_fields(nameTypeStr, nameStr, typeSuffix, anObject, dir = ''):
"""
filename = 'AHF_' + nameTypeStr + '_' + nameStr + typeSuffix
errFlag = False
- with open(dir + filename, 'r') as fp:
+ with open(dir + os.sep + filename, 'r') as fp:
data = fp.read()
data = data.rstrip("\n")
data=data.replace('\n', ',')
@@ -438,7 +439,7 @@ def File_to_obj_fields(nameTypeStr, nameStr, typeSuffix, anObject, dir = ''):
try:
if type(value) is str and key.endswith('Class'):
if value.startswith('AHF_'):
- setattr(anObject, key, Class_from_file(value[4:], ''))
+ setattr(anObject, key, Class_from_file(value[4:], '', 'AHF_'+str(key[:-5])))
else:
setattr(anObject, key, None)
else:
diff --git a/AHF_ContactCheck.py b/AHF_ContactCheck/AHF_ContactCheck.py
similarity index 96%
rename from AHF_ContactCheck.py
rename to AHF_ContactCheck/AHF_ContactCheck.py
index fae498b..194be23 100644
--- a/AHF_ContactCheck.py
+++ b/AHF_ContactCheck/AHF_ContactCheck.py
@@ -1,9 +1,11 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from abc import ABCMeta, abstractmethod
+import sys
+sys.path.append("../..")
-from AHF_Base import AHF_Base
+from abc import ABCMeta, abstractmethod
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_ContactCheck(AHF_Base, metaclass = ABCMeta):
diff --git a/AHF_ContactCheck_BeamBreak.py b/AHF_ContactCheck/AHF_ContactCheck_BeamBreak.py
similarity index 94%
rename from AHF_ContactCheck_BeamBreak.py
rename to AHF_ContactCheck/AHF_ContactCheck_BeamBreak.py
index afbe0c1..4e8b2ec 100755
--- a/AHF_ContactCheck_BeamBreak.py
+++ b/AHF_ContactCheck/AHF_ContactCheck_BeamBreak.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_ContactCheck_Elec import AHF_ContactCheck_Elec
+from AHF_ContactCheck.AHF_ContactCheck_Elec import AHF_ContactCheck_Elec
import RPi.GPIO as GPIO
class AHF_ContactCheck_BeamBreak(AHF_ContactCheck_Elec):
diff --git a/AHF_ContactCheck_Elec.py b/AHF_ContactCheck/AHF_ContactCheck_Elec.py
similarity index 98%
rename from AHF_ContactCheck_Elec.py
rename to AHF_ContactCheck/AHF_ContactCheck_Elec.py
index 5123f24..bc15024 100755
--- a/AHF_ContactCheck_Elec.py
+++ b/AHF_ContactCheck/AHF_ContactCheck_Elec.py
@@ -2,7 +2,7 @@
#-*-coding: utf-8 -*-
import RPi.GPIO as GPIO
from time import time, sleep
-from AHF_ContactCheck import AHF_ContactCheck
+from AHF_ContactCheck.AHF_ContactCheck import AHF_ContactCheck
import AHF_Task
gContactChecker = None
diff --git a/AHF_ContactCheck/__init__.py b/AHF_ContactCheck/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_DataLogger.py b/AHF_DataLogger/AHF_DataLogger.py
similarity index 98%
rename from AHF_DataLogger.py
rename to AHF_DataLogger/AHF_DataLogger.py
index e2276c4..6b3cb60 100644
--- a/AHF_DataLogger.py
+++ b/AHF_DataLogger/AHF_DataLogger.py
@@ -1,12 +1,15 @@
#! /usr/bin/python
# -*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
from collections import deque
-class AHF_DataLogger(AHF_Base, metaclass=ABCMeta):
+class AHF_DataLogger(AHF_Base, metaclass = ABCMeta):
"""
A Data Logger provides an interface to save task data, and to save
and load mouse configuration data. This can be either to text files, or to
diff --git a/AHF_DataLogger_localsql.py b/AHF_DataLogger/AHF_DataLogger_localsql.py
similarity index 99%
rename from AHF_DataLogger_localsql.py
rename to AHF_DataLogger/AHF_DataLogger_localsql.py
index c53410c..8738e1a 100644
--- a/AHF_DataLogger_localsql.py
+++ b/AHF_DataLogger/AHF_DataLogger_localsql.py
@@ -7,7 +7,7 @@
from AHF_Task import Task
from threading import Thread
import AHF_ClassAndDictUtils as CAD
-from AHF_DataLogger import AHF_DataLogger
+from AHF_DataLogger.AHF_DataLogger import AHF_DataLogger
import json
import os
import pwd
diff --git a/AHF_DataLogger_mysql.py b/AHF_DataLogger/AHF_DataLogger_mysql.py
similarity index 99%
rename from AHF_DataLogger_mysql.py
rename to AHF_DataLogger/AHF_DataLogger_mysql.py
index be88032..cac203c 100644
--- a/AHF_DataLogger_mysql.py
+++ b/AHF_DataLogger/AHF_DataLogger_mysql.py
@@ -7,7 +7,7 @@
from AHF_Task import Task
from threading import Thread
import AHF_ClassAndDictUtils as CAD
-from AHF_DataLogger import AHF_DataLogger
+from AHF_DataLogger.AHF_DataLogger import AHF_DataLogger
import json
import os
import pwd
diff --git a/AHF_DataLogger_text.py b/AHF_DataLogger/AHF_DataLogger_text.py
similarity index 99%
rename from AHF_DataLogger_text.py
rename to AHF_DataLogger/AHF_DataLogger_text.py
index 3c1b649..2a0a7b6 100644
--- a/AHF_DataLogger_text.py
+++ b/AHF_DataLogger/AHF_DataLogger_text.py
@@ -5,7 +5,7 @@
from time import time, localtime,timezone, sleep
from datetime import datetime
import AHF_ClassAndDictUtils as CAD
-from AHF_DataLogger import AHF_DataLogger
+from AHF_DataLogger.AHF_DataLogger import AHF_DataLogger
class AHF_DataLogger_text(AHF_DataLogger):
"""
Simple text-based data logger modified from the original Auto Head Fix code
@@ -154,7 +154,6 @@ def storeConfig(self, tag, configDict, source = ""):
CAD.Dict_to_file(configDict, 'mouse', '{:013}'.format(int(tag)), '.jsn', dir = self.configPath)
def saveNewMouse(self, tag, note, dictionary = {}):
- self.storeConfig(tag, dictionary)
self.writeToLogFile(tag, "NewMouse", dictionary, time())
def getMice(self):
diff --git a/AHF_DataLogger_textMySql.py b/AHF_DataLogger/AHF_DataLogger_textMySql.py
similarity index 95%
rename from AHF_DataLogger_textMySql.py
rename to AHF_DataLogger/AHF_DataLogger_textMySql.py
index 2623d78..2a186c5 100644
--- a/AHF_DataLogger_textMySql.py
+++ b/AHF_DataLogger/AHF_DataLogger_textMySql.py
@@ -1,10 +1,10 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-from AHF_DataLogger_text import AHF_DataLogger_text
-from AHF_DataLogger_mysql import AHF_DataLogger_mysql
-from AHF_DataLogger_localsql import AHF_DataLogger_localsql
-from AHF_DataLogger import AHF_DataLogger
+from AHF_DataLogger.AHF_DataLogger_text import AHF_DataLogger_text
+from AHF_DataLogger.AHF_DataLogger_mysql import AHF_DataLogger_mysql
+from AHF_DataLogger.AHF_DataLogger_localsql import AHF_DataLogger_localsql
+from AHF_DataLogger.AHF_DataLogger import AHF_DataLogger
class AHF_DataLogger_textMySql(AHF_DataLogger):
"""
diff --git a/AHF_DataLogger/__init__.py b/AHF_DataLogger/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_HardwareTester.py b/AHF_HardwareTester.py
index 658e317..9ae715b 100755
--- a/AHF_HardwareTester.py
+++ b/AHF_HardwareTester.py
@@ -3,8 +3,8 @@
from collections import OrderedDict
import inspect
-from AHF_Task import Task
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Task import Task
+from AutoHeadFix.AHF_Base import AHF_Base
def Show_testable_objects(anObject):
print('\n*************** Testable Auto Head Fix Objects *******************')
diff --git a/AHF_HeadFixer.py b/AHF_HeadFixer/AHF_HeadFixer.py
similarity index 99%
rename from AHF_HeadFixer.py
rename to AHF_HeadFixer/AHF_HeadFixer.py
index d253f47..00c3099 100755
--- a/AHF_HeadFixer.py
+++ b/AHF_HeadFixer/AHF_HeadFixer.py
@@ -1,10 +1,15 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+
+import sys
+sys.path.append("../..")
+
from time import time, sleep
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
import AHF_Task
from random import random
+
class AHF_HeadFixer(AHF_Base, metaclass= ABCMeta):
"""
Base class for all head fix classs. Other head fixers subclass from this, or from one of its subclasses
diff --git a/AHF_HeadFixer_NoFix.py b/AHF_HeadFixer/AHF_HeadFixer_NoFix.py
similarity index 97%
rename from AHF_HeadFixer_NoFix.py
rename to AHF_HeadFixer/AHF_HeadFixer_NoFix.py
index ae4c204..6764b19 100644
--- a/AHF_HeadFixer_NoFix.py
+++ b/AHF_HeadFixer/AHF_HeadFixer_NoFix.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_HeadFixer import AHF_HeadFixer
+from AHF_HeadFixer.AHF_HeadFixer import AHF_HeadFixer
import AHF_Task
from time import sleep, time
from _thread import start_new_thread
diff --git a/AHF_HeadFixer_PWM.py b/AHF_HeadFixer/AHF_HeadFixer_PWM.py
similarity index 99%
rename from AHF_HeadFixer_PWM.py
rename to AHF_HeadFixer/AHF_HeadFixer_PWM.py
index 51d3a6f..d06deae 100755
--- a/AHF_HeadFixer_PWM.py
+++ b/AHF_HeadFixer/AHF_HeadFixer_PWM.py
@@ -2,7 +2,7 @@
#-*-coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
-from AHF_HeadFixer import AHF_HeadFixer
+from AHF_HeadFixer.AHF_HeadFixer import AHF_HeadFixer
from time import sleep
from _thread import start_new_thread
from random import random
diff --git a/AHF_HeadFixer_PWM_PCA9685.py b/AHF_HeadFixer/AHF_HeadFixer_PWM_PCA9685.py
similarity index 93%
rename from AHF_HeadFixer_PWM_PCA9685.py
rename to AHF_HeadFixer/AHF_HeadFixer_PWM_PCA9685.py
index 4508e44..a72c05e 100644
--- a/AHF_HeadFixer_PWM_PCA9685.py
+++ b/AHF_HeadFixer/AHF_HeadFixer_PWM_PCA9685.py
@@ -12,11 +12,11 @@
# Import the PCA9685 module.
import Adafruit_PCA9685
-from AHF_HeadFixer_PWM import AHF_HeadFixer_PWM
+from AHF_HeadFixer.AHF_HeadFixer_PWM import AHF_HeadFixer_PWM
class AHF_HeadFixer_PWM_PCA9685(AHF_HeadFixer_PWM):
"""
- inherits from AHF_HeadFixer_PWM
+ inherits from AHF_HeadFixer.AHF_HeadFixer_PWM
"""
defaultAddress = 0x40
diff --git a/AHF_HeadFixer_PWM_Pi.py b/AHF_HeadFixer/AHF_HeadFixer_PWM_Pi.py
similarity index 95%
rename from AHF_HeadFixer_PWM_Pi.py
rename to AHF_HeadFixer/AHF_HeadFixer_PWM_Pi.py
index 59c64a0..d51f0fb 100755
--- a/AHF_HeadFixer_PWM_Pi.py
+++ b/AHF_HeadFixer/AHF_HeadFixer_PWM_Pi.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_HeadFixer_PWM import AHF_HeadFixer_PWM
+from AHF_HeadFixer.AHF_HeadFixer_PWM import AHF_HeadFixer_PWM
import ptPWM
from time import sleep
diff --git a/AHF_HeadFixer_Pistons.py b/AHF_HeadFixer/AHF_HeadFixer_Pistons.py
similarity index 98%
rename from AHF_HeadFixer_Pistons.py
rename to AHF_HeadFixer/AHF_HeadFixer_Pistons.py
index de1944d..a0a9181 100755
--- a/AHF_HeadFixer_Pistons.py
+++ b/AHF_HeadFixer/AHF_HeadFixer_Pistons.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_HeadFixer import AHF_HeadFixer
+from AHF_HeadFixer.AHF_HeadFixer import AHF_HeadFixer
import RPi.GPIO as GPIO
from time import sleep
from random import random
diff --git a/AHF_HeadFixer/__init__.py b/AHF_HeadFixer/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_LickDetector.py b/AHF_LickDetector/AHF_LickDetector.py
similarity index 96%
rename from AHF_LickDetector.py
rename to AHF_LickDetector/AHF_LickDetector.py
index b4d39ae..ad0af73 100755
--- a/AHF_LickDetector.py
+++ b/AHF_LickDetector/AHF_LickDetector.py
@@ -1,8 +1,12 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_LickDetector(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_LickDetector_MPR.py b/AHF_LickDetector/AHF_LickDetector_MPR.py
similarity index 99%
rename from AHF_LickDetector_MPR.py
rename to AHF_LickDetector/AHF_LickDetector_MPR.py
index 5677f67..bb4a89a 100755
--- a/AHF_LickDetector_MPR.py
+++ b/AHF_LickDetector/AHF_LickDetector_MPR.py
@@ -2,7 +2,7 @@
#-*-coding: utf-8 -*-
from TouchDetectorMPR121 import TouchDetector
-from AHF_LickDetector import AHF_LickDetector
+from AHF_LickDetector.AHF_LickDetector import AHF_LickDetector
import AHF_Task
from time import time
diff --git a/AHF_LickDetector/__init__.py b/AHF_LickDetector/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_LickDetector_CircuitPython b/AHF_LickDetector_CircuitPython
deleted file mode 100644
index 635d91a..0000000
--- a/AHF_LickDetector_CircuitPython
+++ /dev/null
@@ -1,201 +0,0 @@
-#! /usr/bin/python
-#-*-coding: utf-8 -*-
-
-import adafruit_mpr121
-from AHF_LickDetector import AHF_LickDetector
-import AHF_Task
-from time import time
-
-class AHF_LickDetector_CircuitPython(AHF_LickDetector):
- """
- Lick detector for Auto Head Fix based on 2020 Adafruit Circuit Python MPR121 capacitive touch sensor
- """
- defaultIRQ = 26 # GPIO pin for IRQ signal form lick detector, used for triggering callback
- defaultAddress = 0x5a # i2c addresss is 0x5a(90) with address pin tied to ground address will be 0x5b(91) with address pin tied to 3v3
- defaultTouchThresh = 8 # 8 bit value for what constitutes a touch, recommended by dirkjan
- defaultUntouchThresh = 4 # # 8 bit value for what constitutes an un-touch, recommended by dirkjan
- defaultTouchChannels =(0,1,2,3) # number of channels on the mpr121 is 12, but last channel is sum of all channels
-
- @staticmethod
- def logTouchCallback(touchedChannel):
- """
- custom callback using global task reference from AHF_Task
- """
- AHF_Task.gTask.DataLogger.writeToLogFile(AHF_Task.gTask.tag, 'lick', {'chan' : touchedChannel}, time())
- #newVal = AHF_Task.gTask.Subjects.get(AHF_Task.gTask.tag).get('resultsDict').get('LickDetector', {}).get('licks', 0) + 1
- #AHF_Task.gTask.Subjects.get(AHF_Task.gTask.tag).get('resultsDict').get('LickDetector').update({'licks' : newVal})
-
-
- @staticmethod
- def about():
- return 'Lick detector using the mpr121 capacitive touch sensor breakout from sparkfun over i2c bus'
-
-
- @staticmethod
- def config_user_get(starterDict = {}):
- pin = starterDict.get('IRQpin', AHF_LickDetector_CircuitPython.defaultIRQ)
- response = input('Enter the GPIO pin connected to IRQ pin on the MPR121 breakout(currently %d:) ' % pin)
- if response != '':
- pin = int(response)
- mprAddress = starterDict.get('mprAddress', AHF_LickDetector_CircuitPython.defaultAddress)
- response = input("Enter MPR121 I2C Address, in Hexadecimal, currently 0x%x: " % mprAddress)
- if response != '':
- mprAddress = int(response, 16)
- touchThresh = starterDict.get('touchThresh', AHF_LickDetector_CircuitPython.defaultTouchThresh)
- response = input('Enter 8-bit(0-255) touch threshold value, curently %d: ' % touchThresh)
- if response != '':
- touchthresh = int(response)
- unTouchThresh = starterDict.get('unTouchThresh', AHF_LickDetector_CircuitPython.defaultUntouchThresh)
- response = input('Enter 8-bit(0-255) un-touch threshold value, curently %d: ' % unTouchThresh)
- if response != '':
- unTouchthresh = int(response)
- touchChans = starterDict.get('touchChans', AHF_LickDetector_CircuitPython.defaultTouchChannels)
- response = input('Enter comma-separarted list of channels(0 -11) to monitor, currently {:s}: '.format(str(touchChans)))
- if response != '':
- tempList = []
- for chan in response.split(','):
- tempList.append(int(chan))
- touchChans = tuple(tempList)
- starterDict.update({'mprAddress' : mprAddress, 'IRQpin' : pin, 'touchThresh' : touchThresh})
- starterDict.update({'unTouchThresh' : unTouchThresh, 'touchChans' : touchChans})
- return starterDict
-
-
- def setup(self):
- # read dictionary
- self.IRQpin = self.settingsDict.get('IRQpin')
- self.I2Caddress = self.settingsDict.get('mprAddress')
- self.touchThresh = self.settingsDict.get('touchThresh')
- self.unTouchThresh = self.settingsDict.get('unTouchThresh')
- self.touchChans = self.settingsDict.get('touchChans')
- self.isLogging = False
- # init touch detector
- self.touchDetector = TouchDetector(self.I2Caddress, self.touchThresh, self.unTouchThresh, self.touchChans, self.IRQpin)
- self.touchDetector.addCustomCallback(self.logTouchCallback)
-
- def setdown(self):
- if hasattr(self, 'touchDetector'):
- del self.touchDetector
-
-
- def newResultsDict(self, starterDict = {}):
- """
- Returns a dictionary with fields, initialized to 0,
- """
- starterDict.update({'licks' : starterDict.get('licks', 0)})
- return starterDict
-
-
- def clearResultsDict(self, resultsDict):
- """
- Clears values in the results dictionary, for daily totals of licks on all channels. Could be extended to per channel data
- """
- resultsDict.update({'licks' : 0})
-
-
- def getTouches(self):
- """
- gets touches from mpr121
- """
- return self.touchDetector.touched()
-
-
- def startLickCount(self):
- """
- Zeros the selected list of channels in the global array of licks per channel that the callback function updates.
- Use it to count licks, by zeroing selected channels, then checking the values in the array
- """
- self.touchDetector.startCount()
-
- def resumeLickCount(self):
- """
- Continue the lick counting without zeroing the channels
- """
- self.touchDetector.resumeCount()
-
- def getLickCount(self):
- """
- Get the number of licks for each channel in the global array without stopping the count.
- """
- return self.touchDetector.getCount()
-
-
- def stopLickCount(self, chanList):
- """
- takes a list of channels and returns a list where each member is the number of licks for that channel in the global array
- call zeroLickCount, wait a while for some licks, then call getLickCount
- """
- return self.touchDetector.stopCount()
-
-
- def startLickTiming(self):
- self.touchDetector.startTimeLog()
-
-
- def stopLickTiming(self):
- return self.touchDetector.stopTimeLog()
-
-
- def startLogging(self):
- """
- tells the AHF_LickDetectorCallback to log touches in shell and file(if present)
- """
- self.touchDetector.startCustomCallback()
- self.isLogging = True
-
- def stopLogging(self):
- """
- tells the AHF_LickDetectorCallback to stop logging touches in shell and file(if present)
- but the callback is still running
- """
- self.isLogging = False
- self.touchDetector.stopCustomCallback()
-
-
- def waitForLick(self, timeOut_secs, startFromZero=False):
- """
- Waits for a lick on any channel. Returns channel that was touched, or 0 if timeout expires with no touch,
- or -1 if startFromZero was True and the detector was touched for entire time
- """
- return self.touchDetector.waitForTouch(timeOut_secs, startFromZero)
-
-
- def resetDetector(self):
- """
- Calls MPR121 reset function. Should rarely need to do this? This could be of use in resetting baseline untouched values.
- """
- self.touchDetector._reset()
-
-
-
- def hardwareTest(self):
- from math import log
- """
- tests the lick detector, designed to be called by the hardware tester,can modify IRQ pin in hardware settings
- """
- wasLogging = False
- if self.isLogging:
- wasLogging = True
- self.stopLogging()
- lickError = 0
- self.getTouches()
- print('\nTo pass the test, start with lick spout untouched and touch spout within 10 seconds....')
- lick = self.waitForLick(10, True)
- if lick >= 1:
- print('PASS:Touch registerd on channel %d' % int(log(lick, 2))) # will round to highest number channel reporting touched
- else:
- if lick == -1:
- rStr= 'FAIL: Touch was registered the whole 10 seconds: '
- else:
- rStr= 'FAIL:No Touches were detected in 10 seconds: '
- inputStr=input(rStr + '\nDo you want to change the lick detetctor settings? :')
- if inputStr[0] == 'y' or inputStr[0] == "Y":
- self.setdown()
- self.settingsDict = self.config_user_get(self.settingsDict)
- self.setup()
- inputStr=input(rStr + '\nDo you want to re-calculate base-line values with a re-set? :')
- if inputStr[0] == 'y' or inputStr[0] == "Y":
- self.resetDetector()
- self.touchDetector.set_thresholds(self.touchThresh, self.unTouchThresh)
- if wasLogging :
- self.startLogging()
diff --git a/AHF_Notifier.py b/AHF_Notifier/AHF_Notifier.py
similarity index 95%
rename from AHF_Notifier.py
rename to AHF_Notifier/AHF_Notifier.py
index b6d511b..f205f20 100755
--- a/AHF_Notifier.py
+++ b/AHF_Notifier/AHF_Notifier.py
@@ -1,8 +1,10 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Notifier(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_Notifier_Requests.py b/AHF_Notifier/AHF_Notifier_Requests.py
similarity index 98%
rename from AHF_Notifier_Requests.py
rename to AHF_Notifier/AHF_Notifier_Requests.py
index eeb4b68..535f652 100644
--- a/AHF_Notifier_Requests.py
+++ b/AHF_Notifier/AHF_Notifier_Requests.py
@@ -1,6 +1,6 @@
import requests
from time import sleep
-from AHF_Notifier import AHF_Notifier
+from AHF_Notifier.AHF_Notifier import AHF_Notifier
class AHF_Notifier_Requests(AHF_Notifier):
"""
diff --git a/AHF_Notifier/__init__.py b/AHF_Notifier/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Reader.py b/AHF_Reader/AHF_Reader.py
similarity index 85%
rename from AHF_Reader.py
rename to AHF_Reader/AHF_Reader.py
index e010a9a..f715d4d 100644
--- a/AHF_Reader.py
+++ b/AHF_Reader/AHF_Reader.py
@@ -1,7 +1,11 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
+
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Reader(AHF_Base, metaclass = ABCMeta):
diff --git a/AHF_Reader_ID.py b/AHF_Reader/AHF_Reader_ID.py
similarity index 99%
rename from AHF_Reader_ID.py
rename to AHF_Reader/AHF_Reader_ID.py
index 5e796e7..87cfa10 100644
--- a/AHF_Reader_ID.py
+++ b/AHF_Reader/AHF_Reader_ID.py
@@ -7,7 +7,7 @@
import RFIDTagReader
import AHF_Task
-from AHF_Reader import AHF_Reader
+from AHF_Reader.AHF_Reader import AHF_Reader
class AHF_Reader_ID(AHF_Reader):
diff --git a/AHF_Reader/__init__.py b/AHF_Reader/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Rewarder.py b/AHF_Rewarder/AHF_Rewarder.py
similarity index 96%
rename from AHF_Rewarder.py
rename to AHF_Rewarder/AHF_Rewarder.py
index 3ea139f..588e8fb 100755
--- a/AHF_Rewarder.py
+++ b/AHF_Rewarder/AHF_Rewarder.py
@@ -1,9 +1,12 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from time import sleep
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Rewarder(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_Rewarder_solenoid.py b/AHF_Rewarder/AHF_Rewarder_solenoid.py
similarity index 99%
rename from AHF_Rewarder_solenoid.py
rename to AHF_Rewarder/AHF_Rewarder_solenoid.py
index f69edc1..de472dc 100644
--- a/AHF_Rewarder_solenoid.py
+++ b/AHF_Rewarder/AHF_Rewarder_solenoid.py
@@ -2,7 +2,7 @@
#-*-coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
-from AHF_Rewarder import AHF_Rewarder
+from AHF_Rewarder.AHF_Rewarder import AHF_Rewarder
from time import sleep, time
from collections import deque
diff --git a/AHF_Rewarder_solenoid_pt.py b/AHF_Rewarder/AHF_Rewarder_solenoid_pt.py
similarity index 94%
rename from AHF_Rewarder_solenoid_pt.py
rename to AHF_Rewarder/AHF_Rewarder_solenoid_pt.py
index a2de791..2b723f0 100644
--- a/AHF_Rewarder_solenoid_pt.py
+++ b/AHF_Rewarder/AHF_Rewarder_solenoid_pt.py
@@ -1,7 +1,7 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-from AHF_Rewarder_solenoid import AHF_Rewarder_solenoid
+from AHF_Rewarder.AHF_Rewarder_solenoid import AHF_Rewarder_solenoid
from PTSimpleGPIO import CountermandPulse
class AHF_Rewarder_solenoid_pt(AHF_Rewarder_solenoid):
diff --git a/AHF_Rewarder_solenoid_rpi.py b/AHF_Rewarder/AHF_Rewarder_solenoid_rpi.py
similarity index 97%
rename from AHF_Rewarder_solenoid_rpi.py
rename to AHF_Rewarder/AHF_Rewarder_solenoid_rpi.py
index 9d7393e..0eb94f5 100644
--- a/AHF_Rewarder_solenoid_rpi.py
+++ b/AHF_Rewarder/AHF_Rewarder_solenoid_rpi.py
@@ -1,7 +1,7 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-from AHF_Rewarder_solenoid import AHF_Rewarder_solenoid
+from AHF_Rewarder.AHF_Rewarder_solenoid import AHF_Rewarder_solenoid
import AHF_Task
import RPi.GPIO as GPIO
from _thread import start_new_thread
diff --git a/AHF_Rewarder/__init__.py b/AHF_Rewarder/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Stimulator.py b/AHF_Stimulator/AHF_Stimulator.py
similarity index 92%
rename from AHF_Stimulator.py
rename to AHF_Stimulator/AHF_Stimulator.py
index 5d1e0f4..09d93e8 100644
--- a/AHF_Stimulator.py
+++ b/AHF_Stimulator/AHF_Stimulator.py
@@ -1,9 +1,11 @@
#! /usr/bin/python
# -*-coding: utf-8 -*
+import sys
+sys.path.append("../..")
from abc import ABCMeta, abstractmethod
from time import time, sleep
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
from os import chown
from pwd import getpwnam
from grp import getgrnam
@@ -48,7 +50,7 @@ def startVideo(self):
self.lastTime = time()
print(hex(id(self)), 'start')
print(self.lastTime)
- video_name_path = "M" + video_name
+ video_name = 'M' + str(thisTag) + "_" + '%d' % self.lastTime + '.' + extension
#writeToLogFile(expSettings.logFP, thisMouse, "video:" + video_name)
# send socket message to start behavioural camera
self.task.DataLogger.writeToLogFile(thisTag, 'VideoStart', {'name': video_name}, time())
@@ -57,14 +59,14 @@ def startVideo(self):
MESSAGE = str(thisTag) + "_" + "_" + '%d' % self.task.lastFixedTime
self.task.Trigger.doTrigger(MESSAGE)
# start recording and Turn on the blue led
- camera.start_recording(video_name_path)
+ camera.start_recording(video_name)
sleep(self.task.Trigger.cameraStartDelay) # wait a bit so camera has time to start before light turns on, for synchrony accross cameras
self.task.BrainLight.onForStim()
self.task.DataLogger.writeToLogFile(thisTag, 'BrainLEDON', None, time())
else: # turn on the blue light and start the movie
self.task.BrainLight.onForStim()
self.task.DataLogger.writeToLogFile(thisTag, 'BrainLEDON', None, time())
- camera.start_recording(video_name_path)
+ camera.start_recording(video_name)
except Exception as anError:
camera.stop_recording()
print('Error in running trial:' + str(anError))
@@ -89,7 +91,7 @@ def stopVideo(self):
if self.lastTime is None:
print("no last")
return
- video_name_path = "M" + video_name
+ video_name = str(thisTag) + "_" + '%d' % self.lastTime + '.' + extension
if hasattr(self.task, 'Trigger'):
self.task.BrainLight.offForStim() # turn off the blue LED
self.task.DataLogger.writeToLogFile(thisTag, 'BrainLEDOFF', None, time())
diff --git a/AHF_Stimulator/AHF_Stimulator_ClosedLoop.py b/AHF_Stimulator/AHF_Stimulator_ClosedLoop.py
new file mode 100644
index 0000000..63b84f1
--- /dev/null
+++ b/AHF_Stimulator/AHF_Stimulator_ClosedLoop.py
@@ -0,0 +1,169 @@
+#AHF-specific moudules
+from AHF_Stimulator.AHF_Stimulator import AHF_Stimulator
+
+#Closed loop stimulator modules
+import numpy as np
+import sys
+import matplotlib.pyplot as plt
+from PTPWM import PTPWM
+from array import array
+from queue import Queue as queue
+from threading import Thread
+from multiprocessing import Process, Queue
+from time import sleep, time
+from random import random
+from datetime import datetime
+from itertools import combinations,product
+import warnings
+
+import cv2
+import imutils
+import wiringpi as wpi
+import os
+import tables
+import csv
+
+
+class AHF_Stimulator_ClosedLoop(AHF_Stimulator):
+ """
+
+ """
+ defaultSummaryFile = 'expt_summary.csv'
+ defaultAudioPin = -1
+ defaultNumTones = 10
+ defaultRewardThreshold = 50
+ defaultSessionDuration = 2
+ defaultMOGHistory = 15
+ defaultVarThreshold = 3
+
+
+ @staticmethod
+ def about():
+ return 'Closed loop experiment. Rewards given based if brain activity goes above threshold in ROI'
+
+
+ @staticmethod
+ def config_user_get(starterDict = {}):
+ # Summary file name
+ summary_file_name = starterDict.get('summary_file_name', AHF_Stimulator_ClosedLoop.defaultSummaryFile)
+ temp = input('Enter the name of the summary csv file, currently ' + summary_file_name + ' : ')
+ if temp != '':
+ summary_file_name = temp
+ starterDict.update({'summary_file_name' : summary_file_name})
+ # Audio pin
+ audio_pin = starterDict.get('audio_pin', AHF_Stimulator_ClosedLoop.defaultAudioPin)
+ temp = input('Enter the pin for audio tone generation, -1 for output to terminal only, currently ' + str(audio_pin) + ' : ')
+ if temp != '':
+ audio_pin = int(temp)
+ starterDict.update({'audio_pin' : audio_pin})
+ # Number of tones
+ num_tones = starterDict.get('num_tones', AHF_Stimulator_ClosedLoop.defaultNumTones)
+ temp = input('Enter the number of tones for audio tone generation, currently ' + str(num_tones) + ' : ')
+ if temp != '':
+ num_tones = int(temp)
+ starterDict.update({'num_tones' : num_tones})
+ # More configs here
+
+ return AHF_Stimulator.config_user_get(starterDict)
+
+ def config_user_subject_get(self, starterDict = {}):
+ # reward threshold
+ reward_threshold = starterDict.get('reward_threshold', AHF_Stimulator_ClosedLoop.defaultRewardThreshold)
+ temp = input ('Enter the reward threshold for this mouse, currently ' + reward_threshold + ' : ')
+ if temp != '':
+ reward_threshold = temp
+ starterDict.update({'reward_threshold' : reward_threshold})
+ return starterDict
+
+ def config_subject_get(self, starterDict = {}):
+ reward_threshold = starterDict.get('reward_threshold', AHF_Stimulator_ClosedLoop.defaultRewardThreshold)
+ starterDict.update({'reward_threshold' : reward_threshold})
+ return starterDict
+
+ def setup(self):
+ # super() sets up all the laser stuff plus self.headFixTime plus # rewards(not used here)
+ super().setup()
+ self.summary_file_name = self.settingsDict.get('summary_file_name', AHF_Stimulator_ClosedLoop.defaultSummaryFile)
+ self.audio_pin=int(self.settingsDict.get('audio_pin', AHF_Stimulator_ClosedLoop.defaultAudioPin))
+ self.num_tones=int(self.settingsDict.get('num_tones', AHF_Stimulator_ClosedLoop.defaultNumTones))
+ self.moghistory = AHF_Stimulator_ClosedLoop.defaultMOGHistory
+ self.var_threshold = AHF_Stimulator_ClosedLoop.defaultVarThreshold
+
+ # Closed-loop specific settings
+ # Starting audio pin
+ wpi.wiringPiSetupGpio()
+ wpi.softToneCreate(self.audio_pin)
+ # Compute frequency
+ self.freq_dict = self._get_freqs(self.num_tones)
+
+ # General AHF attributes
+ self.rewarder = self.task.Rewarder
+ self.camera = self.task.Camera
+ self.task.DataLogger.startTracking("Outcome", "code", "buffer", 200)
+
+
+ def quitting(self):
+ """
+ Called before AutoHEadFix exits. Gives stimulator chance to do any needed cleanup
+
+ A stimulator may, e.g., open files and wish to close them before exiting, or use hardware that needs to be cleaned up
+ """
+ self.task.Camera.stop_recording()
+ pass
+
+ #=================Main functions called from outside===========================
+ def run(self, level = -1, resultsDict = {}, settingsDict = {}, tag = 0):
+ super().run()
+ super().startVideo()
+ self.tag = self.task.tag
+ print('tag number...')
+ print(str(self.tag))
+
+ if not tag == 0:
+ print('dummy tag used')
+ self.tag = tag
+ else:
+ if self.tag <= 0:
+ print(str(self.tag))
+ super().stopVideo()
+ return
+
+ run_threads = True
+ runSession = True
+ runPreview = True
+ runRecording = True
+
+ fgbg = cv2.createBackgroundSubtractorMOG2(mogHistory, varThreshold, False)
+ cvui.init('closed_loop ROI selection')
+
+
+ def setdown(self):
+ print('Withhold stimulator set down')
+
+
+ def hardwareTest(self):
+ # TODO: Test this
+ self.setup()
+ while(True):
+ inputStr = input('q= quit: ')
+ if inputStr == 'q':
+ break
+ pass
+
+
+ def _get_freqs(self, nTones):
+ # quarter-octave increment factor
+ qo = 2 ** (1 / 4)
+ # initial audio frequency
+ freqs = [1000]
+ freqDict = {}
+
+ #import pdb; pdb.set_trace()
+ for i in range(1, nTones):
+ binSize = int(100 / nTones)
+ freq = freqs[-1] * qo
+
+ freqDict.update({i: freq for i in range(binSize * (i - 1), 101)})
+ freqs.append(freq)
+
+ return freqDict
\ No newline at end of file
diff --git a/AHF_Stimulator_LEDs.py b/AHF_Stimulator/AHF_Stimulator_LEDs.py
similarity index 99%
rename from AHF_Stimulator_LEDs.py
rename to AHF_Stimulator/AHF_Stimulator_LEDs.py
index 634de0f..65b7a32 100644
--- a/AHF_Stimulator_LEDs.py
+++ b/AHF_Stimulator/AHF_Stimulator_LEDs.py
@@ -1,7 +1,7 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
-from AHF_Stimulator_Rewards import AHF_Stimulator_Rewards
+from AHF_Stimulator.AHF_Stimulator_Rewards import AHF_Stimulator_Rewards
import RPi.GPIO as GPIO
from time import time, sleep
from datetime import datetime
diff --git a/AHF_Stimulator_Lever.py b/AHF_Stimulator/AHF_Stimulator_Lever.py
similarity index 99%
rename from AHF_Stimulator_Lever.py
rename to AHF_Stimulator/AHF_Stimulator_Lever.py
index 007791d..86cbc7d 100644
--- a/AHF_Stimulator_Lever.py
+++ b/AHF_Stimulator/AHF_Stimulator_Lever.py
@@ -3,8 +3,8 @@
import ptLeverThread
from array import array
-from AHF_Stimulator import AHF_Stimulator
-from AHF_Rewarder import AHF_Rewarder
+from AHF_Stimulator.AHF_Stimulator import AHF_Stimulator
+from AHF_Rewarder.Rewarder import AHF_Rewarder
import time
from random import random
from PTLeverThread import PTLeverThread
diff --git a/AHF_Stimulator_LickWithhold.py b/AHF_Stimulator/AHF_Stimulator_LickWithhold.py
similarity index 99%
rename from AHF_Stimulator_LickWithhold.py
rename to AHF_Stimulator/AHF_Stimulator_LickWithhold.py
index f916672..028047f 100644
--- a/AHF_Stimulator_LickWithhold.py
+++ b/AHF_Stimulator/AHF_Stimulator_LickWithhold.py
@@ -1,8 +1,8 @@
#AHF-specific moudules
-from AHF_Stimulus_Laser import AHF_Stimulus_Laser
-from AHF_Stimulator_Rewards import AHF_Stimulator_Rewards
-from AHF_Stimulator import AHF_Stimulator
+from AHF_Stimulus.AHF_Stimulus_Laser import AHF_Stimulus_Laser
+from AHF_Stimulator.AHF_Stimulator_Rewards import AHF_Stimulator_Rewards
+from AHF_Stimulator.AHF_Stimulator import AHF_Stimulator
from PTSimpleGPIO import PTSimpleGPIO, Infinite_train, Train
from random import random
import RPi.GPIO as GPIO
diff --git a/AHF_Stimulator_Rewards.py b/AHF_Stimulator/AHF_Stimulator_Rewards.py
similarity index 98%
rename from AHF_Stimulator_Rewards.py
rename to AHF_Stimulator/AHF_Stimulator_Rewards.py
index ec9626c..5e50278 100644
--- a/AHF_Stimulator_Rewards.py
+++ b/AHF_Stimulator/AHF_Stimulator_Rewards.py
@@ -3,13 +3,12 @@
from time import time, localtime,timezone, sleep
from datetime import datetime
-from AHF_Stimulator import AHF_Stimulator
+from AHF_Stimulator.AHF_Stimulator import AHF_Stimulator
class AHF_Stimulator_Rewards(AHF_Stimulator):
defaultRewards = 5
defaultInterval = 3
-
@staticmethod
def about():
return 'Rewards stimulator gives periodic rewards, no interaction from mouse required.'
diff --git a/AHF_Stimulator/__init__.py b/AHF_Stimulator/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Stimulus.py b/AHF_Stimulus/AHF_Stimulus.py
similarity index 92%
rename from AHF_Stimulus.py
rename to AHF_Stimulus/AHF_Stimulus.py
index 8a1d6de..9eb6c6b 100644
--- a/AHF_Stimulus.py
+++ b/AHF_Stimulus/AHF_Stimulus.py
@@ -1,7 +1,10 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Stimulus(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_Stimulus_Laser.py b/AHF_Stimulus/AHF_Stimulus_Laser.py
similarity index 79%
rename from AHF_Stimulus_Laser.py
rename to AHF_Stimulus/AHF_Stimulus_Laser.py
index 8556bd0..a349311 100644
--- a/AHF_Stimulus_Laser.py
+++ b/AHF_Stimulus/AHF_Stimulus_Laser.py
@@ -6,7 +6,7 @@
'''
# AHF-specific moudules
-from AHF_Stimulus import AHF_Stimulus
+from AHF_Stimulus.AHF_Stimulus import AHF_Stimulus
# Laser-stimulator modules
try:
@@ -37,6 +37,18 @@ class AHF_Stimulus_Laser(AHF_Stimulus):
Stimulates a specified region of the mouse's brain with a laser,
controlled via a stepper motor stage. Requires a camera - if using,
cannot record video of the trial with overhead camera (used for aligning)
+
+ The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+ on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+ hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+ more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+
+ Every time a mouse enters, the program will start an image registration process to compare the mouse's brain to that of its reference image.
+ This will generate a transform matrix that maps ROI coordinates into live mouse brain location.
+
+ **Issues: The image registration process takes around 30 seconds per trial, which is far slower than ideal. The bulk of the computation is done
+ in an external package, and we don't know whether it's optimized.**
+
"""
# def __init__(self, cageSettings, expSettings, rewarder, lickDetector, camera):
# super().__init__(cageSettings, expSettings, rewarder, lickDetector, camera)
@@ -47,6 +59,20 @@ def about():
@staticmethod
def config_user_get(starterDict = {}):
+ """
+ Prompts the user for settings for the AHF_Stimulus_Laser class. The following can be changed:
+
+ * **PWM_mode**: used for adding channels to PWM, use default setting 0
+ * **PWM_channel**: current channel for PWM, use default setting 2
+ * **duty_cycle**: duty cycle for the laser out of 100. Indicates the strength of laser, 0 means the laser is off.
+ * **laser_on_time**: how many seconds the laser is on for per pulse/stimulation
+ * **coeff_matrix**: matrix used for matching xy coordinates on user interface and xy coordinates of the stepper motor tracks.
+ * **Shift Register Settings**: DS, Q7S, SHCP, STCP are pins for the shift registers controlling the stepper motors. Keep these as default or as indicated by the wiring diagrams.
+ * **motor_delay**: how long (in seconds) the stepper motor waits between each step, smaller delay means faster maximum movement speed.
+ * **hdf_path**: directory to save hdf5 files
+
+ """
+
defaultMode = 0
defaultChannel = 2
defaultDutyCycle = 0
@@ -126,6 +152,13 @@ def config_user_get(starterDict = {}):
return starterDict
def setup(self):
+ """
+ Initializes the camera, pwm for laser, and relevant stepper motor settings from the settings dictionary.
+
+ This function is usually ran after self.config_user_get(), which ensures the settings dict exists.
+
+ This function also sets up GPIO pins. The pi throws errors when uninitialized pins are used, so make sure setup is called whenever program is restarted.
+ """
self.camera = self.task.Camera
#PWM settings
self.PWM_mode = int(self.settingsDict.get('PWM_mode', 0))
@@ -225,12 +258,22 @@ def setup(self):
self.rewardTimes = []
def trialPrep(self, tag):
+ """
+ Runs once at the start of stimulator. Calls the align() funtion.
+ """
return self.align(tag)
def stimulate(self):
+ """
+ Generates a single pulse with the laser. See pulse() function
+ """
self.pulse(self.laser_on_time, self.duty_cycle)
def length(self):
+ """
+ :return: the laser on time per pulse
+ :rtype: integer
+ """
return self.laser_on_time
def period(self):
@@ -238,6 +281,9 @@ def period(self):
return 0.001
def trialEnd(self):
+ """
+ Procedures to end a trial: stops camera preview and recenters the stepper motors
+ """
#Move laser back to zero position at the end of the trial
self.camera.stop_preview()
self.move_to(np.array([0,0]),topleft=True,join=False)
@@ -245,7 +291,9 @@ def trialEnd(self):
#============== Utility functions for the stepper motors and laser =================
def unlock(self):
- #De-energize the motors by toggling 0 into all shift registers
+ """
+ De-energize the stepper motors by toggling 0 into all shift registers
+ """
GPIO.output(self.DS,0)
for i in range(8):
GPIO.output(self.SHCP,0)
@@ -254,7 +302,9 @@ def unlock(self):
GPIO.output(self.STCP,1)
def feed_byte(self,byte):
- #Toggle a byte into the shjft registers
+ """
+ Toggle a byte into the shjft registers
+ """
for j in byte:
GPIO.output(self.DS,j)
GPIO.output(self.SHCP,0)
@@ -263,8 +313,13 @@ def feed_byte(self,byte):
GPIO.output(self.STCP,1)
def get_state(self):
- # Read out serial output and store state. Feed state back into shift reg.
- # Create empty array to store the state
+ """
+ Read out serial output and store state. Feed state back into shift reg.
+ Create empty array to store the state
+
+ :return: current serial output state
+ :rtype: list of integers
+ """
state = np.empty(8,dtype=int)
for j in range(8):
out = GPIO.input(self.Q7S)
@@ -275,6 +330,14 @@ def get_state(self):
return state.tolist()
def get_dir(self,steps):
+ """
+ Utility function to get the direction of movement from a signed integer
+
+ :param steps: input displacement from user
+ :type steps: signed integer
+ :return: 1 if input is positive, -1 if negative, 0 if no motion
+ :rtype: integer
+ """
if steps > 0:
return 1
elif steps < 0:
@@ -283,6 +346,22 @@ def get_dir(self,steps):
return 0
def get_arrow_dir(self,key):
+ """
+ If arrow keys are pressed, return information fed to stepper motors
+
+ If page_up/down/home/end keys are pressed, return information fed to control UI crosshair.
+
+ Tapping on left shift key will toggle between fast and slow move speed.
+
+ Note: The fastest speed of motor movement depends on the motor_delay in config_user_get.
+
+ Note (signs): The UI and stepper motors both follow the coordinate system with right and down as positive, left and up as negative.
+
+ :param key: current keyboard stroke
+ :type key: keyboard.Key object
+ :return: motor x-axis displacement, motor y-axis displacement, crosshair x-axis displacement, crosshair y-axis displacement
+ :rtype: list of four integers
+ """
# return direction of stepper motor step and cross-hair step.
if key == keyboard.Key.shift:
if self.laser_step == 3:
@@ -313,7 +392,24 @@ def get_arrow_dir(self,key):
return 0,0,0,0
def on_press(self,key):
- # Callback function, which responds to keyboard strokes.
+ """
+ Callback function, which responds to keyboard strokes. Processes the results from get_arrow_dir
+
+ If arrow keys are pressed, queue up motor command and update motor position.
+
+ If page_up/down/home/end keys are pressed, update the crosshair position.
+
+ Space key saves the current stepper motor and crosshair position into arrays laser_points and image_points to be processed by matching()
+
+ Esc key saves the arrays laser_points and image_points arrays and terminates the matching process
+
+ Note: At least 3 points are required for matching
+
+ :param key: [description]
+ :type key: [type]
+ :return: [description]
+ :rtype: [type]
+ """
di = self.get_arrow_dir(key)
if any(np.asarray(di[:2])!=0):
self.mot_q.put(di[:2]) #Queue the motor command
@@ -344,7 +440,9 @@ def on_press(self,key):
pass
def make_cross(self):
- #Define a simple cross-hair and add it as an overlay to the preview
+ """
+ Define a simple cross-hair and add it as an overlay to the preview
+ """
cross = np.zeros((self.overlay_resolution[1],self.overlay_resolution[0],3),dtype=np.uint16)
cross[self.cross_pos[0],:,:] = 0xff
cross[:,self.cross_pos[1],:] = 0xff
@@ -353,9 +451,16 @@ def make_cross(self):
alpha=100)
def update_cross(self,q):
- #Callback function, which processes changes in the cross-hair position.
+ """
+ Callback function which processes changes in the cross-hair position and moves the crosshair on UI
+
+ :param q:
+ :type q: 2 entry array
+ :return: returns false if q contains null entries
+ :rtype: boolean
+ """
while True:
- #Repeatedly check wether queue has something to process
+ #Repeatedly check whether queue has something to process
if not q.empty():
prod = q.get()
if prod is None:
@@ -370,7 +475,18 @@ def update_cross(self,q):
pass
def update_mot(self,mot_q,phase_queue,delay,topleft):
- #Callback funtion to process new motor steps. Runs on a different processor.
+ """
+ Callback funtion to process new motor steps. Infinite loop that runs on a different processor.
+
+ :param mot_q: displacement to move the stepper motors by, updated by on_press
+ :type mot_q: 2-entry array
+ :param phase_queue: queue representing the current motor phase
+ :type phase_queue: 2-entry array
+ :param delay: delay between each step
+ :type delay: integer
+ :param topleft: true if origin is set to top left corner instead of center
+ :type topleft: boolean
+ """
while True:
if not mot_q.empty():
x,y = mot_q.get()
@@ -381,7 +497,20 @@ def update_mot(self,mot_q,phase_queue,delay,topleft):
def move(self,x,y,phase,delay,topleft,mp):
- #Main function, which moves stepper motors by x and y.
+ """
+ Main function, which moves stepper motors by x and y.
+
+ :param x: x-axis displacement
+ :type x: integer
+ :param y: y-axis displacement
+ :type y: integer
+ :param phase: current phase of the stepper motors
+ :type phase: 2 entry array
+ :param delay: delay between each step
+ :type delay: integer
+ :param topleft: true if origin is set to top left corner instead of center
+ :type topleft: boolean
+ """
if mp == True:
phase_x,phase_y = phase.get()
else:
@@ -451,7 +580,17 @@ def move(self,x,y,phase,delay,topleft,mp):
phase.put([phase_x,phase_y])
def move_to(self,new_pos,topleft=True,join=False):
- #High-level function, which invokes self.move to run on another processor
+ """
+ High-level function, which invokes self.move to run on another processor. Moves the stepper motors to the specified position.
+
+ :param new_pos: x, y coordinates of the new position
+ :type new_pos: 2-entry array
+ :param topleft: parameter to the move() function, defaults to True
+ :type topleft: bool, optional
+ :param join: whether to kill process after 30 second timeout, defaults to False
+ :type join: bool, optional
+ """
+ #
steps = np.around(new_pos).astype(int) - self.pos
print('Current:\nx: '+str(self.pos[0])+'\ny: '+str(self.pos[1]))
print('Target:\nx: '+str(new_pos[0])+'\ny: '+str(new_pos[1]))
@@ -479,6 +618,14 @@ def move_to(self,new_pos,topleft=True,join=False):
self.pos += steps
def pulse(self,duration,duty_cycle=0):
+ """
+ Generates one laser pulse
+
+ :param duration: duration of laser pulse
+ :type duration: float
+ :param duty_cycle: duty cycle of the pwm used to drive laser, defaults to 0
+ :type duty_cycle: float, optional
+ """
if duration < 1000:
# for i in range(len(self.array)):
# self.array[i] = 0
@@ -497,6 +644,14 @@ def pulse(self,duration,duty_cycle=0):
#==== High-level Utility functions: Matching of coord systems, target selection and image registration ====
def matcher(self):
+ """
+ Starts GUI to match coordinate systems.
+ The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+ on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+ hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+ more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+
+ """
#GUI to select three points using the matching aid tool.
if keyboard is None:
return
@@ -577,13 +732,18 @@ def solver(image_points,laser_points):
print("Center in laser coords:", np.dot(self.coeff, np.asarray([self.camera.resolution()[0], self.camera.resolution()[1], 1])))
def get_ref_im(self):
- #Save a reference image whithin the mouse object
+ """
+ Save a reference image whithin the mouse object (in hdf5 format)
+ """
print('Taking ref image')
self.mouse.update({'ref_im' : np.empty((self.camera.resolution()[1], self.camera.resolution()[0], 3),dtype=np.uint16)})
self.mouse.update({'timestamp': time()})
self.camera.capture(self.mouse.get('ref_im'),'rgb')
def select_targets(self):
+ """
+ Menu function to select or update targets for one or more mice
+ """
if path.exists(self.hdf_path):
with File(self.hdf_path, 'r+') as hdf:
for tag, mouse in hdf.items():
@@ -596,6 +756,14 @@ def select_targets(self):
# GUI function for the selecting targets
def manual_annot(img):
+ """
+ Draws the target point on the GUI where user clicks
+
+ :param img: reference image of the mouse, the background of target selection
+ :type img: 3D array of dimensions camera y resolution by camera x resolution by 3 (rgb)
+ :return: coordinates of the target
+ :rtype: integer pair
+ """
warnings.filterwarnings("ignore",".*GUI is implemented.*")
plt.figure(figsize=(self.camera.resolution()[0]/100, self.camera.resolution()[1]/100))
plt.imshow(img)
@@ -637,8 +805,26 @@ def manual_annot(img):
def image_registration(self):
- # Runs at the beginning of a new trial
+ """
+ Image registration runs at the beginning of a new trial. Uses discrete fourier transform to find the transformation matrix from reference image
+ to current brain image. Then transforms the target point on reference image to a position to a point on current brain image. Finally transforms that
+ position into action stepper motor x and y steps.
+ """
def trans_mat(angle,x,y,scale):
+ """
+ Utility function to get the transformation matrix
+
+ :param angle: angle to rotate by
+ :type angle: float in degrees
+ :param x: translation in x direction
+ :type x: float
+ :param y: translation in y direction
+ :type y: float
+ :param scale: scaling factor
+ :type scale: float
+ :return: transformation matrix
+ :rtype: n by n matrix, based on the dimensions of x and y
+ """
# Utility function to get the transformation matrix
angle = -1*np.radians(angle)
scale = 1/scale
@@ -688,9 +874,19 @@ def trans_mat(angle,x,y,scale):
#=================Main functions called from outside===========================
def align(self, tag, resultsDict = {}, settingsDict = {}):
"""
- Aligns laser with reference image and assigned targets.
- Returns True if aligned successfully, False otherwise.
+ Process for trial prep. First checks if reference image, target, and match coefficient matrices are present and prompts use to fill those in.
+ Then aligns laser with reference image and assigned target
+
+ :param tag: mouse tag
+ :type tag: integer
+ :param resultsDict: dictionary to save trial results, defaults to {}
+ :type resultsDict: dict, optional
+ :param settingsDict: mouse settings dictionary, defaults to {}
+ :type settingsDict: dict, optional
+ :return: True if aligned successfully, False otherwise
+ :rtype: boolen
"""
+
self.tag = tag
self.mouse = self.task.Subjects.get(self.tag)
self.loadH5()
@@ -777,8 +973,19 @@ def align(self, tag, resultsDict = {}, settingsDict = {}):
def hardwareTest(self):
- # Tester function called from the hardwareTester. Includes Stimulator
- # specific hardware tester.
+ """
+ Tester function called from the hardwareTester. Includes Stimulator specific hardware tester. Functions available include:
+
+ * m: run matching between UI and stepper motors
+ * i: tests a trial with a dummy mouse
+ * r: edit reference image
+ * t: select target ROI
+ * a: test accuracy of laser movement
+ * p: pulses the laser for 1 second
+ * l: camera preview with brainlight
+ * c: test motor movement, user will enter coordinates to move towards
+ """
+
while(True):
inputStr = input('i= dummy trial, r= reference image, m= matching, t= targets, a = accuracy, p= laser tester, c= motor check, l= preview/LED, q= quit: ')
self.tag = 111111111
@@ -872,10 +1079,15 @@ def accuracyTest(self):
ref.attrs.modify('IMAGE_MINMAXRANGE', [0,self.camera.resolution()[0]])
def setdown(self):
- #Remove portions saved in h5
+ """
+ Nothing specifc to setdown in laser module. Only sets down the AHF_Stimulus superclass
+ """
super().setdown()
def loadH5(self):
+ """
+ Loads an hdf file from a specific path self.hdf_path
+ """
if(path.exists(self.hdf_path)):
with File(self.hdf_path, 'r+') as hdf:
for tag, mouse in hdf.items():
@@ -891,6 +1103,9 @@ def loadH5(self):
pass
def editReference(self):
+ """
+ Utility function to view and replace the reference image from menu
+ """
tag = ""
if(path.exists(self.hdf_path)):
with File(self.hdf_path, 'r+') as hdf:
@@ -939,6 +1154,9 @@ def editReference(self):
def h5updater(self):
+ """
+ Updates the mouse's hdf5 file with reference image, targets, trial images, and laser spot information collected from self.mouse
+ """
with File(self.hdf_path, 'r+') as hdf:
mouse = hdf.require_group(str(self.tag))
resolution_shape =( self.camera.resolution()[1], self.camera.resolution()[0], 3) #rgb layers
diff --git a/AHF_Stimulus_None.py b/AHF_Stimulus/AHF_Stimulus_None.py
similarity index 93%
rename from AHF_Stimulus_None.py
rename to AHF_Stimulus/AHF_Stimulus_None.py
index 50d65de..0c4a198 100644
--- a/AHF_Stimulus_None.py
+++ b/AHF_Stimulus/AHF_Stimulus_None.py
@@ -1,6 +1,6 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-from AHF_Stimulus import AHF_Stimulus
+from AHF_Stimulus.AHF_Stimulus import AHF_Stimulus
class AHF_Stimulus_None(AHF_Stimulus):
"""
diff --git a/AHF_Stimulus_VibMotor.py b/AHF_Stimulus/AHF_Stimulus_VibMotor.py
similarity index 98%
rename from AHF_Stimulus_VibMotor.py
rename to AHF_Stimulus/AHF_Stimulus_VibMotor.py
index 4cbc47e..f567959 100644
--- a/AHF_Stimulus_VibMotor.py
+++ b/AHF_Stimulus/AHF_Stimulus_VibMotor.py
@@ -1,6 +1,6 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-from AHF_Stimulus import AHF_Stimulus
+from AHF_Stimulus.AHF_Stimulus import AHF_Stimulus
from PTSimpleGPIO import PTSimpleGPIO, Infinite_train, Train
from time import sleep
from AHF_Task import Task
diff --git a/AHF_Stimulus/__init__.py b/AHF_Stimulus/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Subjects.py b/AHF_Subjects/AHF_Subjects.py
similarity index 97%
rename from AHF_Subjects.py
rename to AHF_Subjects/AHF_Subjects.py
index fd2ea94..fe47aa4 100644
--- a/AHF_Subjects.py
+++ b/AHF_Subjects/AHF_Subjects.py
@@ -1,7 +1,10 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Subjects(AHF_Base, metaclass = ABCMeta):
"""
diff --git a/AHF_Subjects_mice.py b/AHF_Subjects/AHF_Subjects_mice.py
similarity index 98%
rename from AHF_Subjects_mice.py
rename to AHF_Subjects/AHF_Subjects_mice.py
index 27f4941..5ea13ef 100755
--- a/AHF_Subjects_mice.py
+++ b/AHF_Subjects/AHF_Subjects_mice.py
@@ -2,7 +2,7 @@
#-*-coding: utf-8 -*-
-from AHF_Subjects import AHF_Subjects
+from AHF_Subjects.AHF_Subjects import AHF_Subjects
import AHF_ClassAndDictUtils as CAD
import json
import os
@@ -12,7 +12,7 @@
from AHF_Task import Task
from AHF_Reader import AHF_Reader
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
class AHF_Subjects_mice(AHF_Subjects):
"""
class for the mice, as experimental subjects. Contains a dictionary where key id IDtag, and value is a dictionary
@@ -28,6 +28,7 @@ class for the mice, as experimental subjects. Contains a dictionary where key id
jsonNameDefault = "subjects"
inChamberTimeLimitDefault = 300 #seconds
headFixTimeDefault = 40 #seconds
+ configPath = 'AHF_config/'
@staticmethod
@@ -74,7 +75,7 @@ def setup(self):
self.miceDict.update(configTuple)
elif self.loadConfigs == "provide_json": #check file, if not existing or not correct provide a fillable json, then update miceDict when user is ready
try:
- direc = ''
+ direc = ""
if os.getcwd() == "/root":
with open("/home/pi/config.txt", "r") as file:
configs = file.readlines()
@@ -82,7 +83,7 @@ def setup(self):
config = config.split("=")
if config[0] == "path":
direc = config[1].rstrip("\n")
- self.miceDict = CAD.File_to_dict('mice', self.jsonName, '.jsn', direc)
+ self.miceDict = CAD.File_to_dict('mice', self.jsonName, '.jsn', self.configPath)
if self.check_miceDict(self.miceDict) == False:
raise Exception('Could not confirm dictionary')
except Exception as e:
@@ -119,11 +120,11 @@ def create_fillable_json(self):
if stillmore[0] == "n" or stillmore[0] == "N":
moreMice = False
print(self.miceDict)
- CAD.Dict_to_file(self.miceDict, "mice_fillable", self.jsonName, ".jsn")
+ CAD.Dict_to_file(self.miceDict, "mice_fillable", self.jsonName, ".jsn", dir=configPath)
input("Please edit the values in AHF_mice_fillable_" + self.jsonName + '.jsn now. Do not modify the structure.\n' +
"Press enter when done")
os.system("sudo cp AHF_mice_fillable_" + self.jsonName + ".jsn" + " AHF_mice_" + self.jsonName + ".jsn")
- self.miceDict = CAD.File_to_dict('mice', self.jsonName, '.jsn')
+ self.miceDict = CAD.File_to_dict('mice', self.jsonName, '.jsn',dir=configPath)
def depth(self,d, level=0):
@@ -313,13 +314,13 @@ def subjectSettings(self):
elif event[0].lower() == 'a' or event[0].lower() == 't': # other two choices are for adding a mouse by RFID Tag, either reading from Tag Reader, or typing it
self.task.Reader.stopLogging()
self.add(event)
- CAD.Dict_to_file(self.miceDict, "mice", self.jsonName, ".jsn")
+ CAD.Dict_to_file(self.miceDict, "mice", self.jsonName, ".jsn", dir='AHF_config/')
self.task.Reader.startLogging()
else:
break
response = input('Save changes in settings to a json file, too?(recommended)')
if response[0] == 'Y' or response[0] == 'y':
- CAD.Dict_to_file(self.miceDict, "mice", self.jsonName, ".jsn")
+ CAD.Dict_to_file(self.miceDict, "mice", self.jsonName, ".jsn", dir='AHF_config/')
def hardwareTest(self):
diff --git a/AHF_Subjects/__init__.py b/AHF_Subjects/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_Task.py b/AHF_Task.py
index f2ac813..367eafa 100755
--- a/AHF_Task.py
+++ b/AHF_Task.py
@@ -1,6 +1,7 @@
#! /usr/bin/python
#-*-coding: utf-8 -*-
-
+import sys
+sys.path.append('..')
"""
We copy all variables from cage settings and exp settings, plus references to all created objects,
@@ -16,8 +17,9 @@
import grp
import AHF_ClassAndDictUtils as CAD
from abc import ABCMeta
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
import RPi.GPIO as GPIO
+from AHF_BrainLight.AHF_BrainLight import AHF_BrainLight
gTask = None
@@ -40,11 +42,11 @@ def __init__(self, fileName = '', object = None ):
if fileName != '':
# file name passed in may or may not start with AFH_task_ and end with .jsn
self.fileName = fileName
- if self.fileName.startswith('AHF_task_'):
- self.fileName = self.filename[9:]
+ if self.fileName.startswith('AHF_config_'):
+ self.fileName = self.filename[11:]
if self.fileName.endswith('.jsn'):
self.filename = self.fileName.rstrip('.jsn')
- if not CAD.File_exists('task', self.fileName, '.jsn'):
+ if not CAD.File_exists('config', self.fileName, '.jsn'):
self.fileName = ''
else:
self.fileName = ''
@@ -53,7 +55,7 @@ def __init__(self, fileName = '', object = None ):
for key, value in object.items():
if type(value) is str and key.endswith('Class'):
if value.startswith("AHF_"):
- setattr(self, key, CAD.Class_from_file(value[4:], ''))
+ setattr(self, key, CAD.Class_from_file(value[4:], '', dirName='AHF_'+key[:-5]))
else:
setattr(self, key, None)
else:
@@ -62,7 +64,7 @@ def __init__(self, fileName = '', object = None ):
# no file passed in, or passed in file could not be found. Get user to choose a file
if object is None and self.fileName == '':
try:
- self.fileName = CAD.File_from_user('task', 'Auto Head Fix task configuration', '.jsn', True)
+ self.fileName = CAD.File_from_user('config', 'Auto Head Fix task configuration', '.jsn', True)
except FileNotFoundError:
self.fileName = ''
print('Let\'s configure a new task.\n')
@@ -70,7 +72,7 @@ def __init__(self, fileName = '', object = None ):
# if we found a file, try to load it
if object is None and self.fileName != '':
try:
- CAD.File_to_obj_fields('task', self.fileName, '.jsn', self)
+ CAD.File_to_obj_fields('config', self.fileName, '.jsn', self, dir='AHF_config')
except ValueError as e:
print('Unable to open and fully load task configuration:' + str(e))
fileErr = True
@@ -78,29 +80,29 @@ def __init__(self, fileName = '', object = None ):
# things like head fixer that are subclassable need some extra work , when either loaded from file or user queried
########## Head Fixer(obligatory) makes its own dictionary #################################
if not hasattr(self, 'HeadFixerClass') or not hasattr(self, 'HeadFixerDict'):
- self.HeadFixerClass = CAD.Class_from_file('HeadFixer', CAD.File_from_user('HeadFixer', 'Head Fixer Class', '.py'))
+ self.HeadFixerClass = CAD.Class_from_file('HeadFixer', CAD.File_from_user('HeadFixer', 'Head Fixer Class', '.py'), dirName='AHF_HeadFixer')
self.HeadFixerDict = self.HeadFixerClass.config_user_get()
fileErr = True
################################ Stimulator(Obligatory) makes its own dictionary #######################
if not hasattr(self, 'StimulusClass') or not hasattr(self, 'StimulusDict'):
- self.StimulusClass = CAD.Class_from_file('Stimulus', CAD.File_from_user('Stimulus', 'Experiment Stimulus Class', '.py'))
+ self.StimulusClass = CAD.Class_from_file('Stimulus', CAD.File_from_user('Stimulus', 'Experiment Stimulus Class', '.py'), dirName='AHF_Stimulus')
#requires a starter dict?
self.StimulusDict = self.StimulusClass.config_user_get()
fileErr = True
################################ Stimulator(Obligatory) makes its own dictionary #######################
if not hasattr(self, 'StimulatorClass') or not hasattr(self, 'StimulatorDict'):
- self.StimulatorClass = CAD.Class_from_file('Stimulator', CAD.File_from_user('Stimulator', 'Experiment Stimulator Class', '.py'))
+ self.StimulatorClass = CAD.Class_from_file('Stimulator', CAD.File_from_user('Stimulator', 'Experiment Stimulator Class', '.py'), dirName='AHF_Stimulator')
#requires a starter dict?
self.StimulatorDict = self.StimulatorClass.config_user_get()
fileErr = True
################################ Rewarder(Obligatory) class makes its own dictionary #######################
if not hasattr(self, 'RewarderClass') or not hasattr(self, 'RewarderDict'):
- self.RewarderClass = CAD.Class_from_file('Rewarder', CAD.File_from_user('Rewarder', 'Rewarder', '.py'))
+ self.RewarderClass = CAD.Class_from_file('Rewarder', CAD.File_from_user('Rewarder', 'Rewarder', '.py'), dirName='AHF_Rewarder')
self.RewarderDict = self.RewarderClass.config_user_get()
fileErr = True
############################ Reader(Obligatory) makes its own dictionary ##############
if not hasattr(self, 'ReaderClass') or not hasattr(self, 'ReaderDict'):
- self.ReaderClass = CAD.Class_from_file('Reader', CAD.File_from_user('Reader', 'RFID-Tag Reader', '.py'))
+ self.ReaderClass = CAD.Class_from_file('Reader', CAD.File_from_user('Reader', 'RFID-Tag Reader', '.py'), dirName='AHF_Reader')
self.ReaderDict = self.ReaderClass.config_user_get()
fileErr = True
################################ Camera(optional) makes its own dictionary of settings ####################
@@ -111,7 +113,7 @@ def __init__(self, fileName = '', object = None ):
else:
tempInput = input('Does this system have a main camera installed(Y or N):')
if tempInput [0] == 'y' or tempInput [0] == 'Y':
- self.CameraClass = CAD.Class_from_file('Camera', CAD.File_from_user('Camera', 'main camera', '.py'))
+ self.CameraClass = CAD.Class_from_file('Camera', CAD.File_from_user('Camera', 'main camera', '.py'), dirName='AHF_Camera')
self.CameraDict = self.CameraClass.config_user_get()
else:
self.cameraClass = None
@@ -119,12 +121,12 @@ def __init__(self, fileName = '', object = None ):
fileErr = True
############################# ContactCheck(Obligatory) makes its own dictionary of settings ###################
if not hasattr(self, 'ContactCheckClass') or not hasattr(self, 'ContactCheckDict'):
- self.ContactCheckClass = CAD.Class_from_file('ContactCheck', CAD.File_from_user('ContactCheck', 'Contact Checker', '.py'))
+ self.ContactCheckClass = CAD.Class_from_file('ContactCheck', CAD.File_from_user('ContactCheck', 'Contact Checker', '.py'), dirName='AHF_ContactCheck')
self.ContactCheckDict = self.ContactCheckClass.config_user_get()
fileErr = True
############################ NOT just A single GPIO pin for brain illumination, unless you want that ###########
if not hasattr(self, 'BrainLightClass') or not hasattr(self, 'BrainLightDict'):
- self.BrainLightClass = CAD.Class_from_file('BrainLight', CAD.File_from_user('BrainLight', 'Brain illuminator', '.py'))
+ self.BrainLightClass = CAD.Class_from_file('BrainLight', CAD.File_from_user('BrainLight', 'Brain illuminator', '.py'), dirName='AHF_BrainLight')
self.BrainLightDict = self.BrainLightClass.config_user_get()
fileErr = True
####################################### triggers for alerting other computers(Optional) only 1 subclass so far ######################3
@@ -135,7 +137,7 @@ def __init__(self, fileName = '', object = None ):
else:
tempInput = input('Send triggers to start tasks on secondary computers(Y or N):')
if tempInput [0] == 'y' or tempInput [0] == 'Y':
- self.TriggerClass = CAD.Class_from_file('Trigger', CAD.File_from_user('Trigger', 'Trigger', '.py'))
+ self.TriggerClass = CAD.Class_from_file('Trigger', CAD.File_from_user('Trigger', 'Trigger', '.py'), dirName = 'AHF_Trigger')
self.TriggerDict = self.TriggerClass.config_user_get()
else:
self.TriggerClass = None
@@ -149,7 +151,7 @@ def __init__(self, fileName = '', object = None ):
else:
tempInput = input('Does this setup have a Lick Detector installed?(Y or N)')
if tempInput [0] == 'y' or tempInput [0] == 'Y':
- self.LickDetectorClass = CAD.Class_from_file('LickDetector', CAD.File_from_user('LickDetector', 'Lick Detector', '.py'))
+ self.LickDetectorClass = CAD.Class_from_file('LickDetector', CAD.File_from_user('LickDetector', 'Lick Detector', '.py'), dirName='AHF_LickDetector')
self.LickDetectorDict = self.LickDetectorClass.config_user_get()
else:
self.LickDetectorClass = None
@@ -157,7 +159,7 @@ def __init__(self, fileName = '', object = None ):
fileErr = True
###################### DataLogger(Obligatory) for logging data in text files, or database of HD5,or .... #################
if not hasattr(self, 'DataLoggerClass') or not hasattr(self, 'DataLoggerDict'):
- self.DataLoggerClass = CAD.Class_from_file('DataLogger', CAD.File_from_user('DataLogger', 'Data Logger', '.py'))
+ self.DataLoggerClass = CAD.Class_from_file('DataLogger', CAD.File_from_user('DataLogger', 'Data Logger', '.py'), dirName='AHF_DataLogger')
self.DataLoggerDict = self.DataLoggerClass.config_user_get()
fileErr = True
############################ text messaging using textbelt service(Optional) only 1 subclass so far ######################
@@ -168,7 +170,7 @@ def __init__(self, fileName = '', object = None ):
else:
tempInput = input('Send notifications if subject exceeds criterion time in chamber?(Y or N):')
if tempInput[0] == 'y' or tempInput[0] == 'Y':
- self.NotifierClass = CAD.Class_from_file('Notifier', CAD.File_from_user('Notifier', 'Text Messaging Notifier','.py'))
+ self.NotifierClass = CAD.Class_from_file('Notifier', CAD.File_from_user('Notifier', 'Text Messaging Notifier','.py'), dirName='AHF_Notifier')
self.NotifierDict = self.NotifierClass.config_user_get()
self.NotifierDict.update({'cageID': self.DataLoggerDict.get('cageID')})
else:
@@ -177,7 +179,7 @@ def __init__(self, fileName = '', object = None ):
fileErr = True
############################## Subjects only 1 subclass so far(generic mice) ##############
if not hasattr(self, 'SubjectsClass') or not hasattr(self, 'SubjectsDict'):
- self.SubjectsClass = CAD.Class_from_file('Subjects',CAD.File_from_user('Subjects', 'test subjects', '.py'))
+ self.SubjectsClass = CAD.Class_from_file('Subjects',CAD.File_from_user('Subjects', 'test subjects', '.py'), dirName='AHF_Subjects')
self.SubjectsDict = self.SubjectsClass.config_user_get()
fileErr = True
###################### things we track in the main program #################################
@@ -209,7 +211,7 @@ def setup(self):
GPIO.setwarnings(False)
fields = sorted(inspect.getmembers(self))
for item in fields:
- if isinstance(item [1], ABCMeta):
+ if isinstance(item[1], ABCMeta):
baseName =(item [0], item[0][:-5])[item[0].endswith('Class')]
classDict = getattr(self, baseName + 'Dict')
setattr(self, baseName, item [1](self, classDict))
@@ -221,7 +223,7 @@ def setup(self):
if str(temp[0]).lower() == "y":
default = True
for item in fields:
- if isinstance(item [1], ABCMeta):
+ if isinstance(item[1], ABCMeta):
baseName =(item [0], item[0][:-5])[item[0].endswith('Class')]
classDict = getattr(self, baseName + 'Dict')
self.DataLogger.storeConfig("changed_hardware", item[1].__name__, baseName + "Class")
@@ -248,13 +250,13 @@ def saveSettings(self):
if self.fileName != '' and newConfig == '':
newConfig = self.fileName
else:
- if newConfig.startswith('AHF_task_'):
+ if newConfig.startswith('AHF_config_'):
newConfig = newConfig [9 :]
if newConfig.endswith('.jsn'):
newConfig.rstrip('.jsn')
newConfig = ''.join([c for c in newConfig if c.isalpha() or c.isdigit() or c=='_'])
self.fileName = newConfig
- CAD.Obj_fields_to_file(self, 'task', newConfig, '.jsn')
+ CAD.Obj_fields_to_file(self, 'config', newConfig, '.jsn', 'AHF_config/')
def editSettings(self):
@@ -299,7 +301,7 @@ def hardwareTester(self):
itemDict.update(showDict [inputNum -1]) #itemDict = OrderedDict.get(inputNum -1)
kvp = itemDict.popitem()
itemValue = kvp [1]
- itemValue.hardwareTest()
+ itemValue.hardwareTest()
response = input('Save changes in settings to a file?')
if response [0] == 'Y' or response [0] == 'y':
self.saveSettings()
diff --git a/AHF_Trigger.py b/AHF_Trigger/AHF_Trigger.py
similarity index 82%
rename from AHF_Trigger.py
rename to AHF_Trigger/AHF_Trigger.py
index 49f820d..bf385ed 100644
--- a/AHF_Trigger.py
+++ b/AHF_Trigger/AHF_Trigger.py
@@ -1,7 +1,10 @@
#! /usr/bin/python3
#-*-coding: utf-8 -*-
+import sys
+sys.path.append("../..")
+
from abc import ABCMeta, abstractmethod
-from AHF_Base import AHF_Base
+from AutoHeadFix.AHF_Base import AHF_Base
import os
import inspect
diff --git a/AHF_Trigger_UDP.py b/AHF_Trigger/AHF_Trigger_UDP.py
similarity index 98%
rename from AHF_Trigger_UDP.py
rename to AHF_Trigger/AHF_Trigger_UDP.py
index c53cea8..4515c91 100644
--- a/AHF_Trigger_UDP.py
+++ b/AHF_Trigger/AHF_Trigger_UDP.py
@@ -3,7 +3,7 @@
import socket
-from AHF_Trigger import AHF_Trigger
+from AHF_Trigger.AHF_Trigger import AHF_Trigger
class AHF_Trigger_UDP(AHF_Trigger):
"""
diff --git a/AHF_Trigger/__init__.py b/AHF_Trigger/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AHF_task_HeadFix_LW_Laser.jsn b/AHF_config/AHF_config_HeadFix_LW_Laser.jsn
similarity index 97%
rename from AHF_task_HeadFix_LW_Laser.jsn
rename to AHF_config/AHF_config_HeadFix_LW_Laser.jsn
index ce64e91..79550e7 100644
--- a/AHF_task_HeadFix_LW_Laser.jsn
+++ b/AHF_config/AHF_config_HeadFix_LW_Laser.jsn
@@ -2,7 +2,7 @@
"BrainLightDict"={"ledDelay"=3.0
"ledPin"=22}
"CameraClass"="AHF_Camera_PiCam"
-"CameraDict"={"format"="h264"
+"CameraDict"={"format"="rgb"
"framerate"=30
"iso"=0
"previewWin"=[0
@@ -62,7 +62,7 @@
"StimulatorClass"="AHF_Stimulator_LickWithhold"
"StimulatorDict"={"defaultLevel"=3
"lickWrongTimeout"=2
-"speakerDuty"=0.1
+"speakerDuty"=0.2
"speakerFreq"=100
"speakerOffForReward"=1.5
"speakerPin"=25
diff --git a/AHF_task_HeadFix_LW_Serial.jsn b/AHF_config/AHF_config_HeadFix_LW_Serial.jsn
similarity index 100%
rename from AHF_task_HeadFix_LW_Serial.jsn
rename to AHF_config/AHF_config_HeadFix_LW_Serial.jsn
diff --git a/AHF_config/AHF_config_HeadFix_LW_TestCage.jsn b/AHF_config/AHF_config_HeadFix_LW_TestCage.jsn
new file mode 100644
index 0000000..c9ad6ab
--- /dev/null
+++ b/AHF_config/AHF_config_HeadFix_LW_TestCage.jsn
@@ -0,0 +1,92 @@
+{"BrainLightClass"="AHF_BrainLight_1GPIO"
+"BrainLightDict"={"ledDelay"=3.0
+"ledPin"=23}
+"CameraClass"="AHF_Camera_PiCam"
+"CameraDict"={"format"="rgb"
+"iso"=0
+"previewWin"=[0
+0
+640
+480]
+"quality"=20
+"resolution"=[256
+256]
+"shutter_speed"=30000
+"video_path"="/mnt/AHF_Videos/"
+"whiteBalance"=false}
+"ContactCheckClass"="AHF_ContactCheck_BeamBreak"
+"ContactCheckDict"={"contactPUD"="PUD_UP"
+"contactPin"=12
+"contactPolarity"="FALLING"
+"ledPin"=24}
+"DataLoggerClass"="AHF_DataLogger_textMySql"
+"DataLoggerDict"={"DB"="AHF_test_cage"
+"DBhost"="142.103.107.236"
+"DBpwd"="*******************"
+"DBuser"="slavePi"
+"cageID"="test_cage"
+"dataPath"="/mnt/AHF_Videos/"
+"localDatabase"="test_cage"
+"localPassword"="weekendkiller"
+"localUser"="pi"
+"mouseConfigPath"="AHF_config/"
+"oldVersion"=true
+"useLocalSql"=true}
+"HeadFixerClass"="AHF_HeadFixer_PWM_PCA9685"
+"HeadFixerDict"={"servoAddress"=64
+"servoFixedPosition"=695
+"servoReleasedPosition"=945
+"skeddadleTime"=5.0}
+"LickDetectorClass"="AHF_LickDetector_MPR"
+"LickDetectorDict"={"IRQpin"=26
+"mprAddress"=90
+"touchChans"=[0
+1
+2
+3]
+"touchThresh"=8
+"unTouchThresh"=4}
+"NotifierClass"=null
+"NotifierDict"=null
+"ReaderClass"="AHF_Reader_ID"
+"ReaderDict"={"TIRpin"=7
+"inChamberTimeLimit"=600
+"serialPort"="/dev/ttyUSB0"}
+"RewarderClass"="AHF_Rewarder_solenoid_rpi"
+"RewarderDict"={"entryRewardDelay"=5.0
+"maxEntryRewards"=10000
+"rewardPin"=13
+"rewards"={"entry"=0.4
+"task"=0.4
+"test"=1.0}}
+"StimulatorClass"="AHF_Stimulator_LickWithhold"
+"StimulatorDict"={"defaultLevel"=0
+"lickWrongTimeout"=2
+"speakerDuty"=0.1
+"speakerFreq"=400
+"speakerOffForReward"=1.5
+"speakerPin"=11}
+"StimulusClass"="AHF_Stimulus_VibMotor"
+"StimulusDict"={"motorDuty"=0.8
+"motorFreq"=300
+"motorPin"=27
+"pulseTime"=0.2}
+"SubjectsClass"="AHF_Subjects_mice"
+"SubjectsDict"={"inChamberTimeLimit"=300
+"jsonName"="subjects"
+"loadMiceConfigs"="provide_json"}
+"TriggerClass"=null
+"TriggerDict"=null
+"contact"=false
+"contactTime"=0
+"edited"=true
+"entryTime"=0.0
+"fileName"="HeadFix_LickWithhold"
+"fixAgainTime"=1586994292.992053
+"fixed"=false
+"inChamberLimitExceeded"=false
+"isFixTrial"=false
+"lastFixedTag"=0
+"lastFixedTime"=0
+"logToFile"=true
+"tag"=0}
diff --git a/AHF_config/AHF_config_HeadFix_LW_TestCage1.jsn b/AHF_config/AHF_config_HeadFix_LW_TestCage1.jsn
new file mode 100644
index 0000000..a609f66
--- /dev/null
+++ b/AHF_config/AHF_config_HeadFix_LW_TestCage1.jsn
@@ -0,0 +1,92 @@
+{"BrainLightClass"="AHF_BrainLight_1GPIO"
+"BrainLightDict"={"ledDelay"=3.0
+"ledPin"=23}
+"CameraClass"="AHF_Camera_PiCam"
+"CameraDict"={"format"="rgb"
+"iso"=0
+"previewWin"=[0
+0
+640
+480]
+"quality"=20
+"resolution"=[256
+256]
+"shutter_speed"=30000
+"video_path"="/mnt/AHF_Videos/"
+"whiteBalance"=false}
+"ContactCheckClass"="AHF_ContactCheck_BeamBreak"
+"ContactCheckDict"={"contactPUD"="PUD_UP"
+"contactPin"=12
+"contactPolarity"="FALLING"
+"ledPin"=24}
+"DataLoggerClass"="AHF_DataLogger_textMySql"
+"DataLoggerDict"={"DB"="AHF_test_cage"
+"DBhost"="142.103.107.236"
+"DBpwd"="*******************"
+"DBuser"="slavePi"
+"cageID"="test_cage"
+"dataPath"="/mnt/AHF_Videos/"
+"localDatabase"="raw_data"
+"localPassword"="weekendkiller!"
+"localUser"="pi"
+"mouseConfigPath"="AHF_config/"
+"oldVersion"=true
+"useLocalSql"=true}
+"HeadFixerClass"="AHF_HeadFixer_PWM_PCA9685"
+"HeadFixerDict"={"servoAddress"=64
+"servoFixedPosition"=695
+"servoReleasedPosition"=945
+"skeddadleTime"=5.0}
+"LickDetectorClass"="AHF_LickDetector_MPR"
+"LickDetectorDict"={"IRQpin"=26
+"mprAddress"=90
+"touchChans"=[0
+1
+2
+3]
+"touchThresh"=8
+"unTouchThresh"=4}
+"NotifierClass"=null
+"NotifierDict"=null
+"ReaderClass"="AHF_Reader_ID"
+"ReaderDict"={"TIRpin"=7
+"inChamberTimeLimit"=600
+"serialPort"="/dev/ttyUSB0"}
+"RewarderClass"="AHF_Rewarder_solenoid_rpi"
+"RewarderDict"={"entryRewardDelay"=5.0
+"maxEntryRewards"=10000
+"rewardPin"=13
+"rewards"={"entry"=0.4
+"task"=0.4
+"test"=1.0}}
+"StimulatorClass"="AHF_Stimulator_LickWithhold"
+"StimulatorDict"={"defaultLevel"=0
+"lickWrongTimeout"=2
+"speakerDuty"=0.1
+"speakerFreq"=400
+"speakerOffForReward"=1.5
+"speakerPin"=11}
+"StimulusClass"="AHF_Stimulus_VibMotor"
+"StimulusDict"={"motorDuty"=0.8
+"motorFreq"=300
+"motorPin"=27
+"pulseTime"=0.2}
+"SubjectsClass"="AHF_Subjects_mice"
+"SubjectsDict"={"inChamberTimeLimit"=300
+"jsonName"="subjects"
+"loadMiceConfigs"="provide_json"}
+"TriggerClass"=null
+"TriggerDict"=null
+"contact"=false
+"contactTime"=0
+"edited"=true
+"entryTime"=0.0
+"fileName"="HeadFix_LW_TestCage1"
+"fixAgainTime"=Infinity
+"fixed"=false
+"inChamberLimitExceeded"=false
+"isFixTrial"=false
+"lastFixedTag"=0
+"lastFixedTime"=0
+"logToFile"=true
+"tag"=0}
\ No newline at end of file
diff --git a/AHF_task_HeadFix_LickWithhold.jsn b/AHF_config/AHF_config_HeadFix_LickWithhold.jsn
similarity index 90%
rename from AHF_task_HeadFix_LickWithhold.jsn
rename to AHF_config/AHF_config_HeadFix_LickWithhold.jsn
index d87ac6e..d3c115c 100644
--- a/AHF_task_HeadFix_LickWithhold.jsn
+++ b/AHF_config/AHF_config_HeadFix_LickWithhold.jsn
@@ -2,7 +2,7 @@
"BrainLightDict"={"ledDelay"=3.0
"ledPin"=23}
"CameraClass"="AHF_Camera_PiCam"
-"CameraDict"={"format"="h264"
+"CameraDict"={"format"="rgb"
"framerate"=30
"iso"=0
"previewWin"=[0
@@ -30,7 +30,7 @@
"localDatabase"="raw_data"
"localPassword"="AutoHead2015"
"localUser"="pi"
-"mouseConfigPath"="/home/pi/Documents/MiceConfig/"
+"mouseConfigPath"="AHF_config/"
"oldVersion"=true
"useLocalSql"=true}
"HeadFixerClass"="AHF_HeadFixer_PWM_PCA9685"
@@ -54,7 +54,7 @@
"inChamberTimeLimit"=600
"serialPort"="/dev/ttyUSB0"}
"RewarderClass"="AHF_Rewarder_solenoid_rpi"
-"RewarderDict"={"entryRewardDelay"=1.0
+"RewarderDict"={"entryRewardDelay"=5.0
"maxEntryRewards"=10000
"rewardPin"=13
"rewards"={"entry"=0.4
@@ -68,13 +68,13 @@
"speakerOffForReward"=1.5
"speakerPin"=11}
"StimulusClass"="AHF_Stimulus_VibMotor"
-"StimulusDict"={"motorDuty"=1.0
+"StimulusDict"={"motorDuty"=0.8
"motorFreq"=300
"motorPin"=27
"pulseTime"=0.2}
"SubjectsClass"="AHF_Subjects_mice"
"SubjectsDict"={"inChamberTimeLimit"=300
-"jsonName"="_subjects"
+"jsonName"="subjects"
"loadMiceConfigs"="provide_json"}
"TriggerClass"=null
"TriggerDict"=null
@@ -83,7 +83,7 @@
"edited"=true
"entryTime"=0.0
"fileName"="HeadFix_LickWithhold"
-"fixAgainTime"=Infinity
+"fixAgainTime"=1586994292.992053
"fixed"=false
"inChamberLimitExceeded"=false
"isFixTrial"=false
diff --git a/AHF_task_Lever_NoFix.jsn b/AHF_config/AHF_config_Lever_NoFix.jsn
similarity index 100%
rename from AHF_task_Lever_NoFix.jsn
rename to AHF_config/AHF_config_Lever_NoFix.jsn
diff --git a/AHF_config/AHF_config_closed_loop.jsn b/AHF_config/AHF_config_closed_loop.jsn
new file mode 100644
index 0000000..3330d2c
--- /dev/null
+++ b/AHF_config/AHF_config_closed_loop.jsn
@@ -0,0 +1,85 @@
+{"BrainLightClass"="AHF_BrainLight_1GPIO"
+"BrainLightDict"={"ledDelay"=3.0
+"ledPin"=22}
+"CameraClass"="AHF_Camera_PiStream"
+"CameraDict"={"format"="hdf5"
+"framerate"=30
+"iso"=200
+"previewWin"=[0
+0
+640
+480]
+"quality"=20
+"resolution"=[640
+480]
+"sensor_mode"=4
+"shutter_speed"=30000
+"video_path"="/home/pi/Videos"
+"whiteBalance"=false}
+"ContactCheckClass"="AHF_ContactCheck_BeamBreak"
+"ContactCheckDict"={"contactPUD"="PUD_UP"
+"contactPin"=12
+"contactPolarity"="FALLING"
+"ledPin"=24}
+"DataLoggerClass"="AHF_DataLogger_localsql"
+"DataLoggerDict"={"cageID"="cl"
+"localDatabase"="raw_data"
+"localPassword"="AutoHead2015"
+"localUser"="pi"}
+"HeadFixerClass"="AHF_HeadFixer_PWM_PCA9685"
+"HeadFixerDict"={"servoAddress"=64
+"servoFixedPosition"=685
+"servoReleasedPosition"=945
+"skeddadleTime"=5.0}
+"LickDetectorClass"="AHF_LickDetector_MPR"
+"LickDetectorDict"={"IRQpin"=26
+"mprAddress"=90
+"touchChans"=[0
+1
+2
+3]
+"touchThresh"=8
+"unTouchThresh"=4}
+"NotifierClass"=null
+"NotifierDict"=null
+"ReaderClass"="AHF_Reader_ID"
+"ReaderDict"={"TIRpin"=7
+"inChamberTimeLimit"=600
+"serialPort"="/dev/serial0"}
+"RewarderClass"="AHF_Rewarder_solenoid_rpi"
+"RewarderDict"={"entryRewardDelay"=1.0
+"maxEntryRewards"=1000
+"rewardPin"=13
+"rewards"={"entry"=0.2
+"task"=0.4
+"test"=1.0}}
+"StimulatorClass"="AHF_Stimulator_ClosedLoop"
+"StimulatorDict"={"audio_pin"=-1
+"num_tones"=10
+"summary_file_name"="expt_summary.csv"
+"videoPath"=""}
+"StimulusClass"="AHF_Stimulus_VibMotor"
+"StimulusDict"={"motorDuty"=0.8
+"motorFreq"=300
+"motorPin"=27
+"pulseTime"=0.2}
+"SubjectsClass"="AHF_Subjects_mice"
+"SubjectsDict"={"inChamberTimeLimit"=300
+"jsonName"="fillable_testDummy"
+"loadMiceConfigs"="provide_json"}
+"TriggerClass"=null
+"TriggerDict"=null
+"contact"=false
+"contactTime"=0
+"edited"=true
+"entryTime"=0.0
+"fileName"="closed_loop"
+"filename"="temp"
+"fixAgainTime"=Infinity
+"fixed"=false
+"inChamberLimitExceeded"=false
+"isFixTrial"=false
+"lastFixedTag"=0
+"lastFixedTime"=0
+"logToFile"=true
+"tag"=0}
\ No newline at end of file
diff --git a/AHF_mice__subjects.jsn b/AHF_config/AHF_mice_March2020.jsn
similarity index 100%
rename from AHF_mice__subjects.jsn
rename to AHF_config/AHF_mice_March2020.jsn
diff --git a/AHF_mice_fillable_subjects.jsn b/AHF_config/AHF_mice_fillable_subjects.jsn
similarity index 100%
rename from AHF_mice_fillable_subjects.jsn
rename to AHF_config/AHF_mice_fillable_subjects.jsn
diff --git a/AHF_mice_fillable_testDummy.jsn b/AHF_config/AHF_mice_fillable_testDummy.jsn
similarity index 67%
rename from AHF_mice_fillable_testDummy.jsn
rename to AHF_config/AHF_mice_fillable_testDummy.jsn
index 292e18c..8bcb7d3 100644
--- a/AHF_mice_fillable_testDummy.jsn
+++ b/AHF_config/AHF_mice_fillable_testDummy.jsn
@@ -12,11 +12,4 @@
"taskSize"=0.4
"totalBreakBeamRewardsToday"=0
"totalEntryRewardsToday"=0}
-"Stimulator"={"delayTime"=0.5
-"goLikelihood"=0.5
-"lickWithholdTime"=1
-"mouseLevel"=0
-"nRewards"=5
-"responseTime"=2.5
-"rewardInterval"=3
-"rewardNoGo"=true}}}
+"Stimulator"={"reward_threshold" = 50}}}
diff --git a/AHF_config/AHF_mice_subjects.jsn b/AHF_config/AHF_mice_subjects.jsn
new file mode 100644
index 0000000..0adfff0
--- /dev/null
+++ b/AHF_config/AHF_mice_subjects.jsn
@@ -0,0 +1,110 @@
+{"111111111"={"HeadFixer"={"headFixTime"=40
+"propHeadFix"=1.0
+"tightnessHeadFix"=1}
+"Rewarder"={"breakBeamDelay"=1
+"breakBeamSize"=0.1
+"entryDelay"=0
+"entrySize"=0.2
+"lastBreakBeamTime"=0
+"lastEntryTime"=0
+"maxBreakBeamRewards"=200
+"maxEntryRewards"=1000
+"taskSize"=0.4
+"totalBreakBeamRewardsToday"=0
+"totalEntryRewardsToday"=0}
+"Stimulator"={"delayTime"=0.5
+"goLikelihood"=0.5
+"lickWithholdTime"=1
+"mouseLevel"=3
+"nRewards"=5
+"responseTime"=2.5
+"rewardInterval"=3
+"rewardNoGo"=false}}
+"1904230295"={"HeadFixer"={"headFixTime"=40
+"propHeadFix"=0.75
+"tightnessHeadFix"=1}
+"Rewarder"={"breakBeamDelay"=1
+"breakBeamSize"=0.1
+"entryDelay"=0
+"entrySize"=0.2
+"lastBreakBeamTime"=0
+"lastEntryTime"=0
+"maxBreakBeamRewards"=200
+"maxEntryRewards"=1000
+"taskSize"=0.4
+"totalBreakBeamRewardsToday"=0
+"totalEntryRewardsToday"=0}
+"Stimulator"={"delayTime"=0.5
+"goLikelihood"=0.5
+"lickWithholdTime"=1
+"mouseLevel"=0
+"nRewards"=5
+"responseTime"=2.5
+"rewardInterval"=3
+"rewardNoGo"=true}}
+"201608451"={"HeadFixer"={"headFixTime"=40
+"propHeadFix"=0.75
+"tightnessHeadFix"=1}
+"Rewarder"={"breakBeamDelay"=1
+"breakBeamSize"=0.1
+"entryDelay"=900
+"entrySize"=0.2
+"lastBreakBeamTime"=0
+"lastEntryTime"=0
+"maxBreakBeamRewards"=200
+"maxEntryRewards"=1000
+"taskSize"=0.4
+"totalBreakBeamRewardsToday"=0
+"totalEntryRewardsToday"=0}
+"Stimulator"={"delayTime"=0.5
+"goLikelihood"=0.5
+"lickWithholdTime"=1
+"mouseLevel"=0
+"nRewards"=5
+"responseTime"=2.5
+"rewardInterval"=3
+"rewardNoGo"=true}}
+"801010244"={"HeadFixer"={"headFixTime"=40
+"propHeadFix"=0.75
+"tightnessHeadFix"=1}
+"Rewarder"={"breakBeamDelay"=1
+"breakBeamSize"=0.1
+"entryDelay"=0
+"entrySize"=0.2
+"lastBreakBeamTime"=0
+"lastEntryTime"=1580776409.4050555
+"maxBreakBeamRewards"=200
+"maxEntryRewards"=1000
+"taskSize"=0.4
+"totalBreakBeamRewardsToday"=0
+"totalEntryRewardsToday"=1}
+"Stimulator"={"delayTime"=0.5
+"goLikelihood"=0.5
+"lickWithholdTime"=1
+"mouseLevel"=0
+"nRewards"=5
+"responseTime"=2.5
+"rewardInterval"=3
+"rewardNoGo"=true}}
+"801011070"={"HeadFixer"={"headFixTime"=40
+"propHeadFix"=0.75
+"tightnessHeadFix"=1}
+"Rewarder"={"breakBeamDelay"=1
+"breakBeamSize"=0.1
+"entryDelay"=0
+"entrySize"=0.2
+"lastBreakBeamTime"=0
+"lastEntryTime"=0
+"maxBreakBeamRewards"=200
+"maxEntryRewards"=1000
+"taskSize"=0.4
+"totalBreakBeamRewardsToday"=0
+"totalEntryRewardsToday"=0}
+"Stimulator"={"delayTime"=0.5
+"goLikelihood"=0.5
+"lickWithholdTime"=1
+"mouseLevel"=3
+"nRewards"=5
+"responseTime"=0.5
+"rewardInterval"=3
+"rewardNoGo"=true}}}
\ No newline at end of file
diff --git a/AHF_mice_subjects.jsn b/AHF_mice_subjects.jsn
deleted file mode 100644
index 40c2ad0..0000000
--- a/AHF_mice_subjects.jsn
+++ /dev/null
@@ -1,374 +0,0 @@
-{"2018121379"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "124563082475"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121244"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "111111111"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121320"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2016080059"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121279"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121245"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "1"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121234"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "801010240"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "801010258"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "801010565"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "124563082482"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121318"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "801011070"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}
- "2018121343"= {"Rewarder"= {"maxEntryRewards"= 10000
- "breakBeamDelay"= 1
- "taskSize"= 0.4
- "entrySize"= 0.4
- "lastEntryTime"= 0
- "maxBreakBeamRewards"= 200
- "breakBeamSize"= 0.1
- "lastBreakBeamTime"= 0
- "totalEntryRewardsToday"= 0
- "entryDelay"= 0
- "totalBreakBeamRewardsToday"= 0}
- "HeadFixer"= {"tightnessHeadFix"= 1
- "propHeadFix"= 0.0
- "headFixTime"= 40}
- "Stimulator"= {"mouseLevel"= 0
- "responseTime"= 2.5
- "delayTime"= 0.5
- "goLikelihood"= 0.5
- "rewardInterval"= 3
- "nRewards"= 5
- "lickWithholdTime"= 1
- "rewardNoGo"= true}}}
\ No newline at end of file
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/__main__2.py b/__main__2.py
index 4e9c19a..eb938ad 100755
--- a/__main__2.py
+++ b/__main__2.py
@@ -79,8 +79,6 @@ def main():
print(jsonDict)
task = Task(object = jsonDict)
db.close()
- elif argv.__len__() > 1 and argv[1] == "--noedit":
- task = Task('')
else:
task = Task('')
task.editSettings()
@@ -154,14 +152,20 @@ def main():
inputStr += 'S to edit Stimulator settings\n'
inputStr += 'T to edit Task configuration\n'
inputStr += 'L to log a note\n'
- inputStr += 'R to Return to head fix trials\n'
+ inputStr += 'R to save and return to head fix trials\n'
inputStr += 'Q to quit\n:'
while True:
event = input(inputStr)
if event == 'r' or event == "R":
- GPIO.setmode(GPIO.BCM)
+ if hasattr(task, "Camera"):
+ task.Camera.setdown()
+ if hasattr(task, 'BrainLight'):
+ task.BrainLight.setdown()
if hasattr(task, 'LickDetector'):
- task.LickDetector.startLogging()
+ task.LickDetector.setdown()
+ task.editSettings()
+ task.setup()
+ task.Reader.startLogging()
break
elif event == 'q' or event == 'Q':
return
@@ -177,13 +181,11 @@ def main():
elif event == 'T' or event == 't':
if hasattr(task, "Camera"):
task.Camera.setdown()
+ if hasattr(task, 'BrainLight'):
task.BrainLight.setdown()
if hasattr(task, 'LickDetector'):
task.LickDetector.setdown()
task.editSettings()
- #response = input('Save edited settings to file?')
- #if response [0] == 'Y' or response [0] == 'y':
- # task.saveSettings()
task.setup()
print("hello")
elif event == 'S' or event == 's':
diff --git a/docs/build/html/.buildinfo b/docs/.buildinfo
similarity index 82%
rename from docs/build/html/.buildinfo
rename to docs/.buildinfo
index b992ef9..9ea2507 100644
--- a/docs/build/html/.buildinfo
+++ b/docs/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 4ee0f7dfc0b45f7f82e7c9a40e0ba884
+config: 60dd385de4bbbec5fcc01b7ce6b46f8e
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/.doctrees/AHF_BrainLight.doctree b/docs/.doctrees/AHF_BrainLight.doctree
new file mode 100644
index 0000000..3274ce8
Binary files /dev/null and b/docs/.doctrees/AHF_BrainLight.doctree differ
diff --git a/docs/.doctrees/AHF_Camera.doctree b/docs/.doctrees/AHF_Camera.doctree
new file mode 100644
index 0000000..cb08498
Binary files /dev/null and b/docs/.doctrees/AHF_Camera.doctree differ
diff --git a/docs/.doctrees/AHF_ContactCheck.doctree b/docs/.doctrees/AHF_ContactCheck.doctree
new file mode 100644
index 0000000..f4dee97
Binary files /dev/null and b/docs/.doctrees/AHF_ContactCheck.doctree differ
diff --git a/docs/.doctrees/AHF_DataLogger.doctree b/docs/.doctrees/AHF_DataLogger.doctree
new file mode 100644
index 0000000..8c0e394
Binary files /dev/null and b/docs/.doctrees/AHF_DataLogger.doctree differ
diff --git a/docs/.doctrees/AHF_HeadFixer.doctree b/docs/.doctrees/AHF_HeadFixer.doctree
new file mode 100644
index 0000000..dd10fb1
Binary files /dev/null and b/docs/.doctrees/AHF_HeadFixer.doctree differ
diff --git a/docs/.doctrees/AHF_LickDetector.doctree b/docs/.doctrees/AHF_LickDetector.doctree
new file mode 100644
index 0000000..95601b6
Binary files /dev/null and b/docs/.doctrees/AHF_LickDetector.doctree differ
diff --git a/docs/.doctrees/AHF_Notifier.doctree b/docs/.doctrees/AHF_Notifier.doctree
new file mode 100644
index 0000000..0a018bd
Binary files /dev/null and b/docs/.doctrees/AHF_Notifier.doctree differ
diff --git a/docs/.doctrees/AHF_Reader.doctree b/docs/.doctrees/AHF_Reader.doctree
new file mode 100644
index 0000000..119ca20
Binary files /dev/null and b/docs/.doctrees/AHF_Reader.doctree differ
diff --git a/docs/.doctrees/AHF_Rewarder.doctree b/docs/.doctrees/AHF_Rewarder.doctree
new file mode 100644
index 0000000..f4afaf9
Binary files /dev/null and b/docs/.doctrees/AHF_Rewarder.doctree differ
diff --git a/docs/.doctrees/AHF_Stimulator.doctree b/docs/.doctrees/AHF_Stimulator.doctree
new file mode 100644
index 0000000..b341e26
Binary files /dev/null and b/docs/.doctrees/AHF_Stimulator.doctree differ
diff --git a/docs/.doctrees/AHF_Stimulus.doctree b/docs/.doctrees/AHF_Stimulus.doctree
new file mode 100644
index 0000000..f752bcd
Binary files /dev/null and b/docs/.doctrees/AHF_Stimulus.doctree differ
diff --git a/docs/.doctrees/AHF_Subjects.doctree b/docs/.doctrees/AHF_Subjects.doctree
new file mode 100644
index 0000000..0c8f057
Binary files /dev/null and b/docs/.doctrees/AHF_Subjects.doctree differ
diff --git a/docs/.doctrees/AHF_Trigger.doctree b/docs/.doctrees/AHF_Trigger.doctree
new file mode 100644
index 0000000..3f1bfc7
Binary files /dev/null and b/docs/.doctrees/AHF_Trigger.doctree differ
diff --git a/docs/.doctrees/environment.pickle b/docs/.doctrees/environment.pickle
new file mode 100644
index 0000000..0a3000c
Binary files /dev/null and b/docs/.doctrees/environment.pickle differ
diff --git a/docs/.doctrees/index.doctree b/docs/.doctrees/index.doctree
new file mode 100644
index 0000000..2fd78ff
Binary files /dev/null and b/docs/.doctrees/index.doctree differ
diff --git a/docs/.doctrees/modules.doctree b/docs/.doctrees/modules.doctree
new file mode 100644
index 0000000..d895fe5
Binary files /dev/null and b/docs/.doctrees/modules.doctree differ
diff --git a/docs/.doctrees/quickstart.doctree b/docs/.doctrees/quickstart.doctree
new file mode 100644
index 0000000..c850fd5
Binary files /dev/null and b/docs/.doctrees/quickstart.doctree differ
diff --git a/docs/.doctrees/rpi_setup.doctree b/docs/.doctrees/rpi_setup.doctree
new file mode 100644
index 0000000..0aebecc
Binary files /dev/null and b/docs/.doctrees/rpi_setup.doctree differ
diff --git a/docs/.doctrees/util_classes.doctree b/docs/.doctrees/util_classes.doctree
new file mode 100644
index 0000000..d0bb932
Binary files /dev/null and b/docs/.doctrees/util_classes.doctree differ
diff --git a/docs/AHF_BrainLight.html b/docs/AHF_BrainLight.html
new file mode 100644
index 0000000..6438215
--- /dev/null
+++ b/docs/AHF_BrainLight.html
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_BrainLight — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_BrainLight
+
+
AHF_BrainLight.AHF_BrainLight module
+
+
+class AHF_BrainLight.AHF_BrainLight.AHF_BrainLight( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultDelay = 3.0
+
+
+
+
+hardwareTest( )
+generic hardware tester for brain illumination, turns on, waits 2 seconds, turns off
+
+
+
+
+abstract offForStim( )
+Runs when headFixing ends, turning off whatever was turned on
+
+
+
+
+abstract onForStim( )
+Runs when headFixing starts, illuminating the brain or whatever needs illuminating
+
+
+
+
+
+
+
AHF_BrainLight.AHF_BrainLight_1GPIO module
+
+
+class AHF_BrainLight.AHF_BrainLight_1GPIO.AHF_BrainLight_1GPIO( taskP , settingsDictP )
+Bases: AHF_BrainLight.AHF_BrainLight.AHF_BrainLight
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultPin = 23
+
+
+
+
+offForStim( )
+Runs when headFixing ends, turning off whatever was turned on
+
+
+
+
+onForStim( )
+Runs when headFixing starts, illuminating the brain or whatever needs illuminating
+
+
+
+
+static onThread( sleepTime , ledPin )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization of a brain lighter with(possibly updated) info in self.settingsDict
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_BrainLight.rst b/docs/AHF_BrainLight.rst
new file mode 100644
index 0000000..45c15f0
--- /dev/null
+++ b/docs/AHF_BrainLight.rst
@@ -0,0 +1,18 @@
+AHF\_BrainLight
+=======================
+
+AHF\_BrainLight.AHF\_BrainLight module
+--------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_BrainLight.AHF\_BrainLight\_1GPIO module
+---------------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight_1GPIO
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/AHF_Camera.html b/docs/AHF_Camera.html
new file mode 100644
index 0000000..f9a92bb
--- /dev/null
+++ b/docs/AHF_Camera.html
@@ -0,0 +1,386 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Camera — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Camera
+
+
AHF_Camera.AHF_Camera module
+
+
+class AHF_Camera.AHF_Camera.AHF_Camera( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+AHF_Camera is the base class for the main brain imaging camera used in Auto Head Fix
+
+
+abstract resolution( )
+Return the resolution of the camera. Used for certain stimulators.
+
+
+
+
+abstract start_preview( )
+Starts a preview of the camera’s current vision.
+
+
+
+
+abstract start_recording( )
+Starts a recording of the camera’s current vision.
+
+
+
+
+abstract stop_preview( )
+Ends a preview of the camera’s current vision.
+
+
+
+
+abstract stop_recording( )
+Ends a recording of the camera’s current vision.
+
+
+
+
+
+
+
AHF_Camera.AHF_Camera_PiCam module
+
+
+class AHF_Camera.AHF_Camera_PiCam.AHF_Camera_PiCam( taskP , settingsDictP )
+Bases: AHF_Camera.AHF_Camera.AHF_Camera
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+add_overlay( bytes , layer , alpha )
+
+
+
+
+capture( path , type , video_port = False )
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings
+
+
+
+
+remove_overlay( overlay )
+
+
+
+
+resolution( )
+Return the resolution of the camera. Used for certain stimulators.
+
+
+
+
+set_gain( )
+Sets the gain and white balance of the camera based on a 2 second preview - so set illumination as you like before calling
+If ISO for the camera is set to non-zero value, gain is not settable. If pWhiteBalance was set to False, white balancing is not done,
+and gains for red and green are set to 1.
+:raises PiCameraError: error raised by superclass PiCamera from preview
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+start_preview( )
+Starts a preview of the camera’s current vision.
+
+
+
+
+start_recording( video_name )
+Starts a video recording using the saved settings for format, quality, gain, etc.
+A preview of the recording is always shown
+
+Parameters
+video_name – Name of saved recording. Always save to a file, not a PIL, for, example
+
+
+
+
+
+
+stop_preview( )
+Ends a preview of the camera’s current vision.
+
+
+
+
+stop_recording( )
+Stops a video recording previously started with start_recording.
+
+
+
+
+timed_recording( recTime )
+Does a timed video recording using the PiCamera wait_recording function.
+A preview of the recording is always shown
+Control does not pass back to the calling function until the recording is finished
+:param recTime: duration of the recorded video, in seconds
+
+
+
+
+
+
+
AHF_Camera.AHF_Camera_PiStream module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Camera.rst b/docs/AHF_Camera.rst
new file mode 100644
index 0000000..3435bfd
--- /dev/null
+++ b/docs/AHF_Camera.rst
@@ -0,0 +1,27 @@
+AHF\_Camera
+===================
+
+AHF\_Camera.AHF\_Camera module
+------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiCam module
+-------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiCam
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiStream module
+----------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiStream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/AHF_ContactCheck.html b/docs/AHF_ContactCheck.html
new file mode 100644
index 0000000..3dedb57
--- /dev/null
+++ b/docs/AHF_ContactCheck.html
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_ContactCheck — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_ContactCheck.rst b/docs/AHF_ContactCheck.rst
new file mode 100644
index 0000000..d74d003
--- /dev/null
+++ b/docs/AHF_ContactCheck.rst
@@ -0,0 +1,27 @@
+AHF\_ContactCheck
+=========================
+
+AHF\_ContactCheck.AHF\_ContactCheck module
+------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_BeamBreak module
+-----------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_BeamBreak
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_Elec module
+------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_Elec
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/AHF_DataLogger.rst b/docs/AHF_DataLogger.rst
new file mode 100644
index 0000000..054290a
--- /dev/null
+++ b/docs/AHF_DataLogger.rst
@@ -0,0 +1,43 @@
+AHF\_Datalogger
+=======================
+
+AHF\_Datalogger.AHF\_DataLogger module
+--------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_localsql module
+------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_mysql module
+---------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_text module
+--------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/AHF_Datalogger.html b/docs/AHF_Datalogger.html
new file mode 100644
index 0000000..fc6055b
--- /dev/null
+++ b/docs/AHF_Datalogger.html
@@ -0,0 +1,1085 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Datalogger — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Datalogger
+
+
AHF_Datalogger.AHF_DataLogger module
+
+
+class AHF_DataLogger.AHF_DataLogger.AHF_DataLogger( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+A Data Logger provides an interface to save task data, and to save
+and load mouse configuration data. This can be either to text files, or to
+a database, or hd5 files, or some combination thereof. The data logger
+should also print status updates to the shell, but these don’t need to contain
+as much information. The brain imaging data is saved
+separately, but references to movie files should be saved by data logger.
+Similarly, other binary data(lever positons, anyone?) can be saved separately,
+by the Stimulator class, but binary file/posiiton can be saved as an event.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+clearTrackedValues( tag , eventKind , dictKey )
+
+
+
+
+abstract configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+abstract getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+abstract getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+getTrackedEvent( tag , eventKind , dictKey )
+Returns the current value for the specified mouse, event, and key.
+
+
+
+
+isChild = False
+
+
+
+
+abstract makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+abstract newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+abstract readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+resumeTracking( eventKind , dictKey )
+Resumes previously started tracking.
+
+
+
+
+abstract retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+abstract saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+startTracking( eventKind , dictKey , trackingType , size = 0 )
+Begins tracking of the specified key for the specified event.
+Tracks as a circular buffer or daily totals.
+
+
+
+
+stopTracking( eventKind , dictKey )
+Halts previously started tracking.
+
+
+
+
+abstract storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+abstract writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_localsql module
+
+
+class AHF_DataLogger.AHF_DataLogger_localsql.AHF_DataLogger_localsql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Data logger that uses the local mysql database. Used in case of unstable remote connections.
+Mouse data is stored in a specified folder as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_mysql module
+
+
+class AHF_DataLogger.AHF_DataLogger_mysql.AHF_DataLogger_mysql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultDatabase = 'AHF_laser_cage'
+
+
+
+
+defaultHost = '142.103.107.236'
+
+
+
+
+defaultPassword = '*******************'
+
+
+
+
+defaultUser = 'slavePi'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values , remote )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values , remote )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_text module
+
+
+class AHF_DataLogger.AHF_DataLogger_text.AHF_DataLogger_text( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultConfigPath = '/home/pi/Documents/MiceConfig/'
+
+
+
+
+defaultDataPath = '/home/pi/Documents/'
+
+
+
+
+getConfigData( tag )
+returns saved dictionary for given tag
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings
+
+
+
+
+makeLogFile( )
+open a new text log file for today, or open an exisiting text file with ‘a’ for append
+
+
+
+
+makeQuickStatsFile( mice )
+makes a quickStats file for today’s results.
+QuickStats file contains daily totals of rewards and headFixes for each mouse
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( tag , index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+setDateStr( )
+Sets the string corresponding to todays date that is used when making files
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+
+copies settings, creates folders for data and stats, creates initial log file and writes start session
+
+
+dataPath path to data folder
+
+/ logPath statsPath subfolders within data folder
+
+
+
+
+
+logFilePath statsFilePath paths to individual files within corresponding subfolders
+
+
+
+
+
+
+storeConfig( tag , configDict , source = '' )
+saves data to corresponding json text file, overwriting old file
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+Writes the time and type of each event to a text log file, and also to the shell
+Format of the output string: tag time_epoch or datetime event
+The computer-parsable time_epoch is printed to the log file and user-friendly datetime is printed to the shell
+:param tag: the tag of mouse, usually from RFIDTagreader.globalTag
+:param eventKind: the type of event to be printed, entry, exit, reward, etc.
+:param eventDict: a dictionary containing data about the event(may be None if no associated data)
+returns: nothing
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_textMySql module
+
+
+class AHF_DataLogger.AHF_DataLogger_textMySql.AHF_DataLogger_textMySql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Combination of the text data logger and mySQL data logger. Simply does both.
+For Tim.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+useLocalSql = True
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_HeadFixer.html b/docs/AHF_HeadFixer.html
new file mode 100644
index 0000000..bbd906f
--- /dev/null
+++ b/docs/AHF_HeadFixer.html
@@ -0,0 +1,734 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_HeadFixer — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_HeadFixer
+
+
AHF_HeadFixer.AHF_HeadFixer module
+
+
+class AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for all head fix classs. Other head fixers subclass from this, or from one of its subclasses
+boolean for settability of headFixing levels, default is False. Can be used for incremental learning
+
+
+clearResultsDict( resultsDict )
+
+
+
+
+abstract config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+abstract config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultHeadFixTime = 40
+
+
+
+
+defaultPropHeadFix = 0.75
+
+
+
+
+defaultSkeddadleTime = 5
+
+
+
+
+abstract fixMouse( thisTag , resultsDict = {} , settingsDict = {} )
+performs head fixation by energizing a piston, moving a servomotor, etc
+returns True if successful, else false.
+
+
+
+
+abstract hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = False
+
+
+
+
+hasMouseLog( hasContact , isFixed , thisTag , resultsDict )
+Utility function for head fix subclasses
+Run after head fixing to update common results
+
+
+
+
+isChecking = False
+
+
+
+
+static isFixedCheck( )
+
+
+
+
+newResultsDict( starterDict = {} )
+Returns a dictionary counting number of head fixes, subclasses could track more levels of head fixing, e.g.
+
+
+
+
+newSettingsDict( starterDict = {} )
+
+
+
+
+abstract releaseMouse( thisTag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+waitForMouse( thisTag )
+Utility function for head fix subclasses
+Waits for a mouse to either make contact or leave the chamber
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_NoFix module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_NoFix.AHF_HeadFixer_NoFix( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Head Fixer that only checks for contact, does not implement a
+head-fixing mechanism
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Querries user returns dictionary
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultSkeddadleTime = 0.5
+
+
+
+
+fixMouse( tag , resultsDict = {} , settingsDict = {} )
+Just does contact check with super(), does not fix
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = False
+
+
+
+
+isChecking = False
+
+
+
+
+releaseMouse( tag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Abstract class for PWM-based head fixers for servo motors. As long as your subclass maps your PWM range onto
+the appropriate pulse width for the servo, you should be good to go.
+
+
+calculate_steps( individualDict )
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultFixedPosition = 685
+
+
+
+
+defaultReleasePosition = 933
+
+
+
+
+defaultTightnessHeadFix = 1
+
+
+
+
+fixMouse( thisTag , resultsDict = {} , individualDict = {} )
+performs head fixation by energizing a piston, moving a servomotor, etc
+returns True if successful, else false.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = True
+
+
+
+
+individualSettings( starterDict = {} )
+copies servo fixed position to dictionary - there is no reason to have different released positions per subject
+TO DO: add multiple headfixing levels, maybe progression based on resdults
+
+
+
+
+numLevels = 8
+
+
+
+
+releaseMouse( thisTag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+abstract setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+abstract setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer_PWM.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685 module
+
uses PCA9685 code from AdaFruit, install as follows
+sudo apt-get install i2c-tools
+sudo apt-get install python3-smbus
+git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
+git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685.AHF_HeadFixer_PWM_PCA9685( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM
+inherits from AHF_HeadFixer.AHF_HeadFixer_PWM
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultAddress = 64
+
+
+
+
+setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM_Pi module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM_Pi.AHF_HeadFixer_PWM_Pi( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultChannel = 1
+
+
+
+
+setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_Pistons module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_Pistons.AHF_HeadFixer_Pistons( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Head fixer using solenoid-driven pistons to push head bar against front plate
+a single GPIO output triggers a driver of some kind to energize solenoids
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Querries user for pin number for piston, returns dictionary
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultPin = 12
+
+
+
+
+fixMouse( thisTag , resultsDict = {} , settingsDict = {} )
+sets GPIO pin high to trigger pistons
+
+
+
+
+releaseMouse( resultsDict = {} , individualDict = {} )
+sets GPIO pin low to retract pistons
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer_Pistons.random( ) → x in the interval [0, 1).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_HeadFixer.rst b/docs/AHF_HeadFixer.rst
new file mode 100644
index 0000000..ac1984b
--- /dev/null
+++ b/docs/AHF_HeadFixer.rst
@@ -0,0 +1,53 @@
+AHF\_HeadFixer
+======================
+
+
+
+AHF\_HeadFixer.AHF\_HeadFixer module
+------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_NoFix module
+-------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_NoFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM module
+-----------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_PCA9685 module
+--------------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_Pi module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_Pi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_Pistons module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_Pistons
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/AHF_LickDetector.html b/docs/AHF_LickDetector.html
new file mode 100644
index 0000000..04f541e
--- /dev/null
+++ b/docs/AHF_LickDetector.html
@@ -0,0 +1,463 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_LickDetector — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_LickDetector
+
+
AHF_LickDetector.AHF_LickDetector module
+
+
+class AHF_LickDetector.AHF_LickDetector.AHF_LickDetector( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for lick detetctor. Some kind of touch sensor on water port, capacitive or electrical.
+Should only report touches of the lick port, not un-touches. May have multiple channels. Must be
+able to count licks in an independent thread or via a threaded callback
+
+
+abstract getLickCount( )
+
+
+
+
+abstract getTouches( )
+returns number(bit-wise per channel lick detetctor has multiple channels) of which channels are currently touched
+
+
+
+
+abstract resumeLickCount( )
+
+
+
+
+abstract startLickCount( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+abstract startLickTiming( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+abstract startLogging( )
+Starts the datalogger logging licks to the shell, and to a file if one was provided
+
+
+
+
+abstract stopLickCount( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+abstract stopLickTiming( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+abstract stopLogging( )
+Stops the datalogger logging licks to the shell and file
+
+
+
+
+abstract waitForLick( timeOut_secs , startFromZero = False )
+Waits for a lick on any channel. Returns channel that was touched, or 0 if timeout expires with no touch,
+or -1 if startFromZero was True and the detector was touched for entire time
+
+
+
+
+
+
+
AHF_LickDetector.AHF_LickDetector_MPR module
+
+
+class AHF_LickDetector.AHF_LickDetector_MPR.AHF_LickDetector_MPR( taskP , settingsDictP )
+Bases: AHF_LickDetector.AHF_LickDetector.AHF_LickDetector
+Lick detector for Auto Head Fix based on MPR121 capacitive touch sensor
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+clearResultsDict( resultsDict )
+Clears values in the results dictionary, for daily totals of licks on all channels. Could be extended to per channel data
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultAddress = 90
+
+
+
+
+defaultIRQ = 26
+
+
+
+
+defaultTouchChannels = (0, 1, 2, 3)
+
+
+
+
+defaultTouchThresh = 8
+
+
+
+
+defaultUntouchThresh = 4
+
+
+
+
+getLickCount( )
+Get the number of licks for each channel in the global array without stopping the count.
+
+
+
+
+getTouches( )
+gets touches from mpr121
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+static logTouchCallback( touchedChannel )
+custom callback using global task reference from AHF_Task
+
+
+
+
+newResultsDict( starterDict = {} )
+Returns a dictionary with fields, initialized to 0,
+
+
+
+
+resetDetector( )
+Calls MPR121 reset function. Should rarely need to do this? This could be of use in resetting baseline untouched values.
+
+
+
+
+resumeLickCount( )
+Continue the lick counting without zeroing the channels
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+startLickCount( )
+Zeros the selected list of channels in the global array of licks per channel that the callback function updates.
+Use it to count licks, by zeroing selected channels, then checking the values in the array
+
+
+
+
+startLickTiming( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+startLogging( )
+tells the AHF_LickDetectorCallback to log touches in shell and file(if present)
+
+
+
+
+stopLickCount( chanList )
+takes a list of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+stopLickTiming( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+stopLogging( )
+tells the AHF_LickDetectorCallback to stop logging touches in shell and file(if present)
+but the callback is still running
+
+
+
+
+waitForLick( timeOut_secs , startFromZero = False )
+Waits for a lick on any channel. Returns channel that was touched, or 0 if timeout expires with no touch,
+or -1 if startFromZero was True and the detector was touched for entire time
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_LickDetector.rst b/docs/AHF_LickDetector.rst
new file mode 100644
index 0000000..16516c9
--- /dev/null
+++ b/docs/AHF_LickDetector.rst
@@ -0,0 +1,22 @@
+AHF\_LickDetector
+=========================
+
+
+
+AHF\_LickDetector.AHF\_LickDetector module
+------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_LickDetector.AHF\_LickDetector\_MPR module
+-----------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector_MPR
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/AHF_Notes.html b/docs/AHF_Notes.html
deleted file mode 100644
index cf3a2ea..0000000
--- a/docs/AHF_Notes.html
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-
-Auto Head Fix 3
-
-
-Programming and Usage Notes for AHF version 3
-AHF_Task - loads settings and holds references to all other objects
-Cage settings and Experiment settings are no longer be kept in separate files, but are loaded and stored in a single .json file. This file is used to initialize a single object, task, of the class Task, in AHF_Task.py. The Task object initializes the individual obects that provide specific functionality using dictionaries loaded from the .json file. The Task object keeps a reference to each objct it initializes, and each initialized object keeps a reference to the Task object. This way, only one object has to be passed around, and all functionality can be accessed from it.
-
-Some classes that control hardware devices are optional, and all classes are subclassable for different ways of performing the same basic function. Base classes(AHF_HeadFixer, AHF_Rewarder, AHF_Stimulator, AHF_ContactChecker, and AHF_Camera, e.g.) load no harware specific modules; instead they define the interface that must be provided by the subclasses that are specialized for particular hrdware. The base class defines the functions the subclasses must provide, and contain static functions for getting class names and importing classes, and allowing the user to select one of the subclasses. These base classes for specific tasks/hardware in turn inherit from AHF_Base, which defines the interface that AHF_Task uses to interact with the objects it will initialize. For instance, each class will be initialized with a a reference to the Task object, plus dictionary of settings made to its own specifications, and must provide a static function to querry the user for settings to generate a dictionary with those settings. The classes must also specify a test function for use with the hardware tester.
-
-
-Functionality Options for AutoHeadFix Systems
-
-Functionality Description Is Required?
-HeadFixer Stabilizes head for imaging No
-Camera Brain imaging camera controlled by Pi No
-Rewarder Provides rewards for training, water droplet, e.g. Yes
-Stimulator Controls task-specific hardware during headfix session Yes
-Stimulus Interacts with mouse with either a laser, vib. motor, or nothing Yes
-ContactChecker Sgnals that mouse is in position for head fixing or interacting Yes
-TagReader Innovations Design RFID reader with tag-in-range pin Yes
-LickDetector Touch sensor based on mpr121 connected to lick port No
-BrainLight Turns On and Off brain illumination during trials No
-DataLogger Logs all output of system to either text files or SQL database Yes
-
-
-
-
-
-An example snippet of the initialization function for AHF_Task demonstrates how the order imposed by AHF_Task/AHF_Base makes initilaization of tasks as generic as possible. After loading the settings file, this code looks for the HeadFixer class and HeadFixer dictionary in those settings. If not found, the user is querried for the desired headFixer class, and a static function from that class is used to query the user to provide settings that are stored in a dictionary, saved by the Task Object. A static function, denoted in Python by the @staticmethod decorator, is a function defined in a class that does not refer to an object of the class, and can be caled without first initializing an object of the class. In this case, static functions are used to make dictionaries that are then used to initialize the objects of the corresponding classes. Similar code, changing only the name of the functionality provided, is run for the other functionality. If the the names of the base classes and some basic information for each class were saved beforehand, this snippet, and the others for different functionality, could be replaced with a loop.
-
- if not hasattr(self, 'HeadFixerClass') or not hasattr(self, 'HeadFixerDict'):
- tempInput = input('Does this setup have a head fixing mechanism installed?(Y or N):')
- if tempInput [0] == 'y' or tempInput [0] == 'Y':
- self.HeadFixerClass = CAD.Class_from_file('HeadFixer', CAD.File_from_user('HeadFixer', 'Head Fixer Class', '.py'))
- self.HeadFixerDict = self.HeadFixerClass.config_user_get()
-
-
-With classes loaded and dictionaries ready, all named with the same format, the setup function for Task is mostly a loop of calling __init__ for each class with the dictionary for each class, plus the Task object itself. The Task object keeps a reference to the created objets, and each object created should maintain a reference to the task object, making it possible for the various objects to interact, self.task.
-
- fields = sorted(inspect.getmembers(self))
- for item in fields:
- if isinstance(item [1], ABCMeta):
- baseName = item [0].rstrip('Class')
- classDict = getattr(self, baseName + 'Dict')
- setattr(self, baseName, item [1](self, classDict))
-
-
-AHF_Base: base class for objects referenced from task
-Every bit of funtionality that needs to save any settings or initialize any data is subclassed from an abstract base class, AHF_Base. An abstract class is one that can not be initialized. In Python, this is indicated by marking one or more(usually empty) methods within the class with the @abstractmethod decorator, provided by the abc module. The idea is that subclasses will provide their own, non-abstract, version of these methods, with the paramaters and return values defined by the abstract method in the abstract base class. This makes it possible to organize all the code along the same lines for better readibility and to reduce code duplication. If all the classes follow the same conventions, the Task object can manipulate them assured that they will provide the functions defined in AHF_Base. The utility functions found in AHF_ClassAndDictUtils.py for manipulating classes and class/file names, dictionaries, and object fields also rely on this structuring. The code listing for AHF_Base is:
-
-class AHF_Base(metaclass = ABCMeta):
- Defines conventions for classes used for accesing hardware and doing subtasks in AutoHeadFix code
-
- @staticmethod/@abstractmethod
- def about():
- Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
-
- @staticmethod/@abstractmethod
- def config_user_get(starterDict = {}):
- Each class has a static method, config_user_get, to create or edit a settings dictionary, querrying the user for settings,
- with default responses from starterDict, and returns starterDict with settings as edited by the user.
- return starterDict
-
- def newResultsDict(self, starterDict = {}):
- Returns a dictionary with fields, initialized from starterDict, or set to 0, for storing results from actions of the object, used e.g., by head fixer,
- stimulator, or rewarder. Not all sub classes may need to return results, so newResultsDict is not an abstract function
- return starterDict
-
- def clearResultsDict(self, resultsDict):
- Clears values in the results dictionary, useful when you want daily totals Not all classes may store results, so not an abstract function
-
- def newSettingsDict(self, starterDict = {}):
- Returns starterDict, after adding fields filled with default values that can be modified for individual subjects Not all classes may have individualizabe
- settings, so individualSettings is not an abstract function
- return starterDict
-
- def __init__(self, taskP, settingsDictP):
- Each class will be inititialized with a reference to the Task Object, and a settings dictionary. Initialization of a subclass object may be just making a
- reference to the Task object and the settings dict,and running the class's setup function. Thus, this does not need to be an abtract function - your
- class can use this __init__ as is. Class names need to start with AHF_ and the dictionary must follow convention, named for the class with 'Dict' appended.
- self.task=taskP
- self.settingsDict = settingsDictP
- self.setup()
-
- @abstractmethod
- def setup(self):
- Does hardware initialization with(possibly updated) info in self.settingsDict Run by __init__, or can be run separately after editing the settingsDict
-
- @abstractmethod
- def setdown(self):
- oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO pins can be reused, for example.
- This strategy should be used in hardwareTest method, after making changes
-
- def __del__(self):
- For clean up purposes, releases hardware resources with setdown method. Not abstract, as setdown may be all your class needs to do.
- self.setdown()
-
- @abstractmethod
- def hardwareTest(self):
- Tests functionality, gives user a chance to change settings. Not restricted to classes that use hardware. Can be used to test any kind of functionality or
- adjust any kind of settings
-
-Information that is passed around between objects in the code but that is not attached to the task object is almost always passed as dictionaries. The objects that collect the information define the dictionaries that store that information, so, for example, the HeadFixer defines headFixes and Un-fixes(for unfixed trials) in a dictionary returned for newResultsDict. For individuation, each subject can request a results dictionary for each object that wants to collect data, and many object methods will have such a dictionary as a parameter. Settings, as distinct from results, can also be similarly individuated. The starter Dictionary for a class should be loaded from defaults defined in the class. The settings dictionary for a subject will be passed to class methods that need individual settings.
-
-Even the simple blue light to illuminate the brain has been made into a class and subclassed. It serves as a good example of what is involved in subclassing functionality. The abstract base class for functionality to control illumination for imaging is AHF_BrainLight, which inherits from AHF_Base:
-
-class AHF_BrainLight(AHF_Base, metaclass = ABCMeta):
-
- defaultDelay = 3.0
-
- @staticmethod/@abstractmethod
- def config_user_get(starterDict = {}):
- ledDelay = starterDict.get('ledDelay', AHF_BrainLight.defaultDelay)
- response = input('Delay in seconds before turning on\after turning off lights(currently %.2f): ' % ledDelay)
- if response != '':
- ledDelay = float(response)
- starterDict.update({'ledDelay' : ledDelay})
- return starterDict
-
- @abstractmethod
- def onForStim(self):
- Runs when headFixing starts, illuminating the brain or whatever needs illuminating
-
- @abstractmethod
- def offForStim(self):
- Runs when headFixing ends, turning off whatever was turned on
-
- def hardwareTest(self):
- generic hardware tester for brain illumination, turns on, waits 2 seconds, turns off. Subclasses may override this
- saveDelay = self.ledDelay
- self.ledDelay =0
- self.onForStim()
- print('Turning brain illumination ON for two seconds....')
- sleep(2)
- print('Turning brain illumination OFF.')
- self.offForStim()
- self.ledDelay = saveDelay
- result = input('Do you wish to edit brain light settings?')
- if result [0] == 'y' or result [0] == 'Y':
- self.setdown()
- self.settingsDict.update(self.config_user_get(self.settingsDict))
- self.setup()
-
-The only functions that need to be added to AHF_BrainLight are those that deal explicitly with the job of AHF_BrainLight, namely, turning on and off lights for illumination. Subclasses of AHF_BrainLight will still need to provide setup, hardwareTest, and other functions, and these must follow the signatures of those described in AHF_Base and AHF_BrainLight. Some code from a functional
-
-class AHF_BrainLight_1GPIO(AHF_BrainLight):
-
- defaultPin = 23 # default GPIO pin number
-
- @staticmethod
- def about():
- return 'Simplest brain illumination, toggles a single GPIO pin controlling an LED current driver.'
-
- @staticmethod
- def config_user_get(starterDict = {}):
- AHF_BrainLight.config_user_get(starterDict)
- ledPin = starterDict.get('ledPin', AHF_BrainLight_1GPIO.defaultPin)
- result = input('Enter the GPIO pin connected to the blue LED for brain camera illumination, currently %d:' % ledPin)
- if result != '':
- ledPin = int(result)
- starterDict.update({'ledPin':ledPin})
- return starterDict
-
- def setup(self):
- """
- does hardware initialization of a brain lighter with(possibly updated) info in self.settingsDict
- """
- self.ledPin = self.settingsDict.get('ledPin')
- self.ledDelay = self.settingsDict.get('ledDelay')
- GPIO.setup(self.ledPin, GPIO.OUT)
-
-The other classes are organized similarly, with an __init__ that just copies the dictionary, the setup function that initializes object fields from the dicitonary and that does GPIO hardware init, etc. , the config_user_get function that can create a settings dictionary before an object is initialized, and a hardwareTest function that tests the hardware and gives the user a chance to edit the object's settings dictionary, and then runs the setup function. Note that the settings dictionary is created in the Task object, and passed to the __init__ function, which uses the passed in dictionary, not making a fresh copy. That way, editing the settings through the hardwareTest, for instance, will edit the dictionary that is kept by the Task object.
-
-Head Fixer Classes
-AHF_HeadFIxer is the base class for all head fixing classes.
-
-
-What experiment information needs to be separate for each mouse? The Stimulator class will define a lot of task specific stuff, each mouse will have an entry for a stimulator dictionary containing information specific to that mouse. Other things:
-Reward sizes
-number of entry rewards
-head-fix proportions
-Maybe keep these things in experiment settings as defaults, so if a Mouse is created without these values, it gets the global ones as defaults.
-need better management of mouse data within the program, will want to add images, lever position arrays, other non-text data to mouse. pickle or some other serializer thing. Where and how is this data stored?
-
-
-Program Flow Description
-COnfigutation file is loaded or created, task object is created, hardware is initializaed, files for saving data are created. Program enters the top-level loop, waiting on the global variable globalTag to switch from 0. Mouse enters the tube. The tagReader callback reads the tag, and changes global variable globalTag from 0 to the mouse's id.
-
-
Remote control of AHF program using watchdog(pip3 install watchdog) ?
-
-
diff --git a/docs/AHF_Notifier.html b/docs/AHF_Notifier.html
new file mode 100644
index 0000000..c3ac753
--- /dev/null
+++ b/docs/AHF_Notifier.html
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Notifier — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Notifier
+
+
AHF_Notifier.AHF_Notifier module
+
+
+class AHF_Notifier.AHF_Notifier.AHF_Notifier( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Some remote way of notifying somebody, with email or text or something.
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+abstract notify( msgStr )
+a more general method to send text information
+
+
+
+
+abstract notifyStuck( tag , cageID , duration , isStuck )
+Sends a text message with the given information.
+Two types of message can be sent, depending if isStuck is True or False
+No timing is done by the AHF_Notifier class, the durations are only for building the text mssg
+:param tag: RFID tag of the mouse
+:param cageID: cage ID of the mouse that is stuck
+:param durationSecs: how long the mouse has been inside the chamber
+:param isStuck: boolean signifying if the mouse has been inside the chamber for too long, or has just left the chamber
+:return: nothing
+
+
+
+
+
+
+
AHF_Notifier.AHF_Notifier_Requests module
+
+
+class AHF_Notifier.AHF_Notifier_Requests.AHF_Notifier_Requests( taskP , settingsDictP )
+Bases: AHF_Notifier.AHF_Notifier.AHF_Notifier
+sends text messages to a tuple of phone numbers using a web service, textbelt.com
+You need to get an account and pay for some messages to get an account key
+As it uses http requests to send the message to the web service, your Pi needs to be online
+AHF_Notifier_Requests needs requests module, which is not installed by default.
+The best way to install python modules is with pip. Assuming you are using Python 3:
+sudo apt-get install python3-pip
+sudo pip-3 install requests
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+notify( msgStr )
+a more general method to send text information
+
+
+
+
+notifyStuck( tag , cageID , duration , isStuck )
+Sends a text message with the given information.
+Two types of message can be sent, depending if isStuck is True or False
+No timing is done by the AHF_Notifier class, the durations are only for building the text mssg
+:param tag: RFID tag of the mouse
+:param durationSecs: how long the mouse has been inside the chamber
+:param isStuck: boolean signifying if the mouse has been inside the chamber for too long, or has just left the chamber
+:return: nothing
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+textBeltURL = 'http://textbelt.com/text'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Notifier.rst b/docs/AHF_Notifier.rst
new file mode 100644
index 0000000..88f5501
--- /dev/null
+++ b/docs/AHF_Notifier.rst
@@ -0,0 +1,22 @@
+AHF\_Notifier
+=====================
+
+
+
+AHF\_Notifier.AHF\_Notifier module
+----------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Notifier.AHF\_Notifier\_Requests module
+--------------------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier_Requests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/AHF_Reader.html b/docs/AHF_Reader.html
new file mode 100644
index 0000000..828933d
--- /dev/null
+++ b/docs/AHF_Reader.html
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Reader — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Reader
+
+
AHF_Reader.AHF_Reader module
+
+
+class AHF_Reader.AHF_Reader.AHF_Reader( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+
+
+abstract readTag( )
+
+
+
+
+abstract startLogging( )
+starts using data logger to start logging entries/exits
+
+
+
+
+abstract stopLogging( )
+stops data logger from logging entries/exits
+
+
+
+
+
+
+
AHF_Reader.AHF_Reader_ID module
+
+
+class AHF_Reader.AHF_Reader_ID.AHF_Reader_ID( taskP , settingsDictP )
+Bases: AHF_Reader.AHF_Reader.AHF_Reader
+
+
+DO_CHECK_SUM = True
+
+
+
+
+TIME_OUT_SECS = 0.05
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+clearResultsDict( resultsDict )
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+constantCheck( channel )
+
+
+
+
+static customCallback( channel )
+callback sets tag value in global reference to task object.
+DO NOT START CALLBACK BEFORE TASK IS INITED
+also logs entries in TagReader results dict for the mouse the tag corresponds to
+
+
+
+
+defaultChamberTimeLimit = 600
+
+
+
+
+defaultPin = 7
+
+
+
+
+defaultPort = '/dev/ttyUSB0'
+
+
+
+
+gInChamberTimeLimit = 0.0
+
+
+
+
+gStillThere = False
+
+
+
+
+graceTime = 5
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+isChecking = True
+
+
+
+
+newResultsDict( starterDict = {} )
+
+
+
+
+readTag( )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+startLogging( )
+starts using data logger to start logging entries/exits
+
+
+
+
+stopLogging( )
+stops data logger from logging entries/exits
+
+
+
+
+static timeInChamberThread( sleepEndTime )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Reader.rst b/docs/AHF_Reader.rst
new file mode 100644
index 0000000..fb8b86e
--- /dev/null
+++ b/docs/AHF_Reader.rst
@@ -0,0 +1,22 @@
+AHF\_Reader
+===================
+
+
+
+AHF\_Reader.AHF\_Reader module
+------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Reader.AHF\_Reader\_ID module
+----------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader_ID
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/AHF_Rewarder.html b/docs/AHF_Rewarder.html
new file mode 100644
index 0000000..3a05266
--- /dev/null
+++ b/docs/AHF_Rewarder.html
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Rewarder — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Rewarder
+
+
AHF_Rewarder.AHF_Rewarder module
+
+
+class AHF_Rewarder.AHF_Rewarder.AHF_Rewarder( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for all rewarder classs. Other rewarders subclass from this, or from one of its subclasses
+
+
+addRewardToDict( rewardName , rewardSize )
+
+
+
+
+abstract countermandReward( resultsDict = {} , settingsDict = {} )
+
+
+
+
+entryRewardDelayDefault = 1.0
+
+
+
+
+abstract giveReward( rewardName , resultsDict = {} , settingsDict = {} )
+
+
+
+
+abstract giveRewardCM( rewardName , resultsDict = {} , settingsDict = {} )
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+maxBreakBeamRewardsDefault = 200
+
+
+
+
+maxEntryRewardsDefault = 1000
+
+
+
+
+rewardControl( )
+Opens and closes valve, as for testing, or draining the lines
+
+
+
+
+rewardUnits = ''
+
+
+
+
+setCountermandTime( countermandTime )
+
+
+
+
+testAmount = 0
+
+
+
+
+abstract turnOFF( )
+
+
+
+
+abstract turnON( )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder.AHF_Rewarder
+An abstract base class to use a solenoid to deliver water rewards using 1 GPIO pin, subclasses use different timing methods
+
+
+breakBeamHandling( )
+
+
+
+
+clearResultsDict( resultsDict )
+Clears results for daily totals of reward types
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+countermandReward( resultsDict = {} , settingsDict = {} )
+Countermands the previously given reward
+
+
+
+
+defaultBBWait = 1
+
+
+
+
+defaultBreakBeam = 0.1
+
+
+
+
+defaultEntry = 0.2
+
+
+
+
+defaultPin = 13
+
+
+
+
+defaultTask = 0.4
+
+
+
+
+defaultWait = 900
+
+
+
+
+entryHandling( )
+
+
+
+
+giveReward( rewardName , resultsDict = {} , settingsDict = {} )
+Gives reward, if reward name is in dictionary. If an entry reward, must be less than number of max entry rewards per day
+
+
+
+
+giveRewardCM( rewardName , resultsDict = {} , settingsDict = {} )
+Gives a reward that can be countermanded, i.e. cancelled if occurring before a timeour
+
+
+
+
+newResultsDict( )
+Return a dictionary of keys = rewardNames, values = number of rewards given, each mouse will get one of these for reward monitoring each day
+
+
+
+
+results_subject_get( )
+
+
+
+
+rewardUnits = 'Seconds'
+
+
+
+
+abstract setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+testAmount = 1.0
+
+
+
+
+abstract threadCMReward( sleepTime )
+
+
+
+
+abstract threadCountermand( )
+
+
+
+
+abstract threadReward( sleepTime )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid_pt module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid_pt.AHF_Rewarder_solenoid_pt( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid
+A class to use a solenoid to deliver water rewards using 1 GPIO pin, using pulsed thread/PTSimpleGPIO for timing
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+threadCMReward( sleepTime )
+
+
+
+
+threadCountermand( )
+
+
+
+
+threadReward( sleepTime )
+
+
+
+
+turnOFF( )
+
+
+
+
+turnON( )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid_rpi module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid_rpi.AHF_Rewarder_solenoid_rpi( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid
+A class to use a solenoid to deliver water rewards using 1 GPIO pin controlled by RPi.GPIO , using sleep for timing
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+countermandVal = 0
+
+
+
+
+static rewardCMThread( delayTime , sleepTime , rewardPin )
+
+
+
+
+static rewardThread( sleepTime , rewardPin )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+threadCMReward( sleepTime )
+
+
+
+
+threadCountermand( )
+
+
+
+
+threadReward( sleepTime )
+
+
+
+
+turnOFF( )
+
+
+
+
+turnON( )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Rewarder.rst b/docs/AHF_Rewarder.rst
new file mode 100644
index 0000000..a014463
--- /dev/null
+++ b/docs/AHF_Rewarder.rst
@@ -0,0 +1,38 @@
+AHF\_Rewarder
+=====================
+
+
+
+AHF\_Rewarder.AHF\_Rewarder module
+----------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid module
+--------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_pt module
+------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_pt
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_rpi module
+-------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_rpi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/AHF_Stimulator.html b/docs/AHF_Stimulator.html
new file mode 100644
index 0000000..1c173a7
--- /dev/null
+++ b/docs/AHF_Stimulator.html
@@ -0,0 +1,652 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Stimulator — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Stimulator
+
+
AHF_Stimulator.AHF_Stimulator module
+
+
+class AHF_Stimulator.AHF_Stimulator.AHF_Stimulator( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Stimulator does all stimulation and reward during a head fix task
+All events and their timings in a head fix, including rewards, are controlled by a Stimulator.
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+abstract quitting( )
+
+
+
+
+abstract run( level = 0 , resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+startVideo( )
+
+
+
+
+stop( )
+
+
+
+
+stopVideo( )
+
+
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_LEDs module
+
+
+class AHF_Stimulator.AHF_Stimulator_LEDs.AHF_Stimulator_LEDs( taskP )
+Bases: AHF_Stimulator.AHF_Stimulator_Rewards.AHF_Stimulator_Rewards
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configStim( mouse )
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+logFile( )
+
+Called after each head fix, prints more detailed text to the log file, perhaps a line for each event
+
+You may wish to use the same format as writeToLogFile function in __main__.py
+Or you may wish to override with pass and log from the run method
+
+
+
+
+logfile( )
+
+
+
+
+run( resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+
+
+AHF_Stimulator.AHF_Stimulator_LEDs.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_Lever module
+
+
+
AHF_Stimulator.AHF_Stimulator_LickWithhold module
+
+
+class AHF_Stimulator.AHF_Stimulator_LickWithhold.AHF_Stimulator_LickWithhold( taskP , settingsDictP )
+Bases: AHF_Stimulator.AHF_Stimulator.AHF_Stimulator
+
+
AHF_Stimulator_LickWithhold gives mice rewards based on their “level”
+
within the program. These rewards are given based on the mouse’s response
+
to a defined stimulus. Levels are as follows:
+
+
+
Level 0: Mouse gets periodic rewards paired with a stimulus. No input
+
required from the mouse at this stage.
+
Level 1: Mouse gets periodic rewards, again paired with a stimulus. The
+
mouse must refrain from licking for a defined withhold time before another
+
reward is given. If they lick within the withhold time, a buzzer sounds.
+
Level 2: Mouse must lick after a given delay time from the stimulus, and
+
within a defined response time, in order to receive a reward. In brief,
+
this is the “GO” task.
+
Level 3: Mouse must differentiate between two stimuluses, either one pulse
+
for “GO” or two successive pulses for “NO-GO”. In either case, they must
+
wait for the delay time before responding, and then within the response
+
time decide to either lick or not lick. “NO-GO” trials can be rewarded
+
with water or not if desired.
+
For levels 2 and 3, the outcome of the task is recorded as follows:
+
“GO”:
+
-4: licked within delay time, failure
+
-2: did not lick, failure
+
+2: waited until response time to lick and then licked, success
+
“NO-GO”:
+
-3: licked within delay time, failure
+
-1: waited until response time to lick and then licked, failure
+
+1: did not lick, success
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+delayTime_def = 0.5
+
+
+
+
+discrimTask( )
+
+
+
+
+goLikelihood_def = 0.5
+
+
+
+
+goTask( )
+A GO trial. Mouse must lick before getting a reward.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+lickWithholdTime_def = 1
+
+
+
+
+lickWrongTimeout_def = 5
+
+
+
+
+noGoTask( )
+
+
+
+
+quitting( )
+Called before AutoHEadFix exits. Gives stimulator chance to do any needed cleanup
+A stimulator may, e.g., open files and wish to close them before exiting, or use hardware that needs to be cleaned up
+
+
+
+
+responseTime_def = 2.5
+
+
+
+
+rewardNoGo_def = True
+
+
+
+
+rewardTask( )
+
+
+
+
+run( level = - 1 , resultsDict = {} , settingsDict = {} , tag = 0 )
+Called at start of each head fix. Does whatever
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+speakerDuty_def = 0.8
+
+
+
+
+speakerFreq_def = 300
+
+
+
+
+speakerOffForReward_def = 1.5
+
+
+
+
+speakerPin_def = 25
+
+
+
+
+withholdWait( endTime )
+
+
+
+
+
+
+AHF_Stimulator.AHF_Stimulator_LickWithhold.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_Rewards module
+
+
+class AHF_Stimulator.AHF_Stimulator_Rewards.AHF_Stimulator_Rewards( taskP , settingsDictP )
+Bases: AHF_Stimulator.AHF_Stimulator.AHF_Stimulator
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultInterval = 3
+
+
+
+
+defaultRewards = 5
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+nextDay( )
+Called when the next day starts. The stimulator is given the new log file pointer. Can do other things as needed
+:param newFP: the file pointer for the new day’s log file
+
+
+
+
+quitting( )
+Called before AutoHEadFix exits. Gives stimulator chance to do any needed cleanup
+A stimulator may, e.g., open files and wish to close them before exiting, or use hardware that needs to be cleaned up
+
+
+
+
+run( level = 0 , resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Stimulator.rst b/docs/AHF_Stimulator.rst
new file mode 100644
index 0000000..68dc155
--- /dev/null
+++ b/docs/AHF_Stimulator.rst
@@ -0,0 +1,45 @@
+AHF\_Stimulator
+=======================
+
+
+
+AHF\_Stimulator.AHF\_Stimulator module
+--------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LEDs module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LEDs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Lever module
+---------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Lever
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LickWithhold module
+----------------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LickWithhold
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Rewards module
+-----------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Rewards
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/AHF_Stimulus.html b/docs/AHF_Stimulus.html
new file mode 100644
index 0000000..d4d9029
--- /dev/null
+++ b/docs/AHF_Stimulus.html
@@ -0,0 +1,809 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Stimulus — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Stimulus
+
+
AHF_Stimulus.AHF_Stimulus module
+
+
+class AHF_Stimulus.AHF_Stimulus.AHF_Stimulus( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Generic “Stimulus” for use in Stimulators. Interacts with the mouse in
+some defined method based on the type of stimulus. Examples include a
+vibration motor, laser pulse in a specific brain region, or nothing.
+
+
+abstract length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+abstract period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+abstract stimulate( )
+
+
+
+
+abstract trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+abstract trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_Laser module
+
This Stimulator is subclassed from Rewards. It captures a reference image for each
+mouse and includes a user interface to select targets on reference images.
+The Stimulator directs and pulses a laser to selected targets for optogenetic
+stimulation/inhibition.
+
+
+class AHF_Stimulus.AHF_Stimulus_Laser.AHF_Stimulus_Laser( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Stimulates a specified region of the mouse’s brain with a laser,
+controlled via a stepper motor stage. Requires a camera - if using,
+cannot record video of the trial with overhead camera (used for aligning)
+The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+Every time a mouse enters, the program will start an image registration process to compare the mouse’s brain to that of its reference image.
+This will generate a transform matrix that maps ROI coordinates into live mouse brain location.
+Issues: The image registration process takes around 30 seconds per trial, which is far slower than ideal. The bulk of the computation is done
+in an external package, and we don’t know whether it’s optimized.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+accuracyTest( )
+For the given coefficient matrix, moves the laser to the center, then takes an image.
+Then, moves to 100 random points, and then back to center, taking another image.
+These images can then be compared to determine the long-term accuracy of the stepper motors.
+
+
+
+
+align( tag , resultsDict = {} , settingsDict = {} )
+Process for trial prep. First checks if reference image, target, and match coefficient matrices are present and prompts use to fill those in.
+Then aligns laser with reference image and assigned target
+
+Parameters
+
+tag (integer ) – mouse tag
+resultsDict (dict , optional ) – dictionary to save trial results, defaults to {}
+settingsDict (dict , optional ) – mouse settings dictionary, defaults to {}
+
+
+Returns
+True if aligned successfully, False otherwise
+
+Return type
+boolen
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Prompts the user for settings for the AHF_Stimulus_Laser class. The following can be changed:
+
+PWM_mode : used for adding channels to PWM, use default setting 0
+PWM_channel : current channel for PWM, use default setting 2
+duty_cycle : duty cycle for the laser out of 100. Indicates the strength of laser, 0 means the laser is off.
+laser_on_time : how many seconds the laser is on for per pulse/stimulation
+coeff_matrix : matrix used for matching xy coordinates on user interface and xy coordinates of the stepper motor tracks.
+Shift Register Settings : DS, Q7S, SHCP, STCP are pins for the shift registers controlling the stepper motors. Keep these as default or as indicated by the wiring diagrams.
+motor_delay : how long (in seconds) the stepper motor waits between each step, smaller delay means faster maximum movement speed.
+hdf_path : directory to save hdf5 files
+
+
+
+
+
+editReference( )
+Utility function to view and replace the reference image from menu
+
+
+
+
+feed_byte( byte )
+Toggle a byte into the shjft registers
+
+
+
+
+get_arrow_dir( key )
+If arrow keys are pressed, return information fed to stepper motors
+If page_up/down/home/end keys are pressed, return information fed to control UI crosshair.
+Tapping on left shift key will toggle between fast and slow move speed.
+Note: The fastest speed of motor movement depends on the motor_delay in config_user_get.
+Note (signs): The UI and stepper motors both follow the coordinate system with right and down as positive, left and up as negative.
+
+Parameters
+key (keyboard.Key object ) – current keyboard stroke
+
+Returns
+motor x-axis displacement, motor y-axis displacement, crosshair x-axis displacement, crosshair y-axis displacement
+
+Return type
+list of four integers
+
+
+
+
+
+
+get_dir( steps )
+Utility function to get the direction of movement from a signed integer
+
+Parameters
+steps (signed integer ) – input displacement from user
+
+Returns
+1 if input is positive, -1 if negative, 0 if no motion
+
+Return type
+integer
+
+
+
+
+
+
+get_ref_im( )
+Save a reference image whithin the mouse object (in hdf5 format)
+
+
+
+
+get_state( )
+Read out serial output and store state. Feed state back into shift reg.
+Create empty array to store the state
+
+Returns
+current serial output state
+
+Return type
+list of integers
+
+
+
+
+
+
+h5updater( )
+Updates the mouse’s hdf5 file with reference image, targets, trial images, and laser spot information collected from self.mouse
+
+
+
+
+hardwareTest( )
+Tester function called from the hardwareTester. Includes Stimulator specific hardware tester. Functions available include:
+
+m: run matching between UI and stepper motors
+i: tests a trial with a dummy mouse
+r: edit reference image
+t: select target ROI
+a: test accuracy of laser movement
+p: pulses the laser for 1 second
+l: camera preview with brainlight
+c: test motor movement, user will enter coordinates to move towards
+
+
+
+
+
+image_registration( )
+Image registration runs at the beginning of a new trial. Uses discrete fourier transform to find the transformation matrix from reference image
+to current brain image. Then transforms the target point on reference image to a position to a point on current brain image. Finally transforms that
+position into action stepper motor x and y steps.
+
+
+
+
+length( )
+
+Returns
+the laser on time per pulse
+
+Return type
+integer
+
+
+
+
+
+
+loadH5( )
+Loads an hdf file from a specific path self.hdf_path
+
+
+
+
+make_cross( )
+Define a simple cross-hair and add it as an overlay to the preview
+
+
+
+
+matcher( )
+Starts GUI to match coordinate systems.
+The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+
+
+
+
+move( x , y , phase , delay , topleft , mp )
+Main function, which moves stepper motors by x and y.
+
+Parameters
+
+x (integer ) – x-axis displacement
+y (integer ) – y-axis displacement
+phase (2 entry array ) – current phase of the stepper motors
+delay (integer ) – delay between each step
+topleft (boolean ) – true if origin is set to top left corner instead of center
+
+
+
+
+
+
+
+move_to( new_pos , topleft = True , join = False )
+High-level function, which invokes self.move to run on another processor. Moves the stepper motors to the specified position.
+
+Parameters
+
+new_pos (2-entry array ) – x, y coordinates of the new position
+topleft (bool , optional ) – parameter to the move() function, defaults to True
+join (bool , optional ) – whether to kill process after 30 second timeout, defaults to False
+
+
+
+
+
+
+
+on_press( key )
+Callback function, which responds to keyboard strokes. Processes the results from get_arrow_dir
+If arrow keys are pressed, queue up motor command and update motor position.
+If page_up/down/home/end keys are pressed, update the crosshair position.
+Space key saves the current stepper motor and crosshair position into arrays laser_points and image_points to be processed by matching()
+Esc key saves the arrays laser_points and image_points arrays and terminates the matching process
+Note: At least 3 points are required for matching
+
+Parameters
+key ([ type ] ) – [description]
+
+Returns
+[description]
+
+Return type
+[type]
+
+
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+pulse( duration , duty_cycle = 0 )
+Generates one laser pulse
+
+Parameters
+
+duration (float ) – duration of laser pulse
+duty_cycle (float , optional ) – duty cycle of the pwm used to drive laser, defaults to 0
+
+
+
+
+
+
+
+select_targets( )
+Menu function to select or update targets for one or more mice
+
+
+
+
+setdown( )
+Nothing specifc to setdown in laser module. Only sets down the AHF_Stimulus superclass
+
+
+
+
+setup( )
+Initializes the camera, pwm for laser, and relevant stepper motor settings from the settings dictionary.
+This function is usually ran after self.config_user_get(), which ensures the settings dict exists.
+This function also sets up GPIO pins. The pi throws errors when uninitialized pins are used, so make sure setup is called whenever program is restarted.
+
+
+
+
+stimulate( )
+Generates a single pulse with the laser. See pulse() function
+
+
+
+
+trialEnd( )
+Procedures to end a trial: stops camera preview and recenters the stepper motors
+
+
+
+
+trialPrep( tag )
+Runs once at the start of stimulator. Calls the align() funtion.
+
+
+
+
+unlock( )
+De-energize the stepper motors by toggling 0 into all shift registers
+
+
+
+
+update_cross( q )
+Callback function which processes changes in the cross-hair position and moves the crosshair on UI
+
+Parameters
+q (2 entry array ) –
+
+Returns
+returns false if q contains null entries
+
+Return type
+boolean
+
+
+
+
+
+
+update_mot( mot_q , phase_queue , delay , topleft )
+Callback funtion to process new motor steps. Infinite loop that runs on a different processor.
+
+Parameters
+
+mot_q (2-entry array ) – displacement to move the stepper motors by, updated by on_press
+phase_queue (2-entry array ) – queue representing the current motor phase
+delay (integer ) – delay between each step
+topleft (boolean ) – true if origin is set to top left corner instead of center
+
+
+
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_None module
+
+
+class AHF_Stimulus.AHF_Stimulus_None.AHF_Stimulus_None( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Does nothing.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+stimulate( )
+
+
+
+
+trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_VibMotor module
+
+
+class AHF_Stimulus.AHF_Stimulus_VibMotor.AHF_Stimulus_VibMotor( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Vibrates a motor placed on the exterior of the chamber.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+motorDuty_def = 0.8
+
+
+
+
+motorFreq_def = 300
+
+
+
+
+motorPin_def = 27
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+pulseTime_def = 0.2
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+stimulate( )
+
+
+
+
+trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Stimulus.rst b/docs/AHF_Stimulus.rst
new file mode 100644
index 0000000..8bd3460
--- /dev/null
+++ b/docs/AHF_Stimulus.rst
@@ -0,0 +1,38 @@
+AHF\_Stimulus
+=====================
+
+
+
+AHF\_Stimulus.AHF\_Stimulus module
+----------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_Laser module
+-----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_Laser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_None module
+----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_None
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_VibMotor module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_VibMotor
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/AHF_Subjects.html b/docs/AHF_Subjects.html
new file mode 100644
index 0000000..26cbfdd
--- /dev/null
+++ b/docs/AHF_Subjects.html
@@ -0,0 +1,484 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Subjects — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Subjects
+
+
AHF_Subjects.AHF_Subjects module
+
+
+class AHF_Subjects.AHF_Subjects.AHF_Subjects( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for experimental subjects. Defines subject attributes. Subjects must be unique for ID attribute
+Subclasses may wish to define an inner class that describes an object for a single experimental subject.
+
+
+abstract add( IDnum , dataDict )
+Adds a new subject to the pool of subjects, initializing subject fields with data from a dictionary
+returns True if subject was added, false if subject with IDnum already exists in subject pool
+
+
+
+
+abstract check( IDnum )
+returns 1 if IDnum is already in subjects, 0 if IDnum is not in subjects but is elgible to be added, returns -1 if IDnum is not elgible to be added
+
+
+
+
+abstract generator( )
+Generator function that generates dictionaries of settings for all of the subjects in turn
+
+
+
+
+abstract get( IDnum )
+returns results/settings dictionary for individual in group of subjects based on a ID tag.
+
+
+
+
+abstract get_all( )
+
+
+
+
+abstract remove( IDnum )
+Removes a subject from the pool of subjects, based on IDnumber. Returns true if subject with given OD was
+found and removed, returns false if no subject with IDnum was found in pool of subjects
+
+
+
+
+abstract setup( )
+results tuple defines dictionaries for subjects that our favorite objects will write results to
+for making daily tallies of results
+HeadFixer writes number of headfixes and un-fixes to its dictionary
+rewarder writes number and kind of rewards given to its dictionary
+TagReader writes number of chamber entrances to its dictionary
+Stimulator writes results of whatever it does during a head-fix session
+
+
+
+
+abstract show( IDNum = 0 )
+Prints out attributes for subject with given IDNum. If IDNum is 0, prints attributes for all subjects in pool.
+The attributes will be defined by subclass, results provided by stimulator, etc. Returns true if IDNum was found in
+pool, else False
+
+
+
+
+abstract subjectSettings( )
+changes the subject specific parameters that are(usually) independent from basic hardware settings
+e.g. headfix time, headfix tightness, reward size, add or remove a subject to a cage, stimulation specifications,
+task settings
+
+
+
+
+abstract userEdit( )
+Allows user interaction to add and remove subjects, maybe print out and edit individual configuration
+
+
+
+
+
+
+
AHF_Subjects.AHF_Subjects_mice module
+
+
+class AHF_Subjects.AHF_Subjects_mice.AHF_Subjects_mice( taskP , settingsDictP )
+Bases: AHF_Subjects.AHF_Subjects.AHF_Subjects
+class for the mice, as experimental subjects. Contains a dictionary where key id IDtag, and value is a dictionary
+of configuration information for corresponding mouse.
+{mouseid1:{HeadFixer:{}, Stimulator: {}, Rewarder: {}}, mouseid2:…}
+Dictionaries from Stimulator, HeadFixer, Rewarder are configured with
+the config_user_subject_get methods in their respective classes.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+add( IDnum , dataDict = {} , default = True )
+Adds a new subject to the pool of subjects, initializing subject fields with data from a dictionary
+returns True if subject was added, false if subjet with IDnum already exists in subject pool
+
+
+
+
+check( IDnum )
+returns 1 if IDnum is already in subjects, 0 if IDnum is not in subjects but is elgible to be added, returns -1 if IDnum is not elgible to be added
+
+
+
+
+check_miceDict( starterDict = {} )
+
+
+
+
+configPath = 'AHF_config/'
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+create_fillable_json( )
+
+
+
+
+depth( d , level = 0 )
+
+
+
+
+freshMiceDefault = False
+
+
+
+
+generator( )
+A Generator function that generates a(tagID, dictionary) tuple for each of the mice in turn.
+Sample function call: for mouse in myMice.generator():
+
+
+
+
+get( IDnum )
+returns a reference to the dictionary for the mouse with given IDtag. if the mouse tag is not found, makes a new dictionary
+if fresh mice can be added, else returns an empty dicitonary if fresh mice are to be ignored
+
+
+
+
+get_all( )
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+headFixTimeDefault = 40
+
+
+
+
+inChamberTimeLimitDefault = 300
+
+
+
+
+individualSettings( starterDict = {} )
+
+
+
+
+jsonNameDefault = 'subjects'
+
+
+
+
+loadConfigsDefault = 'provide_json'
+
+
+
+
+newDay( )
+
+
+
+
+propHeadFixDefault = 1
+
+
+
+
+remove( IDnum )
+Removes a subject from the pool of subjects, based on IDnumber. Returns true if subject with given OD was
+found and removed, returns false if no subject with IDnum was found in pool of subjects
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+results tuple defines dictionaries for subjects that our favorite objects will write results to
+for making daily tallies of results
+HeadFixer writes number of headfixes and un-fixes to its dictionary
+rewarder writes number and kind of rewards given to its dictionary
+TagReader writes number of chamber entrances to its dictionary
+Stimulator writes results of whatever it does during a head-fix session
+
+
+
+
+show( IDnum = 0 )
+Prints out attributes for subject with given IDNum. If IDNum is 0, prints attributes for all subjects in pool.
+The attributes will be defined by subclass, results provided by stimulator, etc. Returns true if IDNum was found in
+pool, else False
+
+
+
+
+skeddadleTimeDefault = 2
+
+
+
+
+subjectSettings( )
+Allows user to add mice to file, maybe use TagReader, give initial values to paramaters
+
+
+
+
+userEdit( )
+Allows user interaction to add and remove subjects, print out and edit individual configuration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Subjects.rst b/docs/AHF_Subjects.rst
new file mode 100644
index 0000000..2ba53e4
--- /dev/null
+++ b/docs/AHF_Subjects.rst
@@ -0,0 +1,23 @@
+AHF\_Subjects
+=====================
+
+
+
+AHF\_Subjects.AHF\_Subjects module
+----------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Subjects.AHF\_Subjects\_mice module
+----------------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects_mice
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+
diff --git a/docs/AHF_Trigger.html b/docs/AHF_Trigger.html
new file mode 100644
index 0000000..39398ed
--- /dev/null
+++ b/docs/AHF_Trigger.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Trigger — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Trigger
+
+
AHF_Trigger.AHF_Trigger module
+
+
+class AHF_Trigger.AHF_Trigger.AHF_Trigger( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Sends/receives signals as to another pi to start/stop recording
+
+
+abstract doTrigger( message )
+
+
+
+
+abstract getTrigger( )
+
+
+
+
+
+
+
AHF_Trigger.AHF_Trigger_UDP module
+
+
+class AHF_Trigger.AHF_Trigger_UDP.AHF_Trigger_UDP( taskP , settingsDictP )
+Bases: AHF_Trigger.AHF_Trigger.AHF_Trigger
+Sends/receives UDP signals as to another pi to start/stop recording from some device
+AHF_UDPTrig uses the socket module to do the UDP stuff, but it should be part of
+the default install
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+default_UDP_LIST = '127.0.0.1'
+
+
+
+
+default_UDP_PORT = 5007
+
+
+
+
+doTrigger( message )
+Sends a UDP message to the stored list of ip addresses
+
+
+
+
+getTrigger( )
+Waits for a UDP message and returns a string containing the message
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+Makes a new AHF_UDPtrig object using passed in list of ip addresses.
+stores UDPlist in the new object
+sets hasUDP to false if object creation fails because of network error, else True
+
+
+
+
+start_delay = 3.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/AHF_Trigger.rst b/docs/AHF_Trigger.rst
new file mode 100644
index 0000000..b012cb4
--- /dev/null
+++ b/docs/AHF_Trigger.rst
@@ -0,0 +1,19 @@
+AHF\_Trigger
+====================
+
+AHF\_Trigger.AHF\_Trigger module
+--------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Trigger.AHF\_Trigger\_UDP module
+-------------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger_UDP
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/Makefile b/docs/Makefile
index ed88099..d4bb2cb 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -6,7 +6,7 @@
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
-BUILDDIR = build
+BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
diff --git a/docs/_build/.doctrees/AHF_BrainLight.doctree b/docs/_build/.doctrees/AHF_BrainLight.doctree
new file mode 100644
index 0000000..3274ce8
Binary files /dev/null and b/docs/_build/.doctrees/AHF_BrainLight.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Camera.doctree b/docs/_build/.doctrees/AHF_Camera.doctree
new file mode 100644
index 0000000..cb08498
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Camera.doctree differ
diff --git a/docs/_build/.doctrees/AHF_ContactCheck.doctree b/docs/_build/.doctrees/AHF_ContactCheck.doctree
new file mode 100644
index 0000000..f4dee97
Binary files /dev/null and b/docs/_build/.doctrees/AHF_ContactCheck.doctree differ
diff --git a/docs/_build/.doctrees/AHF_DataLogger.doctree b/docs/_build/.doctrees/AHF_DataLogger.doctree
new file mode 100644
index 0000000..8c0e394
Binary files /dev/null and b/docs/_build/.doctrees/AHF_DataLogger.doctree differ
diff --git a/docs/_build/.doctrees/AHF_HeadFixer.doctree b/docs/_build/.doctrees/AHF_HeadFixer.doctree
new file mode 100644
index 0000000..dd10fb1
Binary files /dev/null and b/docs/_build/.doctrees/AHF_HeadFixer.doctree differ
diff --git a/docs/_build/.doctrees/AHF_LickDetector.doctree b/docs/_build/.doctrees/AHF_LickDetector.doctree
new file mode 100644
index 0000000..95601b6
Binary files /dev/null and b/docs/_build/.doctrees/AHF_LickDetector.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Notifier.doctree b/docs/_build/.doctrees/AHF_Notifier.doctree
new file mode 100644
index 0000000..0a018bd
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Notifier.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Reader.doctree b/docs/_build/.doctrees/AHF_Reader.doctree
new file mode 100644
index 0000000..119ca20
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Reader.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Rewarder.doctree b/docs/_build/.doctrees/AHF_Rewarder.doctree
new file mode 100644
index 0000000..f4afaf9
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Rewarder.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Stimulator.doctree b/docs/_build/.doctrees/AHF_Stimulator.doctree
new file mode 100644
index 0000000..b341e26
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Stimulator.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Stimulus.doctree b/docs/_build/.doctrees/AHF_Stimulus.doctree
new file mode 100644
index 0000000..1e3418a
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Stimulus.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Subjects.doctree b/docs/_build/.doctrees/AHF_Subjects.doctree
new file mode 100644
index 0000000..0c8f057
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Subjects.doctree differ
diff --git a/docs/_build/.doctrees/AHF_Trigger.doctree b/docs/_build/.doctrees/AHF_Trigger.doctree
new file mode 100644
index 0000000..3f1bfc7
Binary files /dev/null and b/docs/_build/.doctrees/AHF_Trigger.doctree differ
diff --git a/docs/_build/.doctrees/environment.pickle b/docs/_build/.doctrees/environment.pickle
new file mode 100644
index 0000000..d8ab051
Binary files /dev/null and b/docs/_build/.doctrees/environment.pickle differ
diff --git a/docs/_build/.doctrees/index.doctree b/docs/_build/.doctrees/index.doctree
new file mode 100644
index 0000000..16c7992
Binary files /dev/null and b/docs/_build/.doctrees/index.doctree differ
diff --git a/docs/_build/.doctrees/modules.doctree b/docs/_build/.doctrees/modules.doctree
new file mode 100644
index 0000000..d895fe5
Binary files /dev/null and b/docs/_build/.doctrees/modules.doctree differ
diff --git a/docs/_build/.doctrees/quickstart.doctree b/docs/_build/.doctrees/quickstart.doctree
new file mode 100644
index 0000000..b4e6db2
Binary files /dev/null and b/docs/_build/.doctrees/quickstart.doctree differ
diff --git a/docs/_build/.doctrees/rpi_setup.doctree b/docs/_build/.doctrees/rpi_setup.doctree
new file mode 100644
index 0000000..0aebecc
Binary files /dev/null and b/docs/_build/.doctrees/rpi_setup.doctree differ
diff --git a/docs/_build/.doctrees/util_classes.doctree b/docs/_build/.doctrees/util_classes.doctree
new file mode 100644
index 0000000..d0bb932
Binary files /dev/null and b/docs/_build/.doctrees/util_classes.doctree differ
diff --git a/docs/_build/doctrees/AHF_BrainLight.doctree b/docs/_build/doctrees/AHF_BrainLight.doctree
new file mode 100644
index 0000000..e6121c1
Binary files /dev/null and b/docs/_build/doctrees/AHF_BrainLight.doctree differ
diff --git a/docs/_build/doctrees/AHF_Camera.doctree b/docs/_build/doctrees/AHF_Camera.doctree
new file mode 100644
index 0000000..55e27cb
Binary files /dev/null and b/docs/_build/doctrees/AHF_Camera.doctree differ
diff --git a/docs/_build/doctrees/AHF_ContactCheck.doctree b/docs/_build/doctrees/AHF_ContactCheck.doctree
new file mode 100644
index 0000000..1882f49
Binary files /dev/null and b/docs/_build/doctrees/AHF_ContactCheck.doctree differ
diff --git a/docs/_build/doctrees/AHF_DataLogger.doctree b/docs/_build/doctrees/AHF_DataLogger.doctree
new file mode 100644
index 0000000..c93a16a
Binary files /dev/null and b/docs/_build/doctrees/AHF_DataLogger.doctree differ
diff --git a/docs/_build/doctrees/AHF_Datalogger.doctree b/docs/_build/doctrees/AHF_Datalogger.doctree
new file mode 100644
index 0000000..c93a16a
Binary files /dev/null and b/docs/_build/doctrees/AHF_Datalogger.doctree differ
diff --git a/docs/_build/doctrees/AHF_HeadFixer.doctree b/docs/_build/doctrees/AHF_HeadFixer.doctree
new file mode 100644
index 0000000..e0b3e4b
Binary files /dev/null and b/docs/_build/doctrees/AHF_HeadFixer.doctree differ
diff --git a/docs/_build/doctrees/AHF_LickDetector.doctree b/docs/_build/doctrees/AHF_LickDetector.doctree
new file mode 100644
index 0000000..95f240b
Binary files /dev/null and b/docs/_build/doctrees/AHF_LickDetector.doctree differ
diff --git a/docs/_build/doctrees/AHF_Notifier.doctree b/docs/_build/doctrees/AHF_Notifier.doctree
new file mode 100644
index 0000000..e573272
Binary files /dev/null and b/docs/_build/doctrees/AHF_Notifier.doctree differ
diff --git a/docs/_build/doctrees/AHF_Reader.doctree b/docs/_build/doctrees/AHF_Reader.doctree
new file mode 100644
index 0000000..5e4fcf4
Binary files /dev/null and b/docs/_build/doctrees/AHF_Reader.doctree differ
diff --git a/docs/_build/doctrees/AHF_Rewarder.doctree b/docs/_build/doctrees/AHF_Rewarder.doctree
new file mode 100644
index 0000000..e035789
Binary files /dev/null and b/docs/_build/doctrees/AHF_Rewarder.doctree differ
diff --git a/docs/_build/doctrees/AHF_Stimulator.doctree b/docs/_build/doctrees/AHF_Stimulator.doctree
new file mode 100644
index 0000000..a9259e4
Binary files /dev/null and b/docs/_build/doctrees/AHF_Stimulator.doctree differ
diff --git a/docs/_build/doctrees/AHF_Stimulus.doctree b/docs/_build/doctrees/AHF_Stimulus.doctree
new file mode 100644
index 0000000..0d7dcdc
Binary files /dev/null and b/docs/_build/doctrees/AHF_Stimulus.doctree differ
diff --git a/docs/_build/doctrees/AHF_Subjects.doctree b/docs/_build/doctrees/AHF_Subjects.doctree
new file mode 100644
index 0000000..428c157
Binary files /dev/null and b/docs/_build/doctrees/AHF_Subjects.doctree differ
diff --git a/docs/_build/doctrees/AHF_Trigger.doctree b/docs/_build/doctrees/AHF_Trigger.doctree
new file mode 100644
index 0000000..aba5d4d
Binary files /dev/null and b/docs/_build/doctrees/AHF_Trigger.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_BrainLight.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_BrainLight.doctree
new file mode 100644
index 0000000..e558d1b
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_BrainLight.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Camera.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Camera.doctree
new file mode 100644
index 0000000..83da17a
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Camera.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_ContactCheck.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_ContactCheck.doctree
new file mode 100644
index 0000000..25afd45
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_ContactCheck.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_DataLogger.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_DataLogger.doctree
new file mode 100644
index 0000000..fccf913
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_DataLogger.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_HeadFixer.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_HeadFixer.doctree
new file mode 100644
index 0000000..bb363d2
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_HeadFixer.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_LickDetector.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_LickDetector.doctree
new file mode 100644
index 0000000..52a845a
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_LickDetector.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Notifier.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Notifier.doctree
new file mode 100644
index 0000000..6c38969
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Notifier.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Reader.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Reader.doctree
new file mode 100644
index 0000000..b5baa11
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Reader.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Rewarder.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Rewarder.doctree
new file mode 100644
index 0000000..d527f9c
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Rewarder.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Stimulator.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Stimulator.doctree
new file mode 100644
index 0000000..252b8da
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Stimulator.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Stimulus.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Stimulus.doctree
new file mode 100644
index 0000000..83d4c57
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Stimulus.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Subjects.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Subjects.doctree
new file mode 100644
index 0000000..add9ee7
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Subjects.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.AHF_Trigger.doctree b/docs/_build/doctrees/AutoHeadFix.AHF_Trigger.doctree
new file mode 100644
index 0000000..e4c0441
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.AHF_Trigger.doctree differ
diff --git a/docs/_build/doctrees/AutoHeadFix.doctree b/docs/_build/doctrees/AutoHeadFix.doctree
new file mode 100644
index 0000000..aafea12
Binary files /dev/null and b/docs/_build/doctrees/AutoHeadFix.doctree differ
diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle
new file mode 100644
index 0000000..f5df2e8
Binary files /dev/null and b/docs/_build/doctrees/environment.pickle differ
diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree
new file mode 100644
index 0000000..ca6ecc0
Binary files /dev/null and b/docs/_build/doctrees/index.doctree differ
diff --git a/docs/_build/doctrees/modules.doctree b/docs/_build/doctrees/modules.doctree
new file mode 100644
index 0000000..2a1104c
Binary files /dev/null and b/docs/_build/doctrees/modules.doctree differ
diff --git a/docs/_build/doctrees/quickstart.doctree b/docs/_build/doctrees/quickstart.doctree
new file mode 100644
index 0000000..d3618bd
Binary files /dev/null and b/docs/_build/doctrees/quickstart.doctree differ
diff --git a/docs/_build/doctrees/rpi_setup.doctree b/docs/_build/doctrees/rpi_setup.doctree
new file mode 100644
index 0000000..24d5b41
Binary files /dev/null and b/docs/_build/doctrees/rpi_setup.doctree differ
diff --git a/docs/_build/doctrees/util_classes.doctree b/docs/_build/doctrees/util_classes.doctree
new file mode 100644
index 0000000..c390632
Binary files /dev/null and b/docs/_build/doctrees/util_classes.doctree differ
diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo
new file mode 100644
index 0000000..9ea2507
--- /dev/null
+++ b/docs/_build/html/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: 60dd385de4bbbec5fcc01b7ce6b46f8e
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/_build/html/.doctrees/AHF_BrainLight.doctree b/docs/_build/html/.doctrees/AHF_BrainLight.doctree
new file mode 100644
index 0000000..3274ce8
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_BrainLight.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Camera.doctree b/docs/_build/html/.doctrees/AHF_Camera.doctree
new file mode 100644
index 0000000..cb08498
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Camera.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_ContactCheck.doctree b/docs/_build/html/.doctrees/AHF_ContactCheck.doctree
new file mode 100644
index 0000000..f4dee97
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_ContactCheck.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_DataLogger.doctree b/docs/_build/html/.doctrees/AHF_DataLogger.doctree
new file mode 100644
index 0000000..8c0e394
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_DataLogger.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_HeadFixer.doctree b/docs/_build/html/.doctrees/AHF_HeadFixer.doctree
new file mode 100644
index 0000000..dd10fb1
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_HeadFixer.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_LickDetector.doctree b/docs/_build/html/.doctrees/AHF_LickDetector.doctree
new file mode 100644
index 0000000..95601b6
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_LickDetector.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Notifier.doctree b/docs/_build/html/.doctrees/AHF_Notifier.doctree
new file mode 100644
index 0000000..0a018bd
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Notifier.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Reader.doctree b/docs/_build/html/.doctrees/AHF_Reader.doctree
new file mode 100644
index 0000000..119ca20
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Reader.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Rewarder.doctree b/docs/_build/html/.doctrees/AHF_Rewarder.doctree
new file mode 100644
index 0000000..f4afaf9
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Rewarder.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Stimulator.doctree b/docs/_build/html/.doctrees/AHF_Stimulator.doctree
new file mode 100644
index 0000000..b341e26
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Stimulator.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Stimulus.doctree b/docs/_build/html/.doctrees/AHF_Stimulus.doctree
new file mode 100644
index 0000000..f752bcd
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Stimulus.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Subjects.doctree b/docs/_build/html/.doctrees/AHF_Subjects.doctree
new file mode 100644
index 0000000..0c8f057
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Subjects.doctree differ
diff --git a/docs/_build/html/.doctrees/AHF_Trigger.doctree b/docs/_build/html/.doctrees/AHF_Trigger.doctree
new file mode 100644
index 0000000..3f1bfc7
Binary files /dev/null and b/docs/_build/html/.doctrees/AHF_Trigger.doctree differ
diff --git a/docs/_build/html/.doctrees/environment.pickle b/docs/_build/html/.doctrees/environment.pickle
new file mode 100644
index 0000000..0a3000c
Binary files /dev/null and b/docs/_build/html/.doctrees/environment.pickle differ
diff --git a/docs/_build/html/.doctrees/index.doctree b/docs/_build/html/.doctrees/index.doctree
new file mode 100644
index 0000000..2fd78ff
Binary files /dev/null and b/docs/_build/html/.doctrees/index.doctree differ
diff --git a/docs/_build/html/.doctrees/modules.doctree b/docs/_build/html/.doctrees/modules.doctree
new file mode 100644
index 0000000..d895fe5
Binary files /dev/null and b/docs/_build/html/.doctrees/modules.doctree differ
diff --git a/docs/_build/html/.doctrees/quickstart.doctree b/docs/_build/html/.doctrees/quickstart.doctree
new file mode 100644
index 0000000..c850fd5
Binary files /dev/null and b/docs/_build/html/.doctrees/quickstart.doctree differ
diff --git a/docs/_build/html/.doctrees/rpi_setup.doctree b/docs/_build/html/.doctrees/rpi_setup.doctree
new file mode 100644
index 0000000..0aebecc
Binary files /dev/null and b/docs/_build/html/.doctrees/rpi_setup.doctree differ
diff --git a/docs/_build/html/.doctrees/util_classes.doctree b/docs/_build/html/.doctrees/util_classes.doctree
new file mode 100644
index 0000000..d0bb932
Binary files /dev/null and b/docs/_build/html/.doctrees/util_classes.doctree differ
diff --git a/docs/_build/html/AHF_BrainLight.html b/docs/_build/html/AHF_BrainLight.html
new file mode 100644
index 0000000..6438215
--- /dev/null
+++ b/docs/_build/html/AHF_BrainLight.html
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_BrainLight — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_BrainLight
+
+
AHF_BrainLight.AHF_BrainLight module
+
+
+class AHF_BrainLight.AHF_BrainLight.AHF_BrainLight( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultDelay = 3.0
+
+
+
+
+hardwareTest( )
+generic hardware tester for brain illumination, turns on, waits 2 seconds, turns off
+
+
+
+
+abstract offForStim( )
+Runs when headFixing ends, turning off whatever was turned on
+
+
+
+
+abstract onForStim( )
+Runs when headFixing starts, illuminating the brain or whatever needs illuminating
+
+
+
+
+
+
+
AHF_BrainLight.AHF_BrainLight_1GPIO module
+
+
+class AHF_BrainLight.AHF_BrainLight_1GPIO.AHF_BrainLight_1GPIO( taskP , settingsDictP )
+Bases: AHF_BrainLight.AHF_BrainLight.AHF_BrainLight
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultPin = 23
+
+
+
+
+offForStim( )
+Runs when headFixing ends, turning off whatever was turned on
+
+
+
+
+onForStim( )
+Runs when headFixing starts, illuminating the brain or whatever needs illuminating
+
+
+
+
+static onThread( sleepTime , ledPin )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization of a brain lighter with(possibly updated) info in self.settingsDict
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Camera.html b/docs/_build/html/AHF_Camera.html
new file mode 100644
index 0000000..f9a92bb
--- /dev/null
+++ b/docs/_build/html/AHF_Camera.html
@@ -0,0 +1,386 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Camera — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Camera
+
+
AHF_Camera.AHF_Camera module
+
+
+class AHF_Camera.AHF_Camera.AHF_Camera( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+AHF_Camera is the base class for the main brain imaging camera used in Auto Head Fix
+
+
+abstract resolution( )
+Return the resolution of the camera. Used for certain stimulators.
+
+
+
+
+abstract start_preview( )
+Starts a preview of the camera’s current vision.
+
+
+
+
+abstract start_recording( )
+Starts a recording of the camera’s current vision.
+
+
+
+
+abstract stop_preview( )
+Ends a preview of the camera’s current vision.
+
+
+
+
+abstract stop_recording( )
+Ends a recording of the camera’s current vision.
+
+
+
+
+
+
+
AHF_Camera.AHF_Camera_PiCam module
+
+
+class AHF_Camera.AHF_Camera_PiCam.AHF_Camera_PiCam( taskP , settingsDictP )
+Bases: AHF_Camera.AHF_Camera.AHF_Camera
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+add_overlay( bytes , layer , alpha )
+
+
+
+
+capture( path , type , video_port = False )
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings
+
+
+
+
+remove_overlay( overlay )
+
+
+
+
+resolution( )
+Return the resolution of the camera. Used for certain stimulators.
+
+
+
+
+set_gain( )
+Sets the gain and white balance of the camera based on a 2 second preview - so set illumination as you like before calling
+If ISO for the camera is set to non-zero value, gain is not settable. If pWhiteBalance was set to False, white balancing is not done,
+and gains for red and green are set to 1.
+:raises PiCameraError: error raised by superclass PiCamera from preview
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+start_preview( )
+Starts a preview of the camera’s current vision.
+
+
+
+
+start_recording( video_name )
+Starts a video recording using the saved settings for format, quality, gain, etc.
+A preview of the recording is always shown
+
+Parameters
+video_name – Name of saved recording. Always save to a file, not a PIL, for, example
+
+
+
+
+
+
+stop_preview( )
+Ends a preview of the camera’s current vision.
+
+
+
+
+stop_recording( )
+Stops a video recording previously started with start_recording.
+
+
+
+
+timed_recording( recTime )
+Does a timed video recording using the PiCamera wait_recording function.
+A preview of the recording is always shown
+Control does not pass back to the calling function until the recording is finished
+:param recTime: duration of the recorded video, in seconds
+
+
+
+
+
+
+
AHF_Camera.AHF_Camera_PiStream module
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_ContactCheck.html b/docs/_build/html/AHF_ContactCheck.html
new file mode 100644
index 0000000..3dedb57
--- /dev/null
+++ b/docs/_build/html/AHF_ContactCheck.html
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_ContactCheck — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_DataLogger.html b/docs/_build/html/AHF_DataLogger.html
new file mode 100644
index 0000000..fc6055b
--- /dev/null
+++ b/docs/_build/html/AHF_DataLogger.html
@@ -0,0 +1,1085 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Datalogger — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Datalogger
+
+
AHF_Datalogger.AHF_DataLogger module
+
+
+class AHF_DataLogger.AHF_DataLogger.AHF_DataLogger( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+A Data Logger provides an interface to save task data, and to save
+and load mouse configuration data. This can be either to text files, or to
+a database, or hd5 files, or some combination thereof. The data logger
+should also print status updates to the shell, but these don’t need to contain
+as much information. The brain imaging data is saved
+separately, but references to movie files should be saved by data logger.
+Similarly, other binary data(lever positons, anyone?) can be saved separately,
+by the Stimulator class, but binary file/posiiton can be saved as an event.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+clearTrackedValues( tag , eventKind , dictKey )
+
+
+
+
+abstract configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+abstract getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+abstract getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+getTrackedEvent( tag , eventKind , dictKey )
+Returns the current value for the specified mouse, event, and key.
+
+
+
+
+isChild = False
+
+
+
+
+abstract makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+abstract newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+abstract readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+resumeTracking( eventKind , dictKey )
+Resumes previously started tracking.
+
+
+
+
+abstract retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+abstract saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+startTracking( eventKind , dictKey , trackingType , size = 0 )
+Begins tracking of the specified key for the specified event.
+Tracks as a circular buffer or daily totals.
+
+
+
+
+stopTracking( eventKind , dictKey )
+Halts previously started tracking.
+
+
+
+
+abstract storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+abstract writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_localsql module
+
+
+class AHF_DataLogger.AHF_DataLogger_localsql.AHF_DataLogger_localsql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Data logger that uses the local mysql database. Used in case of unstable remote connections.
+Mouse data is stored in a specified folder as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_mysql module
+
+
+class AHF_DataLogger.AHF_DataLogger_mysql.AHF_DataLogger_mysql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultDatabase = 'AHF_laser_cage'
+
+
+
+
+defaultHost = '142.103.107.236'
+
+
+
+
+defaultPassword = '*******************'
+
+
+
+
+defaultUser = 'slavePi'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values , remote )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values , remote )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_text module
+
+
+class AHF_DataLogger.AHF_DataLogger_text.AHF_DataLogger_text( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultConfigPath = '/home/pi/Documents/MiceConfig/'
+
+
+
+
+defaultDataPath = '/home/pi/Documents/'
+
+
+
+
+getConfigData( tag )
+returns saved dictionary for given tag
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings
+
+
+
+
+makeLogFile( )
+open a new text log file for today, or open an exisiting text file with ‘a’ for append
+
+
+
+
+makeQuickStatsFile( mice )
+makes a quickStats file for today’s results.
+QuickStats file contains daily totals of rewards and headFixes for each mouse
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( tag , index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+setDateStr( )
+Sets the string corresponding to todays date that is used when making files
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+
+copies settings, creates folders for data and stats, creates initial log file and writes start session
+
+
+dataPath path to data folder
+
+/ logPath statsPath subfolders within data folder
+
+
+
+
+
+logFilePath statsFilePath paths to individual files within corresponding subfolders
+
+
+
+
+
+
+storeConfig( tag , configDict , source = '' )
+saves data to corresponding json text file, overwriting old file
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+Writes the time and type of each event to a text log file, and also to the shell
+Format of the output string: tag time_epoch or datetime event
+The computer-parsable time_epoch is printed to the log file and user-friendly datetime is printed to the shell
+:param tag: the tag of mouse, usually from RFIDTagreader.globalTag
+:param eventKind: the type of event to be printed, entry, exit, reward, etc.
+:param eventDict: a dictionary containing data about the event(may be None if no associated data)
+returns: nothing
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_textMySql module
+
+
+class AHF_DataLogger.AHF_DataLogger_textMySql.AHF_DataLogger_textMySql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Combination of the text data logger and mySQL data logger. Simply does both.
+For Tim.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+useLocalSql = True
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Datalogger.html b/docs/_build/html/AHF_Datalogger.html
new file mode 100644
index 0000000..fc6055b
--- /dev/null
+++ b/docs/_build/html/AHF_Datalogger.html
@@ -0,0 +1,1085 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Datalogger — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Datalogger
+
+
AHF_Datalogger.AHF_DataLogger module
+
+
+class AHF_DataLogger.AHF_DataLogger.AHF_DataLogger( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+A Data Logger provides an interface to save task data, and to save
+and load mouse configuration data. This can be either to text files, or to
+a database, or hd5 files, or some combination thereof. The data logger
+should also print status updates to the shell, but these don’t need to contain
+as much information. The brain imaging data is saved
+separately, but references to movie files should be saved by data logger.
+Similarly, other binary data(lever positons, anyone?) can be saved separately,
+by the Stimulator class, but binary file/posiiton can be saved as an event.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+clearTrackedValues( tag , eventKind , dictKey )
+
+
+
+
+abstract configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+abstract getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+abstract getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+getTrackedEvent( tag , eventKind , dictKey )
+Returns the current value for the specified mouse, event, and key.
+
+
+
+
+isChild = False
+
+
+
+
+abstract makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+abstract newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+abstract readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+resumeTracking( eventKind , dictKey )
+Resumes previously started tracking.
+
+
+
+
+abstract retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+abstract saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+startTracking( eventKind , dictKey , trackingType , size = 0 )
+Begins tracking of the specified key for the specified event.
+Tracks as a circular buffer or daily totals.
+
+
+
+
+stopTracking( eventKind , dictKey )
+Halts previously started tracking.
+
+
+
+
+abstract storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+abstract writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_localsql module
+
+
+class AHF_DataLogger.AHF_DataLogger_localsql.AHF_DataLogger_localsql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Data logger that uses the local mysql database. Used in case of unstable remote connections.
+Mouse data is stored in a specified folder as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_mysql module
+
+
+class AHF_DataLogger.AHF_DataLogger_mysql.AHF_DataLogger_mysql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+REQUESTED VALUES:
+“exit” for exits as event
+“lever_pull” as event for lever data
+“positions” as key for the lever positions in the event_dictionary of “lever_pull”
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( settings )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultDatabase = 'AHF_laser_cage'
+
+
+
+
+defaultHost = '142.103.107.236'
+
+
+
+
+defaultPassword = '*******************'
+
+
+
+
+defaultUser = 'slavePi'
+
+
+
+
+getConfigData( tag , source )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getFromDatabase( query , values , remote )
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+localDatabase = 'raw_data'
+
+
+
+
+localHost = 'localhost'
+
+
+
+
+localPassword = '*********************'
+
+
+
+
+localUser = 'pi'
+
+
+
+
+makeLogFile( )
+Initiating database creation
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+pingServers( )
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+saveToDatabase( query , values , remote )
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , configDict , source )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_text module
+
+
+class AHF_DataLogger.AHF_DataLogger_text.AHF_DataLogger_text( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Simple text-based data logger modified from the original Auto Head Fix code
+makes a new text logfile for each day, saved in default data path.
+Mouse data is stored in a specified folder, also as text files, one text file per mouse
+containing JSON formatted configuration and performance data. These files will opened and
+updated after each exit from the experimental tube, in case the program needs to be restarted
+The file name for each mouse contains RFID tag 0-padded to 13 spaces: AHF_mouse_1234567890123.jsn
+
+
+PSEUDO_MUTEX = 0
+The class field PSEUDO_MUTEX helps prevent print statements from different places in the code(main vs
+callbacks) from executing at the same time, which leads to garbled output. Unlike a real mutex, execution
+of the thread is not halted while waiting on the PSEUDO_MUTEX, hence the loops with calls to sleep to
+allow the other threads of execution to continue while waiting for the mutex to be free. Also, read/write
+to the PSEUDO_MUTEX is not atomic; one thread may read PSEUDO_MUTEX as 0, and set it to 1, but in the
+interval between reading and writing to PSEUDO_MUTEX,another thread may have read PSEUDO_MUTEX as 0 and
+both threads think they have the mutex
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+Each configuration file has config data for a single subject. This function loads data
+from all of them in turn, and returning each as a a tuple of(tagID, dictionary)
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultCage = 'cage1'
+
+
+
+
+defaultConfigPath = '/home/pi/Documents/MiceConfig/'
+
+
+
+
+defaultDataPath = '/home/pi/Documents/'
+
+
+
+
+getConfigData( tag )
+returns saved dictionary for given tag
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings
+
+
+
+
+makeLogFile( )
+open a new text log file for today, or open an exisiting text file with ‘a’ for append
+
+
+
+
+makeQuickStatsFile( mice )
+makes a quickStats file for today’s results.
+QuickStats file contains daily totals of rewards and headFixes for each mouse
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( tag , index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary = {} )
+store a new mouse entry in a referenced file
+
+
+
+
+setDateStr( )
+Sets the string corresponding to todays date that is used when making files
+
+
+
+
+setdown( )
+Writes session end and closes log file
+
+
+
+
+setup( )
+
+copies settings, creates folders for data and stats, creates initial log file and writes start session
+
+
+dataPath path to data folder
+
+/ logPath statsPath subfolders within data folder
+
+
+
+
+
+logFilePath statsFilePath paths to individual files within corresponding subfolders
+
+
+
+
+
+
+storeConfig( tag , configDict , source = '' )
+saves data to corresponding json text file, overwriting old file
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+Writes the time and type of each event to a text log file, and also to the shell
+Format of the output string: tag time_epoch or datetime event
+The computer-parsable time_epoch is printed to the log file and user-friendly datetime is printed to the shell
+:param tag: the tag of mouse, usually from RFIDTagreader.globalTag
+:param eventKind: the type of event to be printed, entry, exit, reward, etc.
+:param eventDict: a dictionary containing data about the event(may be None if no associated data)
+returns: nothing
+
+
+
+
+
+
+
AHF_Datalogger.AHF_DataLogger_textMySql module
+
+
+class AHF_DataLogger.AHF_DataLogger_textMySql.AHF_DataLogger_textMySql( taskP , settingsDictP )
+Bases: AHF_DataLogger.AHF_DataLogger.AHF_DataLogger
+Combination of the text data logger and mySQL data logger. Simply does both.
+For Tim.
+
+
+BUFFER_SIZE = 25
+
+
+
+
+TO_FILE = 2
+
+
+
+
+TO_SHELL = 1
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configGenerator( )
+generates configuration data for each subject as(IDtag, dictionary) tuples from some kind of permanent storage
+such as a JSON file, or a database. Will be called when program is started, or restarted and settings
+need to be reloaded.
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+getConfigData( tag )
+returns a dictionary of data that was saved for this reference tag, in some permanent storage such as a JSON file
+Will be called when program is started, or restarted and settings need to be reloaded
+
+
+
+
+getMice( )
+returns a list of mice that are in the dictionary/database
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+makeLogFile( )
+Makes or opens a text log file, or a datbase, or whatever else needs doing. Called once before
+entering main loop of program. DataLogger may make a new file every day in NewDay function, if desired
+
+
+
+
+newDay( )
+At the start of a new day, it was customary for the text-based data logging to start new text files,
+and to make a precis of the day’s results into a a separate text file for easy human reading.
+This “quickStats” file should contain info for each mouse with rewards, head fixes,
+or tasks, and other Stimulator specific data, which Stimulator object will provide for each mouse
+just call the Stimulator class functions for each mouse to get a dictionary of results
+
+
+
+
+readFromLogFile( index )
+Reads the log statement index lines prior to the current line.
+Returns the event and associated dictionary in a tuple.
+
+
+
+
+retireMouse( tag , reason )
+store information about a mouse retirement in a referenced file
+
+
+
+
+saveNewMouse( tag , note , dictionary )
+store a new mouse entry in a referenced file
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+storeConfig( tag , dictionary , source = '' )
+Stores configuration data, given as an IDtag, and dictionary for that tag, in some more permanent storage
+as a JSON text file, or a database or hd5 file, so it can be later retrieved by IDtag
+
+
+
+
+trackingDict = {}
+
+
+
+
+useLocalSql = True
+
+
+
+
+writeToLogFile( tag , eventKind , eventDict , timeStamp , toShellOrFile = 3 )
+The original standard text file method was 4 tab-separated columns, mouse tag, or 0
+if no single tag was applicaple, unix time stamp, ISO formatted time, and event. Event
+could be anything. Now, every event has a kind, and every kind of event defines a
+dictionary. Main program calls writeToLogFile, as well as the Stimulator object
+For text based methods, event should be a dictionary for more complicated stimulator
+results, so an event can be more easily parsed during data analysis.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_HeadFixer.html b/docs/_build/html/AHF_HeadFixer.html
new file mode 100644
index 0000000..bbd906f
--- /dev/null
+++ b/docs/_build/html/AHF_HeadFixer.html
@@ -0,0 +1,734 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_HeadFixer — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_HeadFixer
+
+
AHF_HeadFixer.AHF_HeadFixer module
+
+
+class AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for all head fix classs. Other head fixers subclass from this, or from one of its subclasses
+boolean for settability of headFixing levels, default is False. Can be used for incremental learning
+
+
+clearResultsDict( resultsDict )
+
+
+
+
+abstract config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+abstract config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultHeadFixTime = 40
+
+
+
+
+defaultPropHeadFix = 0.75
+
+
+
+
+defaultSkeddadleTime = 5
+
+
+
+
+abstract fixMouse( thisTag , resultsDict = {} , settingsDict = {} )
+performs head fixation by energizing a piston, moving a servomotor, etc
+returns True if successful, else false.
+
+
+
+
+abstract hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = False
+
+
+
+
+hasMouseLog( hasContact , isFixed , thisTag , resultsDict )
+Utility function for head fix subclasses
+Run after head fixing to update common results
+
+
+
+
+isChecking = False
+
+
+
+
+static isFixedCheck( )
+
+
+
+
+newResultsDict( starterDict = {} )
+Returns a dictionary counting number of head fixes, subclasses could track more levels of head fixing, e.g.
+
+
+
+
+newSettingsDict( starterDict = {} )
+
+
+
+
+abstract releaseMouse( thisTag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+waitForMouse( thisTag )
+Utility function for head fix subclasses
+Waits for a mouse to either make contact or leave the chamber
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_NoFix module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_NoFix.AHF_HeadFixer_NoFix( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Head Fixer that only checks for contact, does not implement a
+head-fixing mechanism
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Querries user returns dictionary
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultSkeddadleTime = 0.5
+
+
+
+
+fixMouse( tag , resultsDict = {} , settingsDict = {} )
+Just does contact check with super(), does not fix
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = False
+
+
+
+
+isChecking = False
+
+
+
+
+releaseMouse( tag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Abstract class for PWM-based head fixers for servo motors. As long as your subclass maps your PWM range onto
+the appropriate pulse width for the servo, you should be good to go.
+
+
+calculate_steps( individualDict )
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultFixedPosition = 685
+
+
+
+
+defaultReleasePosition = 933
+
+
+
+
+defaultTightnessHeadFix = 1
+
+
+
+
+fixMouse( thisTag , resultsDict = {} , individualDict = {} )
+performs head fixation by energizing a piston, moving a servomotor, etc
+returns True if successful, else false.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+hasLevels = True
+
+
+
+
+individualSettings( starterDict = {} )
+copies servo fixed position to dictionary - there is no reason to have different released positions per subject
+TO DO: add multiple headfixing levels, maybe progression based on resdults
+
+
+
+
+numLevels = 8
+
+
+
+
+releaseMouse( thisTag , resultsDict = {} , settingsDict = {} )
+releases mouse from head fixation by relaxing a piston, moving a servomotor, etc
+
+
+
+
+abstract setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+abstract setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer_PWM.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685 module
+
uses PCA9685 code from AdaFruit, install as follows
+sudo apt-get install i2c-tools
+sudo apt-get install python3-smbus
+git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
+git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685.AHF_HeadFixer_PWM_PCA9685( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM
+inherits from AHF_HeadFixer.AHF_HeadFixer_PWM
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultAddress = 64
+
+
+
+
+setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_PWM_Pi module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_PWM_Pi.AHF_HeadFixer_PWM_Pi( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultChannel = 1
+
+
+
+
+setPWM( servoPosition )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+
AHF_HeadFixer.AHF_HeadFixer_Pistons module
+
+
+class AHF_HeadFixer.AHF_HeadFixer_Pistons.AHF_HeadFixer_Pistons( taskP , settingsDictP )
+Bases: AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer
+Head fixer using solenoid-driven pistons to push head bar against front plate
+a single GPIO output triggers a driver of some kind to energize solenoids
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Querries user for pin number for piston, returns dictionary
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultPin = 12
+
+
+
+
+fixMouse( thisTag , resultsDict = {} , settingsDict = {} )
+sets GPIO pin high to trigger pistons
+
+
+
+
+releaseMouse( resultsDict = {} , individualDict = {} )
+sets GPIO pin low to retract pistons
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+gets settings from dict, not @abstract because this may be all you nees, as for HeadFixer_NoFix
+
+
+
+
+
+
+AHF_HeadFixer.AHF_HeadFixer_Pistons.random( ) → x in the interval [0, 1).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_LickDetector.html b/docs/_build/html/AHF_LickDetector.html
new file mode 100644
index 0000000..04f541e
--- /dev/null
+++ b/docs/_build/html/AHF_LickDetector.html
@@ -0,0 +1,463 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_LickDetector — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_LickDetector
+
+
AHF_LickDetector.AHF_LickDetector module
+
+
+class AHF_LickDetector.AHF_LickDetector.AHF_LickDetector( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for lick detetctor. Some kind of touch sensor on water port, capacitive or electrical.
+Should only report touches of the lick port, not un-touches. May have multiple channels. Must be
+able to count licks in an independent thread or via a threaded callback
+
+
+abstract getLickCount( )
+
+
+
+
+abstract getTouches( )
+returns number(bit-wise per channel lick detetctor has multiple channels) of which channels are currently touched
+
+
+
+
+abstract resumeLickCount( )
+
+
+
+
+abstract startLickCount( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+abstract startLickTiming( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+abstract startLogging( )
+Starts the datalogger logging licks to the shell, and to a file if one was provided
+
+
+
+
+abstract stopLickCount( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+abstract stopLickTiming( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+abstract stopLogging( )
+Stops the datalogger logging licks to the shell and file
+
+
+
+
+abstract waitForLick( timeOut_secs , startFromZero = False )
+Waits for a lick on any channel. Returns channel that was touched, or 0 if timeout expires with no touch,
+or -1 if startFromZero was True and the detector was touched for entire time
+
+
+
+
+
+
+
AHF_LickDetector.AHF_LickDetector_MPR module
+
+
+class AHF_LickDetector.AHF_LickDetector_MPR.AHF_LickDetector_MPR( taskP , settingsDictP )
+Bases: AHF_LickDetector.AHF_LickDetector.AHF_LickDetector
+Lick detector for Auto Head Fix based on MPR121 capacitive touch sensor
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+clearResultsDict( resultsDict )
+Clears values in the results dictionary, for daily totals of licks on all channels. Could be extended to per channel data
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+defaultAddress = 90
+
+
+
+
+defaultIRQ = 26
+
+
+
+
+defaultTouchChannels = (0, 1, 2, 3)
+
+
+
+
+defaultTouchThresh = 8
+
+
+
+
+defaultUntouchThresh = 4
+
+
+
+
+getLickCount( )
+Get the number of licks for each channel in the global array without stopping the count.
+
+
+
+
+getTouches( )
+gets touches from mpr121
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+static logTouchCallback( touchedChannel )
+custom callback using global task reference from AHF_Task
+
+
+
+
+newResultsDict( starterDict = {} )
+Returns a dictionary with fields, initialized to 0,
+
+
+
+
+resetDetector( )
+Calls MPR121 reset function. Should rarely need to do this? This could be of use in resetting baseline untouched values.
+
+
+
+
+resumeLickCount( )
+Continue the lick counting without zeroing the channels
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+startLickCount( )
+Zeros the selected list of channels in the global array of licks per channel that the callback function updates.
+Use it to count licks, by zeroing selected channels, then checking the values in the array
+
+
+
+
+startLickTiming( )
+Zeros the array that stores lick counts for each channel, and makes sure callback is filling the array for requested channels
+
+
+
+
+startLogging( )
+tells the AHF_LickDetectorCallback to log touches in shell and file(if present)
+
+
+
+
+stopLickCount( chanList )
+takes a list of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+stopLickTiming( )
+takes a tuple of channels and returns a list where each member is the number of licks for that channel in the global array
+call zeroLickCount, wait a while for some licks, then call getLickCount
+
+
+
+
+stopLogging( )
+tells the AHF_LickDetectorCallback to stop logging touches in shell and file(if present)
+but the callback is still running
+
+
+
+
+waitForLick( timeOut_secs , startFromZero = False )
+Waits for a lick on any channel. Returns channel that was touched, or 0 if timeout expires with no touch,
+or -1 if startFromZero was True and the detector was touched for entire time
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Notifier.html b/docs/_build/html/AHF_Notifier.html
new file mode 100644
index 0000000..c3ac753
--- /dev/null
+++ b/docs/_build/html/AHF_Notifier.html
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Notifier — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Notifier
+
+
AHF_Notifier.AHF_Notifier module
+
+
+class AHF_Notifier.AHF_Notifier.AHF_Notifier( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Some remote way of notifying somebody, with email or text or something.
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+abstract notify( msgStr )
+a more general method to send text information
+
+
+
+
+abstract notifyStuck( tag , cageID , duration , isStuck )
+Sends a text message with the given information.
+Two types of message can be sent, depending if isStuck is True or False
+No timing is done by the AHF_Notifier class, the durations are only for building the text mssg
+:param tag: RFID tag of the mouse
+:param cageID: cage ID of the mouse that is stuck
+:param durationSecs: how long the mouse has been inside the chamber
+:param isStuck: boolean signifying if the mouse has been inside the chamber for too long, or has just left the chamber
+:return: nothing
+
+
+
+
+
+
+
AHF_Notifier.AHF_Notifier_Requests module
+
+
+class AHF_Notifier.AHF_Notifier_Requests.AHF_Notifier_Requests( taskP , settingsDictP )
+Bases: AHF_Notifier.AHF_Notifier.AHF_Notifier
+sends text messages to a tuple of phone numbers using a web service, textbelt.com
+You need to get an account and pay for some messages to get an account key
+As it uses http requests to send the message to the web service, your Pi needs to be online
+AHF_Notifier_Requests needs requests module, which is not installed by default.
+The best way to install python modules is with pip. Assuming you are using Python 3:
+sudo apt-get install python3-pip
+sudo pip-3 install requests
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+notify( msgStr )
+a more general method to send text information
+
+
+
+
+notifyStuck( tag , cageID , duration , isStuck )
+Sends a text message with the given information.
+Two types of message can be sent, depending if isStuck is True or False
+No timing is done by the AHF_Notifier class, the durations are only for building the text mssg
+:param tag: RFID tag of the mouse
+:param durationSecs: how long the mouse has been inside the chamber
+:param isStuck: boolean signifying if the mouse has been inside the chamber for too long, or has just left the chamber
+:return: nothing
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+textBeltURL = 'http://textbelt.com/text'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Reader.html b/docs/_build/html/AHF_Reader.html
new file mode 100644
index 0000000..828933d
--- /dev/null
+++ b/docs/_build/html/AHF_Reader.html
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Reader — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Reader
+
+
AHF_Reader.AHF_Reader module
+
+
+class AHF_Reader.AHF_Reader.AHF_Reader( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+
+
+abstract readTag( )
+
+
+
+
+abstract startLogging( )
+starts using data logger to start logging entries/exits
+
+
+
+
+abstract stopLogging( )
+stops data logger from logging entries/exits
+
+
+
+
+
+
+
AHF_Reader.AHF_Reader_ID module
+
+
+class AHF_Reader.AHF_Reader_ID.AHF_Reader_ID( taskP , settingsDictP )
+Bases: AHF_Reader.AHF_Reader.AHF_Reader
+
+
+DO_CHECK_SUM = True
+
+
+
+
+TIME_OUT_SECS = 0.05
+
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+clearResultsDict( resultsDict )
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+constantCheck( channel )
+
+
+
+
+static customCallback( channel )
+callback sets tag value in global reference to task object.
+DO NOT START CALLBACK BEFORE TASK IS INITED
+also logs entries in TagReader results dict for the mouse the tag corresponds to
+
+
+
+
+defaultChamberTimeLimit = 600
+
+
+
+
+defaultPin = 7
+
+
+
+
+defaultPort = '/dev/ttyUSB0'
+
+
+
+
+gInChamberTimeLimit = 0.0
+
+
+
+
+gStillThere = False
+
+
+
+
+graceTime = 5
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+isChecking = True
+
+
+
+
+newResultsDict( starterDict = {} )
+
+
+
+
+readTag( )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+startLogging( )
+starts using data logger to start logging entries/exits
+
+
+
+
+stopLogging( )
+stops data logger from logging entries/exits
+
+
+
+
+static timeInChamberThread( sleepEndTime )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Rewarder.html b/docs/_build/html/AHF_Rewarder.html
new file mode 100644
index 0000000..3a05266
--- /dev/null
+++ b/docs/_build/html/AHF_Rewarder.html
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Rewarder — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Rewarder
+
+
AHF_Rewarder.AHF_Rewarder module
+
+
+class AHF_Rewarder.AHF_Rewarder.AHF_Rewarder( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for all rewarder classs. Other rewarders subclass from this, or from one of its subclasses
+
+
+addRewardToDict( rewardName , rewardSize )
+
+
+
+
+abstract countermandReward( resultsDict = {} , settingsDict = {} )
+
+
+
+
+entryRewardDelayDefault = 1.0
+
+
+
+
+abstract giveReward( rewardName , resultsDict = {} , settingsDict = {} )
+
+
+
+
+abstract giveRewardCM( rewardName , resultsDict = {} , settingsDict = {} )
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+maxBreakBeamRewardsDefault = 200
+
+
+
+
+maxEntryRewardsDefault = 1000
+
+
+
+
+rewardControl( )
+Opens and closes valve, as for testing, or draining the lines
+
+
+
+
+rewardUnits = ''
+
+
+
+
+setCountermandTime( countermandTime )
+
+
+
+
+testAmount = 0
+
+
+
+
+abstract turnOFF( )
+
+
+
+
+abstract turnON( )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder.AHF_Rewarder
+An abstract base class to use a solenoid to deliver water rewards using 1 GPIO pin, subclasses use different timing methods
+
+
+breakBeamHandling( )
+
+
+
+
+clearResultsDict( resultsDict )
+Clears results for daily totals of reward types
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+countermandReward( resultsDict = {} , settingsDict = {} )
+Countermands the previously given reward
+
+
+
+
+defaultBBWait = 1
+
+
+
+
+defaultBreakBeam = 0.1
+
+
+
+
+defaultEntry = 0.2
+
+
+
+
+defaultPin = 13
+
+
+
+
+defaultTask = 0.4
+
+
+
+
+defaultWait = 900
+
+
+
+
+entryHandling( )
+
+
+
+
+giveReward( rewardName , resultsDict = {} , settingsDict = {} )
+Gives reward, if reward name is in dictionary. If an entry reward, must be less than number of max entry rewards per day
+
+
+
+
+giveRewardCM( rewardName , resultsDict = {} , settingsDict = {} )
+Gives a reward that can be countermanded, i.e. cancelled if occurring before a timeour
+
+
+
+
+newResultsDict( )
+Return a dictionary of keys = rewardNames, values = number of rewards given, each mouse will get one of these for reward monitoring each day
+
+
+
+
+results_subject_get( )
+
+
+
+
+rewardUnits = 'Seconds'
+
+
+
+
+abstract setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+testAmount = 1.0
+
+
+
+
+abstract threadCMReward( sleepTime )
+
+
+
+
+abstract threadCountermand( )
+
+
+
+
+abstract threadReward( sleepTime )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid_pt module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid_pt.AHF_Rewarder_solenoid_pt( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid
+A class to use a solenoid to deliver water rewards using 1 GPIO pin, using pulsed thread/PTSimpleGPIO for timing
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+threadCMReward( sleepTime )
+
+
+
+
+threadCountermand( )
+
+
+
+
+threadReward( sleepTime )
+
+
+
+
+turnOFF( )
+
+
+
+
+turnON( )
+
+
+
+
+
+
+
AHF_Rewarder.AHF_Rewarder_solenoid_rpi module
+
+
+class AHF_Rewarder.AHF_Rewarder_solenoid_rpi.AHF_Rewarder_solenoid_rpi( taskP , settingsDictP )
+Bases: AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid
+A class to use a solenoid to deliver water rewards using 1 GPIO pin controlled by RPi.GPIO , using sleep for timing
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+countermandVal = 0
+
+
+
+
+static rewardCMThread( delayTime , sleepTime , rewardPin )
+
+
+
+
+static rewardThread( sleepTime , rewardPin )
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+threadCMReward( sleepTime )
+
+
+
+
+threadCountermand( )
+
+
+
+
+threadReward( sleepTime )
+
+
+
+
+turnOFF( )
+
+
+
+
+turnON( )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Stimulator.html b/docs/_build/html/AHF_Stimulator.html
new file mode 100644
index 0000000..1c173a7
--- /dev/null
+++ b/docs/_build/html/AHF_Stimulator.html
@@ -0,0 +1,652 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Stimulator — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Stimulator
+
+
AHF_Stimulator.AHF_Stimulator module
+
+
+class AHF_Stimulator.AHF_Stimulator.AHF_Stimulator( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Stimulator does all stimulation and reward during a head fix task
+All events and their timings in a head fix, including rewards, are controlled by a Stimulator.
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+abstract quitting( )
+
+
+
+
+abstract run( level = 0 , resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+startVideo( )
+
+
+
+
+stop( )
+
+
+
+
+stopVideo( )
+
+
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_LEDs module
+
+
+class AHF_Stimulator.AHF_Stimulator_LEDs.AHF_Stimulator_LEDs( taskP )
+Bases: AHF_Stimulator.AHF_Stimulator_Rewards.AHF_Stimulator_Rewards
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+configStim( mouse )
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+logFile( )
+
+Called after each head fix, prints more detailed text to the log file, perhaps a line for each event
+
+You may wish to use the same format as writeToLogFile function in __main__.py
+Or you may wish to override with pass and log from the run method
+
+
+
+
+logfile( )
+
+
+
+
+run( resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+
+
+AHF_Stimulator.AHF_Stimulator_LEDs.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_Lever module
+
+
+
AHF_Stimulator.AHF_Stimulator_LickWithhold module
+
+
+class AHF_Stimulator.AHF_Stimulator_LickWithhold.AHF_Stimulator_LickWithhold( taskP , settingsDictP )
+Bases: AHF_Stimulator.AHF_Stimulator.AHF_Stimulator
+
+
AHF_Stimulator_LickWithhold gives mice rewards based on their “level”
+
within the program. These rewards are given based on the mouse’s response
+
to a defined stimulus. Levels are as follows:
+
+
+
Level 0: Mouse gets periodic rewards paired with a stimulus. No input
+
required from the mouse at this stage.
+
Level 1: Mouse gets periodic rewards, again paired with a stimulus. The
+
mouse must refrain from licking for a defined withhold time before another
+
reward is given. If they lick within the withhold time, a buzzer sounds.
+
Level 2: Mouse must lick after a given delay time from the stimulus, and
+
within a defined response time, in order to receive a reward. In brief,
+
this is the “GO” task.
+
Level 3: Mouse must differentiate between two stimuluses, either one pulse
+
for “GO” or two successive pulses for “NO-GO”. In either case, they must
+
wait for the delay time before responding, and then within the response
+
time decide to either lick or not lick. “NO-GO” trials can be rewarded
+
with water or not if desired.
+
For levels 2 and 3, the outcome of the task is recorded as follows:
+
“GO”:
+
-4: licked within delay time, failure
+
-2: did not lick, failure
+
+2: waited until response time to lick and then licked, success
+
“NO-GO”:
+
-3: licked within delay time, failure
+
-1: waited until response time to lick and then licked, failure
+
+1: did not lick, success
+
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+delayTime_def = 0.5
+
+
+
+
+discrimTask( )
+
+
+
+
+goLikelihood_def = 0.5
+
+
+
+
+goTask( )
+A GO trial. Mouse must lick before getting a reward.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+lickWithholdTime_def = 1
+
+
+
+
+lickWrongTimeout_def = 5
+
+
+
+
+noGoTask( )
+
+
+
+
+quitting( )
+Called before AutoHEadFix exits. Gives stimulator chance to do any needed cleanup
+A stimulator may, e.g., open files and wish to close them before exiting, or use hardware that needs to be cleaned up
+
+
+
+
+responseTime_def = 2.5
+
+
+
+
+rewardNoGo_def = True
+
+
+
+
+rewardTask( )
+
+
+
+
+run( level = - 1 , resultsDict = {} , settingsDict = {} , tag = 0 )
+Called at start of each head fix. Does whatever
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+speakerDuty_def = 0.8
+
+
+
+
+speakerFreq_def = 300
+
+
+
+
+speakerOffForReward_def = 1.5
+
+
+
+
+speakerPin_def = 25
+
+
+
+
+withholdWait( endTime )
+
+
+
+
+
+
+AHF_Stimulator.AHF_Stimulator_LickWithhold.random( ) → x in the interval [0, 1).
+
+
+
+
+
AHF_Stimulator.AHF_Stimulator_Rewards module
+
+
+class AHF_Stimulator.AHF_Stimulator_Rewards.AHF_Stimulator_Rewards( taskP , settingsDictP )
+Bases: AHF_Stimulator.AHF_Stimulator.AHF_Stimulator
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+defaultInterval = 3
+
+
+
+
+defaultRewards = 5
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+nextDay( )
+Called when the next day starts. The stimulator is given the new log file pointer. Can do other things as needed
+:param newFP: the file pointer for the new day’s log file
+
+
+
+
+quitting( )
+Called before AutoHEadFix exits. Gives stimulator chance to do any needed cleanup
+A stimulator may, e.g., open files and wish to close them before exiting, or use hardware that needs to be cleaned up
+
+
+
+
+run( level = 0 , resultsDict = {} , settingsDict = {} )
+Called at start of each head fix. Does whatever
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Stimulus.html b/docs/_build/html/AHF_Stimulus.html
new file mode 100644
index 0000000..d4d9029
--- /dev/null
+++ b/docs/_build/html/AHF_Stimulus.html
@@ -0,0 +1,809 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Stimulus — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Stimulus
+
+
AHF_Stimulus.AHF_Stimulus module
+
+
+class AHF_Stimulus.AHF_Stimulus.AHF_Stimulus( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Generic “Stimulus” for use in Stimulators. Interacts with the mouse in
+some defined method based on the type of stimulus. Examples include a
+vibration motor, laser pulse in a specific brain region, or nothing.
+
+
+abstract length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+abstract period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+abstract stimulate( )
+
+
+
+
+abstract trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+abstract trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_Laser module
+
This Stimulator is subclassed from Rewards. It captures a reference image for each
+mouse and includes a user interface to select targets on reference images.
+The Stimulator directs and pulses a laser to selected targets for optogenetic
+stimulation/inhibition.
+
+
+class AHF_Stimulus.AHF_Stimulus_Laser.AHF_Stimulus_Laser( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Stimulates a specified region of the mouse’s brain with a laser,
+controlled via a stepper motor stage. Requires a camera - if using,
+cannot record video of the trial with overhead camera (used for aligning)
+The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+Every time a mouse enters, the program will start an image registration process to compare the mouse’s brain to that of its reference image.
+This will generate a transform matrix that maps ROI coordinates into live mouse brain location.
+Issues: The image registration process takes around 30 seconds per trial, which is far slower than ideal. The bulk of the computation is done
+in an external package, and we don’t know whether it’s optimized.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+accuracyTest( )
+For the given coefficient matrix, moves the laser to the center, then takes an image.
+Then, moves to 100 random points, and then back to center, taking another image.
+These images can then be compared to determine the long-term accuracy of the stepper motors.
+
+
+
+
+align( tag , resultsDict = {} , settingsDict = {} )
+Process for trial prep. First checks if reference image, target, and match coefficient matrices are present and prompts use to fill those in.
+Then aligns laser with reference image and assigned target
+
+Parameters
+
+tag (integer ) – mouse tag
+resultsDict (dict , optional ) – dictionary to save trial results, defaults to {}
+settingsDict (dict , optional ) – mouse settings dictionary, defaults to {}
+
+
+Returns
+True if aligned successfully, False otherwise
+
+Return type
+boolen
+
+
+
+
+
+
+static config_user_get( starterDict = {} )
+Prompts the user for settings for the AHF_Stimulus_Laser class. The following can be changed:
+
+PWM_mode : used for adding channels to PWM, use default setting 0
+PWM_channel : current channel for PWM, use default setting 2
+duty_cycle : duty cycle for the laser out of 100. Indicates the strength of laser, 0 means the laser is off.
+laser_on_time : how many seconds the laser is on for per pulse/stimulation
+coeff_matrix : matrix used for matching xy coordinates on user interface and xy coordinates of the stepper motor tracks.
+Shift Register Settings : DS, Q7S, SHCP, STCP are pins for the shift registers controlling the stepper motors. Keep these as default or as indicated by the wiring diagrams.
+motor_delay : how long (in seconds) the stepper motor waits between each step, smaller delay means faster maximum movement speed.
+hdf_path : directory to save hdf5 files
+
+
+
+
+
+editReference( )
+Utility function to view and replace the reference image from menu
+
+
+
+
+feed_byte( byte )
+Toggle a byte into the shjft registers
+
+
+
+
+get_arrow_dir( key )
+If arrow keys are pressed, return information fed to stepper motors
+If page_up/down/home/end keys are pressed, return information fed to control UI crosshair.
+Tapping on left shift key will toggle between fast and slow move speed.
+Note: The fastest speed of motor movement depends on the motor_delay in config_user_get.
+Note (signs): The UI and stepper motors both follow the coordinate system with right and down as positive, left and up as negative.
+
+Parameters
+key (keyboard.Key object ) – current keyboard stroke
+
+Returns
+motor x-axis displacement, motor y-axis displacement, crosshair x-axis displacement, crosshair y-axis displacement
+
+Return type
+list of four integers
+
+
+
+
+
+
+get_dir( steps )
+Utility function to get the direction of movement from a signed integer
+
+Parameters
+steps (signed integer ) – input displacement from user
+
+Returns
+1 if input is positive, -1 if negative, 0 if no motion
+
+Return type
+integer
+
+
+
+
+
+
+get_ref_im( )
+Save a reference image whithin the mouse object (in hdf5 format)
+
+
+
+
+get_state( )
+Read out serial output and store state. Feed state back into shift reg.
+Create empty array to store the state
+
+Returns
+current serial output state
+
+Return type
+list of integers
+
+
+
+
+
+
+h5updater( )
+Updates the mouse’s hdf5 file with reference image, targets, trial images, and laser spot information collected from self.mouse
+
+
+
+
+hardwareTest( )
+Tester function called from the hardwareTester. Includes Stimulator specific hardware tester. Functions available include:
+
+m: run matching between UI and stepper motors
+i: tests a trial with a dummy mouse
+r: edit reference image
+t: select target ROI
+a: test accuracy of laser movement
+p: pulses the laser for 1 second
+l: camera preview with brainlight
+c: test motor movement, user will enter coordinates to move towards
+
+
+
+
+
+image_registration( )
+Image registration runs at the beginning of a new trial. Uses discrete fourier transform to find the transformation matrix from reference image
+to current brain image. Then transforms the target point on reference image to a position to a point on current brain image. Finally transforms that
+position into action stepper motor x and y steps.
+
+
+
+
+length( )
+
+Returns
+the laser on time per pulse
+
+Return type
+integer
+
+
+
+
+
+
+loadH5( )
+Loads an hdf file from a specific path self.hdf_path
+
+
+
+
+make_cross( )
+Define a simple cross-hair and add it as an overlay to the preview
+
+
+
+
+matcher( )
+Starts GUI to match coordinate systems.
+The laser trial setup starts with a matching/alignment process. A reference image will be taken and the user will select a region of interest (ROI)
+on that image. Then the camera preview will start, allowing the user to move the laser with arrow keys to the position of a crosshair on the UI,
+hitting space will confirm the two position match. The user then moves the crosshair with home/pageup/pagedown/end keys and repeat this process two
+more times. After this process, exit with esc key and a coefficient matrix will be generated to match laser and user position in the future.
+
+
+
+
+move( x , y , phase , delay , topleft , mp )
+Main function, which moves stepper motors by x and y.
+
+Parameters
+
+x (integer ) – x-axis displacement
+y (integer ) – y-axis displacement
+phase (2 entry array ) – current phase of the stepper motors
+delay (integer ) – delay between each step
+topleft (boolean ) – true if origin is set to top left corner instead of center
+
+
+
+
+
+
+
+move_to( new_pos , topleft = True , join = False )
+High-level function, which invokes self.move to run on another processor. Moves the stepper motors to the specified position.
+
+Parameters
+
+new_pos (2-entry array ) – x, y coordinates of the new position
+topleft (bool , optional ) – parameter to the move() function, defaults to True
+join (bool , optional ) – whether to kill process after 30 second timeout, defaults to False
+
+
+
+
+
+
+
+on_press( key )
+Callback function, which responds to keyboard strokes. Processes the results from get_arrow_dir
+If arrow keys are pressed, queue up motor command and update motor position.
+If page_up/down/home/end keys are pressed, update the crosshair position.
+Space key saves the current stepper motor and crosshair position into arrays laser_points and image_points to be processed by matching()
+Esc key saves the arrays laser_points and image_points arrays and terminates the matching process
+Note: At least 3 points are required for matching
+
+Parameters
+key ([ type ] ) – [description]
+
+Returns
+[description]
+
+Return type
+[type]
+
+
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+pulse( duration , duty_cycle = 0 )
+Generates one laser pulse
+
+Parameters
+
+duration (float ) – duration of laser pulse
+duty_cycle (float , optional ) – duty cycle of the pwm used to drive laser, defaults to 0
+
+
+
+
+
+
+
+select_targets( )
+Menu function to select or update targets for one or more mice
+
+
+
+
+setdown( )
+Nothing specifc to setdown in laser module. Only sets down the AHF_Stimulus superclass
+
+
+
+
+setup( )
+Initializes the camera, pwm for laser, and relevant stepper motor settings from the settings dictionary.
+This function is usually ran after self.config_user_get(), which ensures the settings dict exists.
+This function also sets up GPIO pins. The pi throws errors when uninitialized pins are used, so make sure setup is called whenever program is restarted.
+
+
+
+
+stimulate( )
+Generates a single pulse with the laser. See pulse() function
+
+
+
+
+trialEnd( )
+Procedures to end a trial: stops camera preview and recenters the stepper motors
+
+
+
+
+trialPrep( tag )
+Runs once at the start of stimulator. Calls the align() funtion.
+
+
+
+
+unlock( )
+De-energize the stepper motors by toggling 0 into all shift registers
+
+
+
+
+update_cross( q )
+Callback function which processes changes in the cross-hair position and moves the crosshair on UI
+
+Parameters
+q (2 entry array ) –
+
+Returns
+returns false if q contains null entries
+
+Return type
+boolean
+
+
+
+
+
+
+update_mot( mot_q , phase_queue , delay , topleft )
+Callback funtion to process new motor steps. Infinite loop that runs on a different processor.
+
+Parameters
+
+mot_q (2-entry array ) – displacement to move the stepper motors by, updated by on_press
+phase_queue (2-entry array ) – queue representing the current motor phase
+delay (integer ) – delay between each step
+topleft (boolean ) – true if origin is set to top left corner instead of center
+
+
+
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_None module
+
+
+class AHF_Stimulus.AHF_Stimulus_None.AHF_Stimulus_None( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Does nothing.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+stimulate( )
+
+
+
+
+trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
AHF_Stimulus.AHF_Stimulus_VibMotor module
+
+
+class AHF_Stimulus.AHF_Stimulus_VibMotor.AHF_Stimulus_VibMotor( taskP , settingsDictP )
+Bases: AHF_Stimulus.AHF_Stimulus.AHF_Stimulus
+Vibrates a motor placed on the exterior of the chamber.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+length( )
+Return length of stimulus (e.g. pulse duration)
+
+
+
+
+motorDuty_def = 0.8
+
+
+
+
+motorFreq_def = 300
+
+
+
+
+motorPin_def = 27
+
+
+
+
+period( )
+Return period of stimulus (1/frequency for motor/laser)
+
+
+
+
+pulseTime_def = 0.2
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+stimulate( )
+
+
+
+
+trialEnd( )
+Code to be run at end of trial. E.g. moving laser to zero position
+
+
+
+
+trialPrep( tag )
+Prepares stimulus for trial: e.g. aligns laser, preps vib. motor, etc
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Subjects.html b/docs/_build/html/AHF_Subjects.html
new file mode 100644
index 0000000..26cbfdd
--- /dev/null
+++ b/docs/_build/html/AHF_Subjects.html
@@ -0,0 +1,484 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Subjects — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Subjects
+
+
AHF_Subjects.AHF_Subjects module
+
+
+class AHF_Subjects.AHF_Subjects.AHF_Subjects( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Base class for experimental subjects. Defines subject attributes. Subjects must be unique for ID attribute
+Subclasses may wish to define an inner class that describes an object for a single experimental subject.
+
+
+abstract add( IDnum , dataDict )
+Adds a new subject to the pool of subjects, initializing subject fields with data from a dictionary
+returns True if subject was added, false if subject with IDnum already exists in subject pool
+
+
+
+
+abstract check( IDnum )
+returns 1 if IDnum is already in subjects, 0 if IDnum is not in subjects but is elgible to be added, returns -1 if IDnum is not elgible to be added
+
+
+
+
+abstract generator( )
+Generator function that generates dictionaries of settings for all of the subjects in turn
+
+
+
+
+abstract get( IDnum )
+returns results/settings dictionary for individual in group of subjects based on a ID tag.
+
+
+
+
+abstract get_all( )
+
+
+
+
+abstract remove( IDnum )
+Removes a subject from the pool of subjects, based on IDnumber. Returns true if subject with given OD was
+found and removed, returns false if no subject with IDnum was found in pool of subjects
+
+
+
+
+abstract setup( )
+results tuple defines dictionaries for subjects that our favorite objects will write results to
+for making daily tallies of results
+HeadFixer writes number of headfixes and un-fixes to its dictionary
+rewarder writes number and kind of rewards given to its dictionary
+TagReader writes number of chamber entrances to its dictionary
+Stimulator writes results of whatever it does during a head-fix session
+
+
+
+
+abstract show( IDNum = 0 )
+Prints out attributes for subject with given IDNum. If IDNum is 0, prints attributes for all subjects in pool.
+The attributes will be defined by subclass, results provided by stimulator, etc. Returns true if IDNum was found in
+pool, else False
+
+
+
+
+abstract subjectSettings( )
+changes the subject specific parameters that are(usually) independent from basic hardware settings
+e.g. headfix time, headfix tightness, reward size, add or remove a subject to a cage, stimulation specifications,
+task settings
+
+
+
+
+abstract userEdit( )
+Allows user interaction to add and remove subjects, maybe print out and edit individual configuration
+
+
+
+
+
+
+
AHF_Subjects.AHF_Subjects_mice module
+
+
+class AHF_Subjects.AHF_Subjects_mice.AHF_Subjects_mice( taskP , settingsDictP )
+Bases: AHF_Subjects.AHF_Subjects.AHF_Subjects
+class for the mice, as experimental subjects. Contains a dictionary where key id IDtag, and value is a dictionary
+of configuration information for corresponding mouse.
+{mouseid1:{HeadFixer:{}, Stimulator: {}, Rewarder: {}}, mouseid2:…}
+Dictionaries from Stimulator, HeadFixer, Rewarder are configured with
+the config_user_subject_get methods in their respective classes.
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+add( IDnum , dataDict = {} , default = True )
+Adds a new subject to the pool of subjects, initializing subject fields with data from a dictionary
+returns True if subject was added, false if subjet with IDnum already exists in subject pool
+
+
+
+
+check( IDnum )
+returns 1 if IDnum is already in subjects, 0 if IDnum is not in subjects but is elgible to be added, returns -1 if IDnum is not elgible to be added
+
+
+
+
+check_miceDict( starterDict = {} )
+
+
+
+
+configPath = 'AHF_config/'
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+create_fillable_json( )
+
+
+
+
+depth( d , level = 0 )
+
+
+
+
+freshMiceDefault = False
+
+
+
+
+generator( )
+A Generator function that generates a(tagID, dictionary) tuple for each of the mice in turn.
+Sample function call: for mouse in myMice.generator():
+
+
+
+
+get( IDnum )
+returns a reference to the dictionary for the mouse with given IDtag. if the mouse tag is not found, makes a new dictionary
+if fresh mice can be added, else returns an empty dicitonary if fresh mice are to be ignored
+
+
+
+
+get_all( )
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+headFixTimeDefault = 40
+
+
+
+
+inChamberTimeLimitDefault = 300
+
+
+
+
+individualSettings( starterDict = {} )
+
+
+
+
+jsonNameDefault = 'subjects'
+
+
+
+
+loadConfigsDefault = 'provide_json'
+
+
+
+
+newDay( )
+
+
+
+
+propHeadFixDefault = 1
+
+
+
+
+remove( IDnum )
+Removes a subject from the pool of subjects, based on IDnumber. Returns true if subject with given OD was
+found and removed, returns false if no subject with IDnum was found in pool of subjects
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+results tuple defines dictionaries for subjects that our favorite objects will write results to
+for making daily tallies of results
+HeadFixer writes number of headfixes and un-fixes to its dictionary
+rewarder writes number and kind of rewards given to its dictionary
+TagReader writes number of chamber entrances to its dictionary
+Stimulator writes results of whatever it does during a head-fix session
+
+
+
+
+show( IDnum = 0 )
+Prints out attributes for subject with given IDNum. If IDNum is 0, prints attributes for all subjects in pool.
+The attributes will be defined by subclass, results provided by stimulator, etc. Returns true if IDNum was found in
+pool, else False
+
+
+
+
+skeddadleTimeDefault = 2
+
+
+
+
+subjectSettings( )
+Allows user to add mice to file, maybe use TagReader, give initial values to paramaters
+
+
+
+
+userEdit( )
+Allows user interaction to add and remove subjects, print out and edit individual configuration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/AHF_Trigger.html b/docs/_build/html/AHF_Trigger.html
new file mode 100644
index 0000000..39398ed
--- /dev/null
+++ b/docs/_build/html/AHF_Trigger.html
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+ AHF_Trigger — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AHF_Trigger
+
+
AHF_Trigger.AHF_Trigger module
+
+
+class AHF_Trigger.AHF_Trigger.AHF_Trigger( taskP , settingsDictP )
+Bases: AutoHeadFix.AHF_Base.AHF_Base
+Sends/receives signals as to another pi to start/stop recording
+
+
+abstract doTrigger( message )
+
+
+
+
+abstract getTrigger( )
+
+
+
+
+
+
+
AHF_Trigger.AHF_Trigger_UDP module
+
+
+class AHF_Trigger.AHF_Trigger_UDP.AHF_Trigger_UDP( taskP , settingsDictP )
+Bases: AHF_Trigger.AHF_Trigger.AHF_Trigger
+Sends/receives UDP signals as to another pi to start/stop recording from some device
+AHF_UDPTrig uses the socket module to do the UDP stuff, but it should be part of
+the default install
+
+
+static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+default_UDP_LIST = '127.0.0.1'
+
+
+
+
+default_UDP_PORT = 5007
+
+
+
+
+doTrigger( message )
+Sends a UDP message to the stored list of ip addresses
+
+
+
+
+getTrigger( )
+Waits for a UDP message and returns a string containing the message
+
+
+
+
+hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+setup( )
+Makes a new AHF_UDPtrig object using passed in list of ip addresses.
+stores UDPlist in the new object
+sets hasUDP to false if object creation fails because of network error, else True
+
+
+
+
+start_delay = 3.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/_sources/AHF_BrainLight.rst.txt b/docs/_build/html/_sources/AHF_BrainLight.rst.txt
new file mode 100644
index 0000000..45c15f0
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_BrainLight.rst.txt
@@ -0,0 +1,18 @@
+AHF\_BrainLight
+=======================
+
+AHF\_BrainLight.AHF\_BrainLight module
+--------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_BrainLight.AHF\_BrainLight\_1GPIO module
+---------------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight_1GPIO
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AHF_Camera.rst.txt b/docs/_build/html/_sources/AHF_Camera.rst.txt
new file mode 100644
index 0000000..3435bfd
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Camera.rst.txt
@@ -0,0 +1,27 @@
+AHF\_Camera
+===================
+
+AHF\_Camera.AHF\_Camera module
+------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiCam module
+-------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiCam
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiStream module
+----------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiStream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_ContactCheck.rst.txt b/docs/_build/html/_sources/AHF_ContactCheck.rst.txt
new file mode 100644
index 0000000..d74d003
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_ContactCheck.rst.txt
@@ -0,0 +1,27 @@
+AHF\_ContactCheck
+=========================
+
+AHF\_ContactCheck.AHF\_ContactCheck module
+------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_BeamBreak module
+-----------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_BeamBreak
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_Elec module
+------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_Elec
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_DataLogger.rst.txt b/docs/_build/html/_sources/AHF_DataLogger.rst.txt
new file mode 100644
index 0000000..054290a
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_DataLogger.rst.txt
@@ -0,0 +1,43 @@
+AHF\_Datalogger
+=======================
+
+AHF\_Datalogger.AHF\_DataLogger module
+--------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_localsql module
+------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_mysql module
+---------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_text module
+--------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_Datalogger.rst.txt b/docs/_build/html/_sources/AHF_Datalogger.rst.txt
new file mode 100644
index 0000000..054290a
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Datalogger.rst.txt
@@ -0,0 +1,43 @@
+AHF\_Datalogger
+=======================
+
+AHF\_Datalogger.AHF\_DataLogger module
+--------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_localsql module
+------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_mysql module
+---------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_text module
+--------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_HeadFixer.rst.txt b/docs/_build/html/_sources/AHF_HeadFixer.rst.txt
new file mode 100644
index 0000000..ac1984b
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_HeadFixer.rst.txt
@@ -0,0 +1,53 @@
+AHF\_HeadFixer
+======================
+
+
+
+AHF\_HeadFixer.AHF\_HeadFixer module
+------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_NoFix module
+-------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_NoFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM module
+-----------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_PCA9685 module
+--------------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_Pi module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_Pi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_Pistons module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_Pistons
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_LickDetector.rst.txt b/docs/_build/html/_sources/AHF_LickDetector.rst.txt
new file mode 100644
index 0000000..16516c9
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_LickDetector.rst.txt
@@ -0,0 +1,22 @@
+AHF\_LickDetector
+=========================
+
+
+
+AHF\_LickDetector.AHF\_LickDetector module
+------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_LickDetector.AHF\_LickDetector\_MPR module
+-----------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector_MPR
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_build/html/_sources/AHF_Notifier.rst.txt b/docs/_build/html/_sources/AHF_Notifier.rst.txt
new file mode 100644
index 0000000..88f5501
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Notifier.rst.txt
@@ -0,0 +1,22 @@
+AHF\_Notifier
+=====================
+
+
+
+AHF\_Notifier.AHF\_Notifier module
+----------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Notifier.AHF\_Notifier\_Requests module
+--------------------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier_Requests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_build/html/_sources/AHF_Reader.rst.txt b/docs/_build/html/_sources/AHF_Reader.rst.txt
new file mode 100644
index 0000000..fb8b86e
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Reader.rst.txt
@@ -0,0 +1,22 @@
+AHF\_Reader
+===================
+
+
+
+AHF\_Reader.AHF\_Reader module
+------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Reader.AHF\_Reader\_ID module
+----------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader_ID
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_build/html/_sources/AHF_Rewarder.rst.txt b/docs/_build/html/_sources/AHF_Rewarder.rst.txt
new file mode 100644
index 0000000..a014463
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Rewarder.rst.txt
@@ -0,0 +1,38 @@
+AHF\_Rewarder
+=====================
+
+
+
+AHF\_Rewarder.AHF\_Rewarder module
+----------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid module
+--------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_pt module
+------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_pt
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_rpi module
+-------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_rpi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_build/html/_sources/AHF_Stimulator.rst.txt b/docs/_build/html/_sources/AHF_Stimulator.rst.txt
new file mode 100644
index 0000000..68dc155
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Stimulator.rst.txt
@@ -0,0 +1,45 @@
+AHF\_Stimulator
+=======================
+
+
+
+AHF\_Stimulator.AHF\_Stimulator module
+--------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LEDs module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LEDs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Lever module
+---------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Lever
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LickWithhold module
+----------------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LickWithhold
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Rewards module
+-----------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Rewards
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AHF_Stimulus.rst.txt b/docs/_build/html/_sources/AHF_Stimulus.rst.txt
new file mode 100644
index 0000000..8bd3460
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Stimulus.rst.txt
@@ -0,0 +1,38 @@
+AHF\_Stimulus
+=====================
+
+
+
+AHF\_Stimulus.AHF\_Stimulus module
+----------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_Laser module
+-----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_Laser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_None module
+----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_None
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_VibMotor module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_VibMotor
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_build/html/_sources/AHF_Subjects.rst.txt b/docs/_build/html/_sources/AHF_Subjects.rst.txt
new file mode 100644
index 0000000..2ba53e4
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Subjects.rst.txt
@@ -0,0 +1,23 @@
+AHF\_Subjects
+=====================
+
+
+
+AHF\_Subjects.AHF\_Subjects module
+----------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Subjects.AHF\_Subjects\_mice module
+----------------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects_mice
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+
diff --git a/docs/_build/html/_sources/AHF_Trigger.rst.txt b/docs/_build/html/_sources/AHF_Trigger.rst.txt
new file mode 100644
index 0000000..b012cb4
--- /dev/null
+++ b/docs/_build/html/_sources/AHF_Trigger.rst.txt
@@ -0,0 +1,19 @@
+AHF\_Trigger
+====================
+
+AHF\_Trigger.AHF\_Trigger module
+--------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Trigger.AHF\_Trigger\_UDP module
+-------------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger_UDP
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_BrainLight.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_BrainLight.rst.txt
new file mode 100644
index 0000000..fd469f5
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_BrainLight.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_BrainLight package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_BrainLight.AHF\_BrainLight module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_BrainLight.AHF\_BrainLight\_1GPIO module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight.AHF_BrainLight_1GPIO
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Camera.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Camera.rst.txt
new file mode 100644
index 0000000..1cc9594
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Camera.rst.txt
@@ -0,0 +1,38 @@
+AutoHeadFix.AHF\_Camera package
+===============================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera module
+------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera\_PiCam module
+-------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera_PiCam
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera\_PiStream module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera_PiStream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt
new file mode 100644
index 0000000..4643c6e
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt
@@ -0,0 +1,38 @@
+AutoHeadFix.AHF\_ContactCheck package
+=====================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck module
+------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck\_BeamBreak module
+-----------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck_BeamBreak
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck\_Elec module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck_Elec
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_DataLogger.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_DataLogger.rst.txt
new file mode 100644
index 0000000..c0d5798
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_DataLogger.rst.txt
@@ -0,0 +1,54 @@
+AutoHeadFix.AHF\_DataLogger package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_localsql module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_mysql module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_text module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt
new file mode 100644
index 0000000..6509ed8
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt
@@ -0,0 +1,62 @@
+AutoHeadFix.AHF\_HeadFixer package
+==================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer module
+------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_NoFix module
+-------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_NoFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM module
+-----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_PCA9685 module
+--------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_Pi module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM_Pi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_Pistons module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_Pistons
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_LickDetector.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_LickDetector.rst.txt
new file mode 100644
index 0000000..c441999
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_LickDetector.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_LickDetector package
+=====================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_LickDetector.AHF\_LickDetector module
+------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_LickDetector.AHF\_LickDetector\_MPR module
+-----------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector.AHF_LickDetector_MPR
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Notifier.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Notifier.rst.txt
new file mode 100644
index 0000000..bdf3bd0
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Notifier.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Notifier package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Notifier.AHF\_Notifier module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Notifier.AHF\_Notifier\_Requests module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier.AHF_Notifier_Requests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Reader.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Reader.rst.txt
new file mode 100644
index 0000000..ea2f4e0
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Reader.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Reader package
+===============================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Reader.AHF\_Reader module
+------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Reader.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Reader.AHF\_Reader\_ID module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Reader.AHF_Reader_ID
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Rewarder.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Rewarder.rst.txt
new file mode 100644
index 0000000..9a8341f
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Rewarder.rst.txt
@@ -0,0 +1,46 @@
+AutoHeadFix.AHF\_Rewarder package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid\_pt module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid_pt
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid\_rpi module
+-------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid_rpi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulator.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulator.rst.txt
new file mode 100644
index 0000000..eb26745
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulator.rst.txt
@@ -0,0 +1,54 @@
+AutoHeadFix.AHF\_Stimulator package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_LEDs module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_LEDs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_Lever module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_Lever
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_LickWithhold module
+----------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_LickWithhold
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_Rewards module
+-----------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_Rewards
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulus.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulus.rst.txt
new file mode 100644
index 0000000..9dd0294
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Stimulus.rst.txt
@@ -0,0 +1,46 @@
+AutoHeadFix.AHF\_Stimulus package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_Laser module
+-----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_Laser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_None module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_None
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_VibMotor module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_VibMotor
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Subjects.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Subjects.rst.txt
new file mode 100644
index 0000000..d743d88
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Subjects.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Subjects package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Subjects.AHF\_Subjects module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Subjects.AHF\_Subjects\_mice module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects.AHF_Subjects_mice
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.AHF_Trigger.rst.txt b/docs/_build/html/_sources/AutoHeadFix.AHF_Trigger.rst.txt
new file mode 100644
index 0000000..b6a6800
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.AHF_Trigger.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Trigger package
+================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Trigger.AHF\_Trigger module
+--------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Trigger.AHF\_Trigger\_UDP module
+-------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger.AHF_Trigger_UDP
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/AutoHeadFix.rst.txt b/docs/_build/html/_sources/AutoHeadFix.rst.txt
new file mode 100644
index 0000000..530e612
--- /dev/null
+++ b/docs/_build/html/_sources/AutoHeadFix.rst.txt
@@ -0,0 +1,105 @@
+AutoHeadFix package
+===================
+
+Subpackages
+-----------
+
+.. toctree::
+
+ AutoHeadFix.AHF_BrainLight
+ AutoHeadFix.AHF_Camera
+ AutoHeadFix.AHF_ContactCheck
+ AutoHeadFix.AHF_DataLogger
+ AutoHeadFix.AHF_HeadFixer
+ AutoHeadFix.AHF_LickDetector
+ AutoHeadFix.AHF_Notifier
+ AutoHeadFix.AHF_Reader
+ AutoHeadFix.AHF_Rewarder
+ AutoHeadFix.AHF_Stimulator
+ AutoHeadFix.AHF_Stimulus
+ AutoHeadFix.AHF_Subjects
+ AutoHeadFix.AHF_Trigger
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Base module
+----------------------------
+
+.. automodule:: AutoHeadFix.AHF_Base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ClassAndDictUtils module
+-----------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ClassAndDictUtils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HardwareTester module
+--------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HardwareTester
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Task module
+----------------------------
+
+.. automodule:: AutoHeadFix.AHF_Task
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ValveControl module
+------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ValveControl
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.Subject\_update module
+----------------------------------
+
+.. automodule:: AutoHeadFix.Subject_update
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.quickstats module
+-----------------------------
+
+.. automodule:: AutoHeadFix.quickstats
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.restart\_if\_no\_data module
+----------------------------------------
+
+.. automodule:: AutoHeadFix.restart_if_no_data
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.water\_failsafe module
+----------------------------------
+
+.. automodule:: AutoHeadFix.water_failsafe
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt
new file mode 100644
index 0000000..309eeac
--- /dev/null
+++ b/docs/_build/html/_sources/index.rst.txt
@@ -0,0 +1,16 @@
+.. AutoHeadFix documentation master file, created by
+ sphinx-quickstart on Sun Apr 5 17:25:18 2020.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to AutoHeadFix's documentation!
+=======================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ rpi_setup
+ quickstart
+ modules
+
diff --git a/docs/_build/html/_sources/modules.rst.txt b/docs/_build/html/_sources/modules.rst.txt
new file mode 100644
index 0000000..94393b1
--- /dev/null
+++ b/docs/_build/html/_sources/modules.rst.txt
@@ -0,0 +1,18 @@
+AutoHeadFix Code Documentation
+=======================================
+
+.. toctree::
+ util_classes
+ AHF_BrainLight
+ AHF_Camera
+ AHF_ContactCheck
+ AHF_DataLogger
+ AHF_HeadFixer
+ AHF_LickDetector
+ AHF_Notifier
+ AHF_Reader
+ AHF_Rewarder
+ AHF_Stimulator
+ AHF_Stimulus
+ AHF_Subjects
+ AHF_Trigger
diff --git a/docs/_build/html/_sources/quickstart.rst.txt b/docs/_build/html/_sources/quickstart.rst.txt
new file mode 100644
index 0000000..4886f00
--- /dev/null
+++ b/docs/_build/html/_sources/quickstart.rst.txt
@@ -0,0 +1,94 @@
+Quick Start
+==========================
+
+Installation of AutoHeadFix
+-----------------------------
+
+To downlowd the setup script for AutoHeadFix, `click here `_.
+
+**Installation Walk Through**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+**Important**:
+
+* Having multiple installations can cause things to break if this is not your first time running this script in the trash make sure to delete all old folders and empty your trash
+* A config.txt file will be included in the repository, you must change the variables (eg path, password) to your installation specific details.
+* All cageID's must be unique.
+
+|
+
+Developers
+---------------
+
+* For notes and structure information from the developer, `click here `_.
+* To clone the source code, `click here `_.
+
+|
+
+Usage
+------
+
+**First Time Configuration**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Generic Usage Guide**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Cron Creation**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Changing Mouse Specific Var**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Training Difficulty**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
\ No newline at end of file
diff --git a/docs/_build/html/_sources/rpi_setup.rst.txt b/docs/_build/html/_sources/rpi_setup.rst.txt
new file mode 100644
index 0000000..9d7edc6
--- /dev/null
+++ b/docs/_build/html/_sources/rpi_setup.rst.txt
@@ -0,0 +1,17 @@
+General Raspberry Pi Setup
+==========================
+
+Installing OS and General Setup
+--------------------------------
+
+There are many guides available online for Raspberry Pi setup. This guide from medium contains the basic setup, `click here `_
+
+
+Mounting Hard Drive
+--------------------
+
+AutoHeadFix records many videos and an external hard drive is necessary.
+
+* Make sure your hard drive is powered by an external hub, as the pi itself may not provide enough voltage for the hard drive. *
+
+You will also need to format and mount your hard drive as outlined `here `_ .
diff --git a/docs/_build/html/_sources/util_classes.rst.txt b/docs/_build/html/_sources/util_classes.rst.txt
new file mode 100644
index 0000000..35517e5
--- /dev/null
+++ b/docs/_build/html/_sources/util_classes.rst.txt
@@ -0,0 +1,23 @@
+Auto Head Fix Util and Base Classes
+===================================
+
+AHF_Base
+--------
+.. automodule:: AHF_Base
+ :members:
+
+AHF_ClassAndDictUtils
+---------------------
+.. automodule:: AHF_ClassAndDictUtils
+ :members:
+
+AHF_HardwareTester
+--------------------
+.. automodule:: AHF_HardwareTester
+ :members:
+
+AHF_Task
+--------
+.. automodule:: AHF_Task
+ :members:
+
diff --git a/docs/build/html/_static/basic.css b/docs/_build/html/_static/basic.css
similarity index 98%
rename from docs/build/html/_static/basic.css
rename to docs/_build/html/_static/basic.css
index ea6972d..0119285 100644
--- a/docs/build/html/_static/basic.css
+++ b/docs/_build/html/_static/basic.css
@@ -4,7 +4,7 @@
*
* Sphinx stylesheet -- basic theme.
*
- * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
+ * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@@ -672,6 +672,10 @@ div.code-block-caption + div > div.highlight > pre {
margin-top: 0;
}
+div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+}
+
div.code-block-caption span.caption-number {
padding: 0.1em 0.3em;
font-style: italic;
diff --git a/docs/_build/html/_static/css/badge_only.css b/docs/_build/html/_static/css/badge_only.css
new file mode 100644
index 0000000..3c33cef
--- /dev/null
+++ b/docs/_build/html/_static/css/badge_only.css
@@ -0,0 +1 @@
+.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
diff --git a/docs/_build/html/_static/css/theme.css b/docs/_build/html/_static/css/theme.css
new file mode 100644
index 0000000..aed8cef
--- /dev/null
+++ b/docs/_build/html/_static/css/theme.css
@@ -0,0 +1,6 @@
+/* sphinx_rtd_theme version 0.4.3 | MIT license */
+/* Built 20190212 16:02 */
+*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:.5cm}p,h2,.rst-content .toctree-wrapper p.caption,h3{orphans:3;widows:3}h2,.rst-content .toctree-wrapper p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content .code-block-caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.7.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"),url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.wy-menu-vertical li span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.rst-content .fa-pull-left.admonition-title,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content dl dt .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.rst-content code.download span.fa-pull-left:first-child,.fa-pull-left.icon{margin-right:.3em}.fa.fa-pull-right,.wy-menu-vertical li span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.rst-content .fa-pull-right.admonition-title,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content dl dt .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.rst-content code.download span.fa-pull-right:first-child,.fa-pull-right.icon{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content .code-block-caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content .code-block-caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:""}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-signing:before,.fa-sign-language:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-vcard:before,.fa-address-card:before{content:""}.fa-vcard-o:before,.fa-address-card-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content .code-block-caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content table>caption .headerlink,.rst-content table>caption a .headerlink,a .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content table>caption .headerlink,.rst-content table>caption .btn .headerlink,.btn .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content table>caption .headerlink,.rst-content table>caption .nav .headerlink,.nav .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.btn .rst-content .code-block-caption .fa-large.headerlink,.rst-content .code-block-caption .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.nav .rst-content .code-block-caption .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.btn .rst-content .code-block-caption .fa-spin.headerlink,.rst-content .code-block-caption .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.nav .rst-content .code-block-caption .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.admonition{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo,.rst-content .wy-alert-warning.admonition{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title,.rst-content .wy-alert-warning.admonition .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.admonition{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.admonition{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.admonition{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 .3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.3576515979%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.3576515979%;width:48.821174201%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.3576515979%;width:31.7615656014%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type="datetime-local"]{padding:.34375em .625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{position:absolute;content:"";display:block;left:0;top:0;width:36px;height:12px;border-radius:4px;background:#ccc;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27AE60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:.3em;display:block}.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content .toctree-wrapper p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content .toctree-wrapper p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:before,.wy-breadcrumbs:after{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs li code,.wy-breadcrumbs li .rst-content tt,.rst-content .wy-breadcrumbs li tt{padding:5px;border:none;background:none}.wy-breadcrumbs li code.literal,.wy-breadcrumbs li .rst-content tt.literal,.rst-content .wy-breadcrumbs li tt.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#3a7ca8;height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin:12px 0 0 0;display:block;font-weight:bold;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a{color:#404040}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980B9;text-align:center;padding:.809em;display:block;color:#fcfcfc;margin-bottom:.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:normal;color:rgba(255,255,255,0.3)}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:gray}footer p{margin-bottom:12px}footer span.commit code,footer span.commit .rst-content tt,.rst-content footer span.commit tt{padding:0px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:1em;background:none;border:none;color:gray}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{width:100%}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:before,.rst-breadcrumbs-buttons:after{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-side-scroll{width:auto}.wy-side-nav-search{width:auto}.wy-menu.wy-menu-vertical{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1100px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;display:block;overflow:auto}.rst-content pre.literal-block,.rst-content div[class^='highlight']{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px 0}.rst-content pre.literal-block div[class^='highlight'],.rst-content div[class^='highlight'] div[class^='highlight']{padding:0px;border:none;margin:0}.rst-content div[class^='highlight'] td.code{width:100%}.rst-content .linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;display:block;overflow:auto}.rst-content div[class^='highlight'] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content pre.literal-block,.rst-content div[class^='highlight'] pre,.rst-content .linenodiv pre{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:12px;line-height:1.4}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^='highlight'],.rst-content div[class^='highlight'] pre{white-space:pre-wrap}}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last,.rst-content .admonition .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .line-block{margin-left:0px;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink{visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after,.rst-content .code-block-caption .headerlink:after{content:"";font-family:FontAwesome}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after,.rst-content .code-block-caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-0.4em;line-height:0;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:gray}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation tt,.rst-content table.docutils.citation code,.rst-content table.docutils.footnote tt,.rst-content table.docutils.footnote code{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}.rst-content table.docutils td .last,.rst-content table.docutils td .last :last-child{margin-bottom:0}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content tt,.rst-content tt,.rst-content code{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;padding:2px 5px}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal{color:#E74C3C}.rst-content tt.xref,a .rst-content tt,.rst-content tt.xref,.rst-content code.xref,a .rst-content tt,a .rst-content code{font-weight:bold;color:#404040}.rst-content pre,.rst-content kbd,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold;margin-bottom:12px}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-weight:normal;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child,.rst-content code.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-regular.eot");src:url("../fonts/Lato/lato-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-regular.woff2") format("woff2"),url("../fonts/Lato/lato-regular.woff") format("woff"),url("../fonts/Lato/lato-regular.ttf") format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bold.eot");src:url("../fonts/Lato/lato-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bold.woff2") format("woff2"),url("../fonts/Lato/lato-bold.woff") format("woff"),url("../fonts/Lato/lato-bold.ttf") format("truetype");font-weight:700;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bolditalic.eot");src:url("../fonts/Lato/lato-bolditalic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bolditalic.woff2") format("woff2"),url("../fonts/Lato/lato-bolditalic.woff") format("woff"),url("../fonts/Lato/lato-bolditalic.ttf") format("truetype");font-weight:700;font-style:italic}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-italic.eot");src:url("../fonts/Lato/lato-italic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-italic.woff2") format("woff2"),url("../fonts/Lato/lato-italic.woff") format("woff"),url("../fonts/Lato/lato-italic.ttf") format("truetype");font-weight:400;font-style:italic}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:url("../fonts/RobotoSlab/roboto-slab.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype")}
diff --git a/docs/build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js
similarity index 97%
rename from docs/build/html/_static/doctools.js
rename to docs/_build/html/_static/doctools.js
index b33f87f..daccd20 100644
--- a/docs/build/html/_static/doctools.js
+++ b/docs/_build/html/_static/doctools.js
@@ -4,7 +4,7 @@
*
* Sphinx JavaScript utilities for all documentation.
*
- * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
+ * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@@ -283,10 +283,11 @@ var Documentation = {
},
initOnKeyListeners: function() {
- $(document).keyup(function(event) {
+ $(document).keydown(function(event) {
var activeElementType = document.activeElement.tagName;
// don't navigate when in search box or textarea
- if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
+ if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
+ && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) {
switch (event.keyCode) {
case 37: // left
var prevHref = $('link[rel="prev"]').prop('href');
diff --git a/docs/build/html/_static/documentation_options.js b/docs/_build/html/_static/documentation_options.js
similarity index 86%
rename from docs/build/html/_static/documentation_options.js
rename to docs/_build/html/_static/documentation_options.js
index 3adf28f..e970480 100644
--- a/docs/build/html/_static/documentation_options.js
+++ b/docs/_build/html/_static/documentation_options.js
@@ -1,8 +1,9 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
- VERSION: '2.0.0',
+ VERSION: '2.1.0',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
+ BUILDER: 'html',
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
diff --git a/docs/build/html/_static/file.png b/docs/_build/html/_static/file.png
similarity index 100%
rename from docs/build/html/_static/file.png
rename to docs/_build/html/_static/file.png
diff --git a/docs/_build/html/_static/fonts/Inconsolata-Bold.ttf b/docs/_build/html/_static/fonts/Inconsolata-Bold.ttf
new file mode 100644
index 0000000..809c1f5
Binary files /dev/null and b/docs/_build/html/_static/fonts/Inconsolata-Bold.ttf differ
diff --git a/docs/_build/html/_static/fonts/Inconsolata-Regular.ttf b/docs/_build/html/_static/fonts/Inconsolata-Regular.ttf
new file mode 100644
index 0000000..fc981ce
Binary files /dev/null and b/docs/_build/html/_static/fonts/Inconsolata-Regular.ttf differ
diff --git a/docs/_build/html/_static/fonts/Inconsolata.ttf b/docs/_build/html/_static/fonts/Inconsolata.ttf
new file mode 100644
index 0000000..4b8a36d
Binary files /dev/null and b/docs/_build/html/_static/fonts/Inconsolata.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato-Bold.ttf b/docs/_build/html/_static/fonts/Lato-Bold.ttf
new file mode 100644
index 0000000..1d23c70
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato-Bold.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato-Regular.ttf b/docs/_build/html/_static/fonts/Lato-Regular.ttf
new file mode 100644
index 0000000..0f3d0f8
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato-Regular.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bold.eot b/docs/_build/html/_static/fonts/Lato/lato-bold.eot
new file mode 100644
index 0000000..3361183
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bold.eot differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bold.ttf b/docs/_build/html/_static/fonts/Lato/lato-bold.ttf
new file mode 100644
index 0000000..29f691d
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bold.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bold.woff b/docs/_build/html/_static/fonts/Lato/lato-bold.woff
new file mode 100644
index 0000000..c6dff51
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bold.woff differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bold.woff2 b/docs/_build/html/_static/fonts/Lato/lato-bold.woff2
new file mode 100644
index 0000000..bb19504
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bold.woff2 differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot
new file mode 100644
index 0000000..3d41549
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.eot differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf
new file mode 100644
index 0000000..f402040
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff
new file mode 100644
index 0000000..88ad05b
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2
new file mode 100644
index 0000000..c4e3d80
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-bolditalic.woff2 differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-italic.eot b/docs/_build/html/_static/fonts/Lato/lato-italic.eot
new file mode 100644
index 0000000..3f82642
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-italic.eot differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-italic.ttf b/docs/_build/html/_static/fonts/Lato/lato-italic.ttf
new file mode 100644
index 0000000..b4bfc9b
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-italic.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-italic.woff b/docs/_build/html/_static/fonts/Lato/lato-italic.woff
new file mode 100644
index 0000000..76114bc
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-italic.woff differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-italic.woff2 b/docs/_build/html/_static/fonts/Lato/lato-italic.woff2
new file mode 100644
index 0000000..3404f37
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-italic.woff2 differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-regular.eot b/docs/_build/html/_static/fonts/Lato/lato-regular.eot
new file mode 100644
index 0000000..11e3f2a
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-regular.eot differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-regular.ttf b/docs/_build/html/_static/fonts/Lato/lato-regular.ttf
new file mode 100644
index 0000000..74decd9
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-regular.ttf differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-regular.woff b/docs/_build/html/_static/fonts/Lato/lato-regular.woff
new file mode 100644
index 0000000..ae1307f
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-regular.woff differ
diff --git a/docs/_build/html/_static/fonts/Lato/lato-regular.woff2 b/docs/_build/html/_static/fonts/Lato/lato-regular.woff2
new file mode 100644
index 0000000..3bf9843
Binary files /dev/null and b/docs/_build/html/_static/fonts/Lato/lato-regular.woff2 differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab-Bold.ttf b/docs/_build/html/_static/fonts/RobotoSlab-Bold.ttf
new file mode 100644
index 0000000..df5d1df
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab-Bold.ttf differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab-Regular.ttf b/docs/_build/html/_static/fonts/RobotoSlab-Regular.ttf
new file mode 100644
index 0000000..eb52a79
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab-Regular.ttf differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
new file mode 100644
index 0000000..79dc8ef
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
new file mode 100644
index 0000000..df5d1df
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff
new file mode 100644
index 0000000..6cb6000
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
new file mode 100644
index 0000000..7059e23
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
new file mode 100644
index 0000000..2f7ca78
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
new file mode 100644
index 0000000..eb52a79
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff
new file mode 100644
index 0000000..f815f63
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ
diff --git a/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
new file mode 100644
index 0000000..f2c76e5
Binary files /dev/null and b/docs/_build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ
diff --git a/docs/_build/html/_static/fonts/fontawesome-webfont.eot b/docs/_build/html/_static/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000..e9f60ca
Binary files /dev/null and b/docs/_build/html/_static/fonts/fontawesome-webfont.eot differ
diff --git a/docs/_build/html/_static/fonts/fontawesome-webfont.svg b/docs/_build/html/_static/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000..855c845
--- /dev/null
+++ b/docs/_build/html/_static/fonts/fontawesome-webfont.svg
@@ -0,0 +1,2671 @@
+
+
+
+
+Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ By ,,,
+Copyright Dave Gandy 2016. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_build/html/_static/fonts/fontawesome-webfont.ttf b/docs/_build/html/_static/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..35acda2
Binary files /dev/null and b/docs/_build/html/_static/fonts/fontawesome-webfont.ttf differ
diff --git a/docs/_build/html/_static/fonts/fontawesome-webfont.woff b/docs/_build/html/_static/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..400014a
Binary files /dev/null and b/docs/_build/html/_static/fonts/fontawesome-webfont.woff differ
diff --git a/docs/_build/html/_static/fonts/fontawesome-webfont.woff2 b/docs/_build/html/_static/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000..4d13fc6
Binary files /dev/null and b/docs/_build/html/_static/fonts/fontawesome-webfont.woff2 differ
diff --git a/docs/build/html/_static/jquery-3.4.1.js b/docs/_build/html/_static/jquery-3.4.1.js
similarity index 100%
rename from docs/build/html/_static/jquery-3.4.1.js
rename to docs/_build/html/_static/jquery-3.4.1.js
diff --git a/docs/build/html/_static/jquery.js b/docs/_build/html/_static/jquery.js
similarity index 100%
rename from docs/build/html/_static/jquery.js
rename to docs/_build/html/_static/jquery.js
diff --git a/docs/_build/html/_static/js/modernizr.min.js b/docs/_build/html/_static/js/modernizr.min.js
new file mode 100644
index 0000000..f65d479
--- /dev/null
+++ b/docs/_build/html/_static/js/modernizr.min.js
@@ -0,0 +1,4 @@
+/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
+ * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
+ */
+;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML=" ",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f"),i("table.docutils.footnote").wrap(""),i("table.docutils.citation").wrap("
"),i(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var e=i(this);expand=i(' '),expand.on("click",function(n){return t.toggleCurrent(e),n.stopPropagation(),!1}),e.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}0this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var r=0,n=["ms","moz","webkit","o"],e=0;e');
- if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
+ var requestUrl = "";
+ if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
// dirhtml builder
var dirname = item[0] + '/';
if (dirname.match(/\/index\/$/)) {
@@ -253,15 +259,15 @@ var Search = {
} else if (dirname == 'index/') {
dirname = '';
}
- listItem.append($(' ').attr('href',
- DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
- highlightstring + item[2]).html(item[1]));
+ requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
+
} else {
// normal html builders
- listItem.append($(' ').attr('href',
- item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
- highlightstring + item[2]).html(item[1]));
+ requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
}
+ listItem.append($(' ').attr('href',
+ requestUrl +
+ highlightstring + item[2]).html(item[1]));
if (item[3]) {
listItem.append($(' (' + item[3] + ') '));
Search.output.append(listItem);
@@ -269,7 +275,7 @@ var Search = {
displayNextItem();
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
- $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX,
+ $.ajax({url: requestUrl,
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
@@ -424,7 +430,7 @@ var Search = {
for (j = 0; j < _files.length; j++) {
file = _files[j];
if (!(file in scoreMap))
- scoreMap[file] = {}
+ scoreMap[file] = {};
scoreMap[file][word] = o.score;
}
});
@@ -432,7 +438,7 @@ var Search = {
// create the mapping
for (j = 0; j < files.length; j++) {
file = files[j];
- if (file in fileMap)
+ if (file in fileMap && fileMap[file].indexOf(word) === -1)
fileMap[file].push(word);
else
fileMap[file] = [word];
diff --git a/docs/build/html/_static/underscore-1.3.1.js b/docs/_build/html/_static/underscore-1.3.1.js
similarity index 100%
rename from docs/build/html/_static/underscore-1.3.1.js
rename to docs/_build/html/_static/underscore-1.3.1.js
diff --git a/docs/build/html/_static/underscore.js b/docs/_build/html/_static/underscore.js
similarity index 100%
rename from docs/build/html/_static/underscore.js
rename to docs/_build/html/_static/underscore.js
diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html
new file mode 100644
index 0000000..05b44f1
--- /dev/null
+++ b/docs/_build/html/genindex.html
@@ -0,0 +1,2162 @@
+
+
+
+
+
+
+
+
+
+
+
+ Index — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Docs »
+
+ Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index
+
+
+
A
+ |
B
+ |
C
+ |
D
+ |
E
+ |
F
+ |
G
+ |
H
+ |
I
+ |
J
+ |
L
+ |
M
+ |
N
+ |
O
+ |
P
+ |
Q
+ |
R
+ |
S
+ |
T
+ |
U
+ |
W
+
+
+
A
+
+
+
B
+
+
+
C
+
+
+
D
+
+
+
E
+
+
+
F
+
+
+
G
+
+
+
H
+
+
+
I
+
+
+
J
+
+
+
L
+
+
+
M
+
+
+
N
+
+
+
O
+
+
+
P
+
+
+
Q
+
+
+
R
+
+
+
S
+
+
+
T
+
+
+
U
+
+
+
W
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html
new file mode 100644
index 0000000..f13ff36
--- /dev/null
+++ b/docs/_build/html/index.html
@@ -0,0 +1,235 @@
+
+
+
+
+
+
+
+
+
+
+ Welcome to AutoHeadFix’s documentation! — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome to AutoHeadFix’s documentation!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/modules.html b/docs/_build/html/modules.html
new file mode 100644
index 0000000..0d4344a
--- /dev/null
+++ b/docs/_build/html/modules.html
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix Code Documentation — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AutoHeadFix Code Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv
new file mode 100644
index 0000000..8801390
Binary files /dev/null and b/docs/_build/html/objects.inv differ
diff --git a/docs/_build/html/py-modindex.html b/docs/_build/html/py-modindex.html
new file mode 100644
index 0000000..bd30566
--- /dev/null
+++ b/docs/_build/html/py-modindex.html
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+
+
+
+
+ Python Module Index — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Docs »
+
+ Python Module Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Python Module Index
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/quickstart.html b/docs/_build/html/quickstart.html
new file mode 100644
index 0000000..10255ab
--- /dev/null
+++ b/docs/_build/html/quickstart.html
@@ -0,0 +1,278 @@
+
+
+
+
+
+
+
+
+
+
+ Quick Start — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Quick Start
+
+
Installation of AutoHeadFix
+
To downlowd the setup script for AutoHeadFix, click here .
+
Installation Walk Through
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+ Important :
+
+Having multiple installations can cause things to break if this is not your first time running this script in the trash make sure to delete all old folders and empty your trash
+A config.txt file will be included in the repository, you must change the variables (eg path, password) to your installation specific details.
+All cageID’s must be unique.
+
+
+
+
+
Developers
+
+For notes and structure information from the developer, click here .
+To clone the source code, click here .
+
+
+
+
+
Usage
+
First Time Configuration
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
Generic Usage Guide
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
Cron Creation
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
Changing Mouse Specific Var
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
Training Difficulty
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/rpi_setup.html b/docs/_build/html/rpi_setup.html
new file mode 100644
index 0000000..c24e1e0
--- /dev/null
+++ b/docs/_build/html/rpi_setup.html
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+ General Raspberry Pi Setup — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
General Raspberry Pi Setup
+
+
Installing OS and General Setup
+
There are many guides available online for Raspberry Pi setup. This guide from medium contains the basic setup, click here
+
+
+
Mounting Hard Drive
+
AutoHeadFix records many videos and an external hard drive is necessary.
+
+
You will also need to format and mount your hard drive as outlined here .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/search.html b/docs/_build/html/search.html
new file mode 100644
index 0000000..6e3d382
--- /dev/null
+++ b/docs/_build/html/search.html
@@ -0,0 +1,209 @@
+
+
+
+
+
+
+
+
+
+
+ Search — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Docs »
+
+ Search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please activate JavaScript to enable the search
+ functionality.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js
new file mode 100644
index 0000000..e98da33
--- /dev/null
+++ b/docs/_build/html/searchindex.js
@@ -0,0 +1 @@
+Search.setIndex({docnames:["AHF_BrainLight","AHF_Camera","AHF_ContactCheck","AHF_DataLogger","AHF_HeadFixer","AHF_LickDetector","AHF_Notifier","AHF_Reader","AHF_Rewarder","AHF_Stimulator","AHF_Stimulus","AHF_Subjects","AHF_Trigger","index","modules","quickstart","rpi_setup","util_classes"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":2,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["AHF_BrainLight.rst","AHF_Camera.rst","AHF_ContactCheck.rst","AHF_DataLogger.rst","AHF_HeadFixer.rst","AHF_LickDetector.rst","AHF_Notifier.rst","AHF_Reader.rst","AHF_Rewarder.rst","AHF_Stimulator.rst","AHF_Stimulus.rst","AHF_Subjects.rst","AHF_Trigger.rst","index.rst","modules.rst","quickstart.rst","rpi_setup.rst","util_classes.rst"],objects:{"":{AHF_Base:[17,0,0,"-"],AHF_ClassAndDictUtils:[17,0,0,"-"],AHF_HardwareTester:[17,0,0,"-"],AHF_Task:[17,0,0,"-"]},"AHF_Base.AHF_Base":{about:[17,2,1,""],config_subject_get:[17,2,1,""],config_user_get:[17,2,1,""],config_user_subject_get:[17,2,1,""],hardwareTest:[17,2,1,""],setdown:[17,2,1,""],setup:[17,2,1,""]},"AHF_BrainLight.AHF_BrainLight":{AHF_BrainLight:[0,1,1,""]},"AHF_BrainLight.AHF_BrainLight.AHF_BrainLight":{config_user_get:[0,2,1,""],defaultDelay:[0,3,1,""],hardwareTest:[0,2,1,""],offForStim:[0,2,1,""],onForStim:[0,2,1,""]},"AHF_BrainLight.AHF_BrainLight_1GPIO":{AHF_BrainLight_1GPIO:[0,1,1,""]},"AHF_BrainLight.AHF_BrainLight_1GPIO.AHF_BrainLight_1GPIO":{about:[0,2,1,""],config_user_get:[0,2,1,""],defaultPin:[0,3,1,""],offForStim:[0,2,1,""],onForStim:[0,2,1,""],onThread:[0,2,1,""],setdown:[0,2,1,""],setup:[0,2,1,""]},"AHF_Camera.AHF_Camera":{AHF_Camera:[1,1,1,""]},"AHF_Camera.AHF_Camera.AHF_Camera":{resolution:[1,2,1,""],start_preview:[1,2,1,""],start_recording:[1,2,1,""],stop_preview:[1,2,1,""],stop_recording:[1,2,1,""]},"AHF_Camera.AHF_Camera_PiCam":{AHF_Camera_PiCam:[1,1,1,""]},"AHF_Camera.AHF_Camera_PiCam.AHF_Camera_PiCam":{about:[1,2,1,""],add_overlay:[1,2,1,""],capture:[1,2,1,""],config_user_get:[1,2,1,""],hardwareTest:[1,2,1,""],remove_overlay:[1,2,1,""],resolution:[1,2,1,""],set_gain:[1,2,1,""],setdown:[1,2,1,""],setup:[1,2,1,""],start_preview:[1,2,1,""],start_recording:[1,2,1,""],stop_preview:[1,2,1,""],stop_recording:[1,2,1,""],timed_recording:[1,2,1,""]},"AHF_ContactCheck.AHF_ContactCheck":{AHF_ContactCheck:[2,1,1,""]},"AHF_ContactCheck.AHF_ContactCheck.AHF_ContactCheck":{checkContact:[2,2,1,""],hardwareTest:[2,2,1,""],startLogging:[2,2,1,""],stopLogging:[2,2,1,""],turnOff:[2,2,1,""],turnOn:[2,2,1,""],waitForContact:[2,2,1,""],waitForNoContact:[2,2,1,""]},"AHF_ContactCheck.AHF_ContactCheck_BeamBreak":{AHF_ContactCheck_BeamBreak:[2,1,1,""]},"AHF_ContactCheck.AHF_ContactCheck_BeamBreak.AHF_ContactCheck_BeamBreak":{about:[2,2,1,""],config_user_get:[2,2,1,""],defaultLEDPin:[2,3,1,""],defaultPin:[2,3,1,""],setup:[2,2,1,""],turnOff:[2,2,1,""],turnOn:[2,2,1,""]},"AHF_ContactCheck.AHF_ContactCheck_Elec":{AHF_ContactCheck_Elec:[2,1,1,""]},"AHF_ContactCheck.AHF_ContactCheck_Elec.AHF_ContactCheck_Elec":{about:[2,2,1,""],checkContact:[2,2,1,""],config_user_get:[2,2,1,""],contactCheckCallback:[2,2,1,""],debounceTime:[2,3,1,""],defaultPUD:[2,3,1,""],defaultPin:[2,3,1,""],defaultPolarity:[2,3,1,""],setdown:[2,2,1,""],setup:[2,2,1,""],startLogging:[2,2,1,""],stopLogging:[2,2,1,""],waitForContact:[2,2,1,""],waitForNoContact:[2,2,1,""]},"AHF_DataLogger.AHF_DataLogger":{AHF_DataLogger:[3,1,1,""]},"AHF_DataLogger.AHF_DataLogger.AHF_DataLogger":{BUFFER_SIZE:[3,3,1,""],TO_FILE:[3,3,1,""],TO_SHELL:[3,3,1,""],clearTrackedValues:[3,2,1,""],configGenerator:[3,2,1,""],getConfigData:[3,2,1,""],getMice:[3,2,1,""],getTrackedEvent:[3,2,1,""],isChild:[3,3,1,""],makeLogFile:[3,2,1,""],newDay:[3,2,1,""],readFromLogFile:[3,2,1,""],resumeTracking:[3,2,1,""],retireMouse:[3,2,1,""],saveNewMouse:[3,2,1,""],startTracking:[3,2,1,""],stopTracking:[3,2,1,""],storeConfig:[3,2,1,""],trackingDict:[3,3,1,""],writeToLogFile:[3,2,1,""]},"AHF_DataLogger.AHF_DataLogger_localsql":{AHF_DataLogger_localsql:[3,1,1,""]},"AHF_DataLogger.AHF_DataLogger_localsql.AHF_DataLogger_localsql":{PSEUDO_MUTEX:[3,3,1,""],about:[3,2,1,""],configGenerator:[3,2,1,""],config_user_get:[3,2,1,""],defaultCage:[3,3,1,""],getConfigData:[3,2,1,""],getFromDatabase:[3,2,1,""],getMice:[3,2,1,""],hardwareTest:[3,2,1,""],localDatabase:[3,3,1,""],localHost:[3,3,1,""],localPassword:[3,3,1,""],localUser:[3,3,1,""],makeLogFile:[3,2,1,""],newDay:[3,2,1,""],pingServers:[3,2,1,""],readFromLogFile:[3,2,1,""],retireMouse:[3,2,1,""],saveNewMouse:[3,2,1,""],saveToDatabase:[3,2,1,""],setdown:[3,2,1,""],setup:[3,2,1,""],storeConfig:[3,2,1,""],writeToLogFile:[3,2,1,""]},"AHF_DataLogger.AHF_DataLogger_mysql":{AHF_DataLogger_mysql:[3,1,1,""]},"AHF_DataLogger.AHF_DataLogger_mysql.AHF_DataLogger_mysql":{PSEUDO_MUTEX:[3,3,1,""],about:[3,2,1,""],configGenerator:[3,2,1,""],config_user_get:[3,2,1,""],defaultCage:[3,3,1,""],defaultDatabase:[3,3,1,""],defaultHost:[3,3,1,""],defaultPassword:[3,3,1,""],defaultUser:[3,3,1,""],getConfigData:[3,2,1,""],getFromDatabase:[3,2,1,""],getMice:[3,2,1,""],hardwareTest:[3,2,1,""],localDatabase:[3,3,1,""],localHost:[3,3,1,""],localPassword:[3,3,1,""],localUser:[3,3,1,""],makeLogFile:[3,2,1,""],newDay:[3,2,1,""],pingServers:[3,2,1,""],readFromLogFile:[3,2,1,""],retireMouse:[3,2,1,""],saveNewMouse:[3,2,1,""],saveToDatabase:[3,2,1,""],setdown:[3,2,1,""],setup:[3,2,1,""],storeConfig:[3,2,1,""],writeToLogFile:[3,2,1,""]},"AHF_DataLogger.AHF_DataLogger_text":{AHF_DataLogger_text:[3,1,1,""]},"AHF_DataLogger.AHF_DataLogger_text.AHF_DataLogger_text":{PSEUDO_MUTEX:[3,3,1,""],about:[3,2,1,""],configGenerator:[3,2,1,""],config_user_get:[3,2,1,""],defaultCage:[3,3,1,""],defaultConfigPath:[3,3,1,""],defaultDataPath:[3,3,1,""],getConfigData:[3,2,1,""],getMice:[3,2,1,""],hardwareTest:[3,2,1,""],makeLogFile:[3,2,1,""],makeQuickStatsFile:[3,2,1,""],newDay:[3,2,1,""],readFromLogFile:[3,2,1,""],retireMouse:[3,2,1,""],saveNewMouse:[3,2,1,""],setDateStr:[3,2,1,""],setdown:[3,2,1,""],setup:[3,2,1,""],storeConfig:[3,2,1,""],writeToLogFile:[3,2,1,""]},"AHF_DataLogger.AHF_DataLogger_textMySql":{AHF_DataLogger_textMySql:[3,1,1,""]},"AHF_DataLogger.AHF_DataLogger_textMySql.AHF_DataLogger_textMySql":{BUFFER_SIZE:[3,3,1,""],TO_FILE:[3,3,1,""],TO_SHELL:[3,3,1,""],about:[3,2,1,""],configGenerator:[3,2,1,""],config_user_get:[3,2,1,""],getConfigData:[3,2,1,""],getMice:[3,2,1,""],hardwareTest:[3,2,1,""],makeLogFile:[3,2,1,""],newDay:[3,2,1,""],readFromLogFile:[3,2,1,""],retireMouse:[3,2,1,""],saveNewMouse:[3,2,1,""],setdown:[3,2,1,""],setup:[3,2,1,""],storeConfig:[3,2,1,""],trackingDict:[3,3,1,""],useLocalSql:[3,3,1,""],writeToLogFile:[3,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer":{AHF_HeadFixer:[4,1,1,""],random:[4,4,1,""]},"AHF_HeadFixer.AHF_HeadFixer.AHF_HeadFixer":{clearResultsDict:[4,2,1,""],config_subject_get:[4,2,1,""],config_user_get:[4,2,1,""],config_user_subject_get:[4,2,1,""],defaultHeadFixTime:[4,3,1,""],defaultPropHeadFix:[4,3,1,""],defaultSkeddadleTime:[4,3,1,""],fixMouse:[4,2,1,""],hardwareTest:[4,2,1,""],hasLevels:[4,3,1,""],hasMouseLog:[4,2,1,""],isChecking:[4,3,1,""],isFixedCheck:[4,2,1,""],newResultsDict:[4,2,1,""],newSettingsDict:[4,2,1,""],releaseMouse:[4,2,1,""],setup:[4,2,1,""],waitForMouse:[4,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer_NoFix":{AHF_HeadFixer_NoFix:[4,1,1,""]},"AHF_HeadFixer.AHF_HeadFixer_NoFix.AHF_HeadFixer_NoFix":{about:[4,2,1,""],config_subject_get:[4,2,1,""],config_user_get:[4,2,1,""],config_user_subject_get:[4,2,1,""],defaultSkeddadleTime:[4,3,1,""],fixMouse:[4,2,1,""],hardwareTest:[4,2,1,""],hasLevels:[4,3,1,""],isChecking:[4,3,1,""],releaseMouse:[4,2,1,""],setdown:[4,2,1,""],setup:[4,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM":{AHF_HeadFixer_PWM:[4,1,1,""],random:[4,4,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM.AHF_HeadFixer_PWM":{calculate_steps:[4,2,1,""],config_subject_get:[4,2,1,""],config_user_get:[4,2,1,""],config_user_subject_get:[4,2,1,""],defaultFixedPosition:[4,3,1,""],defaultReleasePosition:[4,3,1,""],defaultTightnessHeadFix:[4,3,1,""],fixMouse:[4,2,1,""],hardwareTest:[4,2,1,""],hasLevels:[4,3,1,""],individualSettings:[4,2,1,""],numLevels:[4,3,1,""],releaseMouse:[4,2,1,""],setPWM:[4,2,1,""],setdown:[4,2,1,""],setup:[4,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685":{AHF_HeadFixer_PWM_PCA9685:[4,1,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685.AHF_HeadFixer_PWM_PCA9685":{about:[4,2,1,""],config_user_get:[4,2,1,""],defaultAddress:[4,3,1,""],setPWM:[4,2,1,""],setdown:[4,2,1,""],setup:[4,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM_Pi":{AHF_HeadFixer_PWM_Pi:[4,1,1,""]},"AHF_HeadFixer.AHF_HeadFixer_PWM_Pi.AHF_HeadFixer_PWM_Pi":{about:[4,2,1,""],config_user_get:[4,2,1,""],defaultChannel:[4,3,1,""],setPWM:[4,2,1,""],setdown:[4,2,1,""],setup:[4,2,1,""]},"AHF_HeadFixer.AHF_HeadFixer_Pistons":{AHF_HeadFixer_Pistons:[4,1,1,""],random:[4,4,1,""]},"AHF_HeadFixer.AHF_HeadFixer_Pistons.AHF_HeadFixer_Pistons":{about:[4,2,1,""],config_subject_get:[4,2,1,""],config_user_get:[4,2,1,""],config_user_subject_get:[4,2,1,""],defaultPin:[4,3,1,""],fixMouse:[4,2,1,""],releaseMouse:[4,2,1,""],setdown:[4,2,1,""],setup:[4,2,1,""]},"AHF_LickDetector.AHF_LickDetector":{AHF_LickDetector:[5,1,1,""]},"AHF_LickDetector.AHF_LickDetector.AHF_LickDetector":{getLickCount:[5,2,1,""],getTouches:[5,2,1,""],resumeLickCount:[5,2,1,""],startLickCount:[5,2,1,""],startLickTiming:[5,2,1,""],startLogging:[5,2,1,""],stopLickCount:[5,2,1,""],stopLickTiming:[5,2,1,""],stopLogging:[5,2,1,""],waitForLick:[5,2,1,""]},"AHF_LickDetector.AHF_LickDetector_MPR":{AHF_LickDetector_MPR:[5,1,1,""]},"AHF_LickDetector.AHF_LickDetector_MPR.AHF_LickDetector_MPR":{about:[5,2,1,""],clearResultsDict:[5,2,1,""],config_user_get:[5,2,1,""],defaultAddress:[5,3,1,""],defaultIRQ:[5,3,1,""],defaultTouchChannels:[5,3,1,""],defaultTouchThresh:[5,3,1,""],defaultUntouchThresh:[5,3,1,""],getLickCount:[5,2,1,""],getTouches:[5,2,1,""],hardwareTest:[5,2,1,""],logTouchCallback:[5,2,1,""],newResultsDict:[5,2,1,""],resetDetector:[5,2,1,""],resumeLickCount:[5,2,1,""],setdown:[5,2,1,""],setup:[5,2,1,""],startLickCount:[5,2,1,""],startLickTiming:[5,2,1,""],startLogging:[5,2,1,""],stopLickCount:[5,2,1,""],stopLickTiming:[5,2,1,""],stopLogging:[5,2,1,""],waitForLick:[5,2,1,""]},"AHF_Notifier.AHF_Notifier":{AHF_Notifier:[6,1,1,""]},"AHF_Notifier.AHF_Notifier.AHF_Notifier":{hardwareTest:[6,2,1,""],notify:[6,2,1,""],notifyStuck:[6,2,1,""]},"AHF_Notifier.AHF_Notifier_Requests":{AHF_Notifier_Requests:[6,1,1,""]},"AHF_Notifier.AHF_Notifier_Requests.AHF_Notifier_Requests":{about:[6,2,1,""],config_user_get:[6,2,1,""],notify:[6,2,1,""],notifyStuck:[6,2,1,""],setdown:[6,2,1,""],setup:[6,2,1,""],textBeltURL:[6,3,1,""]},"AHF_Reader.AHF_Reader":{AHF_Reader:[7,1,1,""]},"AHF_Reader.AHF_Reader.AHF_Reader":{readTag:[7,2,1,""],startLogging:[7,2,1,""],stopLogging:[7,2,1,""]},"AHF_Reader.AHF_Reader_ID":{AHF_Reader_ID:[7,1,1,""]},"AHF_Reader.AHF_Reader_ID.AHF_Reader_ID":{DO_CHECK_SUM:[7,3,1,""],TIME_OUT_SECS:[7,3,1,""],about:[7,2,1,""],clearResultsDict:[7,2,1,""],config_user_get:[7,2,1,""],constantCheck:[7,2,1,""],customCallback:[7,2,1,""],defaultChamberTimeLimit:[7,3,1,""],defaultPin:[7,3,1,""],defaultPort:[7,3,1,""],gInChamberTimeLimit:[7,3,1,""],gStillThere:[7,3,1,""],graceTime:[7,3,1,""],hardwareTest:[7,2,1,""],isChecking:[7,3,1,""],newResultsDict:[7,2,1,""],readTag:[7,2,1,""],setdown:[7,2,1,""],setup:[7,2,1,""],startLogging:[7,2,1,""],stopLogging:[7,2,1,""],timeInChamberThread:[7,2,1,""]},"AHF_Rewarder.AHF_Rewarder":{AHF_Rewarder:[8,1,1,""]},"AHF_Rewarder.AHF_Rewarder.AHF_Rewarder":{addRewardToDict:[8,2,1,""],countermandReward:[8,2,1,""],entryRewardDelayDefault:[8,3,1,""],giveReward:[8,2,1,""],giveRewardCM:[8,2,1,""],hardwareTest:[8,2,1,""],maxBreakBeamRewardsDefault:[8,3,1,""],maxEntryRewardsDefault:[8,3,1,""],rewardControl:[8,2,1,""],rewardUnits:[8,3,1,""],setCountermandTime:[8,2,1,""],testAmount:[8,3,1,""],turnOFF:[8,2,1,""],turnON:[8,2,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid":{AHF_Rewarder_solenoid:[8,1,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid.AHF_Rewarder_solenoid":{breakBeamHandling:[8,2,1,""],clearResultsDict:[8,2,1,""],config_subject_get:[8,2,1,""],config_user_get:[8,2,1,""],config_user_subject_get:[8,2,1,""],countermandReward:[8,2,1,""],defaultBBWait:[8,3,1,""],defaultBreakBeam:[8,3,1,""],defaultEntry:[8,3,1,""],defaultPin:[8,3,1,""],defaultTask:[8,3,1,""],defaultWait:[8,3,1,""],entryHandling:[8,2,1,""],giveReward:[8,2,1,""],giveRewardCM:[8,2,1,""],newResultsDict:[8,2,1,""],results_subject_get:[8,2,1,""],rewardUnits:[8,3,1,""],setup:[8,2,1,""],testAmount:[8,3,1,""],threadCMReward:[8,2,1,""],threadCountermand:[8,2,1,""],threadReward:[8,2,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid_pt":{AHF_Rewarder_solenoid_pt:[8,1,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid_pt.AHF_Rewarder_solenoid_pt":{about:[8,2,1,""],setdown:[8,2,1,""],setup:[8,2,1,""],threadCMReward:[8,2,1,""],threadCountermand:[8,2,1,""],threadReward:[8,2,1,""],turnOFF:[8,2,1,""],turnON:[8,2,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid_rpi":{AHF_Rewarder_solenoid_rpi:[8,1,1,""]},"AHF_Rewarder.AHF_Rewarder_solenoid_rpi.AHF_Rewarder_solenoid_rpi":{about:[8,2,1,""],countermandVal:[8,3,1,""],rewardCMThread:[8,2,1,""],rewardThread:[8,2,1,""],setdown:[8,2,1,""],setup:[8,2,1,""],threadCMReward:[8,2,1,""],threadCountermand:[8,2,1,""],threadReward:[8,2,1,""],turnOFF:[8,2,1,""],turnON:[8,2,1,""]},"AHF_Stimulator.AHF_Stimulator":{AHF_Stimulator:[9,1,1,""]},"AHF_Stimulator.AHF_Stimulator.AHF_Stimulator":{config_user_get:[9,2,1,""],quitting:[9,2,1,""],run:[9,2,1,""],startVideo:[9,2,1,""],stop:[9,2,1,""],stopVideo:[9,2,1,""]},"AHF_Stimulator.AHF_Stimulator_LEDs":{AHF_Stimulator_LEDs:[9,1,1,""],random:[9,4,1,""]},"AHF_Stimulator.AHF_Stimulator_LEDs.AHF_Stimulator_LEDs":{about:[9,2,1,""],configStim:[9,2,1,""],config_subject_get:[9,2,1,""],config_user_get:[9,2,1,""],config_user_subject_get:[9,2,1,""],hardwareTest:[9,2,1,""],logFile:[9,2,1,""],logfile:[9,2,1,""],run:[9,2,1,""],setup:[9,2,1,""]},"AHF_Stimulator.AHF_Stimulator_LickWithhold":{AHF_Stimulator_LickWithhold:[9,1,1,""],random:[9,4,1,""]},"AHF_Stimulator.AHF_Stimulator_LickWithhold.AHF_Stimulator_LickWithhold":{about:[9,2,1,""],config_subject_get:[9,2,1,""],config_user_get:[9,2,1,""],config_user_subject_get:[9,2,1,""],delayTime_def:[9,3,1,""],discrimTask:[9,2,1,""],goLikelihood_def:[9,3,1,""],goTask:[9,2,1,""],hardwareTest:[9,2,1,""],lickWithholdTime_def:[9,3,1,""],lickWrongTimeout_def:[9,3,1,""],noGoTask:[9,2,1,""],quitting:[9,2,1,""],responseTime_def:[9,3,1,""],rewardNoGo_def:[9,3,1,""],rewardTask:[9,2,1,""],run:[9,2,1,""],setdown:[9,2,1,""],setup:[9,2,1,""],speakerDuty_def:[9,3,1,""],speakerFreq_def:[9,3,1,""],speakerOffForReward_def:[9,3,1,""],speakerPin_def:[9,3,1,""],withholdWait:[9,2,1,""]},"AHF_Stimulator.AHF_Stimulator_Rewards":{AHF_Stimulator_Rewards:[9,1,1,""]},"AHF_Stimulator.AHF_Stimulator_Rewards.AHF_Stimulator_Rewards":{about:[9,2,1,""],config_subject_get:[9,2,1,""],config_user_get:[9,2,1,""],config_user_subject_get:[9,2,1,""],defaultInterval:[9,3,1,""],defaultRewards:[9,3,1,""],hardwareTest:[9,2,1,""],nextDay:[9,2,1,""],quitting:[9,2,1,""],run:[9,2,1,""],setdown:[9,2,1,""],setup:[9,2,1,""]},"AHF_Stimulus.AHF_Stimulus":{AHF_Stimulus:[10,1,1,""]},"AHF_Stimulus.AHF_Stimulus.AHF_Stimulus":{length:[10,2,1,""],period:[10,2,1,""],stimulate:[10,2,1,""],trialEnd:[10,2,1,""],trialPrep:[10,2,1,""]},"AHF_Stimulus.AHF_Stimulus_Laser":{AHF_Stimulus_Laser:[10,1,1,""]},"AHF_Stimulus.AHF_Stimulus_Laser.AHF_Stimulus_Laser":{about:[10,2,1,""],accuracyTest:[10,2,1,""],align:[10,2,1,""],config_user_get:[10,2,1,""],editReference:[10,2,1,""],feed_byte:[10,2,1,""],get_arrow_dir:[10,2,1,""],get_dir:[10,2,1,""],get_ref_im:[10,2,1,""],get_state:[10,2,1,""],h5updater:[10,2,1,""],hardwareTest:[10,2,1,""],image_registration:[10,2,1,""],length:[10,2,1,""],loadH5:[10,2,1,""],make_cross:[10,2,1,""],matcher:[10,2,1,""],move:[10,2,1,""],move_to:[10,2,1,""],on_press:[10,2,1,""],period:[10,2,1,""],pulse:[10,2,1,""],select_targets:[10,2,1,""],setdown:[10,2,1,""],setup:[10,2,1,""],stimulate:[10,2,1,""],trialEnd:[10,2,1,""],trialPrep:[10,2,1,""],unlock:[10,2,1,""],update_cross:[10,2,1,""],update_mot:[10,2,1,""]},"AHF_Stimulus.AHF_Stimulus_None":{AHF_Stimulus_None:[10,1,1,""]},"AHF_Stimulus.AHF_Stimulus_None.AHF_Stimulus_None":{about:[10,2,1,""],config_user_get:[10,2,1,""],hardwareTest:[10,2,1,""],length:[10,2,1,""],period:[10,2,1,""],setdown:[10,2,1,""],setup:[10,2,1,""],stimulate:[10,2,1,""],trialEnd:[10,2,1,""],trialPrep:[10,2,1,""]},"AHF_Stimulus.AHF_Stimulus_VibMotor":{AHF_Stimulus_VibMotor:[10,1,1,""]},"AHF_Stimulus.AHF_Stimulus_VibMotor.AHF_Stimulus_VibMotor":{about:[10,2,1,""],config_user_get:[10,2,1,""],hardwareTest:[10,2,1,""],length:[10,2,1,""],motorDuty_def:[10,3,1,""],motorFreq_def:[10,3,1,""],motorPin_def:[10,3,1,""],period:[10,2,1,""],pulseTime_def:[10,3,1,""],setdown:[10,2,1,""],setup:[10,2,1,""],stimulate:[10,2,1,""],trialEnd:[10,2,1,""],trialPrep:[10,2,1,""]},"AHF_Subjects.AHF_Subjects":{AHF_Subjects:[11,1,1,""]},"AHF_Subjects.AHF_Subjects.AHF_Subjects":{add:[11,2,1,""],check:[11,2,1,""],generator:[11,2,1,""],get:[11,2,1,""],get_all:[11,2,1,""],remove:[11,2,1,""],setup:[11,2,1,""],show:[11,2,1,""],subjectSettings:[11,2,1,""],userEdit:[11,2,1,""]},"AHF_Subjects.AHF_Subjects_mice":{AHF_Subjects_mice:[11,1,1,""]},"AHF_Subjects.AHF_Subjects_mice.AHF_Subjects_mice":{about:[11,2,1,""],add:[11,2,1,""],check:[11,2,1,""],check_miceDict:[11,2,1,""],configPath:[11,3,1,""],config_user_get:[11,2,1,""],create_fillable_json:[11,2,1,""],depth:[11,2,1,""],freshMiceDefault:[11,3,1,""],generator:[11,2,1,""],get:[11,2,1,""],get_all:[11,2,1,""],hardwareTest:[11,2,1,""],headFixTimeDefault:[11,3,1,""],inChamberTimeLimitDefault:[11,3,1,""],individualSettings:[11,2,1,""],jsonNameDefault:[11,3,1,""],loadConfigsDefault:[11,3,1,""],newDay:[11,2,1,""],propHeadFixDefault:[11,3,1,""],remove:[11,2,1,""],setdown:[11,2,1,""],setup:[11,2,1,""],show:[11,2,1,""],skeddadleTimeDefault:[11,3,1,""],subjectSettings:[11,2,1,""],userEdit:[11,2,1,""]},"AHF_Task.Task":{saveSettings:[17,2,1,""],setup:[17,2,1,""]},"AHF_Trigger.AHF_Trigger":{AHF_Trigger:[12,1,1,""]},"AHF_Trigger.AHF_Trigger.AHF_Trigger":{doTrigger:[12,2,1,""],getTrigger:[12,2,1,""]},"AHF_Trigger.AHF_Trigger_UDP":{AHF_Trigger_UDP:[12,1,1,""]},"AHF_Trigger.AHF_Trigger_UDP.AHF_Trigger_UDP":{about:[12,2,1,""],config_user_get:[12,2,1,""],default_UDP_LIST:[12,3,1,""],default_UDP_PORT:[12,3,1,""],doTrigger:[12,2,1,""],getTrigger:[12,2,1,""],hardwareTest:[12,2,1,""],setdown:[12,2,1,""],setup:[12,2,1,""],start_delay:[12,3,1,""]},AHF_Base:{AHF_Base:[17,1,1,""]},AHF_BrainLight:{AHF_BrainLight:[0,0,0,"-"],AHF_BrainLight_1GPIO:[0,0,0,"-"]},AHF_Camera:{AHF_Camera:[1,0,0,"-"],AHF_Camera_PiCam:[1,0,0,"-"]},AHF_ClassAndDictUtils:{Class_from_file:[17,4,1,""],Dict_to_file:[17,4,1,""],Dict_to_obj_fields:[17,4,1,""],Edit_dict:[17,4,1,""],File_exists:[17,4,1,""],File_from_user:[17,4,1,""],File_to_dict:[17,4,1,""],File_to_obj_fields:[17,4,1,""],Obj_fields_to_file:[17,4,1,""],Show_ordered_dict:[17,4,1,""]},AHF_ContactCheck:{AHF_ContactCheck:[2,0,0,"-"],AHF_ContactCheck_BeamBreak:[2,0,0,"-"],AHF_ContactCheck_Elec:[2,0,0,"-"]},AHF_DataLogger:{AHF_DataLogger:[3,0,0,"-"],AHF_DataLogger_localsql:[3,0,0,"-"],AHF_DataLogger_mysql:[3,0,0,"-"],AHF_DataLogger_text:[3,0,0,"-"],AHF_DataLogger_textMySql:[3,0,0,"-"]},AHF_HardwareTester:{hardwareTester:[17,4,1,""]},AHF_HeadFixer:{AHF_HeadFixer:[4,0,0,"-"],AHF_HeadFixer_NoFix:[4,0,0,"-"],AHF_HeadFixer_PWM:[4,0,0,"-"],AHF_HeadFixer_PWM_PCA9685:[4,0,0,"-"],AHF_HeadFixer_PWM_Pi:[4,0,0,"-"],AHF_HeadFixer_Pistons:[4,0,0,"-"]},AHF_LickDetector:{AHF_LickDetector:[5,0,0,"-"],AHF_LickDetector_MPR:[5,0,0,"-"]},AHF_Notifier:{AHF_Notifier:[6,0,0,"-"],AHF_Notifier_Requests:[6,0,0,"-"]},AHF_Reader:{AHF_Reader:[7,0,0,"-"],AHF_Reader_ID:[7,0,0,"-"]},AHF_Rewarder:{AHF_Rewarder:[8,0,0,"-"],AHF_Rewarder_solenoid:[8,0,0,"-"],AHF_Rewarder_solenoid_pt:[8,0,0,"-"],AHF_Rewarder_solenoid_rpi:[8,0,0,"-"]},AHF_Stimulator:{AHF_Stimulator:[9,0,0,"-"],AHF_Stimulator_LEDs:[9,0,0,"-"],AHF_Stimulator_LickWithhold:[9,0,0,"-"],AHF_Stimulator_Rewards:[9,0,0,"-"]},AHF_Stimulus:{AHF_Stimulus:[10,0,0,"-"],AHF_Stimulus_Laser:[10,0,0,"-"],AHF_Stimulus_None:[10,0,0,"-"],AHF_Stimulus_VibMotor:[10,0,0,"-"]},AHF_Subjects:{AHF_Subjects:[11,0,0,"-"],AHF_Subjects_mice:[11,0,0,"-"]},AHF_Task:{Task:[17,1,1,""]},AHF_Trigger:{AHF_Trigger:[12,0,0,"-"],AHF_Trigger_UDP:[12,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:function"},terms:{"abstract":[0,1,2,3,4,5,6,7,8,9,10,11,12,17],"boolean":[4,6,10],"break":15,"byte":[1,10],"case":[3,9],"class":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14],"default":[0,1,2,3,4,5,6,7,8,9,10,11,12,17],"final":10,"float":[10,17],"function":[1,2,3,4,5,6,7,8,9,10,11,12,17],"import":[15,17],"int":17,"long":[4,6,10],"new":[3,9,10,11,12],"null":10,"return":[0,1,2,3,4,5,6,7,8,9,10,11,12,17],"static":[0,1,2,3,4,5,6,7,8,9,10,11,12,17],"super":4,"throw":10,"true":[2,3,4,5,6,7,8,9,10,11,12,17],"var":15,"while":[3,5,17],For:[3,9,10,15],NOT:7,Q7S:10,The:[3,6,9,10,11,17],Then:10,There:16,These:[3,9,10],Use:5,Used:[1,3],Uses:10,Using:17,Will:3,__dict__:17,__init__:[1,2,3,5,6,7,8,9,10,17],__main__:9,abl:5,about:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],acces:17,account:6,accuraci:10,accuracytest:10,action:10,adafruit:4,adafruit_python_gpio:4,adafruit_python_pca9685:4,add:[4,10,11],add_overlai:1,added:11,adding:10,address:12,addrewardtodict:8,adict:17,after:[1,2,3,4,5,6,7,8,9,10,17],again:9,against:4,ahead:17,ahf_:17,ahf_bas:[0,1,2,3,4,5,6,7,8,9,10,11,12,14],ahf_brainlight:[13,14],ahf_brainlight_1gpio:14,ahf_camera:[13,14],ahf_camera_picam:14,ahf_camera_pistream:14,ahf_classanddictutil:14,ahf_config:11,ahf_contactcheck:[13,14],ahf_contactcheck_beambreak:14,ahf_contactcheck_elec:14,ahf_datalogg:[13,14],ahf_datalogger_localsql:14,ahf_datalogger_mysql:14,ahf_datalogger_text:14,ahf_datalogger_textmysql:14,ahf_hardwaretest:14,ahf_headfix:[13,14],ahf_headfixer_nofix:14,ahf_headfixer_piston:14,ahf_headfixer_pwm:14,ahf_headfixer_pwm_pca9685:14,ahf_headfixer_pwm_pi:14,ahf_laser_cag:3,ahf_lickdetector:[13,14],ahf_lickdetector_mpr:14,ahf_lickdetectorcallback:5,ahf_mouse_1234567890123:3,ahf_notifi:[13,14],ahf_notifier_request:14,ahf_read:[13,14],ahf_reader_id:14,ahf_reward:[13,14],ahf_rewarder_solenoid:14,ahf_rewarder_solenoid_pt:14,ahf_rewarder_solenoid_rpi:14,ahf_stimul:[13,14],ahf_stimulator_l:14,ahf_stimulator_lev:14,ahf_stimulator_lickwithhold:14,ahf_stimulator_reward:14,ahf_stimulu:[13,14],ahf_stimulus_las:14,ahf_stimulus_non:14,ahf_stimulus_vibmotor:14,ahf_subject:[13,14],ahf_subjects_mic:14,ahf_task:[5,14],ahf_task_:17,ahf_trigg:[13,14],ahf_trigger_udp:14,ahf_udptrig:12,align:10,all:[3,4,5,8,9,10,11,15,17],allow:[3,10,11,17],alpha:1,alreadi:11,also:[3,7,10,16],alwai:1,analysi:3,ani:[0,2,3,4,5,6,7,8,9,10,11,12,17],anobject:17,anoth:[3,9,10,12],anydict:17,anyon:3,anyth:3,append:3,applicapl:3,appropri:4,apt:[4,6],around:10,arrai:[5,10],arrow:10,ask:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],assign:10,associ:3,assum:[6,17],assumpt:17,atom:3,attribut:[11,17],auto:[1,3,5,13,14],autoheadfix:[0,1,2,3,4,5,6,7,8,9,10,11,12,16,17],avail:[10,16],axi:10,back:[1,10],background:2,balanc:1,bar:4,base:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14],baselin:5,basic:[11,16],becaus:[4,12,17],been:6,befor:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],begin:[3,10],best:6,between:[3,9,10],binari:3,bit:[5,17],bool:[1,2,3,4,5,6,7,8,9,10,11,12,17],boolen:10,both:[3,10],brain:[0,1,3,10],brainlight:10,breakbeamhandl:8,brief:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],browser:15,buffer:3,buffer_s:3,build:6,built:17,bulk:10,buzzer:9,cage1:3,cage:[6,11],cageid:[6,15],calculate_step:4,call:[1,3,5,9,10,11,17],callback:[3,5,7,10],camera:[1,10,17],can:[0,1,2,3,4,5,6,7,8,9,10,11,12,15,17],cancel:8,cannot:10,capacit:5,captur:[1,10],caus:15,center:10,certain:1,chamber:[4,6,10,11],chanc:[1,2,3,4,5,6,7,8,9,10,11,12,17],chang:[1,2,3,4,5,6,7,8,9,10,11,12,15,17],chanlist:5,channel:[2,5,7,10],check:[4,5,10,11],check_micedict:11,checkcontact:2,choos:17,circular:3,class_from_fil:17,classs:[4,8],clean:9,cleanup:9,clear:[5,8],clearresultsdict:[4,5,7,8],cleartrackedvalu:3,click:[15,16],clone:[4,15],close:[1,3,8,9],code:[3,4,10,13,15,17],coeff_matrix:10,coeffici:10,collect:10,column:3,com:[4,6],combin:[3,17],command:10,common:4,compar:10,complet:[1,2,3,5,6,7,8,9,10,17],complic:3,comput:[3,10],config:[3,15,17],config_subject_get:[4,8,9,17],config_user_get:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],config_user_subject_get:[4,8,9,11,17],configdict:3,configgener:3,configpath:11,configstim:9,configur:[3,11,15,17],confirm:10,connect:3,constantcheck:7,contact:[2,4],contactcheck:2,contactcheckcallback:2,contain:[3,10,11,12,16,17],content:[13,17],continu:[3,5],control:[1,8,9,10],convent:17,coordin:10,copi:[3,4,17],corner:10,correspond:[3,7,11],could:[3,4,5],count:[4,5],countermand:8,countermandreward:8,countermandtim:8,countermandv:8,creat:[3,10,17],create_fillable_json:11,creation:[3,12,15],cron:15,cross:10,crosshair:10,current:[1,3,5,10,17],custom:5,customari:3,customcallback:7,cycl:10,dai:[3,8,9],daili:[3,5,8,11],data:[3,5,7,11],databas:3,datadict:11,datalogg:[3,5],datapath:3,datbas:3,date:3,datetim:3,debouncetim:2,decid:9,default_udp_list:12,default_udp_port:12,defaultaddress:[4,5],defaultbbwait:8,defaultbreakbeam:8,defaultcag:3,defaultchambertimelimit:7,defaultchannel:4,defaultconfigpath:3,defaultdatabas:3,defaultdatapath:3,defaultdelai:0,defaultentri:8,defaultfixedposit:4,defaultheadfixtim:4,defaulthost:3,defaultinterv:9,defaultirq:5,defaultledpin:2,defaultpassword:3,defaultpin:[0,2,4,7,8],defaultpolar:2,defaultport:7,defaultpropheadfix:4,defaultpud:2,defaultreleaseposit:4,defaultreward:9,defaultskeddadletim:4,defaulttask:8,defaulttightnessheadfix:4,defaulttouchchannel:5,defaulttouchthresh:5,defaultuntouchthresh:5,defaultus:3,defaultwait:8,defin:[3,9,10,11,17],delai:[2,9,10],delaytim:8,delaytime_def:9,delet:15,deliv:8,depend:[6,10],depth:11,describ:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],descript:10,desir:[3,9],detail:[9,15],detector:5,determin:10,detetctor:5,dev:7,develop:13,devic:12,diagram:10,dicitonari:[11,17],dict:[4,7,8,9,10,17],dict_to_fil:17,dict_to_obj_field:17,dictionai:17,dictionari:[3,4,5,8,9,10,11,17],dictkei:3,did:9,differ:[3,4,8,10],differenti:9,difficulti:15,dir:17,direct:10,directori:[10,17],dirnam:17,discret:10,discrimtask:9,displac:10,do_check_sum:7,document:3,doe:[0,1,2,3,4,5,6,7,8,9,10,11,15,17],doing:[3,17],don:[3,10,17],done:[1,6,10],dotrigg:12,down:10,downlowd:15,drain:8,drive:[10,13],driven:4,driver:4,dummi:10,dump:17,durat:[1,6,10],durationsec:6,dure:[3,9,11],duti:10,duty_cycl:10,each:[3,5,8,9,10,11,17],easi:[3,17],easili:3,edit:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],edit_dict:17,editrefer:10,either:[3,4,9],electr:5,elgibl:11,els:[3,4,11,12,17],email:6,empti:[10,11,15],encod:17,end:[0,1,3,10,17],endtim:9,energ:[4,10],enough:16,ensur:10,enter:[3,10],entir:5,entranc:11,entri:[3,7,8,10,17],entryhandl:8,entryrewarddelaydefault:8,error:[1,2,3,5,6,7,8,9,10,12,17],esc:10,etc:[1,3,4,10,11],event:[3,9],event_dictionari:3,eventdict:3,eventkind:3,everi:[3,10],everyth:17,exampl:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],execut:3,exisit:3,exist:[10,11,17],exit:[3,7,9,10],experi:17,experiment:[3,11],expir:5,extend:5,exterior:10,extern:[10,16],fail:12,failur:9,fall:2,fals:[1,3,4,5,6,7,10,11,12,17],far:10,fashion:17,fast:10,faster:10,fastest:10,favorit:11,fed:10,feed:10,feed_byt:10,field:[3,5,11,17],file:[1,3,5,9,10,11,15,17],file_exist:17,file_from_us:17,file_to_dict:17,file_to_obj_field:17,filenam:17,filenotfounderror:17,fill:[5,10],find:10,finish:1,first:[10,15],fix:[1,3,4,5,9,11,13,14],fixat:4,fixer:4,fixmous:4,folder:[3,15,17],follow:[4,9,10],format:[1,3,9,10,16],found:[11,17],four:10,fourier:10,free:3,frequenc:10,fresh:11,freshmicedefault:11,friendli:3,from:[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17],front:4,funtion:10,futur:10,gain:1,garbl:3,gener:[0,3,6,10,11,13,15,17],get:[3,4,5,6,8,9,10,11,17],get_al:11,get_arrow_dir:10,get_dir:10,get_ref_im:10,get_stat:10,getconfigdata:3,getfromdatabas:3,getlickcount:5,getmic:3,gettouch:5,gettrackedev:3,gettrigg:12,ginchambertimelimit:7,git:4,github:4,give:[1,2,3,4,5,6,7,8,9,10,11,12,17],given:[3,6,8,9,10,11],givereward:8,giverewardcm:8,global:[5,7],globaltag:3,golikelihood_def:9,good:4,gotask:9,gpio:[0,2,3,4,5,6,7,8,9,10,11,12,17],gracetim:7,green:1,group:11,gstillther:7,gtask:2,gui:10,guid:[15,16],h5updat:10,hair:10,halt:3,hard:13,hardwar:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],hardwaretest:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],has:[3,5,6,17],hascontact:4,haslevel:4,hasmouselog:4,hasudp:12,have:[2,3,4,5,6,7,8,9,10,11,12,15,17],hd5:3,hdf5:10,hdf:10,hdf_path:10,head:[1,3,4,5,9,11,13,14],headfix:[0,3,4,11,17],headfixer_nofix:4,headfixtimedefault:11,help:3,henc:3,here:[15,16],high:[4,10],hit:10,home:[3,10],how:[6,10],http:[4,6],hub:16,human:3,i2c:4,ideal:10,idnum:11,idnumb:11,idtag:[3,11],ignor:11,illumin:[0,1],imag:[1,3,10],image_point:10,image_registr:10,immedi:2,implement:4,inchambertimelimitdefault:11,includ:[9,10,15],increment:4,independ:[5,11],index:3,indic:10,individu:[3,4,8,9,11,17],individualdict:4,individualset:[4,11],infinit:10,info:[0,1,2,3,5,6,7,8,9,10,17],inform:[3,6,10,11,15],inherit:4,inhibit:10,init:[7,17],initi:[0,1,2,3,5,6,7,8,9,10,11,17],inititi:17,inner:11,input:[9,10],insid:6,instal:[4,6,12,13],instead:10,integ:10,interact:[10,11],interest:10,interfac:[3,10],interv:[3,4,9],invok:10,ischeck:[4,7],ischild:3,isfix:4,isfixedcheck:4,iso:[1,3],isstuck:6,issu:10,its:[4,8,10,11],itself:16,join:10,jsn:[3,17],json:[3,17],jsonnamedefault:11,just:[3,4,6],keep:10,kei:[3,6,8,10,11,17],keyboard:10,kill:10,kind:[3,4,5,11],know:[10,17],laser:10,laser_on_tim:10,laser_point:10,later:3,layer:1,lead:3,learn:4,least:10,leav:4,ledpin:0,left:[6,10],length:10,less:8,level:[4,9,10,11],lever:3,lever_pul:3,lick:[5,9],lickwithholdtime_def:9,lickwrongtimeout_def:9,lighter:0,like:1,line:[3,8,9],list:[3,5,10,12,17],live:10,load:[3,10,17],loadconfigsdefault:11,loadh5:10,local:3,localdatabas:3,localhost:3,localpassword:3,localus:3,locat:10,log:[1,2,3,5,7,9],logfil:[3,9],logfilepath:3,logger:[3,7],logpath:3,logtouchcallback:5,longnam:17,look:17,loop:[3,10],low:4,made:17,mai:[3,4,5,9,11,16],main:[1,3,10,17],make:[3,4,5,10,11,12,15,16,17],make_cross:10,makelogfil:3,makenew:17,makequickstatsfil:3,mani:[10,16],map:[4,10],match:[10,17],matcher:10,matric:10,matrix:10,max:8,maxbreakbeamrewardsdefault:8,maxentryrewardsdefault:8,maximum:10,mayb:[4,11],mean:10,mechan:4,medium:16,member:[5,17],menu:10,messag:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],method:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],mice:[3,9,10,11],miceconfig:3,modifi:[3,17],modul:[14,17],monitor:8,more:[3,4,6,9,10],mot_q:10,motion:10,motor:[4,10],motor_delai:10,motorduty_def:10,motorfreq_def:10,motorpin_def:10,mount:13,mous:[3,4,6,7,8,9,10,11,15],mouseid1:11,mouseid2:11,move:[4,10],move_to:10,movement:10,movi:3,mp4:15,mpr121:5,msgstr:6,mssg:6,much:3,multipl:[4,5,15],must:[5,8,9,11,15],mutex:3,mymic:11,mysql:3,name:[1,3,8,17],namestr:17,nametypestr:17,necessari:16,nee:4,need:[0,3,5,6,9,16,17],neg:10,network:12,new_po:10,newdai:[3,11],newfp:9,newresultsdict:[4,5,7,8],newsettingsdict:4,next:9,nextdai:9,nogotask:9,non:1,none:[3,17],note:[3,10,15],noth:[3,6,10,17],notifi:6,notifystuck:6,now:3,number:[4,5,6,8,11,17],numlevel:4,obj_fields_to_fil:17,object:[3,7,10,11,12,17],objectdict:17,occur:8,off:[0,10],offforstim:0,old:[3,15],on_press:10,onc:[3,10],one:[3,4,5,8,9,10,17],onforstim:0,onli:[4,5,6,10,17],onlin:[6,16],onthread:0,onto:4,open:[3,8,9],oppposit:[0,2,3,4,5,6,7,8,9,10,11,12,17],optim:10,option:10,optogenet:10,order:[9,17],origin:[3,10],other:[3,4,8,9,17],otherwis:10,our:11,out:[10,11],outcom:9,outlin:16,output:[3,4,10],overhead:10,overlai:[1,10],overrid:9,overwrit:3,own:17,packag:10,pad:3,page_up:10,pagedown:10,pageup:10,pai:6,pair:9,param:[1,3,6,9,17],paramat:11,paramet:[1,4,8,9,10,11,17],pars:3,parsabl:3,part:12,pass:[1,9,12,17],password:15,path:[1,3,10,15],pca9685:4,per:[3,4,5,8,10],perform:[3,4],perhap:9,period:[9,10],perman:3,phase:10,phase_queu:10,phone:6,picamera:1,picameraerror:1,pick:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],pil:1,pin:[0,2,3,4,5,6,7,8,9,10,11,12,17],pingserv:3,pip:6,piston:4,place:[3,10],plan:17,plate:4,point:10,pointer:9,pool:11,port:5,posiiton:3,posit:[3,4,10],positon:3,possibl:[0,1,2,3,5,6,7,8,9,10,17],power:16,preci:3,prep:10,prepar:10,present:[5,10],press:10,prevent:3,preview:[1,10],previous:[1,3,8],print:[3,9,11,17],prior:3,procedur:10,process:10,processor:10,program:[3,9,10,17],progress:4,prompt:[4,8,9,10,17],propheadfixdefault:11,provid:[3,5,11,16],provide_json:11,pseudo_mutex:3,ptsimplegpio:8,pud_up:2,puls:[4,8,9,10],pulsetime_def:10,push:4,pwhitebal:1,pwm:[4,10],pwm_channel:10,pwm_mode:10,python3:[4,6],python:[6,17],qualiti:1,queri:3,querri:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],queue:10,quick:13,quickstat:3,quit:9,rais:[1,17],ran:10,random:[4,9,10],rang:4,rare:5,raspberri:13,raw_data:3,read:[3,10],readfromlogfil:3,readtag:7,real:3,reason:[3,4],receiv:[9,12],recent:10,recogn:17,record:[1,9,10,12,16],recreat:17,rectim:1,red:1,refer:[3,5,7,10,11],referenc:3,refrain:9,reg:10,region:10,regist:10,registr:10,relax:4,releas:[0,2,3,4,5,6,7,8,9,10,11,12,17],releasemous:4,relev:10,reload:3,remot:[3,6],remov:11,remove_overlai:1,repeat:10,replac:10,report:5,repositori:15,repres:10,request:[3,5,6],requir:[9,10],resdult:4,reset:5,resetdetector:5,resolut:1,resouc:[0,2,3,4,5,6,7,8,9,10,11,12,17],respect:11,respond:[9,10],respons:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],responsetime_def:9,restart:[3,10],result:[3,4,5,7,8,10,11],results_subject_get:8,resultsdict:[4,5,7,8,9,10],resum:3,resumelickcount:5,resumetrack:3,retir:3,retiremous:3,retract:4,retriev:3,reus:[0,2,3,4,5,6,7,8,9,10,11,12,17],reward:[3,8,9,10,11,17],rewardcmthread:8,rewardcontrol:8,rewardnam:8,rewardnogo_def:9,rewardpin:8,rewards:8,rewardtask:9,rewardthread:8,rewardunit:8,rfid:[3,6],rfidtagread:3,right:10,roi:10,rpi:8,run:[0,1,2,3,4,5,6,7,8,9,10,11,12,15,17],same:[3,9,17],sampl:11,save:[1,3,10,17],savenewmous:3,saveset:17,savetodatabas:3,screen:17,script:15,second:[0,1,8,10],see:10,select:[5,10,17],select_target:10,self:[0,1,2,3,5,6,7,8,9,10,17],send:[6,12],sensor:5,sent:6,separ:[1,2,3,5,6,7,8,9,10,17],serial:10,servic:6,servo:4,servomotor:4,servoposit:4,session:[1,3,11],set:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],set_gain:1,setcountermandtim:8,setdatestr:3,setdown:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],setpwm:4,settabl:[1,4],settingsdict:[0,1,2,3,4,5,6,7,8,9,10,17],settingsdictp:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],setup:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,17],shcp:10,shell:[3,5],shift:10,shjft:10,should:[0,2,3,4,5,6,7,8,9,10,11,12,17],show:11,show_ordered_dict:17,shown:1,sign:10,signal:12,signifi:6,similarli:3,simpl:[3,10],simpli:3,singl:[3,4,10,11,17],size:[3,11],skeddadletimedefault:11,slavepi:3,sleep:[3,8],sleependtim:7,sleeptim:[0,8],slow:10,slower:10,smaller:10,smbu:4,socket:12,solenoid:[4,8],some:[3,4,5,6,10,12],somebodi:6,someth:6,sound:9,sourc:[3,15],space:[3,10],speakerduty_def:9,speakerfreq_def:9,speakeroffforreward_def:9,speakerpin_def:9,specif:[3,10,11,15],specifc:10,specifi:[3,10],speed:10,spot:10,stage:[9,10],stamp:3,standard:[3,17],start:[0,1,2,3,5,7,9,10,12,13,17],start_delai:12,start_preview:1,start_record:1,starterdict:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],startfromzero:5,startlickcount:5,startlicktim:5,startlog:[2,5,7],starttrack:3,startvideo:9,stat:3,state:10,statement:3,statsfilepath:3,statspath:3,statu:3,stcp:10,step:10,stepper:10,still:5,stimul:[1,3,9,10,11,17],stimulu:[9,10],stimulus:9,stop:[1,2,5,7,9,10,12],stop_preview:1,stop_record:1,stoplickcount:5,stoplicktim:5,stoplog:[2,5,7],stoptrack:3,stopvideo:9,storag:3,store:[3,5,10,12,17],storeconfig:3,strategi:[0,2,3,4,5,6,7,8,9,10,11,12,17],strength:10,string:[3,12,17],strip:17,stroke:10,structur:15,stuck:6,stuff:12,sub:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],subclass:[4,8,10,11],subfold:3,subject:[3,4,11],subjectset:11,subjet:11,subtask:17,success:[4,9],successfulli:10,sudo:[4,6],superclass:[1,10],support:15,sure:[5,10,15,16],system:10,tab:3,tag:[3,4,6,7,9,10,11],tagid:[3,11],tagread:[7,11,17],take:[5,10],taken:10,talli:11,tap:10,target:10,task:[2,3,5,7,9,11,17],taskp:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],tell:5,term:10,termin:10,test:[1,2,3,4,5,6,7,8,9,10,11,12,17],testamount:8,tester:[0,10,17],text:[3,6,9,17],textbelt:6,textbelturl:6,than:[8,10],thei:[3,9],them:[3,9],thereof:3,thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17],thing:[9,15,17],think:3,thistag:4,those:10,thr:17,thread:[3,5,8],threadcmreward:8,threadcountermand:8,threadreward:8,through:[15,17],tight:11,tim:3,time:[1,3,5,6,8,9,10,11,15,17],time_epoch:3,time_out_sec:7,timed_record:1,timeinchamberthread:7,timeour:8,timeout:[5,10],timeout_sec:5,timeoutsec:2,timestamp:3,to_fil:3,to_shel:3,todai:3,toggl:10,too:6,tool:4,top:10,topleft:10,toshellorfil:3,total:[3,5,8],touch:5,touchedchannel:5,toward:10,track:[3,4,10],trackingdict:3,trackingtyp:3,train:15,transform:10,trash:15,trawl:17,trial:[9,10],trialend:10,trialprep:10,trigger:4,truth:[1,2,3,5,6,7,8,9,10,17],ttyusb0:7,tube:3,tupl:[3,5,6,11,17],turn:[0,3,11],turnoff:[2,8],turnon:[2,8],two:[6,9,10],txt:15,type:[1,3,6,8,10,15,17],typesuffix:17,udp:12,udplist:12,uniniti:10,uniqu:[11,15],unix:3,unlik:3,unlock:10,unstabl:3,until:[1,9],untouch:5,updat:[0,1,2,3,4,5,6,7,8,9,10,17],update_cross:10,update_mot:10,upon:17,usag:13,use:[2,5,8,9,10,11],used:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],uselocalsql:3,user:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],useredit:11,uses:[3,4,6,12],using:[1,4,5,6,7,8,10,12],usual:[3,10,11],util:[4,10,13,14],valu:[1,3,5,7,8,11,17],valv:8,variabl:[15,17],variou:17,verifi:17,via:[5,10],vib:10,vibrat:10,video:[1,10,15,16],video_nam:1,video_port:1,view:10,vision:1,voltag:16,wai:[6,17],wait:[0,3,4,5,9,10,12],wait_record:1,waitforcontact:2,waitforlick:5,waitformous:4,waitfornocontact:2,walk:15,water:[5,8,9],web:6,well:[3,17],whatev:[0,3,9,11],when:[0,1,2,3,4,5,6,7,8,9,10,11,12,17],whenev:10,where:[5,11],whether:10,which:[3,5,6,10,17],white:1,whithin:10,width:4,wire:10,wise:5,wish:[9,11],withhold:9,withholdwait:9,within:[3,9],without:[1,2,3,5,6,7,8,9,10,17],work:17,write:[1,3,11,17],writetologfil:[3,9],you:[1,4,6,9,15,16,17],your:[0,1,2,3,4,5,6,7,8,9,10,11,12,15,16,17],zero:[1,5,10],zerolickcount:5},titles:["AHF_BrainLight","AHF_Camera","AHF_ContactCheck","AHF_Datalogger","AHF_HeadFixer","AHF_LickDetector","AHF_Notifier","AHF_Reader","AHF_Rewarder","AHF_Stimulator","AHF_Stimulus","AHF_Subjects","AHF_Trigger","Welcome to AutoHeadFix\u2019s documentation!","AutoHeadFix Code Documentation","Quick Start","General Raspberry Pi Setup","Auto Head Fix Util and Base Classes"],titleterms:{"class":17,ahf_bas:17,ahf_brainlight:0,ahf_brainlight_1gpio:0,ahf_camera:1,ahf_camera_picam:1,ahf_camera_pistream:1,ahf_classanddictutil:17,ahf_contactcheck:2,ahf_contactcheck_beambreak:2,ahf_contactcheck_elec:2,ahf_datalogg:3,ahf_datalogger_localsql:3,ahf_datalogger_mysql:3,ahf_datalogger_text:3,ahf_datalogger_textmysql:3,ahf_hardwaretest:17,ahf_headfix:4,ahf_headfixer_nofix:4,ahf_headfixer_piston:4,ahf_headfixer_pwm:4,ahf_headfixer_pwm_pca9685:4,ahf_headfixer_pwm_pi:4,ahf_lickdetector:5,ahf_lickdetector_mpr:5,ahf_notifi:6,ahf_notifier_request:6,ahf_read:7,ahf_reader_id:7,ahf_reward:8,ahf_rewarder_solenoid:8,ahf_rewarder_solenoid_pt:8,ahf_rewarder_solenoid_rpi:8,ahf_stimul:9,ahf_stimulator_l:9,ahf_stimulator_lev:9,ahf_stimulator_lickwithhold:9,ahf_stimulator_reward:9,ahf_stimulu:10,ahf_stimulus_las:10,ahf_stimulus_non:10,ahf_stimulus_vibmotor:10,ahf_subject:11,ahf_subjects_mic:11,ahf_task:17,ahf_trigg:12,ahf_trigger_udp:12,auto:17,autoheadfix:[13,14,15],base:17,code:14,develop:15,document:[13,14],drive:16,fix:17,gener:16,hard:16,head:17,instal:[15,16],modul:[0,1,2,3,4,5,6,7,8,9,10,11,12],mount:16,quick:15,raspberri:16,setup:16,start:15,usag:15,util:17,welcom:13}})
\ No newline at end of file
diff --git a/docs/_build/html/util_classes.html b/docs/_build/html/util_classes.html
new file mode 100644
index 0000000..9116cf0
--- /dev/null
+++ b/docs/_build/html/util_classes.html
@@ -0,0 +1,418 @@
+
+
+
+
+
+
+
+
+
+
+ Auto Head Fix Util and Base Classes — AutoHeadFix 2.1.0 documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AutoHeadFix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Auto Head Fix Util and Base Classes
+
+
AHF_Base
+
+
AHF_Base.py
+
The base upon which everything else is built
+
+
+class AHF_Base.AHF_Base( taskP , settingsDictP )
+Defines conventions for classes used for accesing hardware and doing subtasks in AutoHeadFix code
+Each class has a static method, config_user_get, to create or edit a settings dictionary, and will be inititialized
+with a settings dictionary. The setup function does hardware initialization, or other inititialization.
+
+
+abstract static about( )
+Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
+
+
+
+
+config_subject_get( starterDict = {} )
+
+Returns
+dict – the default dictionary for individualized parameters
+
+
+
+
+
+
+abstract static config_user_get( starterDict = {} )
+static method that querries user for settings, with default responses from starterDict,
+and returns starterDict with settings as edited by the user.
+
+
+
+
+config_user_subject_get( starterDict = {} )
+Prompts the user for individualized parameters, with default responses
+from starterDict, and returns starterDict with settings
+as edited by the user.
+
+
+
+
+abstract hardwareTest( )
+Tests functionality, gives user a chance to change settings.
+:Returns: bool – True if any settings have changed
+
+
+
+
+abstract setdown( )
+oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
+pins can be reused, for example. This strategy should be used in hardwareTest method.
+
+
+
+
+abstract setup( )
+does hardware initialization with(possibly updated) info in self.settingsDict
+Run by __init__, or can be run separately after editing the settingsDict
+
+Returns
+bool – the truth that setup completed without errors
+
+
+
+
+
+
+
+
+
+
AHF_ClassAndDictUtils
+
+
+AHF_ClassAndDictUtils.Class_from_file( nameTypeStr , nameStr , dirName = '' )
+Imports a module from a fileName(stripped of the .py) and returns the class
+Assumes the class is named the same as the module. To get
+
+
+
+
+AHF_ClassAndDictUtils.Dict_to_file( anyDict , nameTypeStr , nameStr , typeSuffix , dir = '' )
+Saves a dicitonary as JSON encoded text file
+
+
+
+
+AHF_ClassAndDictUtils.Dict_to_obj_fields( anObject , aDict )
+Sets attributes for the object anObject from the keys and values of dictionay aDict
+
+
+
+
+AHF_ClassAndDictUtils.Edit_dict( anyDict , longName )
+Edits values in a passed in dict, in a generic way, not having to know ahead of time the name and type of each setting
+Assumption is made that lists/tuples contain only strings, ints, or float types, and that all members of any list/tuple are same type
+
+
+
+
+AHF_ClassAndDictUtils.File_exists( nameTypeStr , nameStr , typeSuffix )
+Returns true if a file with name ‘AHF_ ’ + nameTypeStr + ‘_’ + nameStr + typeSuffix exists in current directory
+
+
+
+
+AHF_ClassAndDictUtils.File_from_user( nameTypeStr , longName , typeSuffix , makeNew = False )
+Static method that trawls through current folder looking for python files matching nameTypeStr
+Allows user to choose from the list of files found. Files are recognized by names starting
+with ‘AHF_ ’ + nameTypeStr’ + ‘_’ and ending with ‘.typeSuffix’
+Raises: FileNotFoundError if no nameStr class files found
+
+
+
+
+AHF_ClassAndDictUtils.File_to_dict( nameTypeStr , nameStr , typeSuffix , dir = '' )
+Sets attributes for the object anObject from the keys and values of dictionay aDict loaded from the file
+
+
+
+
+AHF_ClassAndDictUtils.File_to_obj_fields( nameTypeStr , nameStr , typeSuffix , anObject , dir = '' )
+Sets attributes for the object anObject from the keys and values of dictionay aDict loaded from the file
+
+
+
+
+AHF_ClassAndDictUtils.Obj_fields_to_file( anObject , nameTypeStr , nameStr , typeSuffix , dir = '' )
+Writes a file containing a json dictionary of all the fields of the object anObject
+
+
+
+
+AHF_ClassAndDictUtils.Show_ordered_dict( objectDict , longName )
+Dumps standard dictionary settings into an ordered dictionary, prints settings to screen in a numbered fashion from the ordered dictionary,
+making it easy to select a setting to change. Returns an ordered dictionary of {number:(key:value),} used by edit_dict function
+
+
+
+
+
AHF_HardwareTester
+
+
+AHF_HardwareTester.hardwareTester( task )
+Hardware Tester for Auto Head Fixing, allows you to verify the various hardware bits are working
+
+
+
+
+
AHF_Task
+
+
+class AHF_Task.Task( fileName = '' , object = None )
+The plan is to copy all variables from settings, user, into a single object
+The object will have fields for things loaded from hardware config dictionary and experiment config dictionary
+as well as fields for objects created when program runs(headFixer, TagReader, rewarder, camera, stimulator)
+Objects that are created will have a dictionary of their own as an entry in the main dictionay
+Using the same names in the object fields as in the dictionary, and only loading one dictionary from
+a combined settings file, we don’t need a dictionary while thr program is running because the task object can recreate the dict
+with self.__dict__
+
+
+saveSettings( )
+Saves current configuration stored in the task object into AHF_task_*.jsn
+Call this function after modifying the contents of the task to save your changes
+
+Param
+none
+
+Returns
+nothing
+
+
+
+
+
+
+setup( )
+Sets up hardware and other objects that need setting up, each object is made by initing a class with a dictionary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/_sources/AHF_BrainLight.rst.txt b/docs/_sources/AHF_BrainLight.rst.txt
new file mode 100644
index 0000000..45c15f0
--- /dev/null
+++ b/docs/_sources/AHF_BrainLight.rst.txt
@@ -0,0 +1,18 @@
+AHF\_BrainLight
+=======================
+
+AHF\_BrainLight.AHF\_BrainLight module
+--------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_BrainLight.AHF\_BrainLight\_1GPIO module
+---------------------------------------------
+
+.. automodule:: AHF_BrainLight.AHF_BrainLight_1GPIO
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AHF_Camera.rst.txt b/docs/_sources/AHF_Camera.rst.txt
new file mode 100644
index 0000000..3435bfd
--- /dev/null
+++ b/docs/_sources/AHF_Camera.rst.txt
@@ -0,0 +1,27 @@
+AHF\_Camera
+===================
+
+AHF\_Camera.AHF\_Camera module
+------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiCam module
+-------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiCam
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Camera.AHF\_Camera\_PiStream module
+----------------------------------------
+
+.. automodule:: AHF_Camera.AHF_Camera_PiStream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AHF_ContactCheck.rst.txt b/docs/_sources/AHF_ContactCheck.rst.txt
new file mode 100644
index 0000000..d74d003
--- /dev/null
+++ b/docs/_sources/AHF_ContactCheck.rst.txt
@@ -0,0 +1,27 @@
+AHF\_ContactCheck
+=========================
+
+AHF\_ContactCheck.AHF\_ContactCheck module
+------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_BeamBreak module
+-----------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_BeamBreak
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_ContactCheck.AHF\_ContactCheck\_Elec module
+------------------------------------------------
+
+.. automodule:: AHF_ContactCheck.AHF_ContactCheck_Elec
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AHF_Datalogger.rst.txt b/docs/_sources/AHF_Datalogger.rst.txt
new file mode 100644
index 0000000..054290a
--- /dev/null
+++ b/docs/_sources/AHF_Datalogger.rst.txt
@@ -0,0 +1,43 @@
+AHF\_Datalogger
+=======================
+
+AHF\_Datalogger.AHF\_DataLogger module
+--------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_localsql module
+------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_mysql module
+---------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_text module
+--------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Datalogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------
+
+.. automodule:: AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AHF_HeadFixer.rst.txt b/docs/_sources/AHF_HeadFixer.rst.txt
new file mode 100644
index 0000000..ac1984b
--- /dev/null
+++ b/docs/_sources/AHF_HeadFixer.rst.txt
@@ -0,0 +1,53 @@
+AHF\_HeadFixer
+======================
+
+
+
+AHF\_HeadFixer.AHF\_HeadFixer module
+------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_NoFix module
+-------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_NoFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM module
+-----------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_PCA9685 module
+--------------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_Pi module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_PWM_Pi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_HeadFixer.AHF\_HeadFixer\_Pistons module
+---------------------------------------------
+
+.. automodule:: AHF_HeadFixer.AHF_HeadFixer_Pistons
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AHF_LickDetector.rst.txt b/docs/_sources/AHF_LickDetector.rst.txt
new file mode 100644
index 0000000..16516c9
--- /dev/null
+++ b/docs/_sources/AHF_LickDetector.rst.txt
@@ -0,0 +1,22 @@
+AHF\_LickDetector
+=========================
+
+
+
+AHF\_LickDetector.AHF\_LickDetector module
+------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_LickDetector.AHF\_LickDetector\_MPR module
+-----------------------------------------------
+
+.. automodule:: AHF_LickDetector.AHF_LickDetector_MPR
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_sources/AHF_Notifier.rst.txt b/docs/_sources/AHF_Notifier.rst.txt
new file mode 100644
index 0000000..88f5501
--- /dev/null
+++ b/docs/_sources/AHF_Notifier.rst.txt
@@ -0,0 +1,22 @@
+AHF\_Notifier
+=====================
+
+
+
+AHF\_Notifier.AHF\_Notifier module
+----------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Notifier.AHF\_Notifier\_Requests module
+--------------------------------------------
+
+.. automodule:: AHF_Notifier.AHF_Notifier_Requests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_sources/AHF_Reader.rst.txt b/docs/_sources/AHF_Reader.rst.txt
new file mode 100644
index 0000000..fb8b86e
--- /dev/null
+++ b/docs/_sources/AHF_Reader.rst.txt
@@ -0,0 +1,22 @@
+AHF\_Reader
+===================
+
+
+
+AHF\_Reader.AHF\_Reader module
+------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Reader.AHF\_Reader\_ID module
+----------------------------------
+
+.. automodule:: AHF_Reader.AHF_Reader_ID
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_sources/AHF_Rewarder.rst.txt b/docs/_sources/AHF_Rewarder.rst.txt
new file mode 100644
index 0000000..a014463
--- /dev/null
+++ b/docs/_sources/AHF_Rewarder.rst.txt
@@ -0,0 +1,38 @@
+AHF\_Rewarder
+=====================
+
+
+
+AHF\_Rewarder.AHF\_Rewarder module
+----------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid module
+--------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_pt module
+------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_pt
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Rewarder.AHF\_Rewarder\_solenoid\_rpi module
+-------------------------------------------------
+
+.. automodule:: AHF_Rewarder.AHF_Rewarder_solenoid_rpi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_sources/AHF_Stimulator.rst.txt b/docs/_sources/AHF_Stimulator.rst.txt
new file mode 100644
index 0000000..68dc155
--- /dev/null
+++ b/docs/_sources/AHF_Stimulator.rst.txt
@@ -0,0 +1,45 @@
+AHF\_Stimulator
+=======================
+
+
+
+AHF\_Stimulator.AHF\_Stimulator module
+--------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LEDs module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LEDs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Lever module
+---------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Lever
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_LickWithhold module
+----------------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_LickWithhold
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulator.AHF\_Stimulator\_Rewards module
+-----------------------------------------------
+
+.. automodule:: AHF_Stimulator.AHF_Stimulator_Rewards
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AHF_Stimulus.rst.txt b/docs/_sources/AHF_Stimulus.rst.txt
new file mode 100644
index 0000000..8bd3460
--- /dev/null
+++ b/docs/_sources/AHF_Stimulus.rst.txt
@@ -0,0 +1,38 @@
+AHF\_Stimulus
+=====================
+
+
+
+AHF\_Stimulus.AHF\_Stimulus module
+----------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_Laser module
+-----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_Laser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_None module
+----------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_None
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Stimulus.AHF\_Stimulus\_VibMotor module
+--------------------------------------------
+
+.. automodule:: AHF_Stimulus.AHF_Stimulus_VibMotor
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
diff --git a/docs/_sources/AHF_Subjects.rst.txt b/docs/_sources/AHF_Subjects.rst.txt
new file mode 100644
index 0000000..2ba53e4
--- /dev/null
+++ b/docs/_sources/AHF_Subjects.rst.txt
@@ -0,0 +1,23 @@
+AHF\_Subjects
+=====================
+
+
+
+AHF\_Subjects.AHF\_Subjects module
+----------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Subjects.AHF\_Subjects\_mice module
+----------------------------------------
+
+.. automodule:: AHF_Subjects.AHF_Subjects_mice
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+
diff --git a/docs/_sources/AHF_Trigger.rst.txt b/docs/_sources/AHF_Trigger.rst.txt
new file mode 100644
index 0000000..b012cb4
--- /dev/null
+++ b/docs/_sources/AHF_Trigger.rst.txt
@@ -0,0 +1,19 @@
+AHF\_Trigger
+====================
+
+AHF\_Trigger.AHF\_Trigger module
+--------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AHF\_Trigger.AHF\_Trigger\_UDP module
+-------------------------------------
+
+.. automodule:: AHF_Trigger.AHF_Trigger_UDP
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/docs/_sources/AutoHeadFix.AHF_BrainLight.rst.txt b/docs/_sources/AutoHeadFix.AHF_BrainLight.rst.txt
new file mode 100644
index 0000000..fd469f5
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_BrainLight.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_BrainLight package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_BrainLight.AHF\_BrainLight module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_BrainLight.AHF\_BrainLight\_1GPIO module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight.AHF_BrainLight_1GPIO
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_BrainLight
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Camera.rst.txt b/docs/_sources/AutoHeadFix.AHF_Camera.rst.txt
new file mode 100644
index 0000000..1cc9594
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Camera.rst.txt
@@ -0,0 +1,38 @@
+AutoHeadFix.AHF\_Camera package
+===============================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera module
+------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera\_PiCam module
+-------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera_PiCam
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Camera.AHF\_Camera\_PiStream module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Camera.AHF_Camera_PiStream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Camera
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt b/docs/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt
new file mode 100644
index 0000000..4643c6e
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_ContactCheck.rst.txt
@@ -0,0 +1,38 @@
+AutoHeadFix.AHF\_ContactCheck package
+=====================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck module
+------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck\_BeamBreak module
+-----------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck_BeamBreak
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ContactCheck.AHF\_ContactCheck\_Elec module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck.AHF_ContactCheck_Elec
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_ContactCheck
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_DataLogger.rst.txt b/docs/_sources/AutoHeadFix.AHF_DataLogger.rst.txt
new file mode 100644
index 0000000..c0d5798
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_DataLogger.rst.txt
@@ -0,0 +1,54 @@
+AutoHeadFix.AHF\_DataLogger package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_localsql module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_localsql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_mysql module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_text module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_text
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_DataLogger.AHF\_DataLogger\_textMySql module
+-------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger.AHF_DataLogger_textMySql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_DataLogger
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt b/docs/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt
new file mode 100644
index 0000000..6509ed8
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_HeadFixer.rst.txt
@@ -0,0 +1,62 @@
+AutoHeadFix.AHF\_HeadFixer package
+==================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer module
+------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_NoFix module
+-------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_NoFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM module
+-----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_PCA9685 module
+--------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM_PCA9685
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_PWM\_Pi module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_PWM_Pi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HeadFixer.AHF\_HeadFixer\_Pistons module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer.AHF_HeadFixer_Pistons
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_HeadFixer
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_LickDetector.rst.txt b/docs/_sources/AutoHeadFix.AHF_LickDetector.rst.txt
new file mode 100644
index 0000000..c441999
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_LickDetector.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_LickDetector package
+=====================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_LickDetector.AHF\_LickDetector module
+------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_LickDetector.AHF\_LickDetector\_MPR module
+-----------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector.AHF_LickDetector_MPR
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_LickDetector
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Notifier.rst.txt b/docs/_sources/AutoHeadFix.AHF_Notifier.rst.txt
new file mode 100644
index 0000000..bdf3bd0
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Notifier.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Notifier package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Notifier.AHF\_Notifier module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Notifier.AHF\_Notifier\_Requests module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier.AHF_Notifier_Requests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Notifier
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Reader.rst.txt b/docs/_sources/AutoHeadFix.AHF_Reader.rst.txt
new file mode 100644
index 0000000..ea2f4e0
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Reader.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Reader package
+===============================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Reader.AHF\_Reader module
+------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Reader.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Reader.AHF\_Reader\_ID module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Reader.AHF_Reader_ID
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Reader
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Rewarder.rst.txt b/docs/_sources/AutoHeadFix.AHF_Rewarder.rst.txt
new file mode 100644
index 0000000..9a8341f
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Rewarder.rst.txt
@@ -0,0 +1,46 @@
+AutoHeadFix.AHF\_Rewarder package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid\_pt module
+------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid_pt
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Rewarder.AHF\_Rewarder\_solenoid\_rpi module
+-------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder.AHF_Rewarder_solenoid_rpi
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Rewarder
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Stimulator.rst.txt b/docs/_sources/AutoHeadFix.AHF_Stimulator.rst.txt
new file mode 100644
index 0000000..eb26745
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Stimulator.rst.txt
@@ -0,0 +1,54 @@
+AutoHeadFix.AHF\_Stimulator package
+===================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator module
+--------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_LEDs module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_LEDs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_Lever module
+---------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_Lever
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_LickWithhold module
+----------------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_LickWithhold
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulator.AHF\_Stimulator\_Rewards module
+-----------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator.AHF_Stimulator_Rewards
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulator
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Stimulus.rst.txt b/docs/_sources/AutoHeadFix.AHF_Stimulus.rst.txt
new file mode 100644
index 0000000..9dd0294
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Stimulus.rst.txt
@@ -0,0 +1,46 @@
+AutoHeadFix.AHF\_Stimulus package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_Laser module
+-----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_Laser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_None module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_None
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Stimulus.AHF\_Stimulus\_VibMotor module
+--------------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus.AHF_Stimulus_VibMotor
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Stimulus
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Subjects.rst.txt b/docs/_sources/AutoHeadFix.AHF_Subjects.rst.txt
new file mode 100644
index 0000000..d743d88
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Subjects.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Subjects package
+=================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Subjects.AHF\_Subjects module
+----------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Subjects.AHF\_Subjects\_mice module
+----------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects.AHF_Subjects_mice
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Subjects
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.AHF_Trigger.rst.txt b/docs/_sources/AutoHeadFix.AHF_Trigger.rst.txt
new file mode 100644
index 0000000..b6a6800
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.AHF_Trigger.rst.txt
@@ -0,0 +1,30 @@
+AutoHeadFix.AHF\_Trigger package
+================================
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Trigger.AHF\_Trigger module
+--------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Trigger.AHF\_Trigger\_UDP module
+-------------------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger.AHF_Trigger_UDP
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix.AHF_Trigger
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/AutoHeadFix.rst.txt b/docs/_sources/AutoHeadFix.rst.txt
new file mode 100644
index 0000000..530e612
--- /dev/null
+++ b/docs/_sources/AutoHeadFix.rst.txt
@@ -0,0 +1,105 @@
+AutoHeadFix package
+===================
+
+Subpackages
+-----------
+
+.. toctree::
+
+ AutoHeadFix.AHF_BrainLight
+ AutoHeadFix.AHF_Camera
+ AutoHeadFix.AHF_ContactCheck
+ AutoHeadFix.AHF_DataLogger
+ AutoHeadFix.AHF_HeadFixer
+ AutoHeadFix.AHF_LickDetector
+ AutoHeadFix.AHF_Notifier
+ AutoHeadFix.AHF_Reader
+ AutoHeadFix.AHF_Rewarder
+ AutoHeadFix.AHF_Stimulator
+ AutoHeadFix.AHF_Stimulus
+ AutoHeadFix.AHF_Subjects
+ AutoHeadFix.AHF_Trigger
+
+Submodules
+----------
+
+AutoHeadFix.AHF\_Base module
+----------------------------
+
+.. automodule:: AutoHeadFix.AHF_Base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ClassAndDictUtils module
+-----------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ClassAndDictUtils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_HardwareTester module
+--------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_HardwareTester
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_Task module
+----------------------------
+
+.. automodule:: AutoHeadFix.AHF_Task
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.AHF\_ValveControl module
+------------------------------------
+
+.. automodule:: AutoHeadFix.AHF_ValveControl
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.Subject\_update module
+----------------------------------
+
+.. automodule:: AutoHeadFix.Subject_update
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.quickstats module
+-----------------------------
+
+.. automodule:: AutoHeadFix.quickstats
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.restart\_if\_no\_data module
+----------------------------------------
+
+.. automodule:: AutoHeadFix.restart_if_no_data
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+AutoHeadFix.water\_failsafe module
+----------------------------------
+
+.. automodule:: AutoHeadFix.water_failsafe
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+Module contents
+---------------
+
+.. automodule:: AutoHeadFix
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt
new file mode 100644
index 0000000..309eeac
--- /dev/null
+++ b/docs/_sources/index.rst.txt
@@ -0,0 +1,16 @@
+.. AutoHeadFix documentation master file, created by
+ sphinx-quickstart on Sun Apr 5 17:25:18 2020.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to AutoHeadFix's documentation!
+=======================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ rpi_setup
+ quickstart
+ modules
+
diff --git a/docs/_sources/modules.rst.txt b/docs/_sources/modules.rst.txt
new file mode 100644
index 0000000..94393b1
--- /dev/null
+++ b/docs/_sources/modules.rst.txt
@@ -0,0 +1,18 @@
+AutoHeadFix Code Documentation
+=======================================
+
+.. toctree::
+ util_classes
+ AHF_BrainLight
+ AHF_Camera
+ AHF_ContactCheck
+ AHF_DataLogger
+ AHF_HeadFixer
+ AHF_LickDetector
+ AHF_Notifier
+ AHF_Reader
+ AHF_Rewarder
+ AHF_Stimulator
+ AHF_Stimulus
+ AHF_Subjects
+ AHF_Trigger
diff --git a/docs/_sources/quickstart.rst.txt b/docs/_sources/quickstart.rst.txt
new file mode 100644
index 0000000..4886f00
--- /dev/null
+++ b/docs/_sources/quickstart.rst.txt
@@ -0,0 +1,94 @@
+Quick Start
+==========================
+
+Installation of AutoHeadFix
+-----------------------------
+
+To downlowd the setup script for AutoHeadFix, `click here `_.
+
+**Installation Walk Through**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+**Important**:
+
+* Having multiple installations can cause things to break if this is not your first time running this script in the trash make sure to delete all old folders and empty your trash
+* A config.txt file will be included in the repository, you must change the variables (eg path, password) to your installation specific details.
+* All cageID's must be unique.
+
+|
+
+Developers
+---------------
+
+* For notes and structure information from the developer, `click here `_.
+* To clone the source code, `click here `_.
+
+|
+
+Usage
+------
+
+**First Time Configuration**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Generic Usage Guide**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Cron Creation**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Changing Mouse Specific Var**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
+
+|
+
+**Training Difficulty**
+
+.. raw:: html
+
+
+
+ type="video/mp4">
+ Your browser does not support this video type.
+
\ No newline at end of file
diff --git a/docs/_sources/rpi_setup.rst.txt b/docs/_sources/rpi_setup.rst.txt
new file mode 100644
index 0000000..9d7edc6
--- /dev/null
+++ b/docs/_sources/rpi_setup.rst.txt
@@ -0,0 +1,17 @@
+General Raspberry Pi Setup
+==========================
+
+Installing OS and General Setup
+--------------------------------
+
+There are many guides available online for Raspberry Pi setup. This guide from medium contains the basic setup, `click here `_
+
+
+Mounting Hard Drive
+--------------------
+
+AutoHeadFix records many videos and an external hard drive is necessary.
+
+* Make sure your hard drive is powered by an external hub, as the pi itself may not provide enough voltage for the hard drive. *
+
+You will also need to format and mount your hard drive as outlined `here `_ .
diff --git a/docs/_sources/util_classes.rst.txt b/docs/_sources/util_classes.rst.txt
new file mode 100644
index 0000000..35517e5
--- /dev/null
+++ b/docs/_sources/util_classes.rst.txt
@@ -0,0 +1,23 @@
+Auto Head Fix Util and Base Classes
+===================================
+
+AHF_Base
+--------
+.. automodule:: AHF_Base
+ :members:
+
+AHF_ClassAndDictUtils
+---------------------
+.. automodule:: AHF_ClassAndDictUtils
+ :members:
+
+AHF_HardwareTester
+--------------------
+.. automodule:: AHF_HardwareTester
+ :members:
+
+AHF_Task
+--------
+.. automodule:: AHF_Task
+ :members:
+
diff --git a/docs/_static/basic.css b/docs/_static/basic.css
new file mode 100644
index 0000000..0119285
--- /dev/null
+++ b/docs/_static/basic.css
@@ -0,0 +1,768 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+ word-wrap: break-word;
+ overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox form.search {
+ overflow: hidden;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+ float: left;
+ width: 80%;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ float: left;
+ width: 20%;
+ border-left: none;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li div.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ list-style-type: none;
+}
+
+table.indextable > tbody > tr > td > ul {
+ padding-left: 0em;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+/* -- domain module index --------------------------------------------------- */
+
+table.modindextable td {
+ padding: 2px;
+ border-collapse: collapse;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body {
+ min-width: 450px;
+ max-width: 800px;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+a.headerlink {
+ visibility: hidden;
+}
+
+a.brackets:before,
+span.brackets > a:before{
+ content: "[";
+}
+
+a.brackets:after,
+span.brackets > a:after {
+ content: "]";
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+img.align-left, .figure.align-left, object.align-left {
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+
+img.align-right, .figure.align-right, object.align-right {
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+
+img.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+img.align-default, .figure.align-default {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-default {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px 7px 0 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px 7px 0 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+div.admonition dl {
+ margin-bottom: 0;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-default {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+th > p:first-child,
+td > p:first-child {
+ margin-top: 0px;
+}
+
+th > p:last-child,
+td > p:last-child {
+ margin-bottom: 0px;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure {
+ margin: 0.5em;
+ padding: 0.5em;
+}
+
+div.figure p.caption {
+ padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+/* -- hlist styles ---------------------------------------------------------- */
+
+table.hlist td {
+ vertical-align: top;
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+li > p:first-child {
+ margin-top: 0px;
+}
+
+li > p:last-child {
+ margin-bottom: 0px;
+}
+
+dl.footnote > dt,
+dl.citation > dt {
+ float: left;
+}
+
+dl.footnote > dd,
+dl.citation > dd {
+ margin-bottom: 0em;
+}
+
+dl.footnote > dd:after,
+dl.citation > dd:after {
+ content: "";
+ clear: both;
+}
+
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) auto;
+}
+
+dl.field-list > dt {
+ font-weight: bold;
+ word-break: break-word;
+ padding-left: 0.5em;
+ padding-right: 5px;
+}
+
+dl.field-list > dt:after {
+ content: ":";
+}
+
+dl.field-list > dd {
+ padding-left: 0.5em;
+ margin-top: 0em;
+ margin-left: 0em;
+ margin-bottom: 0em;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd > p:first-child {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dt:target, span.highlighted {
+ background-color: #fbe54e;
+}
+
+rect.highlighted {
+ fill: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-family: sans-serif;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+.classifier:before {
+ font-style: normal;
+ margin: 0.5em;
+ content: ":";
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+ overflow-y: hidden; /* fixes display issues on Chrome browsers */
+}
+
+span.pre {
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ -webkit-hyphens: none;
+ hyphens: none;
+}
+
+td.linenos pre {
+ padding: 5px 0px;
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ margin-left: 0.5em;
+}
+
+table.highlighttable td {
+ padding: 0 0.5em 0 0.5em;
+}
+
+div.code-block-caption {
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-caption code {
+ background-color: transparent;
+}
+
+div.code-block-caption + div > div.highlight > pre {
+ margin-top: 0;
+}
+
+div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ padding: 1em 1em 0;
+}
+
+div.literal-block-wrapper div.highlight {
+ margin: 0;
+}
+
+code.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+code.descclassname {
+ background-color: transparent;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+span.eqno a.headerlink {
+ position: relative;
+ left: 0px;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/docs/_static/css/badge_only.css b/docs/_static/css/badge_only.css
new file mode 100644
index 0000000..3c33cef
--- /dev/null
+++ b/docs/_static/css/badge_only.css
@@ -0,0 +1 @@
+.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
diff --git a/docs/_static/css/theme.css b/docs/_static/css/theme.css
new file mode 100644
index 0000000..aed8cef
--- /dev/null
+++ b/docs/_static/css/theme.css
@@ -0,0 +1,6 @@
+/* sphinx_rtd_theme version 0.4.3 | MIT license */
+/* Built 20190212 16:02 */
+*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:.5cm}p,h2,.rst-content .toctree-wrapper p.caption,h3{orphans:3;widows:3}h2,.rst-content .toctree-wrapper p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content .code-block-caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.7.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"),url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.wy-menu-vertical li span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.rst-content .fa-pull-left.admonition-title,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content dl dt .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.rst-content code.download span.fa-pull-left:first-child,.fa-pull-left.icon{margin-right:.3em}.fa.fa-pull-right,.wy-menu-vertical li span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.rst-content .fa-pull-right.admonition-title,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content dl dt .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.rst-content code.download span.fa-pull-right:first-child,.fa-pull-right.icon{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content .code-block-caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content .code-block-caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-hotel:before,.fa-bed:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-yc:before,.fa-y-combinator:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-tv:before,.fa-television:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:""}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-signing:before,.fa-sign-language:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-vcard:before,.fa-address-card:before{content:""}.fa-vcard-o:before,.fa-address-card-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content .code-block-caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content table>caption .headerlink,.rst-content table>caption a .headerlink,a .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content table>caption .headerlink,.rst-content table>caption .btn .headerlink,.btn .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content table>caption .headerlink,.rst-content table>caption .nav .headerlink,.nav .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.btn .rst-content .code-block-caption .fa-large.headerlink,.rst-content .code-block-caption .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.nav .rst-content .code-block-caption .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.btn .rst-content .code-block-caption .fa-spin.headerlink,.rst-content .code-block-caption .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.nav .rst-content .code-block-caption .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.rst-content .admonition{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.admonition{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo,.rst-content .wy-alert-warning.admonition{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title,.rst-content .wy-alert-warning.admonition .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.admonition{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.admonition{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.admonition{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 .3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.3576515979%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.3576515979%;width:48.821174201%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.3576515979%;width:31.7615656014%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type="datetime-local"]{padding:.34375em .625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{position:absolute;content:"";display:block;left:0;top:0;width:36px;height:12px;border-radius:4px;background:#ccc;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27AE60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:.3em;display:block}.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content .toctree-wrapper p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content .toctree-wrapper p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:before,.wy-breadcrumbs:after{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs li code,.wy-breadcrumbs li .rst-content tt,.rst-content .wy-breadcrumbs li tt{padding:5px;border:none;background:none}.wy-breadcrumbs li code.literal,.wy-breadcrumbs li .rst-content tt.literal,.rst-content .wy-breadcrumbs li tt.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#3a7ca8;height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin:12px 0 0 0;display:block;font-weight:bold;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a{color:#404040}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980B9;text-align:center;padding:.809em;display:block;color:#fcfcfc;margin-bottom:.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:normal;color:rgba(255,255,255,0.3)}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:gray}footer p{margin-bottom:12px}footer span.commit code,footer span.commit .rst-content tt,.rst-content footer span.commit tt{padding:0px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:1em;background:none;border:none;color:gray}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{width:100%}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:before,.rst-breadcrumbs-buttons:after{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-side-scroll{width:auto}.wy-side-nav-search{width:auto}.wy-menu.wy-menu-vertical{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1100px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;display:block;overflow:auto}.rst-content pre.literal-block,.rst-content div[class^='highlight']{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px 0}.rst-content pre.literal-block div[class^='highlight'],.rst-content div[class^='highlight'] div[class^='highlight']{padding:0px;border:none;margin:0}.rst-content div[class^='highlight'] td.code{width:100%}.rst-content .linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;display:block;overflow:auto}.rst-content div[class^='highlight'] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content pre.literal-block,.rst-content div[class^='highlight'] pre,.rst-content .linenodiv pre{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;font-size:12px;line-height:1.4}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^='highlight'],.rst-content div[class^='highlight'] pre{white-space:pre-wrap}}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last,.rst-content .admonition .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .section ol p:last-child,.rst-content .section ul p:last-child{margin-bottom:24px}.rst-content .line-block{margin-left:0px;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content .code-block-caption .headerlink{visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after,.rst-content .code-block-caption .headerlink:after{content:"";font-family:FontAwesome}.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content .toctree-wrapper p.caption:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after,.rst-content .code-block-caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:baseline;position:relative;top:-0.4em;line-height:0;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:gray}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation tt,.rst-content table.docutils.citation code,.rst-content table.docutils.footnote tt,.rst-content table.docutils.footnote code{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}.rst-content table.docutils td .last,.rst-content table.docutils td .last :last-child{margin-bottom:0}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content tt,.rst-content tt,.rst-content code{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace;padding:2px 5px}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal{color:#E74C3C}.rst-content tt.xref,a .rst-content tt,.rst-content tt.xref,.rst-content code.xref,a .rst-content tt,a .rst-content code{font-weight:bold;color:#404040}.rst-content pre,.rst-content kbd,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold;margin-bottom:12px}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-weight:normal;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child,.rst-content code.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-regular.eot");src:url("../fonts/Lato/lato-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-regular.woff2") format("woff2"),url("../fonts/Lato/lato-regular.woff") format("woff"),url("../fonts/Lato/lato-regular.ttf") format("truetype");font-weight:400;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bold.eot");src:url("../fonts/Lato/lato-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bold.woff2") format("woff2"),url("../fonts/Lato/lato-bold.woff") format("woff"),url("../fonts/Lato/lato-bold.ttf") format("truetype");font-weight:700;font-style:normal}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-bolditalic.eot");src:url("../fonts/Lato/lato-bolditalic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-bolditalic.woff2") format("woff2"),url("../fonts/Lato/lato-bolditalic.woff") format("woff"),url("../fonts/Lato/lato-bolditalic.ttf") format("truetype");font-weight:700;font-style:italic}@font-face{font-family:"Lato";src:url("../fonts/Lato/lato-italic.eot");src:url("../fonts/Lato/lato-italic.eot?#iefix") format("embedded-opentype"),url("../fonts/Lato/lato-italic.woff2") format("woff2"),url("../fonts/Lato/lato-italic.woff") format("woff"),url("../fonts/Lato/lato-italic.ttf") format("truetype");font-weight:400;font-style:italic}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:url("../fonts/RobotoSlab/roboto-slab.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot");src:url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"),url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype")}
diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js
new file mode 100644
index 0000000..daccd20
--- /dev/null
+++ b/docs/_static/doctools.js
@@ -0,0 +1,315 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+if (!window.console || !console.firebug) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
+ "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
+ "profile", "profileEnd"];
+ window.console = {};
+ for (var i = 0; i < names.length; ++i)
+ window.console[names[i]] = function() {};
+}
+ */
+
+/**
+ * small helper function to urldecode strings
+ */
+jQuery.urldecode = function(x) {
+ return decodeURIComponent(x).replace(/\+/g, ' ');
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+ if (typeof s === 'undefined')
+ s = document.location.search;
+ var parts = s.substr(s.indexOf('?') + 1).split('&');
+ var result = {};
+ for (var i = 0; i < parts.length; i++) {
+ var tmp = parts[i].split('=', 2);
+ var key = jQuery.urldecode(tmp[0]);
+ var value = jQuery.urldecode(tmp[1]);
+ if (key in result)
+ result[key].push(value);
+ else
+ result[key] = [value];
+ }
+ return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+ function highlight(node, addItems) {
+ if (node.nodeType === 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 &&
+ !jQuery(node.parentNode).hasClass(className) &&
+ !jQuery(node.parentNode).hasClass("nohighlight")) {
+ var span;
+ var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
+ if (isInSVG) {
+ span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+ } else {
+ span = document.createElement("span");
+ span.className = className;
+ }
+ span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+ node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+ document.createTextNode(val.substr(pos + text.length)),
+ node.nextSibling));
+ node.nodeValue = val.substr(0, pos);
+ if (isInSVG) {
+ var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+ var bbox = node.parentElement.getBBox();
+ rect.x.baseVal.value = bbox.x;
+ rect.y.baseVal.value = bbox.y;
+ rect.width.baseVal.value = bbox.width;
+ rect.height.baseVal.value = bbox.height;
+ rect.setAttribute('class', className);
+ addItems.push({
+ "parent": node.parentNode,
+ "target": rect});
+ }
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this, addItems);
+ });
+ }
+ }
+ var addItems = [];
+ var result = this.each(function() {
+ highlight(this, addItems);
+ });
+ for (var i = 0; i < addItems.length; ++i) {
+ jQuery(addItems[i].parent).before(addItems[i].target);
+ }
+ return result;
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+ init : function() {
+ this.fixFirefoxAnchorBug();
+ this.highlightSearchWords();
+ this.initIndexTable();
+ if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
+ this.initOnKeyListeners();
+ }
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS : {},
+ PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
+ LOCALE : 'unknown',
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext : function(string) {
+ var translated = Documentation.TRANSLATIONS[string];
+ if (typeof translated === 'undefined')
+ return string;
+ return (typeof translated === 'string') ? translated : translated[0];
+ },
+
+ ngettext : function(singular, plural, n) {
+ var translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated === 'undefined')
+ return (n == 1) ? singular : plural;
+ return translated[Documentation.PLURALEXPR(n)];
+ },
+
+ addTranslations : function(catalog) {
+ for (var key in catalog.messages)
+ this.TRANSLATIONS[key] = catalog.messages[key];
+ this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+ this.LOCALE = catalog.locale;
+ },
+
+ /**
+ * add context elements like header anchor links
+ */
+ addContextElements : function() {
+ $('div[id] > :header:first').each(function() {
+ $('').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this headline')).
+ appendTo(this);
+ });
+ $('dt[id]').each(function() {
+ $('').
+ attr('href', '#' + this.id).
+ attr('title', _('Permalink to this definition')).
+ appendTo(this);
+ });
+ },
+
+ /**
+ * workaround a firefox stupidity
+ * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
+ */
+ fixFirefoxAnchorBug : function() {
+ if (document.location.hash && $.browser.mozilla)
+ window.setTimeout(function() {
+ document.location.href += '';
+ }, 10);
+ },
+
+ /**
+ * highlight the search words provided in the url in the text
+ */
+ highlightSearchWords : function() {
+ var params = $.getQueryParameters();
+ var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+ if (terms.length) {
+ var body = $('div.body');
+ if (!body.length) {
+ body = $('body');
+ }
+ window.setTimeout(function() {
+ $.each(terms, function() {
+ body.highlightText(this.toLowerCase(), 'highlighted');
+ });
+ }, 10);
+ $('' + _('Hide Search Matches') + '
')
+ .appendTo($('#searchbox'));
+ }
+ },
+
+ /**
+ * init the domain index toggle buttons
+ */
+ initIndexTable : function() {
+ var togglers = $('img.toggler').click(function() {
+ var src = $(this).attr('src');
+ var idnum = $(this).attr('id').substr(7);
+ $('tr.cg-' + idnum).toggle();
+ if (src.substr(-9) === 'minus.png')
+ $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
+ else
+ $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
+ }).css('display', '');
+ if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
+ togglers.click();
+ }
+ },
+
+ /**
+ * helper function to hide the search marks again
+ */
+ hideSearchWords : function() {
+ $('#searchbox .highlight-link').fadeOut(300);
+ $('span.highlighted').removeClass('highlighted');
+ },
+
+ /**
+ * make the url absolute
+ */
+ makeURL : function(relativeURL) {
+ return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
+ },
+
+ /**
+ * get the current relative url
+ */
+ getCurrentURL : function() {
+ var path = document.location.pathname;
+ var parts = path.split(/\//);
+ $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
+ if (this === '..')
+ parts.pop();
+ });
+ var url = parts.join('/');
+ return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
+ },
+
+ initOnKeyListeners: function() {
+ $(document).keydown(function(event) {
+ var activeElementType = document.activeElement.tagName;
+ // don't navigate when in search box or textarea
+ if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
+ && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) {
+ switch (event.keyCode) {
+ case 37: // left
+ var prevHref = $('link[rel="prev"]').prop('href');
+ if (prevHref) {
+ window.location.href = prevHref;
+ return false;
+ }
+ case 39: // right
+ var nextHref = $('link[rel="next"]').prop('href');
+ if (nextHref) {
+ window.location.href = nextHref;
+ return false;
+ }
+ }
+ }
+ });
+ }
+};
+
+// quick alias for translations
+_ = Documentation.gettext;
+
+$(document).ready(function() {
+ Documentation.init();
+});
diff --git a/docs/_static/documentation_options.js b/docs/_static/documentation_options.js
new file mode 100644
index 0000000..e970480
--- /dev/null
+++ b/docs/_static/documentation_options.js
@@ -0,0 +1,11 @@
+var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
+ VERSION: '2.1.0',
+ LANGUAGE: 'None',
+ COLLAPSE_INDEX: false,
+ BUILDER: 'html',
+ FILE_SUFFIX: '.html',
+ HAS_SOURCE: true,
+ SOURCELINK_SUFFIX: '.txt',
+ NAVIGATION_WITH_KEYS: false
+};
\ No newline at end of file
diff --git a/docs/_static/file.png b/docs/_static/file.png
new file mode 100644
index 0000000..a858a41
Binary files /dev/null and b/docs/_static/file.png differ
diff --git a/docs/_static/fonts/Inconsolata-Bold.ttf b/docs/_static/fonts/Inconsolata-Bold.ttf
new file mode 100644
index 0000000..809c1f5
Binary files /dev/null and b/docs/_static/fonts/Inconsolata-Bold.ttf differ
diff --git a/docs/_static/fonts/Inconsolata-Regular.ttf b/docs/_static/fonts/Inconsolata-Regular.ttf
new file mode 100644
index 0000000..fc981ce
Binary files /dev/null and b/docs/_static/fonts/Inconsolata-Regular.ttf differ
diff --git a/docs/_static/fonts/Inconsolata.ttf b/docs/_static/fonts/Inconsolata.ttf
new file mode 100644
index 0000000..4b8a36d
Binary files /dev/null and b/docs/_static/fonts/Inconsolata.ttf differ
diff --git a/docs/_static/fonts/Lato-Bold.ttf b/docs/_static/fonts/Lato-Bold.ttf
new file mode 100644
index 0000000..1d23c70
Binary files /dev/null and b/docs/_static/fonts/Lato-Bold.ttf differ
diff --git a/docs/_static/fonts/Lato-Regular.ttf b/docs/_static/fonts/Lato-Regular.ttf
new file mode 100644
index 0000000..0f3d0f8
Binary files /dev/null and b/docs/_static/fonts/Lato-Regular.ttf differ
diff --git a/docs/_static/fonts/Lato/lato-bold.eot b/docs/_static/fonts/Lato/lato-bold.eot
new file mode 100644
index 0000000..3361183
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bold.eot differ
diff --git a/docs/_static/fonts/Lato/lato-bold.ttf b/docs/_static/fonts/Lato/lato-bold.ttf
new file mode 100644
index 0000000..29f691d
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bold.ttf differ
diff --git a/docs/_static/fonts/Lato/lato-bold.woff b/docs/_static/fonts/Lato/lato-bold.woff
new file mode 100644
index 0000000..c6dff51
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bold.woff differ
diff --git a/docs/_static/fonts/Lato/lato-bold.woff2 b/docs/_static/fonts/Lato/lato-bold.woff2
new file mode 100644
index 0000000..bb19504
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bold.woff2 differ
diff --git a/docs/_static/fonts/Lato/lato-bolditalic.eot b/docs/_static/fonts/Lato/lato-bolditalic.eot
new file mode 100644
index 0000000..3d41549
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bolditalic.eot differ
diff --git a/docs/_static/fonts/Lato/lato-bolditalic.ttf b/docs/_static/fonts/Lato/lato-bolditalic.ttf
new file mode 100644
index 0000000..f402040
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bolditalic.ttf differ
diff --git a/docs/_static/fonts/Lato/lato-bolditalic.woff b/docs/_static/fonts/Lato/lato-bolditalic.woff
new file mode 100644
index 0000000..88ad05b
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bolditalic.woff differ
diff --git a/docs/_static/fonts/Lato/lato-bolditalic.woff2 b/docs/_static/fonts/Lato/lato-bolditalic.woff2
new file mode 100644
index 0000000..c4e3d80
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-bolditalic.woff2 differ
diff --git a/docs/_static/fonts/Lato/lato-italic.eot b/docs/_static/fonts/Lato/lato-italic.eot
new file mode 100644
index 0000000..3f82642
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-italic.eot differ
diff --git a/docs/_static/fonts/Lato/lato-italic.ttf b/docs/_static/fonts/Lato/lato-italic.ttf
new file mode 100644
index 0000000..b4bfc9b
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-italic.ttf differ
diff --git a/docs/_static/fonts/Lato/lato-italic.woff b/docs/_static/fonts/Lato/lato-italic.woff
new file mode 100644
index 0000000..76114bc
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-italic.woff differ
diff --git a/docs/_static/fonts/Lato/lato-italic.woff2 b/docs/_static/fonts/Lato/lato-italic.woff2
new file mode 100644
index 0000000..3404f37
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-italic.woff2 differ
diff --git a/docs/_static/fonts/Lato/lato-regular.eot b/docs/_static/fonts/Lato/lato-regular.eot
new file mode 100644
index 0000000..11e3f2a
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-regular.eot differ
diff --git a/docs/_static/fonts/Lato/lato-regular.ttf b/docs/_static/fonts/Lato/lato-regular.ttf
new file mode 100644
index 0000000..74decd9
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-regular.ttf differ
diff --git a/docs/_static/fonts/Lato/lato-regular.woff b/docs/_static/fonts/Lato/lato-regular.woff
new file mode 100644
index 0000000..ae1307f
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-regular.woff differ
diff --git a/docs/_static/fonts/Lato/lato-regular.woff2 b/docs/_static/fonts/Lato/lato-regular.woff2
new file mode 100644
index 0000000..3bf9843
Binary files /dev/null and b/docs/_static/fonts/Lato/lato-regular.woff2 differ
diff --git a/docs/_static/fonts/RobotoSlab-Bold.ttf b/docs/_static/fonts/RobotoSlab-Bold.ttf
new file mode 100644
index 0000000..df5d1df
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab-Bold.ttf differ
diff --git a/docs/_static/fonts/RobotoSlab-Regular.ttf b/docs/_static/fonts/RobotoSlab-Regular.ttf
new file mode 100644
index 0000000..eb52a79
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab-Regular.ttf differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
new file mode 100644
index 0000000..79dc8ef
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
new file mode 100644
index 0000000..df5d1df
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff
new file mode 100644
index 0000000..6cb6000
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
new file mode 100644
index 0000000..7059e23
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
new file mode 100644
index 0000000..2f7ca78
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
new file mode 100644
index 0000000..eb52a79
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff
new file mode 100644
index 0000000..f815f63
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ
diff --git a/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
new file mode 100644
index 0000000..f2c76e5
Binary files /dev/null and b/docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ
diff --git a/docs/_static/fonts/fontawesome-webfont.eot b/docs/_static/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000..e9f60ca
Binary files /dev/null and b/docs/_static/fonts/fontawesome-webfont.eot differ
diff --git a/docs/_static/fonts/fontawesome-webfont.svg b/docs/_static/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000..855c845
--- /dev/null
+++ b/docs/_static/fonts/fontawesome-webfont.svg
@@ -0,0 +1,2671 @@
+
+
+
+
+Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ By ,,,
+Copyright Dave Gandy 2016. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/_static/fonts/fontawesome-webfont.ttf b/docs/_static/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..35acda2
Binary files /dev/null and b/docs/_static/fonts/fontawesome-webfont.ttf differ
diff --git a/docs/_static/fonts/fontawesome-webfont.woff b/docs/_static/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..400014a
Binary files /dev/null and b/docs/_static/fonts/fontawesome-webfont.woff differ
diff --git a/docs/_static/fonts/fontawesome-webfont.woff2 b/docs/_static/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000..4d13fc6
Binary files /dev/null and b/docs/_static/fonts/fontawesome-webfont.woff2 differ
diff --git a/docs/build/html/_static/jquery-3.2.1.js b/docs/_static/jquery-3.4.1.js
similarity index 89%
rename from docs/build/html/_static/jquery-3.2.1.js
rename to docs/_static/jquery-3.4.1.js
index d2d8ca4..773ad95 100644
--- a/docs/build/html/_static/jquery-3.2.1.js
+++ b/docs/_static/jquery-3.4.1.js
@@ -1,5 +1,5 @@
/*!
- * jQuery JavaScript Library v3.2.1
+ * jQuery JavaScript Library v3.4.1
* https://jquery.com/
*
* Includes Sizzle.js
@@ -9,7 +9,7 @@
* Released under the MIT license
* https://jquery.org/license
*
- * Date: 2017-03-20T18:59Z
+ * Date: 2019-05-01T21:04Z
*/
( function( global, factory ) {
@@ -71,16 +71,70 @@ var ObjectFunctionString = fnToString.call( Object );
var support = {};
+var isFunction = function isFunction( obj ) {
+ // Support: Chrome <=57, Firefox <=52
+ // In some browsers, typeof returns "function" for HTML elements
+ // (i.e., `typeof document.createElement( "object" ) === "function"`).
+ // We don't want to classify *any* DOM node as a function.
+ return typeof obj === "function" && typeof obj.nodeType !== "number";
+ };
- function DOMEval( code, doc ) {
+
+var isWindow = function isWindow( obj ) {
+ return obj != null && obj === obj.window;
+ };
+
+
+
+
+ var preservedScriptAttributes = {
+ type: true,
+ src: true,
+ nonce: true,
+ noModule: true
+ };
+
+ function DOMEval( code, node, doc ) {
doc = doc || document;
- var script = doc.createElement( "script" );
+ var i, val,
+ script = doc.createElement( "script" );
script.text = code;
+ if ( node ) {
+ for ( i in preservedScriptAttributes ) {
+
+ // Support: Firefox 64+, Edge 18+
+ // Some browsers don't support the "nonce" property on scripts.
+ // On the other hand, just using `getAttribute` is not enough as
+ // the `nonce` attribute is reset to an empty string whenever it
+ // becomes browsing-context connected.
+ // See https://github.com/whatwg/html/issues/2369
+ // See https://html.spec.whatwg.org/#nonce-attributes
+ // The `node.getAttribute` check was added for the sake of
+ // `jQuery.globalEval` so that it can fake a nonce-containing node
+ // via an object.
+ val = node[ i ] || node.getAttribute && node.getAttribute( i );
+ if ( val ) {
+ script.setAttribute( i, val );
+ }
+ }
+ }
doc.head.appendChild( script ).parentNode.removeChild( script );
}
+
+
+function toType( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android <=2.3 only (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+}
/* global Symbol */
// Defining this global in .eslintrc.json would create a danger of using the global
// unguarded in another place, it seems safer to define global only for this module
@@ -88,7 +142,7 @@ var support = {};
var
- version = "3.2.1",
+ version = "3.4.1",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
@@ -100,16 +154,7 @@ var
// Support: Android <=4.0 only
// Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
- // Matches dashed string for camelizing
- rmsPrefix = /^-ms-/,
- rdashAlpha = /-([a-z])/g,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return letter.toUpperCase();
- };
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
jQuery.fn = jQuery.prototype = {
@@ -209,7 +254,7 @@ jQuery.extend = jQuery.fn.extend = function() {
}
// Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ if ( typeof target !== "object" && !isFunction( target ) ) {
target = {};
}
@@ -226,25 +271,28 @@ jQuery.extend = jQuery.fn.extend = function() {
// Extend the base object
for ( name in options ) {
- src = target[ name ];
copy = options[ name ];
+ // Prevent Object.prototype pollution
// Prevent never-ending loop
- if ( target === copy ) {
+ if ( name === "__proto__" || target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
( copyIsArray = Array.isArray( copy ) ) ) ) {
+ src = target[ name ];
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && Array.isArray( src ) ? src : [];
-
+ // Ensure proper type for the source value
+ if ( copyIsArray && !Array.isArray( src ) ) {
+ clone = [];
+ } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
+ clone = {};
} else {
- clone = src && jQuery.isPlainObject( src ) ? src : {};
+ clone = src;
}
+ copyIsArray = false;
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
@@ -275,28 +323,6 @@ jQuery.extend( {
noop: function() {},
- isFunction: function( obj ) {
- return jQuery.type( obj ) === "function";
- },
-
- isWindow: function( obj ) {
- return obj != null && obj === obj.window;
- },
-
- isNumeric: function( obj ) {
-
- // As of jQuery 3.0, isNumeric is limited to
- // strings and numbers (primitives or objects)
- // that can be coerced to finite numbers (gh-2662)
- var type = jQuery.type( obj );
- return ( type === "number" || type === "string" ) &&
-
- // parseFloat NaNs numeric-cast false positives ("")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- !isNaN( obj - parseFloat( obj ) );
- },
-
isPlainObject: function( obj ) {
var proto, Ctor;
@@ -319,9 +345,6 @@ jQuery.extend( {
},
isEmptyObject: function( obj ) {
-
- /* eslint-disable no-unused-vars */
- // See https://github.com/eslint/eslint/issues/6125
var name;
for ( name in obj ) {
@@ -330,27 +353,9 @@ jQuery.extend( {
return true;
},
- type: function( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
-
- // Support: Android <=2.3 only (functionish RegExp)
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call( obj ) ] || "object" :
- typeof obj;
- },
-
// Evaluates a script in a global context
- globalEval: function( code ) {
- DOMEval( code );
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Support: IE <=9 - 11, Edge 12 - 13
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ globalEval: function( code, options ) {
+ DOMEval( code, { nonce: options && options.nonce } );
},
each: function( obj, callback ) {
@@ -473,37 +478,6 @@ jQuery.extend( {
// A global GUID counter for objects
guid: 1,
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var tmp, args, proxy;
-
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- args = slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
- return proxy;
- },
-
- now: Date.now,
-
// jQuery.support is not used in Core but other projects attach their
// properties to it so it needs to exist.
support: support
@@ -526,9 +500,9 @@ function isArrayLike( obj ) {
// hasOwn isn't used here due to false negatives
// regarding Nodelist length in IE
var length = !!obj && "length" in obj && obj.length,
- type = jQuery.type( obj );
+ type = toType( obj );
- if ( type === "function" || jQuery.isWindow( obj ) ) {
+ if ( isFunction( obj ) || isWindow( obj ) ) {
return false;
}
@@ -537,14 +511,14 @@ function isArrayLike( obj ) {
}
var Sizzle =
/*!
- * Sizzle CSS Selector Engine v2.3.3
+ * Sizzle CSS Selector Engine v2.3.4
* https://sizzlejs.com/
*
- * Copyright jQuery Foundation and other contributors
+ * Copyright JS Foundation and other contributors
* Released under the MIT license
- * http://jquery.org/license
+ * https://js.foundation/
*
- * Date: 2016-08-08
+ * Date: 2019-04-08
*/
(function( window ) {
@@ -578,6 +552,7 @@ var i,
classCache = createCache(),
tokenCache = createCache(),
compilerCache = createCache(),
+ nonnativeSelectorCache = createCache(),
sortOrder = function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
@@ -639,8 +614,7 @@ var i,
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
-
- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+ rdescend = new RegExp( whitespace + "|>" ),
rpseudo = new RegExp( pseudos ),
ridentifier = new RegExp( "^" + identifier + "$" ),
@@ -661,6 +635,7 @@ var i,
whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
},
+ rhtml = /HTML$/i,
rinputs = /^(?:input|select|textarea|button)$/i,
rheader = /^h\d$/i,
@@ -715,9 +690,9 @@ var i,
setDocument();
},
- disabledAncestor = addCombinator(
+ inDisabledFieldset = addCombinator(
function( elem ) {
- return elem.disabled === true && ("form" in elem || "label" in elem);
+ return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
},
{ dir: "parentNode", next: "legend" }
);
@@ -830,18 +805,22 @@ function Sizzle( selector, context, results, seed ) {
// Take advantage of querySelectorAll
if ( support.qsa &&
- !compilerCache[ selector + " " ] &&
- (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
-
- if ( nodeType !== 1 ) {
- newContext = context;
- newSelector = selector;
+ !nonnativeSelectorCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) &&
- // qSA looks outside Element context, which is not what we want
- // Thanks to Andrew Dupont for this workaround technique
- // Support: IE <=8
+ // Support: IE 8 only
// Exclude object elements
- } else if ( context.nodeName.toLowerCase() !== "object" ) {
+ (nodeType !== 1 || context.nodeName.toLowerCase() !== "object") ) {
+
+ newSelector = selector;
+ newContext = context;
+
+ // qSA considers elements outside a scoping root when evaluating child or
+ // descendant combinators, which is not what we want.
+ // In such cases, we work around the behavior by prefixing every selector in the
+ // list with an ID selector referencing the scope context.
+ // Thanks to Andrew Dupont for this technique.
+ if ( nodeType === 1 && rdescend.test( selector ) ) {
// Capture the context ID, setting it first if necessary
if ( (nid = context.getAttribute( "id" )) ) {
@@ -863,17 +842,16 @@ function Sizzle( selector, context, results, seed ) {
context;
}
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch ( qsaError ) {
- } finally {
- if ( nid === expando ) {
- context.removeAttribute( "id" );
- }
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ nonnativeSelectorCache( selector, true );
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
}
}
}
@@ -1037,7 +1015,7 @@ function createDisabledPseudo( disabled ) {
// Where there is no isDisabled, check manually
/* jshint -W018 */
elem.isDisabled !== !disabled &&
- disabledAncestor( elem ) === disabled;
+ inDisabledFieldset( elem ) === disabled;
}
return elem.disabled === disabled;
@@ -1094,10 +1072,13 @@ support = Sizzle.support = {};
* @returns {Boolean} True iff elem is a non-HTML XML node
*/
isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
+ var namespace = elem.namespaceURI,
+ docElem = (elem.ownerDocument || elem).documentElement;
+
+ // Support: IE <=8
+ // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
+ // https://bugs.jquery.com/ticket/4833
+ return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
};
/**
@@ -1519,11 +1500,8 @@ Sizzle.matchesSelector = function( elem, expr ) {
setDocument( elem );
}
- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
-
if ( support.matchesSelector && documentIsHTML &&
- !compilerCache[ expr + " " ] &&
+ !nonnativeSelectorCache[ expr + " " ] &&
( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
@@ -1537,7 +1515,9 @@ Sizzle.matchesSelector = function( elem, expr ) {
elem.document && elem.document.nodeType !== 11 ) {
return ret;
}
- } catch (e) {}
+ } catch (e) {
+ nonnativeSelectorCache( expr, true );
+ }
}
return Sizzle( expr, document, null, [ elem ] ).length > 0;
@@ -1996,7 +1976,7 @@ Expr = Sizzle.selectors = {
"contains": markFunction(function( text ) {
text = text.replace( runescape, funescape );
return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
};
}),
@@ -2135,7 +2115,11 @@ Expr = Sizzle.selectors = {
}),
"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
+ var i = argument < 0 ?
+ argument + length :
+ argument > length ?
+ length :
+ argument;
for ( ; --i >= 0; ) {
matchIndexes.push( i );
}
@@ -2848,11 +2832,9 @@ var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|
-var risSimple = /^.[^:#\[\.,]*$/;
-
// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
- if ( jQuery.isFunction( qualifier ) ) {
+ if ( isFunction( qualifier ) ) {
return jQuery.grep( elements, function( elem, i ) {
return !!qualifier.call( elem, i, elem ) !== not;
} );
@@ -2872,16 +2854,8 @@ function winnow( elements, qualifier, not ) {
} );
}
- // Simple selector that can be filtered directly, removing non-Elements
- if ( risSimple.test( qualifier ) ) {
- return jQuery.filter( qualifier, elements, not );
- }
-
- // Complex selector, compare the two sets, removing non-Elements
- qualifier = jQuery.filter( qualifier, elements );
- return jQuery.grep( elements, function( elem ) {
- return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
- } );
+ // Filtered directly for both simple and complex selectors
+ return jQuery.filter( qualifier, elements, not );
}
jQuery.filter = function( expr, elems, not ) {
@@ -3002,7 +2976,7 @@ var rootjQuery,
for ( match in context ) {
// Properties of context are called as methods if possible
- if ( jQuery.isFunction( this[ match ] ) ) {
+ if ( isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
// ...and otherwise set as attributes
@@ -3045,7 +3019,7 @@ var rootjQuery,
// HANDLE: $(function)
// Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
+ } else if ( isFunction( selector ) ) {
return root.ready !== undefined ?
root.ready( selector ) :
@@ -3195,18 +3169,18 @@ jQuery.each( {
return siblings( elem.firstChild );
},
contents: function( elem ) {
- if ( nodeName( elem, "iframe" ) ) {
- return elem.contentDocument;
- }
+ if ( typeof elem.contentDocument !== "undefined" ) {
+ return elem.contentDocument;
+ }
- // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
- // Treat the template element as a regular one in browsers that
- // don't support it.
- if ( nodeName( elem, "template" ) ) {
- elem = elem.content || elem;
- }
+ // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
+ // Treat the template element as a regular one in browsers that
+ // don't support it.
+ if ( nodeName( elem, "template" ) ) {
+ elem = elem.content || elem;
+ }
- return jQuery.merge( [], elem.childNodes );
+ return jQuery.merge( [], elem.childNodes );
}
}, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) {
@@ -3360,11 +3334,11 @@ jQuery.Callbacks = function( options ) {
( function add( args ) {
jQuery.each( args, function( _, arg ) {
- if ( jQuery.isFunction( arg ) ) {
+ if ( isFunction( arg ) ) {
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
- } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+ } else if ( arg && arg.length && toType( arg ) !== "string" ) {
// Inspect recursively
add( arg );
@@ -3479,11 +3453,11 @@ function adoptValue( value, resolve, reject, noValue ) {
try {
// Check for promise aspect first to privilege synchronous behavior
- if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
+ if ( value && isFunction( ( method = value.promise ) ) ) {
method.call( value ).done( resolve ).fail( reject );
// Other thenables
- } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
+ } else if ( value && isFunction( ( method = value.then ) ) ) {
method.call( value, resolve, reject );
// Other non-thenables
@@ -3541,14 +3515,14 @@ jQuery.extend( {
jQuery.each( tuples, function( i, tuple ) {
// Map tuples (progress, done, fail) to arguments (done, fail, progress)
- var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
+ var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
// deferred.progress(function() { bind to newDefer or newDefer.notify })
// deferred.done(function() { bind to newDefer or newDefer.resolve })
// deferred.fail(function() { bind to newDefer or newDefer.reject })
deferred[ tuple[ 1 ] ]( function() {
var returned = fn && fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
+ if ( returned && isFunction( returned.promise ) ) {
returned.promise()
.progress( newDefer.notify )
.done( newDefer.resolve )
@@ -3602,7 +3576,7 @@ jQuery.extend( {
returned.then;
// Handle a returned thenable
- if ( jQuery.isFunction( then ) ) {
+ if ( isFunction( then ) ) {
// Special processors (notify) just wait for resolution
if ( special ) {
@@ -3698,7 +3672,7 @@ jQuery.extend( {
resolve(
0,
newDefer,
- jQuery.isFunction( onProgress ) ?
+ isFunction( onProgress ) ?
onProgress :
Identity,
newDefer.notifyWith
@@ -3710,7 +3684,7 @@ jQuery.extend( {
resolve(
0,
newDefer,
- jQuery.isFunction( onFulfilled ) ?
+ isFunction( onFulfilled ) ?
onFulfilled :
Identity
)
@@ -3721,7 +3695,7 @@ jQuery.extend( {
resolve(
0,
newDefer,
- jQuery.isFunction( onRejected ) ?
+ isFunction( onRejected ) ?
onRejected :
Thrower
)
@@ -3761,8 +3735,15 @@ jQuery.extend( {
// fulfilled_callbacks.disable
tuples[ 3 - i ][ 2 ].disable,
+ // rejected_handlers.disable
+ // fulfilled_handlers.disable
+ tuples[ 3 - i ][ 3 ].disable,
+
// progress_callbacks.lock
- tuples[ 0 ][ 2 ].lock
+ tuples[ 0 ][ 2 ].lock,
+
+ // progress_handlers.lock
+ tuples[ 0 ][ 3 ].lock
);
}
@@ -3832,7 +3813,7 @@ jQuery.extend( {
// Use .then() to unwrap secondary thenables (cf. gh-3000)
if ( master.state() === "pending" ||
- jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
+ isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
return master.then();
}
@@ -3960,7 +3941,7 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
bulk = key == null;
// Sets many values
- if ( jQuery.type( key ) === "object" ) {
+ if ( toType( key ) === "object" ) {
chainable = true;
for ( i in key ) {
access( elems, fn, i, key[ i ], true, emptyGet, raw );
@@ -3970,7 +3951,7 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
} else if ( value !== undefined ) {
chainable = true;
- if ( !jQuery.isFunction( value ) ) {
+ if ( !isFunction( value ) ) {
raw = true;
}
@@ -4012,6 +3993,23 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
return len ? fn( elems[ 0 ], key ) : emptyGet;
};
+
+
+// Matches dashed string for camelizing
+var rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([a-z])/g;
+
+// Used by camelCase as callback to replace()
+function fcamelCase( all, letter ) {
+ return letter.toUpperCase();
+}
+
+// Convert dashed to camelCase; used by the css and data modules
+// Support: IE <=9 - 11, Edge 12 - 15
+// Microsoft forgot to hump their vendor prefix (#9572)
+function camelCase( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+}
var acceptData = function( owner ) {
// Accepts only:
@@ -4074,14 +4072,14 @@ Data.prototype = {
// Handle: [ owner, key, value ] args
// Always use camelCase key (gh-2257)
if ( typeof data === "string" ) {
- cache[ jQuery.camelCase( data ) ] = value;
+ cache[ camelCase( data ) ] = value;
// Handle: [ owner, { properties } ] args
} else {
// Copy the properties one-by-one to the cache object
for ( prop in data ) {
- cache[ jQuery.camelCase( prop ) ] = data[ prop ];
+ cache[ camelCase( prop ) ] = data[ prop ];
}
}
return cache;
@@ -4091,7 +4089,7 @@ Data.prototype = {
this.cache( owner ) :
// Always use camelCase key (gh-2257)
- owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
+ owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
},
access: function( owner, key, value ) {
@@ -4139,9 +4137,9 @@ Data.prototype = {
// If key is an array of keys...
// We always set camelCase keys, so remove that.
- key = key.map( jQuery.camelCase );
+ key = key.map( camelCase );
} else {
- key = jQuery.camelCase( key );
+ key = camelCase( key );
// If a key with the spaces exists, use it.
// Otherwise, create an array by matching non-whitespace
@@ -4287,7 +4285,7 @@ jQuery.fn.extend( {
if ( attrs[ i ] ) {
name = attrs[ i ].name;
if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice( 5 ) );
+ name = camelCase( name.slice( 5 ) );
dataAttr( elem, name, data[ name ] );
}
}
@@ -4491,6 +4489,26 @@ var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+var documentElement = document.documentElement;
+
+
+
+ var isAttached = function( elem ) {
+ return jQuery.contains( elem.ownerDocument, elem );
+ },
+ composed = { composed: true };
+
+ // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
+ // Check attachment across shadow DOM boundaries when possible (gh-3504)
+ // Support: iOS 10.0-10.2 only
+ // Early iOS 10 versions support `attachShadow` but not `getRootNode`,
+ // leading to errors. We need to check for `getRootNode`.
+ if ( documentElement.getRootNode ) {
+ isAttached = function( elem ) {
+ return jQuery.contains( elem.ownerDocument, elem ) ||
+ elem.getRootNode( composed ) === elem.ownerDocument;
+ };
+ }
var isHiddenWithinTree = function( elem, el ) {
// isHiddenWithinTree might be called from jQuery#filter function;
@@ -4505,7 +4523,7 @@ var isHiddenWithinTree = function( elem, el ) {
// Support: Firefox <=43 - 45
// Disconnected elements can have computed display: none, so first confirm that elem is
// in the document.
- jQuery.contains( elem.ownerDocument, elem ) &&
+ isAttached( elem ) &&
jQuery.css( elem, "display" ) === "none";
};
@@ -4534,8 +4552,7 @@ var swap = function( elem, options, callback, args ) {
function adjustCSS( elem, prop, valueParts, tween ) {
- var adjusted,
- scale = 1,
+ var adjusted, scale,
maxIterations = 20,
currentValue = tween ?
function() {
@@ -4548,35 +4565,39 @@ function adjustCSS( elem, prop, valueParts, tween ) {
unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
// Starting value computation is required for potential unit mismatches
- initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ initialInUnit = elem.nodeType &&
+ ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
rcssNum.exec( jQuery.css( elem, prop ) );
if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+ // Support: Firefox <=54
+ // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
+ initial = initial / 2;
+
// Trust units reported by jQuery.css
unit = unit || initialInUnit[ 3 ];
- // Make sure we update the tween properties later on
- valueParts = valueParts || [];
-
// Iteratively approximate from a nonzero starting point
initialInUnit = +initial || 1;
- do {
-
- // If previous iteration zeroed out, double until we get *something*.
- // Use string for doubling so we don't accidentally see scale as unchanged below
- scale = scale || ".5";
+ while ( maxIterations-- ) {
- // Adjust and apply
- initialInUnit = initialInUnit / scale;
+ // Evaluate and update our best guess (doubling guesses that zero out).
+ // Finish if the scale equals or crosses 1 (making the old*new product non-positive).
jQuery.style( elem, prop, initialInUnit + unit );
+ if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
+ maxIterations = 0;
+ }
+ initialInUnit = initialInUnit / scale;
- // Update scale, tolerating zero or NaN from tween.cur()
- // Break the loop if scale is unchanged or perfect, or if we've just had enough.
- } while (
- scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
- );
+ }
+
+ initialInUnit = initialInUnit * 2;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
}
if ( valueParts ) {
@@ -4692,9 +4713,9 @@ jQuery.fn.extend( {
} );
var rcheckableType = ( /^(?:checkbox|radio)$/i );
-var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
+var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
-var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
@@ -4764,7 +4785,7 @@ function setGlobalEval( elems, refElements ) {
var rhtml = /<|?\w+;/;
function buildFragment( elems, context, scripts, selection, ignored ) {
- var elem, tmp, tag, wrap, contains, j,
+ var elem, tmp, tag, wrap, attached, j,
fragment = context.createDocumentFragment(),
nodes = [],
i = 0,
@@ -4776,7 +4797,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) {
if ( elem || elem === 0 ) {
// Add nodes directly
- if ( jQuery.type( elem ) === "object" ) {
+ if ( toType( elem ) === "object" ) {
// Support: Android <=4.0 only, PhantomJS 1 only
// push.apply(_, arraylike) throws on ancient WebKit
@@ -4828,13 +4849,13 @@ function buildFragment( elems, context, scripts, selection, ignored ) {
continue;
}
- contains = jQuery.contains( elem.ownerDocument, elem );
+ attached = isAttached( elem );
// Append to fragment
tmp = getAll( fragment.appendChild( elem ), "script" );
// Preserve script evaluation history
- if ( contains ) {
+ if ( attached ) {
setGlobalEval( tmp );
}
@@ -4877,8 +4898,6 @@ function buildFragment( elems, context, scripts, selection, ignored ) {
div.innerHTML = "";
support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
} )();
-var documentElement = document.documentElement;
-
var
@@ -4894,8 +4913,19 @@ function returnFalse() {
return false;
}
+// Support: IE <=9 - 11+
+// focus() and blur() are asynchronous, except when they are no-op.
+// So expect focus to be synchronous when the element is already active,
+// and blur to be synchronous when the element is not already active.
+// (focus and blur are always synchronous in other supported browsers,
+// this just defines when we can count on it).
+function expectSync( elem, type ) {
+ return ( elem === safeActiveElement() ) === ( type === "focus" );
+}
+
// Support: IE <=9 only
-// See #13393 for more info
+// Accessing document.activeElement can throw unexpectedly
+// https://bugs.jquery.com/ticket/13393
function safeActiveElement() {
try {
return document.activeElement;
@@ -5195,9 +5225,10 @@ jQuery.event = {
while ( ( handleObj = matched.handlers[ j++ ] ) &&
!event.isImmediatePropagationStopped() ) {
- // Triggered event must either 1) have no namespace, or 2) have namespace(s)
- // a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+ // If the event is namespaced, then each handler is only invoked if it is
+ // specially universal or its namespaces are a superset of the event's.
+ if ( !event.rnamespace || handleObj.namespace === false ||
+ event.rnamespace.test( handleObj.namespace ) ) {
event.handleObj = handleObj;
event.data = handleObj.data;
@@ -5286,7 +5317,7 @@ jQuery.event = {
enumerable: true,
configurable: true,
- get: jQuery.isFunction( hook ) ?
+ get: isFunction( hook ) ?
function() {
if ( this.originalEvent ) {
return hook( this.originalEvent );
@@ -5321,39 +5352,51 @@ jQuery.event = {
// Prevent triggered image.load events from bubbling to window.load
noBubble: true
},
- focus: {
+ click: {
- // Fire native event if possible so blur/focus sequence is correct
- trigger: function() {
- if ( this !== safeActiveElement() && this.focus ) {
- this.focus();
- return false;
- }
- },
- delegateType: "focusin"
- },
- blur: {
- trigger: function() {
- if ( this === safeActiveElement() && this.blur ) {
- this.blur();
- return false;
+ // Utilize native event to ensure correct state for checkable inputs
+ setup: function( data ) {
+
+ // For mutual compressibility with _default, replace `this` access with a local var.
+ // `|| data` is dead code meant only to preserve the variable through minification.
+ var el = this || data;
+
+ // Claim the first handler
+ if ( rcheckableType.test( el.type ) &&
+ el.click && nodeName( el, "input" ) ) {
+
+ // dataPriv.set( el, "click", ... )
+ leverageNative( el, "click", returnTrue );
}
+
+ // Return false to allow normal processing in the caller
+ return false;
},
- delegateType: "focusout"
- },
- click: {
+ trigger: function( data ) {
- // For checkbox, fire native event so checked state will be right
- trigger: function() {
- if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
- this.click();
- return false;
+ // For mutual compressibility with _default, replace `this` access with a local var.
+ // `|| data` is dead code meant only to preserve the variable through minification.
+ var el = this || data;
+
+ // Force setup before triggering a click
+ if ( rcheckableType.test( el.type ) &&
+ el.click && nodeName( el, "input" ) ) {
+
+ leverageNative( el, "click" );
}
+
+ // Return non-false to allow normal event-path propagation
+ return true;
},
- // For cross-browser consistency, don't fire native .click() on links
+ // For cross-browser consistency, suppress native .click() on links
+ // Also prevent it if we're currently inside a leveraged native-event stack
_default: function( event ) {
- return nodeName( event.target, "a" );
+ var target = event.target;
+ return rcheckableType.test( target.type ) &&
+ target.click && nodeName( target, "input" ) &&
+ dataPriv.get( target, "click" ) ||
+ nodeName( target, "a" );
}
},
@@ -5370,6 +5413,93 @@ jQuery.event = {
}
};
+// Ensure the presence of an event listener that handles manually-triggered
+// synthetic events by interrupting progress until reinvoked in response to
+// *native* events that it fires directly, ensuring that state changes have
+// already occurred before other listeners are invoked.
+function leverageNative( el, type, expectSync ) {
+
+ // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
+ if ( !expectSync ) {
+ if ( dataPriv.get( el, type ) === undefined ) {
+ jQuery.event.add( el, type, returnTrue );
+ }
+ return;
+ }
+
+ // Register the controller as a special universal handler for all event namespaces
+ dataPriv.set( el, type, false );
+ jQuery.event.add( el, type, {
+ namespace: false,
+ handler: function( event ) {
+ var notAsync, result,
+ saved = dataPriv.get( this, type );
+
+ if ( ( event.isTrigger & 1 ) && this[ type ] ) {
+
+ // Interrupt processing of the outer synthetic .trigger()ed event
+ // Saved data should be false in such cases, but might be a leftover capture object
+ // from an async native handler (gh-4350)
+ if ( !saved.length ) {
+
+ // Store arguments for use when handling the inner native event
+ // There will always be at least one argument (an event object), so this array
+ // will not be confused with a leftover capture object.
+ saved = slice.call( arguments );
+ dataPriv.set( this, type, saved );
+
+ // Trigger the native event and capture its result
+ // Support: IE <=9 - 11+
+ // focus() and blur() are asynchronous
+ notAsync = expectSync( this, type );
+ this[ type ]();
+ result = dataPriv.get( this, type );
+ if ( saved !== result || notAsync ) {
+ dataPriv.set( this, type, false );
+ } else {
+ result = {};
+ }
+ if ( saved !== result ) {
+
+ // Cancel the outer synthetic event
+ event.stopImmediatePropagation();
+ event.preventDefault();
+ return result.value;
+ }
+
+ // If this is an inner synthetic event for an event with a bubbling surrogate
+ // (focus or blur), assume that the surrogate already propagated from triggering the
+ // native event and prevent that from happening again here.
+ // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
+ // bubbling surrogate propagates *after* the non-bubbling base), but that seems
+ // less bad than duplication.
+ } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
+ event.stopPropagation();
+ }
+
+ // If this is a native event triggered above, everything is now in order
+ // Fire an inner synthetic event with the original arguments
+ } else if ( saved.length ) {
+
+ // ...and capture the result
+ dataPriv.set( this, type, {
+ value: jQuery.event.trigger(
+
+ // Support: IE <=9 - 11+
+ // Extend with the prototype to reset the above stopImmediatePropagation()
+ jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
+ saved.slice( 1 ),
+ this
+ )
+ } );
+
+ // Abort handling of the native event
+ event.stopImmediatePropagation();
+ }
+ }
+ } );
+}
+
jQuery.removeEvent = function( elem, type, handle ) {
// This "if" is needed for plain objects
@@ -5421,7 +5551,7 @@ jQuery.Event = function( src, props ) {
}
// Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
+ this.timeStamp = src && src.timeStamp || Date.now();
// Mark it as fixed
this[ jQuery.expando ] = true;
@@ -5482,6 +5612,7 @@ jQuery.each( {
shiftKey: true,
view: true,
"char": true,
+ code: true,
charCode: true,
key: true,
keyCode: true,
@@ -5528,6 +5659,33 @@ jQuery.each( {
}
}, jQuery.event.addProp );
+jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
+ jQuery.event.special[ type ] = {
+
+ // Utilize native event if possible so blur/focus sequence is correct
+ setup: function() {
+
+ // Claim the first handler
+ // dataPriv.set( this, "focus", ... )
+ // dataPriv.set( this, "blur", ... )
+ leverageNative( this, type, expectSync );
+
+ // Return false to allow normal processing in the caller
+ return false;
+ },
+ trigger: function() {
+
+ // Force setup before trigger
+ leverageNative( this, type );
+
+ // Return non-false to allow normal event-path propagation
+ return true;
+ },
+
+ delegateType: delegateType
+ };
+} );
+
// Create mouseenter/leave events using mouseover/out and event-time checks
// so that event delegation works in jQuery.
// Do the same for pointerenter/pointerleave and pointerover/pointerout
@@ -5620,14 +5778,13 @@ var
/* eslint-enable */
- // Support: IE <=10 - 11, Edge 12 - 13
+ // Support: IE <=10 - 11, Edge 12 - 13 only
// In IE/Edge using regex groups here causes severe slowdowns.
// See https://connect.microsoft.com/IE/feedback/details/1736512/
rnoInnerhtml = /
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Base Classes
-
-
AHF_Base.py
-
The base upon which everything else is built
-
-
-class AHF_Base( taskP , settingsDictP )
-Defines conventions for classes used for accesing hardware and doing subtasks in AutoHeadFix code
-Each class has a static method, config_user_get, to create or edit a settings dictionary, and will be inititialized
-with a settings dictionary. The setup function does hardware initialization, or other inititialization.
-
-
-abstract static about( )
-Returns a brief message describing your sub-class, used when asking user to pick a sub-class of this class
-
-
-
-
-config_subject_get( starterDict={} )
-
-Returns
-dict – the default dictionary for individualized parameters
-
-
-
-
-
-
-abstract static config_user_get( starterDict={} )
-static method that querries user for settings, with default responses from starterDict,
-and returns starterDict with settings as edited by the user.
-
-
-
-
-config_user_subject_get( starterDict={} )
-Prompts the user for individualized parameters, with default responses
-from starterDict, and returns starterDict with settings
-as edited by the user.
-
-
-
-
-abstract hardwareTest( )
-Tests functionality, gives user a chance to change settings.
-:Returns: bool – True if any settings have changed
-
-
-
-
-abstract setdown( )
-oppposite of setup. Releases any hardware resouces. can be run before editing settings so GPIO
-pins can be reused, for example. This strategy should be used in hardwareTest method.
-
-
-
-
-abstract setup( )
-does hardware initialization with(possibly updated) info in self.settingsDict
-Run by __init__, or can be run separately after editing the settingsDict
-
-Returns
-bool – the truth that setup completed without errors
-
-
-
-
-
-
-
-
We copy all variables from cage settings and exp settings, plus references to all created objects,
-into a single object called Task
-
-
-
-
-
-
-
-
-
-
-
-
-