Kitaya lab

オリジナル課題の追加3(Phase0)




Phase0のコードは以下になります。
前の章で触れたとおり、このコードは課題条件の入力中に実行されます。


=======================================================================================================================
       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
               
               mMaxCorrectNum = ttk.Label(MainWindowRightFrame, text='MaxCorrectNum', width=ColumnWidth).grid(row=0, column=0, sticky=W)    # Put label
               MaxCorrectNumVar = IntVar(MainWindowRoot)  # Declare a variable for input column
               iMaxCorrectNum = ttk.Entry(MainWindowRightFrame, textvariable=MaxCorrectNumVar, width=ColumnWidth).grid(row=1,column=0)  # Create input column and link it with the variable
               
               mTimeLimit = ttk.Label(MainWindowRightFrame, text='TimeLimit(min)', width=ColumnWidth).grid(row=0, column=1, sticky=W)
               TimeLimitVar = IntVar(MainWindowRoot)
               iTimeLimit = ttk.Entry(MainWindowRightFrame, textvariable=TimeLimitVar, width=ColumnWidth).grid(row=1, column=1)
               
               mLickDur = ttk.Label(MainWindowRightFrame, text='LickDur(s)', width=ColumnWidth).grid(row=0, column=2, sticky=W)
               LickDurVar = IntVar(MainWindowRoot)
               iLickDur = ttk.Entry(MainWindowRightFrame, textvariable=LickDurVar, width=ColumnWidth).grid(row=1, column=2)


               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 thisprogram
               else:  # If save file doesn't exist
                   MaxCorrectNumVar.set(80)  # Substitute 80 into the variable

               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 + '/LickDur.dat') == True:
                   with open(Str + '/LickDur.dat', 'rb') as PickleInst[GetTaskID()]:
                       LickDurVar.set(pickle.load(PickleInst[GetTaskID()]))
               else:
                   LickDurVar.set(2)


               PutRoiGui(0, 1, 1, 0)  # Put setting GUI of the indicated ROI on ROI window (ROI number, Detection mode, Thresholddirection, ShowSymbol or not)
               PutRoiGui(19, 0, 0, 1)

               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)

               RemoveAllServoGui() # Remove all GUI on the Servo GUI
               PutServoGui(3)  # Put a servo GUI for channel 3 on the Servo GUI

               Phase0_Init = 1 # Set a flag which indicating phase0 initialization has done
=======================================================================================================================



まず冒頭でif Phase0_Init == 0:と言う文があります。
この中には初期化命令(ボタンや入力欄の配置など)が含まれており、Phase0に入った最初のフレームのみで実行されます。

まずRemoveMainRightWidget()でメイン画面の右側(↓)を一旦クリアし、その後課題条件の入力欄やラベルを配置しています。



この課題の最初のパラメータである最大正解数の入力GUIを配置しています。

=======================================================================================================================
mMaxCorrectNum = ttk.Label(MainWindowRightFrame, text='MaxCorrectNum', width=ColumnWidth).grid(row=0 column=0, sticky=W)    # Put label
MaxCorrectNumVar = IntVar(MainWindowRoot)  # Declare a variable for input column
iMaxCorrectNum = ttk.Entry(MainWindowRightFrame, textvariable=MaxCorrectNumVar, width=ColumnWidth).grid(row=1 column=0)  # Create input column and link it with the variable
=======================================================================================================================


mMaxCorrectNum = ttk.Label(MainWindowRightFrame, text='MaxCorrectNum', width=ColumnWidth).grid(row=0, column=0, sticky=W)    # Put label

まずは"MaxCorrectNum"という文字をラベルオブジェクトとして生成し、メインウィンドウの右区画の0行目の0列目に左寄せで配置しています。sticky=WはWestで左詰めで表示するという意味です。


MaxCorrectNumVar = IntVar(MainWindowRoot)  # Declare a variable for input column
次はIntVarと言う型の変数を宣言しています。この型は入力欄と関連付けられる特殊な変数です。


iMaxCorrectNum = ttk.Entry(MainWindowRightFrame, textvariable=MaxCorrectNumVar, width=ColumnWidth).grid(row=1 column=0)  # Create input column and link it with the variable
最後に入力欄オブジェクトを生成、配置しています。textvariable=MaxCorrectNumVarで入力された値を先ほど作ったMaxCorrectNumVarに渡すように指示しています。また配置場所は1行目の0列目と指示しています。


以下同じパターンでTimeLimit, LickDurの入力GUIを生成、配置しています。




次に課題パラメータ変数の値のセーブデータがある場合、それをロードする処理です。
オペラントハウスでは各課題毎に保存用のフォルダが存在し、各パラメータの変数の値はそれぞれが1ファイルとしてそのフォルダ内に保存されます。もしフォルダやファイルが見つからない場合、新たに生成され、デフォルト値が入るのでもし特定の課題のパラメータを初期化したい場合は対応するセーブフォルダを削除してプログラムを起動してください。

=======================================================================================================================
           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 thisprogram
           else:   # If save file doesn't exist
               MaxCorrectNumVar.set(80)     # Substitute 80 into the variable

           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+'/LickDur.dat') == True:
               with open(Str+'/LickDur.dat', 'rb') as PickleInst[GetTaskID()]:
                   LickDurVar.set(pickle.load(PickleInst[GetTaskID()]))
           else:
               LickDurVar.set(2)
=======================================================================================================================




Str = "ParametersForTask" + str(GetTaskID())
今回の課題のセーブデータは"ParametersForTask90"と言うフォルダに保存されているので、まずそのフォルダ名の文字列を作成します。GetTaskID()を実行すると現在の課題番号である"90"が返って来ます。

そしてそれを使いデータファイルが存在しているかをif os.path.exists(Str+'/MaxCorrectNum.dat') == True:で確認します。


with open(Str+'/MaxCorrectNum.dat', 'rb') as PickleInst[GetTaskID()]:
   MaxCorrectNumVar.set(pickle.load(PickleInst[GetTaskID()]))  # Substitute loaded data into the variable of this program

もし存在していれば次の行の命令で保存された値をプログラムの変数(MaxCorrectNumVar)へ格納します。Var型の変数は"="ではなく、変数名.set(代入内容)で値を格納します。


else:   # If save file doesn't exist
   MaxCorrectNumVar.set(80)     # Substitute 80 into the variable

もしデータファイルが見つからない場合はelse以下が実行されるので(初めて課題を実行する場合など)、代わりに任意の値を代入します(ここでは"80"を入力)。


同じ要領でTimeLimitおよびLickDurの値もロードします。




=======================================================================================================================
PutRoiGui(0, 1, 1, 0)  # Put setting GUI of the indicated ROI on ROI window (ROI number, Detection mode, Threshold direction,ShowSymbol or not)
PutRoiGui(19, 0, 0, 1)
=======================================================================================================================
次の命令は写真のようなROIを生成とそれに対応するGUIの生成です。
<写真要差し替え>


PutRoiGui(0, 1, 1, 0)ではパネル#0用のROIを生成しています。
PutRoiGui(19, 0, 0, 1)では水スリット用のROIを生成しています。


この関数の使い方ですが、ここではパネル#0用のROIを例に取り説明します。

PutRoiGui(0, 1, 1, 0)
最初の引き数(赤字)はどの番号のROIを生成するか指示します。この番号はパネル番号と一致します。


PutRoiGui(0,1, 1, 0)
2番目の引き数はマウスの検出方式を指示します。
1にすると過去5秒間で最も暗かった、もしくは明るかった色がバックグラウンドとなります。どちらになるかは3番目の引き数に依存します。
0だと単にROIウィンドウで指定した値がバックグラウンドになります。


PutRoiGui(0, 1,1, 0)
3番目の引き数は明るい色を検出するか暗い色を検出するかの指示です。1だと明るい色を検出し、0だと暗い色を検出します。
B6でも鼻先は赤外線で照射するとかなり明るく見えるので、ここでは1を指示しています。


PutRoiGui(19, 0,0, 1)
それに対して水スリットでは黒く見えるマウスの後頭部を検出するので0を指示します。


PutRoiGui(0, 1, 1,0)
PutRoiGui(19, 0, 0,1)
最後の引き数は物体を検出した際に赤い四角のシンボルを表示するか否かです。1だと表示されます。




=======================================================================================================================
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)
=======================================================================================================================
これらのコードでDigitalOutputウィンドウのGUIを配置します。



まずRemoveAllDigitalOutGui()でDigitalOutputWindowをクリアしてPutDigitalOutGui(10)でArduinoのデジタル入出力チャネル10番(Cue LED用)に対応したGUIを設置します。また同時に10番のチャネルを出力モードにします。
続く命令で同様に赤外線用のCh12, 天井照明用のCh13の処理を行います。




=======================================================================================================================
RemoveAllServoGui() # Remove all GUI on the Servo GUI
PutServoGui(3)  # Put a servo GUI for channel 3 on the Servo GUI
=======================================================================================================================
最後のコードでServoウィンドウのGUIの配置をしています。


まず前の課題のGUIが残っている場合に備えて念のためRemoveAllServoGui()で一旦Servoウィンドウ上部をクリアし、PutServoGui(3)でチャネル3用のGUIをServoウィンドウに設置し、Arduinoのデジタル入出力チャネル3番をサーボ出力モード(PWM)に変更します。


そして最後にPhase0_Init = 1にする事でこれら初期化命令が再び実行されることを防ぎます。