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 executed once 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 this task
                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 for input 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 input column
                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 indicated here 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 rate threshold 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

                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)
                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 water supply 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 file named "MaxCorrectNum.dat" exist:
                    with open(Str + '/MaxCorrectNum.dat', 'rb') as PickleInst[GetTaskID()]:
                        MaxCorrectNumVar.set(pickle.load(PickleInst[GetTaskID()]))  # Substitute loaded data into the variable of this program
                else:  # If save file doesn't exist
                    MaxCorrectNumVar.set(80)  # Substitute 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 + '/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(19, 0, 0, 1)  # Put setting GUI of the indicated ROI on ROI window (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 on Digital ouput window
                PutDigitalOutGui(12)
                PutDigitalOutGui(13)

                DigitalInOn(7)  # Set the indicated channel as Digital input channel (Receive input from the lever module)
                DigitalInOn(8)

                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)

                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())   # Substitute 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 a value 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+'/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 status display
                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 for progress display
                Phase1_Init = 1 # Flat that phase1 has done
            mStatusVar.set('Test4 task (' + str(GetTaskID()) + ')    Waiting...')    # Show current 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')    # Substitute latest information about current task into "mStatusVar"
                mOngoingResult = ttk.Label(MainWindowRightFrame, textvariable=mOngoingResultVar)
                mOngoingResult.place(x=10, y=18)

                # Substitute task parameter values in StringVars into integer or string variable (to make the cord easeir to read)
                MaxCorrectNum = int(MaxCorrectNumVar.get())   # Get the value of "MaxCorrectNumVar" and convert it from string to integer and substitute into variable named "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())
                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
                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 cycle illumination
                RoofLightOff()  # Turn off the lights on roof (Digital output Ch13)
                InfraredLightOn()   # Turn on the infrared LED illumination (Digital output Ch12)
                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 to Ch3 to inside position

                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 the text 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)
                ServoPosInside(5)   # Insert the indicated lever
                ServoPosInside(6)
                Phase2 = 1

            if Phase2 == 1:   # Lever choice
                LeftLeverStat = DetectLeverPress(7) # Return 1 if current in digital input Ch7 is detected (Check input from left lever)
                RightLeverStat = DetectLeverPress(8) # Return 1 if current in digital input Ch8 is detected (Check input from right lever)
                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 to Ch10
                        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 CorrectPos=="Left" and RightLeverStat==1 or CorrectPos=="Right" and LeftLeverStat==1:    # If touched incorrect lever
                        ServoPosOutside(3)    # Move the water nozzle into inside position
                        ServoPosOutside(5)  # Pull the indicated lever back
                        ServoPosOutside(6)
                        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 mouse initiates 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 exceeds the 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 the touch number doesn't exceed the maximum number
                    Phase2 = 0
                if CorrectNum >= MaxCorrectNum or TrialNum >= MaxTrialNum:  # If the touch number exceeds the maximum number
                    TaskDur = Timer_GetSec(5)  # Keep the task time
                    Phase2 = 5

            if Phase2 == 5:
                ServoPosOutside(5)  # Pull the indicated lever back
                ServoPosOutside(6)
                if CorrectNum < MaxCorrectNum and AwsOn == 'ON':  # If mouse didn't achieved the max correct response
                    Timer_Start(0)
                    Phase2 = 6
                if CorrectNum == MaxCorrectNum or AwsOn == 'OFF':  # If mouse achieved 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 start complemental 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)  # Start complemental 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 supply is finished
                    Phase2 = -1

            if Phase2 == -1 or GetEndTaskNowButtonStat() == 1:  # If the flag is set to finish the task
                LightCycleControlOn()   # Activate automatic light/dark cycle
                ServoPosMiddle(3)   # Moze servo nozzle into middle position
                ServoPosOutside(5)  # Pull the indicated lever back
                ServoPosOutside(6)
                InfraredLightOff()  # Turn off the infrared LED
                if GetRecordingStat() == 1: # If camera is capturing
                    SetEndRecordingTimer(60)    # Onset a timer to finish video recording after 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('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 of each ROI
                Writer_TouchEventTxt.write(GetServoAngle() + "\n")  # Set angles of each servo

                Writer_TouchEventTxt.close()    # Close the text exporter for the result file
                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','The task is finished.') # Send a email (correct number and task duration are added to email title)

                if IsHousingAnalysis == 1 and Phase2 == -1:  # If it is housing analysis
                    if CorrectRate >= NextTaskTh:  # If the score exceed the criteria to switch 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 the bottom of main window
    return