User-defined task #9 (Lever)
This chapter shows how to modify task 92 to create a new task using lever modules as task 93. In the new task, left and right lever are inserted and the subject can get water reward when it touches the correct side. The correct position is fixed throughout the session. To add the task 93, create the task button in the main window as you did in
Chapter #7 and copy and paste main code of task 92() as task 93().
def Task93(): # Test task 4
global Phase
Phase0_Init = 0
Phase1_Init = 0
Phase2_Init = 0
while EndFlag == 0:
OperantHouseUpdate() # Run house keeping function (This must be executedonce per frame)
if GetBackButtonStat()==1: # If "Back" button is clicked
break # Back to the task select phase
if Phase == 0: # Parameter inputs
if Phase0_Init == 0: # Make GUI for the setting of the parameters for thistask
RemoveMainRightWidget() # Remove task buttons
PutStartBackButton() # Put "start" and "back" buttons
ColumnWidth = 14 # Width of input columns
Row = 0
Column = 0
mMaxCorrectNum = ttk.Label(MainWindowRightFrame, text='MaxCorrectNum', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) #Put label
MaxCorrectNumVar = IntVar(MainWindowRoot) # Declare a variable forinput column
iMaxCorrectNum = ttk.Entry(MainWindowRightFrame, textvariable=MaxCorrectNumVar, width=ColumnWidth).grid(row=Row + 1, column=Column) #Create input column and link it with the variable
Column += 1
mMaxTrialNum = ttk.Label(MainWindowRightFrame, text='MaxTrialNum',width=ColumnWidth).grid(row=Row, column=Column, sticky=W)
MaxTrialNumVar = IntVar(MainWindowRoot) # Declare a variable for inputcolumn
iMaxTrialNum = ttk.Entry(MainWindowRightFrame, textvariable=MaxTrialNumVar, width=ColumnWidth).grid(row=Row + 1, column=Column)
Column += 1
mTimeLimit = ttk.Label(MainWindowRightFrame, text='TimeLimit(min)',width=ColumnWidth).grid(row=Row, column=Column, sticky=W)
TimeLimitVar = IntVar(MainWindowRoot)
iTimeLimit = ttk.Entry(MainWindowRightFrame, textvariable=TimeLimitVar,width=ColumnWidth).grid(row=Row + 1, column=Column)
Column += 1
mPunishDur = ttk.Label(MainWindowRightFrame, text='PunishDur(s)', width=ColumnWidth).grid(row=Row, column=Column, sticky=W)
PunishDurVar = IntVar(MainWindowRoot)
iPunishDur = ttk.Entry(MainWindowRightFrame, textvariable=PunishDurVar, width=ColumnWidth).grid(row=Row + 1, column=Column)
Column += 1
mLickDur = ttk.Label(MainWindowRightFrame, text='LickDur(s)', width=ColumnWidth).grid(row=Row, column=Column, sticky=W)
LickDurVar = IntVar(MainWindowRoot)
iLickDur = ttk.Entry(MainWindowRightFrame, textvariable=LickDurVar, width=ColumnWidth).grid(row=Row + 1, column=Column)
Column += 1
mNextTask = ttk.Label(MainWindowRightFrame, text='NextTask#', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # The task number indicatedhere will be the next task if the correct rate exceeds "NextTaskTh"
NextTaskVar = IntVar(MainWindowRoot)
iNextTask = ttk.Entry(MainWindowRightFrame, textvariable=NextTaskVar,width=ColumnWidth).grid(row=Row + 1, column=Column)
Column += 1
mNextTaskTh = ttk.Label(MainWindowRightFrame, text='NextTaskTh%',width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # Correct ratethreshold to switch to the next task
NextTaskThVar = IntVar(MainWindowRoot)
iNextTaskTh = ttk.Entry(MainWindowRightFrame, textvariable=NextTaskThVar, width=ColumnWidth).grid(row=Row + 1, column=Column)
Row += 2 # Begin a new line
Column = 0
mPanelType = ttk.Label(MainWindowRightFrame, text='PanelType', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # Type of panel, Normal:white rectangle panel, Blink: white rectangle bilnking panel, Textured: User customimage (Can be upload at "MainWindow -> Setting -> Panel* texture")
PanelTypeVar = StringVar(MainWindowRightFrame)
tPanelType = OptionMenu(MainWindowRightFrame, PanelTypeVar, "Normal", "Blink", "Textured").grid(row=Row + 1, column=Column, sticky=W)
mCorrectPos = ttk.Label(MainWindowRightFrame, text='CorrectPos', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # Position of correct lever
CorrectPosVar = StringVar(MainWindowRightFrame)
tCorrectPos = OptionMenu(MainWindowRightFrame, CorrectPosVar, "Left", "Right").grid(row=Row + 1, column=Column, sticky=W)
Create a option menu to indicate which lever is assigned as correct.
Column += 1
mWaterCueType = ttk.Label(MainWindowRightFrame, text='WaterCueType', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # If chose blink,reward cue will blink
WaterCueTypeVar = StringVar(MainWindowRightFrame)
tWaterCueType = OptionMenu(MainWindowRightFrame, WaterCueTypeVar,"Normal", "Blink").grid(row=Row + 1, column=Column, sticky=W)
Column += 1
mAwsOn = ttk.Label(MainWindowRightFrame, text='AWS', width=ColumnWidth).grid(row=Row, column=Column, sticky=W) # If ON, complemental watersupply is applied after end of each session
AwsOnVar = StringVar(MainWindowRoot)
tAwsOn = OptionMenu(MainWindowRightFrame, AwsOnVar, "ON", "OFF").grid(row=Row + 1, column=Column, sticky=W)
Str = "ParametersForTask" + str(GetTaskID())
if os.path.exists(Str + '/MaxCorrectNum.dat') == True: # If save filenamed "MaxCorrectNum.dat" exist:
with open(Str + '/MaxCorrectNum.dat', 'rb') as PickleInst[GetTaskID()]:
MaxCorrectNumVar.set(pickle.load(PickleInst[GetTaskID()])) #Assign loaded data into the variable of this program
else: # If save file doesn't exist
MaxCorrectNumVar.set(80) # Assign 80 into the variable
if os.path.exists(Str + '/MaxTrialNum.dat') == True:
with open(Str + '/MaxTrialNum.dat', 'rb') as PickleInst[GetTaskID()]:
MaxTrialNumVar.set(pickle.load(PickleInst[GetTaskID()]))
else:
MaxTrialNumVar.set(110)
if os.path.exists(Str + '/TimeLimit.dat') == True:
with open(Str + '/TimeLimit.dat', 'rb') as PickleInst[GetTaskID()]:
TimeLimitVar.set(pickle.load(PickleInst[GetTaskID()]))
else:
TimeLimitVar.set(600)
if os.path.exists(Str + '/PunishDur.dat') == True:
with open(Str + '/PunishDur.dat', 'rb') as PickleInst[GetTaskID()]:
PunishDurVar.set(pickle.load(PickleInst[GetTaskID()]))
else:
PunishDurVar.set(10)
if os.path.exists(Str + '/LickDur.dat') == True:
with open(Str + '/LickDur.dat', 'rb') as PickleInst[GetTaskID()]:
LickDurVar.set(pickle.load(PickleInst[GetTaskID()]))
else:
LickDurVar.set(2)
if os.path.exists(Str + '/NextTask.dat') == True:
with open(Str + '/NextTask.dat', 'rb') as PickleInst[GetTaskID()]:
NextTaskVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
NextTaskVar.set(93) # Default value
if os.path.exists(Str + '/NextTaskTh.dat') == True:
with open(Str + '/NextTaskTh.dat', 'rb') as PickleInst[GetTaskID()]:
NextTaskThVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
NextTaskThVar.set(80) # Default value
if os.path.exists(Str + '/PanelType.dat') == True:
with open(Str + '/PanelType.dat', 'rb') as PickleInst[GetTaskID()]:
PanelTypeVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
PanelTypeVar.set('Blink') # Default value
if os.path.exists(Str + '/CorrectPos.dat') == True:
with open(Str + '/CorrectPos.dat', 'rb') as PickleInst[GetTaskID()]:
CorrectPosVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
CorrectPosVar.set('Left') # Default value
if os.path.exists(Str + '/WaterCueType.dat') == True:
with open(Str + '/WaterCueType.dat', 'rb') as PickleInst[GetTaskID()]:
WaterCueTypeVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
WaterCueTypeVar.set('Blink') # Default value
if os.path.exists(Str + '/AwsOn.dat') == True:
with open(Str + '/AwsOn.dat', 'rb') as PickleInst[GetTaskID()]:
AwsOnVar.set(pickle.load(PickleInst[GetTaskID()])) # Load
else:
AwsOnVar.set('ON') # Default value
PutRoiGui(0, 1, 1, 0) # Put setting GUI of the indicated ROI on ROIwindow (ROI number, Detection mode, Threshold direction, ShowSymbol or not)
PutRoiGui(1, 1, 1, 0)
Delete the ROIs for panel touch detection.
PutRoiGui(19, 0, 0, 1) # Put setting GUI of the indicated ROI on ROIwindow (ROI number, Detection mode, Threshold direction, ShowSymbol or not)
RemoveAllDigitalOutGui() # Remove all GUIs on the Digital out window
PutDigitalOutGui(10) # Put the digital output GUI for channel 10 onDigital ouput window
PutDigitalOutGui(12)
PutDigitalOutGui(13)
DigitalInOn(7) # Set the indicated channel as Digital input channel(Receive input from the lever module)
DigitalInOn(8)
Make the Ch7/8 to the "input mode" because the program detects the lever pressby checking whether Ch7 or 8 which are connected to levers is grounded.
RemoveAllServoGui() # Remove all GUI on the Servo GUI
PutServoGui(3) # Put a servo GUI for channel 3 on the Servo GUI
PutServoGui(5)
PutServoGui(6)
Add GUIs for the servos that insert and retract levers to the Servo GUI window.
Phase0_Init = 1 # Set a flag which indicating phase0 initialization has done
if GetSaveTrgStat() == 1: # If save trigger is activated
# Parameters will be saved into a folder named "ParametersForTask90"
Str="ParametersForTask"+str(GetTaskID()) # Assign save folder path
if os.path.exists(Str) == False: # If save folder doesn't exist
os.mkdir(Str) # Create the folder
with open(Str+'/MaxCorrectNum.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(MaxCorrectNumVar.get(),PickleInst[GetTaskID()]) # Save avalue of "MaxCorrectNumVar" as "MaxCorrectNum.dat" file
with open(Str+'/MaxTrialNum.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(MaxTrialNumVar.get(),PickleInst[GetTaskID()])
with open(Str+'/TimeLimit.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(TimeLimitVar.get(),PickleInst[GetTaskID()])
with open(Str+'/PunishDur.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(PunishDurVar.get(), PickleInst[GetTaskID()])
with open(Str+'/LickDur.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(LickDurVar.get(), PickleInst[GetTaskID()])
with open(Str + '/NextTask.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(NextTaskVar.get(), PickleInst[GetTaskID()])
with open(Str+'/NextTaskTh.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(NextTaskThVar.get(), PickleInst[GetTaskID()])
with open(Str+'/PanelType.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(PanelTypeVar.get(), PickleInst[GetTaskID()])
with open(Str+'/CorrectPos.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(CorrectPosVar.get(), PickleInst[GetTaskID()])
with open(Str+'/WaterCueType.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(WaterCueTypeVar.get(), PickleInst[GetTaskID()])
with open(Str+'/AwsOn.dat', 'wb') as PickleInst[GetTaskID()]:
pickle.dump(AwsOnVar.get(), PickleInst[GetTaskID()])
if Phase == 1: # Waiting phase (Task will start when the set time arrives)
if Phase1_Init == 0: # If the initialization for phase1 has not done
PutPreTaskButton() # Put "StartNow" and "Back" button on Main window
mStatusVar = StringVar(MainWindowRoot) # Create a variable for statusdisplay
mStatus = ttk.Label(MainWindowRightFrame, textvariable=mStatusVar) #Create label object and link it with Main window
mStatus.place(x=10, y=0) # Place label object on the Main window
mOngoingResultVar = StringVar(MainWindowRoot) # Create a variable forprogress display
Phase1_Init = 1 # Flat that phase1 has done
mStatusVar.set('Test4 task(' + str(GetTaskID()) + ') Waiting...') # Showcurrent status of the Operant House
if IsStartTime() == 1: # Check whether task start time arrives
StartNow() # Start task (Phase number will be "2")
if Phase == 2: # If it is during task
if Phase2_Init == 0: # Initialization of the task
PutEndTaskNowButton() # Put "TaskEnd" button on Main window
mStatusVar.set('Test4 task(' + str(GetTaskID()) + ') Start time ' + str(TaskStartedMonth) + '/' + str(TaskStartedDay) + ' ' + str(TaskStartedHour) + ':' + str(TaskStartedMinute) + ' Running') # Assign latest information about current taskinto "mStatusVar"
mOngoingResult = ttk.Label(MainWindowRightFrame, textvariable=mOngoingResultVar)
mOngoingResult.place(x=10, y=18)
# Assign task parameter values in StringVars into integer or stringvariable (to make the cord easeir to read)
MaxCorrectNum = int(MaxCorrectNumVar.get()) # Get the value of "MaxCorrectNumVar" and convert it from string to integer and assign into variablenamed "MaxCorrectNum"
MaxTrialNum = int(MaxTrialNumVar.get())
TimeLimit = int(TimeLimitVar.get())
PunishDur = int(PunishDurVar.get())
LickDur = int(LickDurVar.get())
NextTask = int(NextTaskVar.get())
NextTaskTh = int(NextTaskThVar.get())
PanelType = PanelTypeVar.get()
CorrectPos = CorrectPosVar.get()
WaterCueType = WaterCueTypeVar.get()
AwsOn = AwsOnVar.get()
# Declar local variables for this task
TrialNum = 0 # Current trial number
CorrectNum = 0 # Current correct trial number
IncorrectNum = 0 # Current incorrect trial number
CorrectRate = 0.0 # Current correct rate
TaskDur = 0 # This will keep the elapsed time during of task
NowDrinking = 0 # Use as trigger
CorrectPanelID = 0 # ID number of current correct panel (0 or 1)
AWS_Latency = 20 # Latency to start AWS (sec)
StartRecording() # Start camera capture / TTL signal output
StartLickRecording() # Start an entry of lick log
LightCycleControlOff() # Deactivate automatic Light/Dark cycleillumination
RoofLightOff() # Turn off the lights on roof (Digital output Ch13)
InfraredLightOn() # Turn on the infrared LED illumination (Digital outputCh12)
if WaterCueType == 'Normal':
DigitalOutOn(10) # Turn on cue LED connected to Ch10
if WaterCueType == 'Blink':
DigitalOutBlinkOn(10) # Start blinking of cue LED connected to Ch10
ServoPosInside(3) # Change the angle of water arm servo connected toCh3 to inside position
if PanelType == 'Normal':
CreateNormalPanel(0) # Create a white-filled square panel as panel #0
CreateNormalPanel(1)
if PanelType == 'Blink':
CreateBlinkPanel(0) # Create a white-filled square blinking panel #0
CreateBlinkPanel(1)
if PanelType == 'Textured':
CreateTexturedPanel(0, 0) # Create a user uploaded image panel #0
CreateTexturedPanel(1, 0)
Remove all touch panel-related variables.
Writer_TouchEventTxt = open(Path + "/" + str(TimeNow.year) + "_" + str(TimeNow.month) + "_" + str(TimeNow.day) + " " + str(TimeNow.hour) + "h" + str(TimeNow.minute) + "m Task" + str(GetTaskID()) + " Touch.txt", 'w') # Initialize thetext exporter for a result file
Writer_TouchEventTxt.write('TrialNum\tResult\t\t\tyyyy/mm/dd\th:m\ts\n') # Write item name on the result file
Writer_TouchEventCsv = open(Path + "/" + str(TimeNow.year) + "_" + str(TimeNow.month) + "_" + str(TimeNow.day) + " " + str(TimeNow.hour) + "h" + str(TimeNow.minute) + "m Task" + str(GetTaskID()) + " Touch.csv", 'w')
print("Task #" + str(GetTaskID()) + " is started at " + str(GetTaskStartedMonth()) + '/' + str(GetTaskStartedDay()) + ' ' + str(GetTaskStartedHour()) + ':' + str(GetTaskStartedMinute()) + ':' + str(GetTaskStartedSecond())) # Enter the start time in the console window of Pycharm
Timer_Start(5) # Start a timer #5 to measure the duration of the task
Phase2 = 2 # Start task from the reward phase
Phase2_Init = 1 # Flag indicating that initialization of Phase2 has done
if Phase2 == 0: # Initiation of new trial
TaskDur = Timer_GetSec(5)
CorrectPanelID = int(random.random()*2) # Determine which panel will beassigned as "correct"
print('CorrectPanelID: ' + str(CorrectPanelID))
ShowPanel(CorrectPanelID) # Display panel #0
ServoPosInside(5) # Insert the indicated lever
ServoPosInside(6)
Insert both the left and right levers at the session start.
Phase2 = 1
if Phase2 == 1: # Lever choice
TouchedPanelID = DetectRoiNosepoke() # Examine which panel istouched (return panel ID. If none of the panels touched, return -1)
if TouchedPanelID != -1 and TouchedPanelID != 19: # If mouse touchesthe panel
TrialNum += 1
if TouchedPanelID == CorrectPanelID: # If touched panel is assignedas correct
LeftLeverStat = DetectLeverPress(7) # Return 1 if current in digital inputCh7 is detected (Check input from left lever)
RightLeverStat = DetectLeverPress(8) # Return 1 if current in digitalinput Ch8 is detected (Check input from right lever)
#TouchedPanelID = DetectRoiNosepoke() # Examine which panel istouched (return panel ID. If none of the panels touched, return -1)
if LeftLeverStat==1 or RightLeverStat==1: # If mouse touches the panel
TrialNum += 1
if CorrectPos=="Left" and LeftLeverStat==1 or CorrectPos=="Right"and RightLeverStat==1: # If touched correct lever
ServoPosInside(3) # Move the water nozzle into inside position
if WaterCueType == 'Normal':
DigitalOutOn(10) # Turn on cue LED connected to Ch10
if WaterCueType == 'Blink':
DigitalOutBlinkOn(10) # Start blinking of cue LED connected toCh10
HidePanel(0) # Turn off panel #0
HidePanel(1) # Turn off panel #1
ServoPosOutside(5) # Pull the indicated lever back
ServoPosOutside(6)
NowDrinking = 0
CorrectNum += 1 # Increase the number of correct response
Writer_TouchEventTxt.write(str(TrialNum)+'\tLeverPressed(Correct)\t'+ str(TimeNow.year)+"/"+str(TimeNow.month)+"/"+str(TimeNow.day)+"\t"+str(TimeNow.hour)+":"+str(TimeNow.minute)+"\t"+str(TimeNow.second)+"."+str(TimeNow.microsecond//1000)+"\n") # Write the response on the text file
Writer_TouchEventCsv.write(str(TrialNum) + ',1,' + str(TimeNow.year) + "," + str(TimeNow.month) + "," + str(TimeNow.day) + "," + str(TimeNow.hour) + "," + str(TimeNow.minute) + "," + str(TimeNow.second) + "." + str(TimeNow.microsecond//1000)+"\n") # Write the response on the csv file
Phase2 = 2 # Start reward phase
if TouchedPanelID != CorrectPanelID: # If touched panel is assignedas incorrect
if CorrectPos=="Left" and RightLeverStat==1 or CorrectPos=="Right" and LeftLeverStat==1: # If touched incorrect lever
ServoPosOutside(3) # Move the water nozzle into inside position
HidePanel(0)
HidePanel(1)
ServoPosOutside(5) # Pull the indicated lever back
ServoPosOutside(6)
Lever press can be checked with DetectLeverPress(Ch#). It returns 1 if thecorresponding lever is pressed. The returned value is held in the variable andchecked if the pressed lever is correct or not. After the process for correct orincorrect response, both levers are retracted.
RoofLightOn() # Turn on the ceiling illumination
IncorrectNum += 1 # Increase the number of correct response
Writer_TouchEventTxt.write(str(TrialNum)+'\tLeverPressed(Incorrect)\t'+ str(TimeNow.year)+"/"+str(TimeNow.month)+"/"+str(TimeNow.day)+"\t"+str(TimeNow.hour)+":"+str(TimeNow.minute)+"\t"+str(TimeNow.second)+"."+str(TimeNow.microsecond//1000)+"\n") # Write the response on the text file
Writer_TouchEventCsv.write(str(TrialNum) + ',2,' + str(TimeNow.year) + "," + str(TimeNow.month) + "," + str(TimeNow.day) + "," + str(TimeNow.hour) + "," + str(TimeNow.minute) + "," + str(TimeNow.second) + "." + str(TimeNow.microsecond//1000)+"\n") # Write the response on the csv file
Timer_Start(0) # Start punishment timer
Phase2 = 3 # Start punish phase
mOngoingResultVar.set('CorrectNum: ' + str(CorrectNum) + ' IncorrectNum: ' + str(IncorrectNum) + ' TrialNum: ' + str(TrialNum))
if Timer_GetSec(5) >= TimeLimit * 60: # If time limit of the task comes
TaskDur = Timer_GetSec(5)
print("Time limit elapsed")
Timer_End(5) # Stop the timer
Phase2 = 5
if Phase2 == 2: # Reward phase
if DetectRoiNosepoke() == 19 and NowDrinking == 0: # If the mouseinitiates nose poking
NowDrinking = 1
Timer_Start(0) # Start lick timer
if NowDrinking == 1: # If the nose poke has begun
if Timer_GetSec(0) >= LickDur: # If the nosepoke duration exceedsthe lick duration
Timer_End(0) # End timer for measuring lick duration
ServoPosMiddle(3) # Move water nozzle back to the middle position
DigitalOutOff(10) # Turn off the cue LED
NowDrinking = 0
Phase2 = 4 # Go to After trial phase
if Phase2 == 3: # Punishment phase
if Timer_GetSec(0) >= PunishDur: # If punishment time is passed
Timer_End(0) # End punishment timer1
RoofLightOff()
ServoPosMiddle(3) # Move water nozzle to the intermediate position
Phase2 = 4 # Go to After trial phase
if Phase2 == 4: # After trial phase
if CorrectNum < MaxCorrectNum and TrialNum < MaxTrialNum: # If thetouch number doesn't exceed the maximum number
Phase2 = 0
if CorrectNum >= MaxCorrectNum or TrialNum >= MaxTrialNum: # If thetouch number exceeds the maximum number
TaskDur = Timer_GetSec(5) # Keep the task time
Phase2 = 5
if Phase2 == 5:
HideAllPanel()
ServoPosOutside(5) # Pull the indicated lever back
ServoPosOutside(6)
Retract both levers at the session end.
if CorrectNum < MaxCorrectNum and AwsOn == 'ON': # If mouse didn'tachieved the max correct response
Timer_Start(0)
Phase2 = 6
if CorrectNum == MaxCorrectNum or AwsOn == 'OFF': # If mouseachieved the max correct response
Phase2 = -1
if Phase2 == 6: # Wait until complemental water supply is started
if Timer_GetSec(0) >= AWS_Latency: # If it past indicated latency to startcomplemental water supply
Timer_End(0)
ArbitaryWaterSupplyDur = (MaxCorrectNum - CorrectNum) * LickDur *1000 # Calculate the duration of complemental water supply
if WaterCueType == 'Normal':
StartArbitaryWaterSupply(3, 10, 0, ArbitaryWaterSupplyDur) # Startcomplemental water supply
if WaterCueType == 'Blink':
StartArbitaryWaterSupply(3, 10, 1, ArbitaryWaterSupplyDur)
print("Arbitrary water supply start")
Phase2 = 7 # Start AWS
if Phase2 == 7: # Keep checking until complemental water supply is finished
if GetArbitaryWaterSupplyStat() == 1: # If the complemental water supplyis finished
Phase2 = -1
if Phase2 == -1 or GetEndTaskNowButtonStat() == 1: # If the flag is set tofinish the task
LightCycleControlOn() # Activate automatic light/dark cycle
ServoPosMiddle(3) # Moze servo nozzle into middle position
DeleteAllPanel() # Remove a panel on touch screen
ServoPosOutside(5) # Pull the indicated lever back
ServoPosOutside(6)
Add lever retraction lines just in case the "EndTask" button is clicked.
InfraredLightOff() # Turn off the infrared LED
if GetRecordingStat() == 1: # If camera is capturing
SetEndRecordingTimer(60) # Onset a timer to finish video recordingafter 60 frames (correspond about 2sec) from now
# Add summary of results into the result file
if CorrectNum > 0 or IncorrectNum > 0:
CorrectRate = int(CorrectNum * 100.0 / TrialNum)
Writer_TouchEventTxt.write('TotalNum:' + str(TrialNum) + ' CorrectNum:'+ str(CorrectNum) + ' IncorrectNum:' + str(IncorrectNum) + ' CorrectRate:' + str(CorrectRate) + '%\n')
Writer_TouchEventTxt.write('SessionStartTime: ' + str(GetTaskStartedMonth()) + '/' + str(GetTaskStartedDay()) + ' ' + str(GetTaskStartedHour()) + ':' + str(GetTaskStartedMinute()) + ':' + str(GetTaskStartedSecond()) + "\n")
Writer_TouchEventTxt.write('SessionEndTime: ' + str(TimeNow.month) + '/' + str(TimeNow.day) + ' ' + str(TimeNow.hour) + ':' + str(TimeNow.minute) + ':' + str(TimeNow.second + (TimeNow.microsecond // 1000) / 1000) + "\n")
Writer_TouchEventTxt.write('TaskDuration(sec): ' + str(TaskDur) + "\n")
# Add experimental conditions into the result file
Writer_TouchEventTxt.write('MaxCorrectNum: '+str(MaxCorrectNum)+"\n")
Writer_TouchEventTxt.write('MaxTrialNum: ' + str(MaxTrialNum) + "\n")
Writer_TouchEventTxt.write('TimeLimit: ' + str(TimeLimit) + "\n")
Writer_TouchEventTxt.write('PunishDur: ' + str(TimeLimit) + "\n")
Writer_TouchEventTxt.write('LickDur: ' + str(LickDur)+"\n")
Writer_TouchEventTxt.write('NextTask: ' + str(NextTask) + "\n")
Writer_TouchEventTxt.write('NextTaskTh: ' + str(NextTaskTh) + "\n")
Writer_TouchEventTxt.write('PanelType: ' + str(PanelType) + "\n")
Writer_TouchEventTxt.write('CorrectPos: ' + CorrectPos + "\n")
Writer_TouchEventTxt.write('WaterCueType: ' + WaterCueType + "\n")
Writer_TouchEventTxt.write('AwsOn: ' + AwsOn + "\n")
Writer_TouchEventTxt.write('RecordFPS: ' + str(GetRecordFps()) + "\n") # Recorded frame number per second
Writer_TouchEventTxt.write(GetRoiSensitivity() + "\n") # Settings ofeach ROI
Writer_TouchEventTxt.write(GetServoAngle() + "\n") # Set angles ofeach servo
Writer_TouchEventTxt.close() # Close the text exporter for the resultfile
Writer_TouchEventCsv.close()
EndLickRecording() # End lick log recording
SendMail(DeviceNameVar.get()+' finished task '+str(GetTaskID())+'.TrialNum:'+str(TrialNum)+' Correct:'+str(CorrectNum)+' Incorrect:'+str(IncorrectNum)+' Rate:'+str(CorrectRate)+'% Dur:'+str(round(Timer_GetSec(5) / 60,1))+' min','Thetask is finished.') # Send a email (correct number and task duration are added to emailtitle)
if IsHousingAnalysis == 1 and Phase2 == -1: # If it is housing analysis
if CorrectRate >= NextTaskTh: # If the score exceed the criteria toswitch to the next task
SwitchTask(NextTask) # Onset the task switching trigger
print("Task was switched to task#" + str(NextTask) + " " + str(GetTaskStartedMonth()) + '/' + str(GetTaskStartedDay()) + ' ' + str(GetTaskStartedHour()) + ':' + str(GetTaskStartedMinute()) + ':' + str(GetTaskStartedSecond()))
if IsHousingAnalysis == 0:
RoofLightOn()
Phase = 1 # Go back to the task-waiting phase
Phase2 = 0
Phase2_Init = 0
SetDispVariable(0, 'Phase2', str(Phase2)) # Display "Phase2" value on thebottom of main window
return
Now the new lever task is completed. Test to see whether the lever modules work properly.
As mentioned in the paper, limiting the space for the movement of mouse to the vicinity of the levers during shaping drastically accelerate the learning in both the homecage and non-homecage analysis.