Skip to content

Commit ccd974c

Browse files
authored
Merge pull request #248 from AllenNeuralDynamics/production_testing
[production merge] 02/13/2024
2 parents 87d1fc8 + 25dd86d commit ccd974c

19 files changed

Lines changed: 463 additions & 349 deletions

README.md

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -280,46 +280,54 @@ To configure automatic updates consistent with the [update protocol](https://git
280280
- **Double dipping**: Double dipping statistics in different behavior epochs and conditions.
281281

282282
### Automatic training
283-
1. In the main dialog, press `Auto Train` button <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/9ef26192-044b-4c22-928f-b328b7ab36ab" width="90"> or `Ctrl + Alt + A` to open the Automatic Training dialog
283+
1. In the main dialog, press `Auto Train` button <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/836a4432-b1b2-4f92-9c66-2441a9d77a82" width="150"> or `Ctrl + Alt + A` to open the Automatic Training dialog
284284
> [!IMPORTANT]
285285
> If the dialog fails to open, check AWS credentials at `~/.aws/credentials`. See [instructions](#for-initial-installation)
286+
286287
2. For the first session of a new mouse:
287-
- Confirm that this is a new mouse<br>
288-
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/bcaafe89-3330-4704-81f9-ab30c259512b" width="400"><br>
289-
- On the right side, select a desired curriculum for the new mouse. Double-check `curriculum_name`, `curriculum_version`, and the diagrams<br>.
290-
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/2e3c030f-f91e-4917-9fa9-7e27af115171" width="700"><br>
291-
- Click buttons to see interative diagrams in browser <br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/bb845129-a12b-445a-8639-0e981a60deb9" height="30">
292-
- Click `Set curriculum` button <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/f1fac3e0-1c84-42e9-9f12-ba11896845b8" width="60"> to confirm
293-
- Now a new entry with `session = 0` is added in `Training history`, and `STAGE_1` of the selected curriculum is suggested by default. <br>
294-
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/90a054ab-71c1-4fa2-b13b-ab06f7895080" width="700"><br>
288+
1. ‼️ So far, the automatic training system cannot handle our previous Stage 1.1 --> Stage 1.2.<br>
289+
For a new mouse, please still use `Coupled Baiting - Stage 1.1` in the "Parameters" page to warm up the mouse as before.<br>
290+
Note we always start with `Coupled Baiting - Stage 1.1` even if `curriculum_name == "Uncoupled ..."` (see [this issue](https://github.com/AllenNeuralDynamics/aind-behavior-blog/issues/241))<br>
291+
![image](https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/13c34f43-ceeb-4a79-927e-242f03608602)<br>
292+
Once you think the mouse is ready for Stage 1.2, please follow the steps below to start using automatic training. <br>(`Stage 1` in `Auto Train`= `Stage 1.2` in the `Parameters` tab.)<br><br>
293+
294+
2. Confirm that this is a new mouse in the automatic training system<br>
295+
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/684d4aac-f9a9-4ce7-9536-61aace828c76" width="400"><br>
296+
3. In "Curriculum Manager", select a desired curriculum for the new mouse. Double-check `curriculum_name` and `curriculum_version`<br>.
297+
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/da03961e-71ef-4c6b-a0c0-37475edd1c66" width="700"><br><br>
298+
4. (Optional) Click buttons to see interative diagrams in browser <br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/99038b93-aef7-48bb-b756-a387bf435a6e" height="30">
299+
5. Click `Set curriculum` button <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/2e3f9abd-afda-4a8c-8475-dfb4f2d8065d" width="300"> to confirm
300+
6. Now a new entry with `session = 0` is added in `Training history`, and `STAGE_1` of the selected curriculum is suggested by default. <br>
301+
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/dac71e11-ed71-4fbc-9c3b-85695aa8ef5c" width="700"><br><br>
295302
3. For a mouse that already started training
296-
- Its training history and curriculum is automatically loaded
297-
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/58a9e583-09a4-4295-84eb-db5ef873df5d" width="900">
298-
- Uncheck `show this mouse only` to see training history from all mice
303+
1. Its training history and curriculum is automatically loaded
304+
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/1dc6e13a-a563-425e-81df-28c0e71a8037" width="900">
305+
2. (Optional) Uncheck `show this mouse only` to see training history from all mice
299306
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/97c05425-7dac-426b-9ba2-aadcfc1868ed" height="30">
300-
- Press `Show all training history` <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/ff1354b6-4b78-4740-a317-b5ec1b83686e" height="30"> to open an interactive plotly chart that visualize all training history in browser
301-
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/af541948-94ab-4f13-b599-ca188be77324" width="700">
307+
3. (Optional) Press `Show auto-training history in Streamlit` <img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/c5dc9f2f-8485-47c3-a7e7-ed23947cc4a1" height="30"> to open the Streamlit app showing all training history in browser
308+
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/194ee69c-14ec-466d-93b7-3b3e26b4ece8" width="1200">
302309
4. Apply and lock training parameters
303-
- Check the curriculum name and stage name shown on the huge green button<br>
304-
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/c46cd82e-76e7-4d7c-914e-41752937fee8" width="200"><br>
305-
- Press the button to apply and lock all curriculum-controlled training parameters in the main GUI (including the "Task").
306-
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/27e72b0d-5317-47ba-ac16-7b22e7374cd7" width="900">
307-
- Note that you can still modify some items in `Training parameters`, such as `Valve open time`, `Give left/right`, and `Next block`.
308-
- You could now close the Auto Training dialog.
309-
- Start the training as usual.
310-
310+
1. Check the curriculum name and stage name shown on the huge green button<br>
311+
<img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/b4bcfd2e-dc68-4349-9208-b06f429c993f" width="200"><br>
312+
2. Press the button to apply and lock all curriculum-controlled training parameters in the main GUI (including the "Task").
313+
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/fabbf0c2-3f9f-4fa3-8945-030105248851" width="1200">
314+
3. Note that you can still modify some items in `Training parameters`, such as `Valve open time`, `Give left/right`, and `Next block`.
315+
4. You could now close the Auto Training dialog.
316+
5. Start the training as usual.
317+
311318
5. Override parameters (not recommended)
312-
- Once `Apply and lock` is pressed, you can press it again to unlock the parameters and override any of them. But in this case, the automatic training mode is disengaged, and this session is considered "off-curriculum".
313-
319+
1. Once `Apply and lock` is pressed, you can press it again to unlock the parameters and override any of them. But in this case, the automatic training mode is disengaged, and this session is considered "off-curriculum". <br>
320+
![image](https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/08b7997c-bdce-421b-8c90-3a7e4dfc5ba7)
321+
314322
6. Override stage (not recommended)
315-
- Check `Override stage` to override the suggested stage. In the example below, `STAGE_FINAL` is suggested, but `STAGE_3` will be actually used (see the green button).
316-
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/92fb9df7-3e54-4bf2-a86a-02c3808c554e" width="700">
323+
1. Check `Override stage` to override the suggested stage. In the example below, `STAGE_FINAL` is suggested, but `STAGE_3` will be actually used (see the green button).
324+
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/3a25ed5c-e92f-4ba4-8fc5-38bd4c498499" width="700">
317325

318326
7. Override curriculum (not recommended)
319-
- If you somehow decide to change the curriculum during training, press `Override curriculum` and set a new curriculum.
320-
- In this case, since all stages from the old curriculum now become "irrelevant", you should always manually select a stage in the ***new*** curriculum to override.
327+
1. If you somehow decide to change the curriculum during training, press `Override curriculum` and set a new curriculum.
328+
2. In this case, since all stages from the old curriculum now become "irrelevant", you should always manually select a stage in the ***new*** curriculum to override.
321329
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/802e5208-dc5f-45f5-8ece-b9241157bf88" width="300">
322-
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/fba62a4b-acdb-49e9-a401-3a382607b0f3" width="700">
330+
<br><img src="https://github.com/AllenNeuralDynamics/dynamic-foraging-task/assets/24734299/9f0f0853-8033-46ff-82a6-38b6c01ec136" width="700">
323331

324332
### Water Calibration
325333

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cd /d C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\foraging_gui
2+
call conda activate Foraging
3+
start "" C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\desktop_shortcuts\start_popup.bat
4+
start "" pythonw Foraging.py 1
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cd /d C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\foraging_gui
2+
call conda activate Foraging
3+
start "" C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\desktop_shortcuts\start_popup.bat
4+
start "" pythonw Foraging.py 2
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cd /d C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\foraging_gui
2+
call conda activate Foraging
3+
start "" C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\desktop_shortcuts\start_popup.bat
4+
start "" pythonw Foraging.py 3
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cd /d C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\foraging_gui
2+
call conda activate Foraging
3+
start "" C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\src\desktop_shortcuts\start_popup.bat
4+
start "" pythonw Foraging.py 4
5+

src/desktop_shortcuts/CameraA.bat

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
cd /d C:\Users\svc_aind_behavior\Documents\camera_workflows
2-
start /min C:\Users\svc_aind_behavior\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxA.bonsai --no-editor
1+
cd /d C:\Users\%USERNAME%\Documents\camera_workflows
2+
echo off
3+
mode 50,10
4+
cls
5+
start /B C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxA.bonsai --no-editor
6+
powershell -window minimized -command ""
7+
timeout 5 > NUL
8+
title CAMERA A
9+
echo This window controls camera A
10+
echo Close this window if camera A is whited out
311

src/desktop_shortcuts/CameraB.bat

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
cd /d C:\Users\svc_aind_behavior\Documents\camera_workflows
2-
start /min C:\Users\svc_aind_behavior\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxB.bonsai --no-editor
1+
cd /d C:\Users\%USERNAME%\Documents\camera_workflows
2+
echo off
3+
mode 50,10
4+
cls
5+
start /B C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxB.bonsai --no-editor
6+
powershell -window minimized -command ""
7+
timeout 5 > NUL
8+
title CAMERA B
9+
echo This window controls camera B
10+
echo Close this window if camera B is whited out
311

src/desktop_shortcuts/CameraC.bat

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
cd /d C:\Users\svc_aind_behavior\Documents\camera_workflows
2-
start /min C:\Users\svc_aind_behavior\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxC.bonsai --no-editor
1+
cd /d C:\Users\%USERNAME%\Documents\camera_workflows
2+
echo off
3+
mode 50,10
4+
cls
5+
start /B C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxC.bonsai --no-editor
6+
powershell -window minimized -command ""
7+
timeout 5 > NUL
8+
title CAMERA C
9+
echo This window controls camera C
10+
echo Close this window if camera C is whited out
311

src/desktop_shortcuts/CameraD.bat

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
cd /d C:\Users\svc_aind_behavior\Documents\camera_workflows
2-
start /min C:\Users\svc_aind_behavior\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxD.bonsai --no-editor
1+
cd /d C:\Users\%USERNAME%\Documents\camera_workflows
2+
echo off
3+
mode 50,10
4+
cls
5+
start /B C:\Users\%USERNAME%\Documents\GitHub\dynamic-foraging-task\bonsai\bonsai Camera_boxD.bonsai --no-editor
6+
powershell -window minimized -command ""
7+
timeout 5 > NUL
8+
title CAMERA D
9+
echo This window controls camera D
10+
echo Close this window if camera D is whited out
311

src/foraging_gui/Dialogs.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,8 @@ def _Laser(self,Numb):
285285
ItemsRight=sorted(ItemsRight)
286286
eval('self.LaserPowerLeft_'+str(Numb)+'.clear()')
287287
eval('self.LaserPowerLeft_'+str(Numb)+'.addItems(ItemsLeft)')
288-
eval('self.LaserPowerLeft_'+str(Numb)+'.clear()')
289-
eval('self.LaserPowerLeft_'+str(Numb)+'.addItems(ItemsRight)')
288+
eval('self.LaserPowerRight_'+str(Numb)+'.clear()')
289+
eval('self.LaserPowerRight_'+str(Numb)+'.addItems(ItemsRight)')
290290
self.MainWindow.WarningLabel.setText('')
291291
self.MainWindow.WarningLabel.setStyleSheet("color: gray;")
292292
else:
@@ -334,7 +334,7 @@ def __init__(self, MainWindow,parent=None):
334334
self.MainWindow=MainWindow
335335
self.FinishLeftValve=0
336336
if not hasattr(self.MainWindow,'WaterCalibrationResults'):
337-
self.MainWindow.LaserCalibrationResults={}
337+
self.MainWindow.WaterCalibrationResults={}
338338
self.WaterCalibrationResults={}
339339
else:
340340
self.WaterCalibrationResults=self.MainWindow.WaterCalibrationResults
@@ -1153,17 +1153,17 @@ def is_file_in_use(file_path):
11531153
except OSError as e:
11541154
return True
11551155

1156-
class ManipulatorDialog(QDialog):
1157-
def __init__(self, MainWindow, parent=None):
1158-
super().__init__(parent)
1159-
uic.loadUi('Manipulator.ui', self)
1156+
#class ManipulatorDialog(QDialog):
1157+
# def __init__(self, MainWindow, parent=None):
1158+
# super().__init__(parent)
1159+
# uic.loadUi('Manipulator.ui', self)
11601160

1161-
class MotorStageDialog(QDialog):
1162-
def __init__(self, MainWindow, parent=None):
1163-
super().__init__(parent)
1164-
uic.loadUi('MotorStage.ui', self)
1165-
1166-
self.MainWindow=MainWindow
1161+
#class MotorStageDialog(QDialog):
1162+
# def __init__(self, MainWindow, parent=None):
1163+
# super().__init__(parent)
1164+
# uic.loadUi('MotorStage.ui', self)
1165+
#
1166+
# self.MainWindow=MainWindow
11671167

11681168
class LaserCalibrationDialog(QDialog):
11691169
def __init__(self, MainWindow, parent=None):
@@ -1288,6 +1288,8 @@ def _GetLaserWaveForm(self):
12881288
self.CLP_InputVoltage=float(self.voltage.text())
12891289
# generate the waveform based on self.CLP_CurrentDuration and Protocol, Frequency, RampingDown, PulseDur
12901290
self._GetLaserAmplitude()
1291+
# send the trigger source. It's '/Dev1/PFI0' ( P2.0 of NIdaq USB6002) by default
1292+
self.MainWindow.Channel.TriggerSource('/Dev1/PFI0')
12911293
# dimension of self.CurrentLaserAmplitude indicates how many locations do we have
12921294
for i in range(len(self.CurrentLaserAmplitude)):
12931295
# in some cases the other paramters except the amplitude could also be different
@@ -1397,10 +1399,9 @@ def _GetTrainingParameters(self,win):
13971399
setattr(self, Prefix+'_'+child.objectName(), child.isChecked())
13981400
def _InitiateATrial(self):
13991401
'''Initiate calibration in bonsai'''
1400-
# send the trigger source. It's '/Dev1/PFI0' ( P2.0 of NIdaq USB6002) by default
1401-
self.MainWindow.Channel.TriggerSource('/Dev1/PFI0')
14021402
# start generating waveform in bonsai
14031403
self.MainWindow.Channel.OptogeneticsCalibration(int(1))
1404+
self.MainWindow.Channel.receive()
14041405
def _CopyFromOpto(self):
14051406
'''Copy the optogenetics parameters'''
14061407
N=[]
@@ -1696,7 +1697,6 @@ def _Open(self):
16961697
# change button color and disable the open button
16971698
self.Open.setEnabled(False)
16981699
self.Open.setStyleSheet("background-color : green;")
1699-
QApplication.processEvents()
17001700
self._GetTrainingParameters(self.MainWindow)
17011701
self._GetLaserWaveForm()
17021702
self.worker2 = Worker(self._Sleep,float(self.LC_Duration_1)+1)
@@ -1935,7 +1935,7 @@ def _connect_auto_training_manager(self):
19351935
except:
19361936
logger.error("AWS connection failed!")
19371937
QMessageBox.critical(self,
1938-
'Error',
1938+
'Box {}, Error'.format(self.MainWindow.box_letter),
19391939
f'AWS connection failed!\n'
19401940
f'Please check your AWS credentials at ~\.aws\credentials!')
19411941
return False
@@ -2009,7 +2009,8 @@ def _connect_curriculum_manager(self):
20092009
bucket='aind-behavior-data',
20102010
root='foraging_auto_training/saved_curriculums/'
20112011
),
2012-
saved_curriculums_local=self.MainWindow.default_saveFolder + '/curriculum_manager/',
2012+
# saved to tmp folder under user's home directory
2013+
saved_curriculums_local=os.path.expanduser('~/.aind_auto_train/curriculum_manager/')
20132014
)
20142015

20152016
def _show_available_curriculums(self):
@@ -2128,7 +2129,7 @@ def _update_stage_to_apply(self):
21282129
def _apply_curriculum(self):
21292130
# Check if a curriculum is selected
21302131
if not hasattr(self, 'selected_curriculum') or self.selected_curriculum is None:
2131-
QMessageBox.critical(self, "Error", "Please select a curriculum!")
2132+
QMessageBox.critical(self, "Box {}, Error".format(self.MainWindow.box_letter), "Please select a curriculum!")
21322133
return
21332134

21342135
# Always enable override stage
@@ -2174,11 +2175,11 @@ def _apply_curriculum(self):
21742175
if self.selected_curriculum['curriculum'] == self.curriculum_in_use:
21752176
# The selected curriculum is the same as the one in use
21762177
logger.info(f"Selected curriculum is the same as the one in use. No change is made.")
2177-
QMessageBox.information(self, "Info", "Selected curriculum is the same as the one in use. No change is made.")
2178+
QMessageBox.information(self, "Box {}, Info".format(self.MainWindow.box_letter), "Selected curriculum is the same as the one in use. No change is made.")
21782179
return
21792180
else:
21802181
# Confirm with the user about overriding the curriculum
2181-
reply = QMessageBox.question(self, "Confirm",
2182+
reply = QMessageBox.question(self, "Box {}, Confirm".format(self.MainWindow.box_letter),
21822183
f"Are you sure you want to override the curriculum?\n"
21832184
f"If yes, please also manually select a training stage.",
21842185
QMessageBox.Yes | QMessageBox.No,
@@ -2284,7 +2285,8 @@ def _set_training_parameters(self, paras_dict, if_press_enter=False):
22842285
task_ind = widget_task.findText(paras_dict['task'])
22852286
if task_ind < 0:
22862287
logger.error(f"Task {paras_dict['task']} not found!")
2287-
QMessageBox.critical(self, "Error", f'''Task "{paras_dict['task']}" not found. Check the curriculum!''')
2288+
QMessageBox.critical(self, "Box {}, Error".format(self.MainWindow.box_letter),
2289+
f'''Task "{paras_dict['task']}" not found. Check the curriculum!''')
22882290
return [] # Return an empty list without setting anything
22892291
else:
22902292
widget_task.setCurrentIndex(task_ind)

0 commit comments

Comments
 (0)