From d50ea9f90283895128058f52ade85c7e7c0e643c Mon Sep 17 00:00:00 2001 From: ZhixiaoSu Date: Thu, 9 May 2024 10:27:15 -0700 Subject: [PATCH 01/13] added rewardDelay --- .../uncoupled_no_baiting_2p0rwdDelay.py | 468 ++++++++++++++++++ code/aind_auto_train/schema/task.py | 1 + 2 files changed, 469 insertions(+) create mode 100644 code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py new file mode 100644 index 0000000..419cbd4 --- /dev/null +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py @@ -0,0 +1,468 @@ +''' +Curriculum for Dynamic Foraging - Uncoupled without Baiting +Adopted from "draft 2, began using 10/17/23" +https://alleninstitute-my.sharepoint.com/:w:/g/personal/katrina_nguyen_alleninstitute_org/EUGu5FS565pLuHhqFYT9yfEBjF7tIDGVEmbwnmcCYJBoWw?e=wD8fX9 + +Run the code to generate the curriculum.json and graphs +Added reward delay and shortened no-lick delay to take care of introduction of extra ITI when early licking + +''' + +#%% +from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT +from aind_auto_train.schema.curriculum import ( + DynamicForagingCurriculum, StageTransitions, TransitionRule, + Decision +) +from aind_auto_train.schema.task import ( + Task, TrainingStage, DynamicForagingParas, + AutoWaterMode, AdvancedBlockMode +) + +# Note this could be any string, not necessarily one of the Task enums +curriculum_name = Task.C0B0 +curriculum_version = "2.0rwdDelay" +curriculum_description = '''2024-04-25 added reward delay and adjust no-lick delay in early training''' + +task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" +task_schema_version = "1.1.0" + +# --- Parameters --- +# Stage 1 with warmup (classical Stage 1.1 + 1.2) + +paras_stage_1_warmup = DynamicForagingParas( + # Metainfo + training_stage=TrainingStage.STAGE_1_WARMUP, + description="Warmup, followed by legendary Coupled Baiting Stage 1.2 (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Warmup ON + warmup='on', + warm_min_trial=50, + warm_max_choice_ratio_bias=0.1, + warm_min_finish_ratio=0.8, + warm_windowsize=20, + + # First session is ** coupled baiting ** + task_url=task_url, + task_schema_version=task_schema_version, + task=Task.C1B1, + + # p_sum = 0.8, p_ratio = [1:0] + BaseRewardSum=0.8, + RewardFamily=3, + RewardPairsN=1, + + # block = [10, 30, 10] + BlockMin=10, + BlockMax=30, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=1, + ITIMax=7, + ITIBeta=3, + + # Add a (fixed) small delay period at the beginning # TODO: automate delay period + DelayMin=0, # almost turned off no lick window + DelayMax=0, + DelayBeta=0, + + # Reward size and reward delay + RewardDelay=0.1, + RightValue_volume=4.0, + LeftValue_volume=4.0, + + # -- Within session automation -- + # Auto water + AutoReward=True, + AutoWaterType=AutoWaterMode.NATURAL, + Unrewarded=3, + Ignored=3, + Multiplier=0.5, + + # Auto block + AdvancedBlockAuto=AdvancedBlockMode.NOW, + SwitchThr=0.5, + PointsInARow=5, + + # Auto stop; set StopIgnores to a large number at the beginning + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # -- Miscs -- + ResponseTime=5.0, # Very long response time at the beginning + RewardConsumeTime=1.0, # Shorter RewardConsumeTime to increase the number of trials + UncoupledReward="", # Only valid in uncoupled task +) + +transition_from_stage_1_warmup = StageTransitions( + from_stage=TrainingStage.STAGE_1_WARMUP, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ), + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_1, + condition_description="After the first session", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ) + + ] +) + +# Stage 1 without warmup (classical 1.2) +paras_stage_1 = DynamicForagingParas( + **{ + **paras_stage_1_warmup.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_1, + description="Phase B in Han's slides (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Turn off Warmup from now on + warmup='off', + + Unrewarded=5, + Ignored=5, + + # Decrease water size to 2.0 from now on + RightValue_volume=2.0, + LeftValue_volume=2.0, + ) + } +) + +transition_from_stage_1 = StageTransitions( + from_stage=TrainingStage.STAGE_1, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ) + ] +) + +paras_stage_2 = DynamicForagingParas( + **{ + **paras_stage_1.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_2, + description="Coupled without baiting (block = [20, 35, 10], p_sum = 0.8, p_ratio = [8:1])", + + # --- Only include changes compared to stage_1 --- + # -- Essentials -- + + # Coupled no baiting + task=Task.C1B0, + + # p_ratio [1:0] -> [8:1] + RewardFamily=1, + RewardPairsN=1, + + # Decrease autowater + Unrewarded=10, + Ignored=10, + + # block length [10, 30, 10] --> [20, 35, 20] + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 7, 3] --> [1, 10, 3] + ITIMax=10, + + # Delay 0.5 --> 1.0 + # DelayMin=0.5, + # DelayMax=0.5, + + # -- Within session automation -- + # Miscs + ResponseTime=1.5, # Decrease response time: 5 --> 1.5 + ) + } +) + +transition_from_stage_2 = StageTransitions( + from_stage=TrainingStage.STAGE_2, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2_noLick, + condition_description="Stay for >= 3 days", + condition="""lambda metrics: + metrics.session_at_current_stage >= 3 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_1, + condition_description="Finished trials < 200 or efficiency < 0.55", + condition="""lambda metrics: + metrics.finished_trials[-1] < 200 + or + metrics.foraging_efficiency[-1] < 0.55 + """, + ), + ] +) + + +paras_stage_2_nolick = DynamicForagingParas( + **{ + **paras_stage_2.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_2_noLick, + description="Coupled without baiting (block = [20, 35, 10], p_sum = 0.8, p_ratio = [8:1]), turn on no lick window", + + # --- Only include changes compared to stage_1 --- + # -- Essentials -- + + # Coupled no baiting + task=Task.C1B0, + + # p_ratio [1:0] -> [8:1] + RewardFamily=1, + RewardPairsN=1, + + # Decrease autowater + Unrewarded=10, + Ignored=10, + + # block length [10, 30, 10] --> [20, 35, 20] + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 7, 3] --> [1, 10, 3] + ITIMax=10, + + # Delay 0.5 --> 1.0 + DelayMin=1.0, + DelayMax=1.0, + + # -- Within session automation -- + # Miscs + ResponseTime=1.5, # Decrease response time: 5 --> 1.5 + ) + } +) + +transition_from_stage_2_nolick = StageTransitions( + from_stage=TrainingStage.STAGE_2_noLick, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_3, + condition_description="Finished trials >= 300 and efficiency >= 0.65 and stay for >= 3 days", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 300 + and + metrics.foraging_efficiency[-1] >= 0.65 + and + metrics.session_at_current_stage >= 3 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_1, + condition_description="Finished trials < 200 or efficiency < 0.55", + condition="""lambda metrics: + metrics.finished_trials[-1] < 200 + or + metrics.foraging_efficiency[-1] < 0.55 + """, + ), + ] +) + +paras_stage_3 = DynamicForagingParas( + **{ + **paras_stage_2_nolick.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_3, + description="Switch to uncoupled; p_rew = [0.1, 0.4, 0.7] or [0.1, 0.5, 0.9]; turn on auto water for 1 days", + + # -- Essentials -- + # Uncoupled no baiting + task=Task.C0B0, + UncoupledReward="0.1, 0.5, 0.9", + + # reward delay + RewardDelay=0.15, # increased from 100ms + + # Final block length for uncoupled task + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 10, 3] --> [1, 15, 3] + ITIMax=15, + + # Turn on auto water for the first day after switching to uncoupled task + AutoReward=True, + Unrewarded=15, # almost turned off + Ignored=15, # almost turned off + + # Turn off auto block + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + # Miscs + ResponseTime=1.5, + ) + } +) + +transition_from_stage_3 = StageTransitions( + from_stage=TrainingStage.STAGE_3, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_FINAL, + condition_description="Just stay for 1 days", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ), + # Once we reach here (C0B0), maybe we should not roll back to C1B0 or C1B1 anymore? + ] +) + +paras_stage_final = DynamicForagingParas( + **{ + **paras_stage_3.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_FINAL, + description="Uncoupled without baiting; p_rew = [0.1, 0.5, 0.9]; turn off auto water", + + # Essentials + # Uncoupled no baiting + task=Task.C0B0, + UncoupledReward="0.1, 0.5, 0.9", + + BlockMin=20, + BlockMax=35, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=2.0, + ITIMax=15.0, + ITIBeta=3.0, + + DelayMin=1.0, + DelayMax=1.0, + DelayBeta=0.0, + + RewardDelay=0.2, + + # Within session automation + AutoReward=False, # Turn off auto water + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # Miscs + ResponseTime=1.5, + RewardConsumeTime=1.0, + ) + } +) + +transition_from_stage_final = StageTransitions( + from_stage=TrainingStage.STAGE_FINAL, + transition_rules=[ + TransitionRule( + # For graduation, obviously we need more requirements. + decision=Decision.PROGRESS, + to_stage=TrainingStage.GRADUATED, + condition_description=("For recent 5 sessions," + "mean finished trials >= 500 and mean efficiency >= 0.70 " + "and total sessions >= 10 and sessions at final >= 5"), + condition="""lambda metrics: + metrics.session_total >= 10 + and + metrics.session_at_current_stage >= 5 + and + np.mean(metrics.finished_trials[-5:]) >= 500 + and + np.mean(metrics.foraging_efficiency[-5:]) >= 0.70 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_3, # Back to C0B0 with auto water + condition_description="For recent 2 sessions, mean finished trials < 300 or efficiency < 0.6", + condition="""lambda metrics: + np.mean(metrics.finished_trials[-2:]) < 300 + or + np.mean(metrics.foraging_efficiency[-2:]) < 0.6 + """, + ), + ] +) + +# --- Curriculum --- +# %% +curriculum = DynamicForagingCurriculum( + curriculum_name=curriculum_name, + curriculum_version=curriculum_version, + curriculum_description=curriculum_description, + + parameters={ + TrainingStage.STAGE_1_WARMUP: paras_stage_1_warmup, + TrainingStage.STAGE_1: paras_stage_1, + TrainingStage.STAGE_2: paras_stage_2, + TrainingStage.STAGE_2_noLick: paras_stage_2_nolick, + TrainingStage.STAGE_3: paras_stage_3, + TrainingStage.STAGE_FINAL: paras_stage_final, + TrainingStage.GRADUATED: paras_stage_final, + }, + + curriculum={ + TrainingStage.STAGE_1_WARMUP: transition_from_stage_1_warmup, + TrainingStage.STAGE_1: transition_from_stage_1, + TrainingStage.STAGE_2: transition_from_stage_2, + TrainingStage.STAGE_2_noLick: transition_from_stage_2_nolick, + TrainingStage.STAGE_3: transition_from_stage_3, + TrainingStage.STAGE_FINAL: transition_from_stage_final, + }, + +) + +# %% +if __name__ == '__main__': + #%% + import os + + curriculum_path = LOCAL_SAVED_CURRICULUM_ROOT + os.makedirs(curriculum_path, exist_ok=True) + + # Save curriculum json and diagrams + curriculum.save_to_json(path=curriculum_path) + curriculum.diagram_rules(path=curriculum_path, + render_file_format='svg') + #%% + curriculum.diagram_paras(path=curriculum_path, + render_file_format='svg', + fontsize=12) + +# %% diff --git a/code/aind_auto_train/schema/task.py b/code/aind_auto_train/schema/task.py index 446d91a..587cfa3 100644 --- a/code/aind_auto_train/schema/task.py +++ b/code/aind_auto_train/schema/task.py @@ -31,6 +31,7 @@ class TrainingStage(str, Enum): STAGE_1_WARMUP = "Stage 1 w/warmup" # Stage 1 with warmup (classical Stage 1.1 + 1.2) STAGE_1 = "Stage 1" # Stage 1 without warmup (classical Stage 1.2) STAGE_2 = "Stage 2" + STAGE_2_noLick = 'Stage 2 noLlick' STAGE_3 = "Stage 3" STAGE_4 = "Stage 4" STAGE_5 = "Stage 5" From 797e3f3d74f527e37410f542b36771ee5713cc48 Mon Sep 17 00:00:00 2001 From: ZhixiaoSu Date: Thu, 9 May 2024 17:20:38 -0700 Subject: [PATCH 02/13] version 2 rewardDelay --- code/aind_auto_train/curriculum_manager.py | 4 ++- code/aind_auto_train/curriculums/1.0 | 0 .../curriculums/src/aind-auto-train | 1 + code/aind_auto_train/curriculums/src/setup | 1 + .../uncoupled_no_baiting_2p0rwdDelay.py | 30 +++++++++---------- 5 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 code/aind_auto_train/curriculums/1.0 create mode 160000 code/aind_auto_train/curriculums/src/aind-auto-train create mode 160000 code/aind_auto_train/curriculums/src/setup diff --git a/code/aind_auto_train/curriculum_manager.py b/code/aind_auto_train/curriculum_manager.py index ea8b2f6..2ab446f 100644 --- a/code/aind_auto_train/curriculum_manager.py +++ b/code/aind_auto_train/curriculum_manager.py @@ -21,7 +21,9 @@ logger = logging.getLogger(__name__) -# Directory for caching df_maseter tables +# # Directory for caching df_maseter tables +# LOCAL_SAVED_CURRICULUM_ROOT = os.path.expanduser( +# '~\aind-foraging-behavior-bonsai-automatic-training\scratch\saved_curriculums/') LOCAL_SAVED_CURRICULUM_ROOT = os.path.expanduser( '~/capsule/scratch/saved_curriculums/') diff --git a/code/aind_auto_train/curriculums/1.0 b/code/aind_auto_train/curriculums/1.0 new file mode 100644 index 0000000..e69de29 diff --git a/code/aind_auto_train/curriculums/src/aind-auto-train b/code/aind_auto_train/curriculums/src/aind-auto-train new file mode 160000 index 0000000..adbfba9 --- /dev/null +++ b/code/aind_auto_train/curriculums/src/aind-auto-train @@ -0,0 +1 @@ +Subproject commit adbfba99656a602547952562c4797b5962661e87 diff --git a/code/aind_auto_train/curriculums/src/setup b/code/aind_auto_train/curriculums/src/setup new file mode 160000 index 0000000..adbfba9 --- /dev/null +++ b/code/aind_auto_train/curriculums/src/setup @@ -0,0 +1 @@ +Subproject commit adbfba99656a602547952562c4797b5962661e87 diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py index 419cbd4..a621dc3 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py @@ -205,7 +205,7 @@ transition_rules=[ TransitionRule( decision=Decision.PROGRESS, - to_stage=TrainingStage.STAGE_2_noLick, + to_stage=TrainingStage.STAGE_3, condition_description="Stay for >= 3 days", condition="""lambda metrics: metrics.session_at_current_stage >= 3 @@ -225,11 +225,11 @@ ) -paras_stage_2_nolick = DynamicForagingParas( +paras_stage_3 = DynamicForagingParas( **{ **paras_stage_2.model_dump(), **dict( - training_stage=TrainingStage.STAGE_2_noLick, + training_stage=TrainingStage.STAGE_3, description="Coupled without baiting (block = [20, 35, 10], p_sum = 0.8, p_ratio = [8:1]), turn on no lick window", # --- Only include changes compared to stage_1 --- @@ -265,12 +265,12 @@ } ) -transition_from_stage_2_nolick = StageTransitions( - from_stage=TrainingStage.STAGE_2_noLick, +transition_from_stage_3 = StageTransitions( + from_stage=TrainingStage.STAGE_3, transition_rules=[ TransitionRule( decision=Decision.PROGRESS, - to_stage=TrainingStage.STAGE_3, + to_stage=TrainingStage.STAGE_4, condition_description="Finished trials >= 300 and efficiency >= 0.65 and stay for >= 3 days", condition="""lambda metrics: metrics.finished_trials[-1] >= 300 @@ -293,11 +293,11 @@ ] ) -paras_stage_3 = DynamicForagingParas( +paras_stage_4 = DynamicForagingParas( **{ - **paras_stage_2_nolick.model_dump(), + **paras_stage_3.model_dump(), **dict( - training_stage=TrainingStage.STAGE_3, + training_stage=TrainingStage.STAGE_4, description="Switch to uncoupled; p_rew = [0.1, 0.4, 0.7] or [0.1, 0.5, 0.9]; turn on auto water for 1 days", # -- Essentials -- @@ -330,8 +330,8 @@ } ) -transition_from_stage_3 = StageTransitions( - from_stage=TrainingStage.STAGE_3, +transition_from_stage_4 = StageTransitions( + from_stage=TrainingStage.STAGE_4, transition_rules=[ TransitionRule( decision=Decision.PROGRESS, @@ -347,7 +347,7 @@ paras_stage_final = DynamicForagingParas( **{ - **paras_stage_3.model_dump(), + **paras_stage_4.model_dump(), **dict( training_stage=TrainingStage.STAGE_FINAL, description="Uncoupled without baiting; p_rew = [0.1, 0.5, 0.9]; turn off auto water", @@ -409,7 +409,7 @@ ), TransitionRule( decision=Decision.ROLLBACK, - to_stage=TrainingStage.STAGE_3, # Back to C0B0 with auto water + to_stage=TrainingStage.STAGE_4, # Back to C0B0 with auto water condition_description="For recent 2 sessions, mean finished trials < 300 or efficiency < 0.6", condition="""lambda metrics: np.mean(metrics.finished_trials[-2:]) < 300 @@ -431,8 +431,8 @@ TrainingStage.STAGE_1_WARMUP: paras_stage_1_warmup, TrainingStage.STAGE_1: paras_stage_1, TrainingStage.STAGE_2: paras_stage_2, - TrainingStage.STAGE_2_noLick: paras_stage_2_nolick, TrainingStage.STAGE_3: paras_stage_3, + TrainingStage.STAGE_4: paras_stage_4, TrainingStage.STAGE_FINAL: paras_stage_final, TrainingStage.GRADUATED: paras_stage_final, }, @@ -441,8 +441,8 @@ TrainingStage.STAGE_1_WARMUP: transition_from_stage_1_warmup, TrainingStage.STAGE_1: transition_from_stage_1, TrainingStage.STAGE_2: transition_from_stage_2, - TrainingStage.STAGE_2_noLick: transition_from_stage_2_nolick, TrainingStage.STAGE_3: transition_from_stage_3, + TrainingStage.STAGE_4: transition_from_stage_4, TrainingStage.STAGE_FINAL: transition_from_stage_final, }, From 1ab3573284af00b005af7646fe5729e5267de53f Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 17:30:03 -0700 Subject: [PATCH 03/13] chore: remove unnecessary files --- code/aind_auto_train/curriculums/1.0 | 0 code/aind_auto_train/curriculums/src/aind-auto-train | 1 - code/aind_auto_train/curriculums/src/setup | 1 - 3 files changed, 2 deletions(-) delete mode 100644 code/aind_auto_train/curriculums/1.0 delete mode 160000 code/aind_auto_train/curriculums/src/aind-auto-train delete mode 160000 code/aind_auto_train/curriculums/src/setup diff --git a/code/aind_auto_train/curriculums/1.0 b/code/aind_auto_train/curriculums/1.0 deleted file mode 100644 index e69de29..0000000 diff --git a/code/aind_auto_train/curriculums/src/aind-auto-train b/code/aind_auto_train/curriculums/src/aind-auto-train deleted file mode 160000 index adbfba9..0000000 --- a/code/aind_auto_train/curriculums/src/aind-auto-train +++ /dev/null @@ -1 +0,0 @@ -Subproject commit adbfba99656a602547952562c4797b5962661e87 diff --git a/code/aind_auto_train/curriculums/src/setup b/code/aind_auto_train/curriculums/src/setup deleted file mode 160000 index adbfba9..0000000 --- a/code/aind_auto_train/curriculums/src/setup +++ /dev/null @@ -1 +0,0 @@ -Subproject commit adbfba99656a602547952562c4797b5962661e87 From f29309c97a514fc61e5d12bd672cce7bd53aee09 Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 17:38:26 -0700 Subject: [PATCH 04/13] feat: remove unused Stage_2_noLick --- code/aind_auto_train/schema/task.py | 1 - 1 file changed, 1 deletion(-) diff --git a/code/aind_auto_train/schema/task.py b/code/aind_auto_train/schema/task.py index 587cfa3..446d91a 100644 --- a/code/aind_auto_train/schema/task.py +++ b/code/aind_auto_train/schema/task.py @@ -31,7 +31,6 @@ class TrainingStage(str, Enum): STAGE_1_WARMUP = "Stage 1 w/warmup" # Stage 1 with warmup (classical Stage 1.1 + 1.2) STAGE_1 = "Stage 1" # Stage 1 without warmup (classical Stage 1.2) STAGE_2 = "Stage 2" - STAGE_2_noLick = 'Stage 2 noLlick' STAGE_3 = "Stage 3" STAGE_4 = "Stage 4" STAGE_5 = "Stage 5" From 2ccff17ae435f76f2e74d64b41fc5e49818359d0 Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 17:49:58 -0700 Subject: [PATCH 05/13] feat: renaming and add [0.1, 0.5, 0.9] to the description --- ..._2p0rwdDelay.py => uncoupled_no_baiting_2p1rwdDelay159.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename code/aind_auto_train/curriculums/{uncoupled_no_baiting_2p0rwdDelay.py => uncoupled_no_baiting_2p1rwdDelay159.py} (98%) diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py similarity index 98% rename from code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py rename to code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py index a621dc3..f7fc3e3 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0rwdDelay.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py @@ -21,8 +21,8 @@ # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 -curriculum_version = "2.0rwdDelay" -curriculum_description = '''2024-04-25 added reward delay and adjust no-lick delay in early training''' +curriculum_version = "2.1rwdDelay" +curriculum_description = '''2024-04-25 added reward delay; decrease no-lick delay in early training; use [0.1, 0.5, 0.9]''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" task_schema_version = "1.1.0" From 0f783c26f964dfbc65ead048ca6127a2a1ee8685 Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 17:50:41 -0700 Subject: [PATCH 06/13] feat: add "159" to version name --- .../curriculums/uncoupled_no_baiting_2p1rwdDelay159.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py index f7fc3e3..d1e9b18 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py @@ -21,7 +21,7 @@ # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 -curriculum_version = "2.1rwdDelay" +curriculum_version = "2.1rwdDelay159" curriculum_description = '''2024-04-25 added reward delay; decrease no-lick delay in early training; use [0.1, 0.5, 0.9]''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" From 8e4b906a4b573a2b58d29fcc936e2b1ad407addf Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 18:01:06 -0700 Subject: [PATCH 07/13] feat: use the latest date --- .../curriculums/uncoupled_no_baiting_2p1rwdDelay159.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py index d1e9b18..56bfa30 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py @@ -22,7 +22,7 @@ # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 curriculum_version = "2.1rwdDelay159" -curriculum_description = '''2024-04-25 added reward delay; decrease no-lick delay in early training; use [0.1, 0.5, 0.9]''' +curriculum_description = '''2024-05-09 added reward delay; decrease no-lick delay in early training; use [0.1, 0.5, 0.9]''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" task_schema_version = "1.1.0" From 5ddeb940e348b4610e6ec8d5a288b4d829c82692 Mon Sep 17 00:00:00 2001 From: han-lab Date: Thu, 9 May 2024 19:07:13 -0700 Subject: [PATCH 08/13] feat: duplicate 2p1 curriculums --- .../curriculums/coupled_baiting_2p1.py | 418 ++++++++++++++++++ .../curriculums/uncoupled_baiting_2p1.py | 402 +++++++++++++++++ .../curriculums/uncoupled_no_baiting_2p1.py | 399 +++++++++++++++++ 3 files changed, 1219 insertions(+) create mode 100644 code/aind_auto_train/curriculums/coupled_baiting_2p1.py create mode 100644 code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py create mode 100644 code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py diff --git a/code/aind_auto_train/curriculums/coupled_baiting_2p1.py b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py new file mode 100644 index 0000000..0f79ad4 --- /dev/null +++ b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py @@ -0,0 +1,418 @@ +''' +Curriculum for Dynamic Foraging - Coupled Baiting +https://alleninstitute.sharepoint.com/:p:/s/NeuralDynamics/EQwuU0I4PBtGsU2wilCHklEBDTXYGT3F-QtaN6iDGJLBmg?e=N10dya + +Run the code to generate the curriculum.json and graphs + +''' + +# %% +from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT + +from aind_auto_train.schema.curriculum import ( + DynamicForagingCurriculum, StageTransitions, TransitionRule, + Decision +) +from aind_auto_train.schema.task import ( + Task, TrainingStage, DynamicForagingParas, + AutoWaterMode, AdvancedBlockMode +) + +curriculum_name = Task.C1B1 +curriculum_version = "2.0" +curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' + +task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" +task_schema_version = "1.1.0" + +# --- Parameters --- +# Stage 1 with warmup (classical Stage 1.1 + 1.2) +paras_stage_1_warmup = DynamicForagingParas( + # Metainfo + task_url=task_url, + task_schema_version=task_schema_version, + task=Task.C1B1, + training_stage=TrainingStage.STAGE_1_WARMUP, # "Phase B" in Han's slides + description="Warmup, followed by Phase B in Han's slides (block = [10, 20, 5], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Warmup ON + warmup='on', + warm_min_trial=50, + warm_max_choice_ratio_bias=0.1, + warm_min_finish_ratio=0.8, + warm_windowsize=20, + + # p_sum = 0.8, p_ratio = [1:0] + BaseRewardSum=0.8, + RewardFamily=3, + RewardPairsN=1, + + # block = [10, 20, 5] + BlockMin=10, + BlockMax=20, + BlockBeta=5, + BlockMinReward=0, + + # Small ITI at the beginning to better engage the animal + ITIMin=1, + ITIMax=7, + ITIBeta=3, + + # Add a (fixed) small delay period at the beginning # TODO: automate delay period + DelayMin=0.5, + DelayMax=0.5, + DelayBeta=0, + + # Reward size and reward delay + RewardDelay=0.0, + RightValue_volume=4.0, + LeftValue_volume=4.0, + + # -- Within session automation -- + # Auto water + AutoReward=True, + AutoWaterType=AutoWaterMode.NATURAL, + Unrewarded=3, + Ignored=3, + Multiplier=0.5, + + # Auto block + AdvancedBlockAuto=AdvancedBlockMode.NOW, + SwitchThr=0.5, + PointsInARow=5, + + # Auto stop; set StopIgnores to a large number at the beginning + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # -- Miscs -- + ResponseTime=5.0, # Very long response time at the beginning + RewardConsumeTime=1.0, # Shorter RewardConsumeTime to increase the number of trials + UncoupledReward="", # Only valid in uncoupled task +) + +transition_from_stage_1_warmup = StageTransitions( + from_stage=TrainingStage.STAGE_1_WARMUP, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ), + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_1, + condition_description="After the first session", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ) + ] +) + +# Stage 1 without warmup (classical 1.2) +paras_stage_1 = DynamicForagingParas( + **{ + **paras_stage_1_warmup.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_1, + description="Phase B in Han's slides (block = [10, 20, 5], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Turn off Warmup from now on + warmup='off', + + Unrewarded=5, + Ignored=5, + + # Decrease water size to 3.0 from now on + RightValue_volume=2.0, + LeftValue_volume=2.0, + ) + } +) + +transition_from_stage_1 = StageTransitions( + from_stage=TrainingStage.STAGE_1, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ) + ] +) + +# "Phase C" in Han's slides +paras_stage_2 = DynamicForagingParas( + **{ + **paras_stage_1.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_2, + description="Phase C in Han's slides (block = [10, 40, 10], p_sum = 0.6, p_ratio = [8:1])", + + # --- Only include changes compared to stage_1 --- + # -- Essentials -- + # p_sum = 0.8 --> 0.6, p_ratio = [1:0] -> [8:1] + BaseRewardSum=0.6, + RewardFamily=1, + RewardPairsN=1, + + # block length [10, 20, 5] --> [10, 40, 10] + BlockMin=10, + BlockMax=40, + BlockBeta=10, + + # ITI [1, 7, 3] --> [1, 10, 5] + ITIMin=1, + ITIMax=10, + ITIBeta=3, + + # Delay 0.5 --> 1.0 + DelayMin=1.0, + DelayMax=1.0, + + # -- Within session automation -- + # Decrease auto water: unrewarded 5 --> 10, ignored 5 --> 10 + Unrewarded=10, + Ignored=10, + + # Increase auto block switch threshold: 0.5 --> 0.6 + SwitchThr=0.6, + StopIgnores=50, # Auto stop on ignores-in-a-row starts to take effect + + # Miscs + ResponseTime=3, # Decrease response time: 5 --> 3 + ) + } +) + +transition_from_stage_2 = StageTransitions( + from_stage=TrainingStage.STAGE_2, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_3, + condition_description="Finished trials >= 300 and efficiency >= 0.65", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 300 + and + metrics.foraging_efficiency[-1] >= 0.65 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_1, + condition_description="Finished trials < 200 or efficiency < 0.55", + condition="""lambda metrics: + metrics.finished_trials[-1] < 200 + or + metrics.foraging_efficiency[-1] < 0.55 + """, + ), + ] +) + +# "Phase D" in Han's slides +paras_stage_3 = DynamicForagingParas( + **{ + **paras_stage_2.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_3, + description="Phase D in Han's slides (block = [10, 40, 10], p_sum = 0.45, p_ratio = [8:1])", + + # -- Essentials -- + # p_sum = 0.6 --> 0.45, p_ratio still [8:1] + BaseRewardSum=0.45, + + # block length [10, 40, 10] --> [20, 60, 20] + BlockMin=20, + BlockMax=60, + BlockBeta=20, + + # ITI [2, 10, 5] --> [3, 15, 5] + ITIMin=1, + ITIMax=15, + ITIBeta=3, + + # Delay 1.0 --> 1.5 + DelayMin=1.5, + DelayMax=1.5, + + # Decrease autowater number (almost turned off) + Unrewarded=15, + Ignored=15, + + # Miscs + ResponseTime=2, # Decrease response time: 3 --> 2 + ) + } +) + +transition_from_stage_3 = StageTransitions( + from_stage=TrainingStage.STAGE_3, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_FINAL, + condition_description="Finished trials >= 400 and efficiency >= 0.7", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 400 + and + metrics.foraging_efficiency[-1] >= 0.7 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials < 300 or efficiency < 0.65", + condition="""lambda metrics: + metrics.finished_trials[-1] < 300 + or + metrics.foraging_efficiency[-1] < 0.65 + """, + ), + ] +) + +# "Phase E" in Han's slides +paras_stage_final = DynamicForagingParas( + **{ + **paras_stage_3.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_FINAL, + description="Phase E in Han's slides (full task: block = [20, 60, 20], p_sum = 0.45, p_ratio = [8:1], [6:1], [3:1], [1:1])", + + # --- Here I explicitly list all parameters again just for clarity --- + # Essentials + + # Warmup OFF + warmup='off', + + # p_sum = 0.45, p_ratio = [8:1] --> [8:1], [6:1], [3:1], [1:1] + BaseRewardSum=0.45, + RewardFamily=1, + RewardPairsN=4, + + # block = [10, 20, 5] (mean ~ 33 trials) + BlockMin=20, + BlockMax=60, + BlockBeta=20, + BlockMinReward=0, + + # ITI [1, 15, 5] --> [1, 30, 5] (mean ~ 6.0 s, not included 1-s no lick window before ITI start) + ITIMin=1, + ITIMax=30, + ITIBeta=3, + + # Delay 1.5 --> 2.0 (Bari et al. 2019) + DelayMin=2.0, + DelayMax=2.0, + DelayBeta=0, + + # Reward size and reward delay + RewardDelay=0.0, + RightValue_volume=2.0, + LeftValue_volume=2.0, + + # Within session automation + AutoReward=False, # Turn off auto water + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + MaxTrial=1000, + MaxTime=90, + StopIgnores=50, + + # Miscs + ResponseTime=1.0, + RewardConsumeTime=3.0, + UncoupledReward="", # Only valid in uncoupled task + ) + } +) + +transition_from_stage_final = StageTransitions( + from_stage=TrainingStage.STAGE_FINAL, + transition_rules=[ + TransitionRule( + # For graduation, obviously we need more requirements. + decision=Decision.PROGRESS, + to_stage=TrainingStage.GRADUATED, + condition_description=("For recent 5 sessions," + "mean finished trials >= 500 and mean efficiency >= 0.70 " + "and total sessions >= 10 and sessions at final >= 5"), + condition="""lambda metrics: + metrics.session_total >= 10 + and + metrics.session_at_current_stage >= 5 + and + np.mean(metrics.finished_trials[-5:]) >= 500 + and + np.mean(metrics.foraging_efficiency[-5:]) >= 0.70 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_3, + condition_description="For recent 2 sessions, mean finished trials < 350 or efficiency < 0.65", + condition="""lambda metrics: + np.mean(metrics.finished_trials[-2:]) < 350 + or + np.mean(metrics.foraging_efficiency[-2:]) < 0.65 + """, + ), + ] +) + +# --- Curriculum --- +# %% +curriculum = DynamicForagingCurriculum( + curriculum_name=curriculum_name, + curriculum_version=curriculum_version, + curriculum_description=curriculum_description, + + parameters={ + TrainingStage.STAGE_1_WARMUP: paras_stage_1_warmup, + TrainingStage.STAGE_1: paras_stage_1, + TrainingStage.STAGE_2: paras_stage_2, + TrainingStage.STAGE_3: paras_stage_3, + TrainingStage.STAGE_FINAL: paras_stage_final, + TrainingStage.GRADUATED: paras_stage_final, + }, + + curriculum={ + TrainingStage.STAGE_1_WARMUP: transition_from_stage_1_warmup, + TrainingStage.STAGE_1: transition_from_stage_1, + TrainingStage.STAGE_2: transition_from_stage_2, + TrainingStage.STAGE_3: transition_from_stage_3, + TrainingStage.STAGE_FINAL: transition_from_stage_final, + }, + +) + +# %% +if __name__ == '__main__': + import os + + curriculum_path = LOCAL_SAVED_CURRICULUM_ROOT + os.makedirs(curriculum_path, exist_ok=True) + + # Save curriculum json and diagrams + curriculum.save_to_json(path=curriculum_path) + curriculum.diagram_rules(path=curriculum_path, + render_file_format='svg') + curriculum.diagram_paras(path=curriculum_path, + render_file_format='svg', + fontsize=12) diff --git a/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py new file mode 100644 index 0000000..eab7c87 --- /dev/null +++ b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py @@ -0,0 +1,402 @@ +''' +Curriculum for Dynamic Foraging - Uncoupled Baiting +Adapted from the Uncoupled Without Baiting curriculum +"draft 2, began using 10/17/23" +https://alleninstitute-my.sharepoint.com/:w:/g/personal/katrina_nguyen_alleninstitute_org/EUGu5FS565pLuHhqFYT9yfEBjF7tIDGVEmbwnmcCYJBoWw?e=wD8fX9 + +Run the code to generate the curriculum.json and graphs + +''' + +# %% +from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT + +from aind_auto_train.schema.curriculum import ( + DynamicForagingCurriculum, StageTransitions, TransitionRule, + Decision +) +from aind_auto_train.schema.task import ( + Task, TrainingStage, DynamicForagingParas, + AutoWaterMode, AdvancedBlockMode +) + +# Note this could be any string, not necessarily one of the Task enums +curriculum_name = "Uncoupled Baiting" +curriculum_version = "2.0" +curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' + +task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" +task_schema_version = "1.1.0" + +# --- Parameters --- +# Stage 1 with warmup (classical Stage 1.1 + 1.2) + +paras_stage_1_warmup = DynamicForagingParas( + # Metainfo + training_stage=TrainingStage.STAGE_1_WARMUP, + description="Warmup, followed by legendary Coupled Baiting Stage 1.2 (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Warmup ON + warmup='on', + warm_min_trial=50, + warm_max_choice_ratio_bias=0.1, + warm_min_finish_ratio=0.8, + warm_windowsize=20, + + # First session is ** coupled baiting ** + task_url=task_url, + task_schema_version=task_schema_version, + task=Task.C1B1, + + # p_sum = 0.8, p_ratio = [1:0] + BaseRewardSum=0.8, + RewardFamily=3, + RewardPairsN=1, + + # block = [10, 30, 10] + BlockMin=10, + BlockMax=30, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=1, + ITIMax=7, + ITIBeta=3, + + # Add a (fixed) small delay period at the beginning # TODO: automate delay period + DelayMin=0.5, + DelayMax=0.5, + DelayBeta=0, + + # Reward size and reward delay + RewardDelay=0.0, + RightValue_volume=4.0, + LeftValue_volume=4.0, + + # -- Within session automation -- + # Auto water + AutoReward=True, + AutoWaterType=AutoWaterMode.NATURAL, + Unrewarded=3, + Ignored=3, + Multiplier=0.5, + + # Auto block + AdvancedBlockAuto=AdvancedBlockMode.NOW, + SwitchThr=0.5, + PointsInARow=5, + + # Auto stop; set StopIgnores to a large number at the beginning + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # -- Miscs -- + ResponseTime=5.0, # Very long response time at the beginning + RewardConsumeTime=1.0, # Shorter RewardConsumeTime to increase the number of trials + UncoupledReward="", # Only valid in uncoupled task +) + +transition_from_stage_1_warmup = StageTransitions( + from_stage=TrainingStage.STAGE_1_WARMUP, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ), + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_1, + condition_description="After the first session", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ) + + ] +) + +# Stage 1 without warmup (classical 1.2) +paras_stage_1 = DynamicForagingParas( + **{ + **paras_stage_1_warmup.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_1, + description="Phase B in Han's slides (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Turn off Warmup from now on + warmup='off', + + Unrewarded=5, + Ignored=5, + + # Decrease water size to 2.0 from now on + RightValue_volume=2.0, + LeftValue_volume=2.0, + ) + } +) + +transition_from_stage_1 = StageTransitions( + from_stage=TrainingStage.STAGE_1, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ) + ] +) + +paras_stage_2 = DynamicForagingParas( + **{ + **paras_stage_1.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_2, + description="Coupled baiting (block = [20, 35, 10], p_sum = 0.8, p_ratio = [8:1])", + + # --- Only include changes compared to stage_1 --- + # -- Essentials -- + + # Coupled baiting + task=Task.C1B1, + + # p_ratio [1:0] -> [8:1] + RewardFamily=1, + RewardPairsN=1, + + # Decrease autowater + Unrewarded=10, + Ignored=10, + + # block length [10, 30, 10] --> [20, 35, 20] + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 7, 3] --> [1, 10, 3] + ITIMax=10, + + # Delay 0.5 --> 1.0 + DelayMin=1.0, + DelayMax=1.0, + + # -- Within session automation -- + # Miscs + ResponseTime=3.0, # Decrease response time: 5 --> 3 + ) + } +) + +transition_from_stage_2 = StageTransitions( + from_stage=TrainingStage.STAGE_2, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_3, + condition_description="Finished trials >= 300 and efficiency >= 0.65 and stay for >= 2 days", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 300 + and + metrics.foraging_efficiency[-1] >= 0.65 + and + metrics.session_at_current_stage >= 2 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_1, + condition_description="Finished trials < 200 or efficiency < 0.55", + condition="""lambda metrics: + metrics.finished_trials[-1] < 200 + or + metrics.foraging_efficiency[-1] < 0.55 + """, + ), + ] +) + +paras_stage_3 = DynamicForagingParas( + **{ + **paras_stage_2.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_3, + description="Switch to uncoupled but still baiting; p_rew = [0.1, 0.4, 0.7]; turn on auto water for 1 day", + + # -- Essentials -- + # Coupled baiting + task=Task.C0B1, + UncoupledReward="0.1, 0.4, 0.7", + + # Delay 1.0 --> 1.5 + DelayMin=1.5, + DelayMax=1.5, + DelayBeta=0.0, + + # Final block length for uncoupled task + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 10, 3] --> [1, 15, 3] + ITIMax=15, + + # Turn on auto water for the first day after switching to uncoupled task + AutoReward=True, + Unrewarded=15, # almost turned off + Ignored=15, # almost turned off + + # Turn off auto block + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + # -- Within session automation -- + # Miscs + ResponseTime=2.0, # Decrease response time: 3 --> 2 + + ) + } +) + +transition_from_stage_3 = StageTransitions( + from_stage=TrainingStage.STAGE_3, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_FINAL, + condition_description="Just stay for 1 day", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ), + # Once we reach here (C0B0), maybe we should not roll back to C1B0 or C1B1 anymore? + ] +) + +paras_stage_final = DynamicForagingParas( + **{ + **paras_stage_3.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_FINAL, + description="Uncoupled baiting; p_rew = [0.1, 0.4, 0.7]; turn off auto water", + + # Essentials + # Coupled baiting + task=Task.C0B1, + UncoupledReward="0.1, 0.4, 0.7", + + BlockMin=20, + BlockMax=35, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=1.0, + ITIMax=30.0, + ITIBeta=3.0, + + DelayMin=2.0, + DelayMax=2.0, + DelayBeta=0.0, + + RewardDelay=0, + + # Within session automation + AutoReward=False, # Turn off auto water + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # Miscs + ResponseTime=1.0, + RewardConsumeTime=3.0, + ) + } +) + +transition_from_stage_final = StageTransitions( + from_stage=TrainingStage.STAGE_FINAL, + transition_rules=[ + TransitionRule( + # For graduation, obviously we need more requirements. + decision=Decision.PROGRESS, + to_stage=TrainingStage.GRADUATED, + condition_description=("For recent 5 sessions," + "mean finished trials >= 500 and mean efficiency >= 0.70 " + "and total sessions >= 10 and sessions at final >= 5"), + condition="""lambda metrics: + metrics.session_total >= 10 + and + metrics.session_at_current_stage >= 5 + and + np.mean(metrics.finished_trials[-5:]) >= 500 + and + np.mean(metrics.foraging_efficiency[-5:]) >= 0.70 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_3, # Back to C0B0 with auto water + condition_description="For recent 2 sessions, mean finished trials < 300 or efficiency < 0.6", + condition="""lambda metrics: + np.mean(metrics.finished_trials[-2:]) < 300 + or + np.mean(metrics.foraging_efficiency[-2:]) < 0.6 + """, + ), + ] +) + +# --- Curriculum --- +# %% +curriculum = DynamicForagingCurriculum( + curriculum_name=curriculum_name, + curriculum_version=curriculum_version, + curriculum_description=curriculum_description, + + parameters={ + TrainingStage.STAGE_1_WARMUP: paras_stage_1_warmup, + TrainingStage.STAGE_1: paras_stage_1, + TrainingStage.STAGE_2: paras_stage_2, + TrainingStage.STAGE_3: paras_stage_3, + TrainingStage.STAGE_FINAL: paras_stage_final, + TrainingStage.GRADUATED: paras_stage_final, + }, + + curriculum={ + TrainingStage.STAGE_1_WARMUP: transition_from_stage_1_warmup, + TrainingStage.STAGE_1: transition_from_stage_1, + TrainingStage.STAGE_2: transition_from_stage_2, + TrainingStage.STAGE_3: transition_from_stage_3, + TrainingStage.STAGE_FINAL: transition_from_stage_final, + }, + +) + +# %% +if __name__ == '__main__': + import os + + curriculum_path = LOCAL_SAVED_CURRICULUM_ROOT + os.makedirs(curriculum_path, exist_ok=True) + + # Save curriculum json and diagrams + curriculum.save_to_json(path=curriculum_path) + curriculum.diagram_rules(path=curriculum_path, + render_file_format='svg') + curriculum.diagram_paras(path=curriculum_path, + render_file_format='svg', + fontsize=12) diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py new file mode 100644 index 0000000..e7c0843 --- /dev/null +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py @@ -0,0 +1,399 @@ +''' +Curriculum for Dynamic Foraging - Uncoupled without Baiting +Adopted from "draft 2, began using 10/17/23" +https://alleninstitute-my.sharepoint.com/:w:/g/personal/katrina_nguyen_alleninstitute_org/EUGu5FS565pLuHhqFYT9yfEBjF7tIDGVEmbwnmcCYJBoWw?e=wD8fX9 + +Run the code to generate the curriculum.json and graphs + +''' + +# %% +from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT + +from aind_auto_train.schema.curriculum import ( + DynamicForagingCurriculum, StageTransitions, TransitionRule, + Decision +) +from aind_auto_train.schema.task import ( + Task, TrainingStage, DynamicForagingParas, + AutoWaterMode, AdvancedBlockMode +) + +# Note this could be any string, not necessarily one of the Task enums +curriculum_name = Task.C0B0 +curriculum_version = "2.0" +curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' + +task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" +task_schema_version = "1.1.0" + +# --- Parameters --- +# Stage 1 with warmup (classical Stage 1.1 + 1.2) + +paras_stage_1_warmup = DynamicForagingParas( + # Metainfo + training_stage=TrainingStage.STAGE_1_WARMUP, + description="Warmup, followed by legendary Coupled Baiting Stage 1.2 (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Warmup ON + warmup='on', + warm_min_trial=50, + warm_max_choice_ratio_bias=0.1, + warm_min_finish_ratio=0.8, + warm_windowsize=20, + + # First session is ** coupled baiting ** + task_url=task_url, + task_schema_version=task_schema_version, + task=Task.C1B1, + + # p_sum = 0.8, p_ratio = [1:0] + BaseRewardSum=0.8, + RewardFamily=3, + RewardPairsN=1, + + # block = [10, 30, 10] + BlockMin=10, + BlockMax=30, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=1, + ITIMax=7, + ITIBeta=3, + + # Add a (fixed) small delay period at the beginning # TODO: automate delay period + DelayMin=0.5, + DelayMax=0.5, + DelayBeta=0, + + # Reward size and reward delay + RewardDelay=0.0, + RightValue_volume=4.0, + LeftValue_volume=4.0, + + # -- Within session automation -- + # Auto water + AutoReward=True, + AutoWaterType=AutoWaterMode.NATURAL, + Unrewarded=3, + Ignored=3, + Multiplier=0.5, + + # Auto block + AdvancedBlockAuto=AdvancedBlockMode.NOW, + SwitchThr=0.5, + PointsInARow=5, + + # Auto stop; set StopIgnores to a large number at the beginning + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # -- Miscs -- + ResponseTime=5.0, # Very long response time at the beginning + RewardConsumeTime=1.0, # Shorter RewardConsumeTime to increase the number of trials + UncoupledReward="", # Only valid in uncoupled task +) + +transition_from_stage_1_warmup = StageTransitions( + from_stage=TrainingStage.STAGE_1_WARMUP, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ), + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_1, + condition_description="After the first session", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ) + + ] +) + +# Stage 1 without warmup (classical 1.2) +paras_stage_1 = DynamicForagingParas( + **{ + **paras_stage_1_warmup.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_1, + description="Phase B in Han's slides (block = [10, 30, 10], p_sum = 0.8, p_ratio = [1:0])", + + # -- Essentials -- + # Turn off Warmup from now on + warmup='off', + + Unrewarded=5, + Ignored=5, + + # Decrease water size to 2.0 from now on + RightValue_volume=2.0, + LeftValue_volume=2.0, + ) + } +) + +transition_from_stage_1 = StageTransitions( + from_stage=TrainingStage.STAGE_1, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_2, + condition_description="Finished trials >= 200 and efficiency >= 0.6", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 200 + and + metrics.foraging_efficiency[-1] >= 0.6 + """, + ) + ] +) + +paras_stage_2 = DynamicForagingParas( + **{ + **paras_stage_1.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_2, + description="Coupled without baiting (block = [20, 35, 10], p_sum = 0.8, p_ratio = [8:1])", + + # --- Only include changes compared to stage_1 --- + # -- Essentials -- + + # Coupled no baiting + task=Task.C1B0, + + # p_ratio [1:0] -> [8:1] + RewardFamily=1, + RewardPairsN=1, + + # Decrease autowater + Unrewarded=10, + Ignored=10, + + # block length [10, 30, 10] --> [20, 35, 20] + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 7, 3] --> [1, 10, 3] + ITIMax=10, + + # Delay 0.5 --> 1.0 + DelayMin=1.0, + DelayMax=1.0, + + # -- Within session automation -- + # Miscs + ResponseTime=3.0, # Decrease response time: 5 --> 3 + ) + } +) + +transition_from_stage_2 = StageTransitions( + from_stage=TrainingStage.STAGE_2, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_3, + condition_description="Finished trials >= 300 and efficiency >= 0.65 and stay for >= 2 days", + condition="""lambda metrics: + metrics.finished_trials[-1] >= 300 + and + metrics.foraging_efficiency[-1] >= 0.65 + and + metrics.session_at_current_stage >= 2 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_1, + condition_description="Finished trials < 200 or efficiency < 0.55", + condition="""lambda metrics: + metrics.finished_trials[-1] < 200 + or + metrics.foraging_efficiency[-1] < 0.55 + """, + ), + ] +) + +paras_stage_3 = DynamicForagingParas( + **{ + **paras_stage_2.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_3, + description="Switch to uncoupled; p_rew = [0.1, 0.4, 0.7]; turn on auto water for 1 day", + + # -- Essentials -- + # Coupled no baiting + task=Task.C0B0, + UncoupledReward="0.1, 0.4, 0.7", + + # Delay 1.0 --> 1.5 + DelayMin=1.5, + DelayMax=1.5, + DelayBeta=0.0, + + # Final block length for uncoupled task + BlockMin=20, + BlockMax=35, + BlockBeta=10, + + # ITI [1, 10, 3] --> [1, 15, 3] + ITIMax=15, + + # Turn on auto water for the first day after switching to uncoupled task + AutoReward=True, + Unrewarded=15, # almost turned off + Ignored=15, # almost turned off + + # Turn off auto block + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + # Miscs + ResponseTime=2.0, # Decrease response time: 3 --> 2 + ) + } +) + +transition_from_stage_3 = StageTransitions( + from_stage=TrainingStage.STAGE_3, + transition_rules=[ + TransitionRule( + decision=Decision.PROGRESS, + to_stage=TrainingStage.STAGE_FINAL, + condition_description="Just stay for 1 day", + condition="""lambda metrics: + metrics.session_at_current_stage >= 1 + """, + ), + # Once we reach here (C0B0), maybe we should not roll back to C1B0 or C1B1 anymore? + ] +) + +paras_stage_final = DynamicForagingParas( + **{ + **paras_stage_3.model_dump(), + **dict( + training_stage=TrainingStage.STAGE_FINAL, + description="Uncoupled without baiting; p_rew = [0.1, 0.4, 0.7]; turn off auto water", + + # Essentials + # Coupled no baiting + task=Task.C0B0, + UncoupledReward="0.1, 0.4, 0.7", + + BlockMin=20, + BlockMax=35, + BlockBeta=10, + BlockMinReward=0, + + ITIMin=1.0, + ITIMax=30.0, + ITIBeta=3.0, + + DelayMin=2.0, + DelayMax=2.0, + DelayBeta=0.0, + + RewardDelay=0, + + # Within session automation + AutoReward=False, # Turn off auto water + AdvancedBlockAuto=AdvancedBlockMode.OFF, # Turn off auto block + + MaxTrial=1000, + MaxTime=90, + StopIgnores=20000, + + # Miscs + ResponseTime=1.0, + RewardConsumeTime=3.0, + ) + } +) + +transition_from_stage_final = StageTransitions( + from_stage=TrainingStage.STAGE_FINAL, + transition_rules=[ + TransitionRule( + # For graduation, obviously we need more requirements. + decision=Decision.PROGRESS, + to_stage=TrainingStage.GRADUATED, + condition_description=("For recent 5 sessions," + "mean finished trials >= 500 and mean efficiency >= 0.70 " + "and total sessions >= 10 and sessions at final >= 5"), + condition="""lambda metrics: + metrics.session_total >= 10 + and + metrics.session_at_current_stage >= 5 + and + np.mean(metrics.finished_trials[-5:]) >= 500 + and + np.mean(metrics.foraging_efficiency[-5:]) >= 0.70 + """, + ), + TransitionRule( + decision=Decision.ROLLBACK, + to_stage=TrainingStage.STAGE_3, # Back to C0B0 with auto water + condition_description="For recent 2 sessions, mean finished trials < 300 or efficiency < 0.6", + condition="""lambda metrics: + np.mean(metrics.finished_trials[-2:]) < 300 + or + np.mean(metrics.foraging_efficiency[-2:]) < 0.6 + """, + ), + ] +) + +# --- Curriculum --- +# %% +curriculum = DynamicForagingCurriculum( + curriculum_name=curriculum_name, + curriculum_version=curriculum_version, + curriculum_description=curriculum_description, + + parameters={ + TrainingStage.STAGE_1_WARMUP: paras_stage_1_warmup, + TrainingStage.STAGE_1: paras_stage_1, + TrainingStage.STAGE_2: paras_stage_2, + TrainingStage.STAGE_3: paras_stage_3, + TrainingStage.STAGE_FINAL: paras_stage_final, + TrainingStage.GRADUATED: paras_stage_final, + }, + + curriculum={ + TrainingStage.STAGE_1_WARMUP: transition_from_stage_1_warmup, + TrainingStage.STAGE_1: transition_from_stage_1, + TrainingStage.STAGE_2: transition_from_stage_2, + TrainingStage.STAGE_3: transition_from_stage_3, + TrainingStage.STAGE_FINAL: transition_from_stage_final, + }, + +) + +# %% +if __name__ == '__main__': + import os + + curriculum_path = LOCAL_SAVED_CURRICULUM_ROOT + os.makedirs(curriculum_path, exist_ok=True) + + # Save curriculum json and diagrams + curriculum.save_to_json(path=curriculum_path) + curriculum.diagram_rules(path=curriculum_path, + render_file_format='svg') + curriculum.diagram_paras(path=curriculum_path, + render_file_format='svg', + fontsize=12) From 21b279cf506ee16acf0160caf93e7e469dfe0908 Mon Sep 17 00:00:00 2001 From: hh_itx_win10 Date: Fri, 10 May 2024 13:38:47 -0700 Subject: [PATCH 09/13] chores: improve logging --- code/aind_auto_train/curriculums/coupled_baiting_1p0.py | 2 ++ code/aind_auto_train/curriculums/coupled_baiting_2p0.py | 2 ++ code/aind_auto_train/curriculums/dummy_task.py | 2 ++ code/aind_auto_train/curriculums/dummy_task_0p2.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_baiting_1p0.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_baiting_2p0.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_no_baiting_1p0.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0.py | 2 ++ .../curriculums/uncoupled_no_baiting_2p1rwdDelay159.py | 2 ++ 9 files changed, 18 insertions(+) diff --git a/code/aind_auto_train/curriculums/coupled_baiting_1p0.py b/code/aind_auto_train/curriculums/coupled_baiting_1p0.py index 92d8af8..0b5989a 100644 --- a/code/aind_auto_train/curriculums/coupled_baiting_1p0.py +++ b/code/aind_auto_train/curriculums/coupled_baiting_1p0.py @@ -8,6 +8,8 @@ # %% from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT +from aind_auto_train import setup_logging +setup_logging() from aind_auto_train.schema.curriculum import ( DynamicForagingCurriculum, StageTransitions, TransitionRule, diff --git a/code/aind_auto_train/curriculums/coupled_baiting_2p0.py b/code/aind_auto_train/curriculums/coupled_baiting_2p0.py index 0f79ad4..a2adef6 100644 --- a/code/aind_auto_train/curriculums/coupled_baiting_2p0.py +++ b/code/aind_auto_train/curriculums/coupled_baiting_2p0.py @@ -8,6 +8,8 @@ # %% from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT +from aind_auto_train import setup_logging +setup_logging() from aind_auto_train.schema.curriculum import ( DynamicForagingCurriculum, StageTransitions, TransitionRule, diff --git a/code/aind_auto_train/curriculums/dummy_task.py b/code/aind_auto_train/curriculums/dummy_task.py index 943c139..eafcf06 100644 --- a/code/aind_auto_train/curriculums/dummy_task.py +++ b/code/aind_auto_train/curriculums/dummy_task.py @@ -6,6 +6,8 @@ from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT from aind_auto_train.schema.task import Task, TrainingStage, DummyTaskParas, DummyTaskMetrics from aind_auto_train.schema.curriculum import DummyTaskCurriculum, StageTransitions, TransitionRule, Decision +from aind_auto_train import setup_logging +setup_logging() meta = dict(task_schema_version="0.1", diff --git a/code/aind_auto_train/curriculums/dummy_task_0p2.py b/code/aind_auto_train/curriculums/dummy_task_0p2.py index 54f1476..c914cea 100644 --- a/code/aind_auto_train/curriculums/dummy_task_0p2.py +++ b/code/aind_auto_train/curriculums/dummy_task_0p2.py @@ -6,6 +6,8 @@ from aind_auto_train.curriculum_manager import LOCAL_SAVED_CURRICULUM_ROOT from aind_auto_train.schema.task import Task, TrainingStage, DummyTaskParas, DummyTaskMetrics from aind_auto_train.schema.curriculum import DummyTaskCurriculum, StageTransitions, TransitionRule, Decision +from aind_auto_train import setup_logging +setup_logging() meta = dict(task_schema_version="0.1", diff --git a/code/aind_auto_train/curriculums/uncoupled_baiting_1p0.py b/code/aind_auto_train/curriculums/uncoupled_baiting_1p0.py index 5626cb9..087c55b 100644 --- a/code/aind_auto_train/curriculums/uncoupled_baiting_1p0.py +++ b/code/aind_auto_train/curriculums/uncoupled_baiting_1p0.py @@ -19,6 +19,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = "Uncoupled Baiting" diff --git a/code/aind_auto_train/curriculums/uncoupled_baiting_2p0.py b/code/aind_auto_train/curriculums/uncoupled_baiting_2p0.py index eab7c87..1b3b94d 100644 --- a/code/aind_auto_train/curriculums/uncoupled_baiting_2p0.py +++ b/code/aind_auto_train/curriculums/uncoupled_baiting_2p0.py @@ -19,6 +19,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = "Uncoupled Baiting" diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_1p0.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_1p0.py index 7690606..0cf1630 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_1p0.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_1p0.py @@ -18,6 +18,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0.py index e7c0843..53b484f 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p0.py @@ -18,6 +18,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py index d1e9b18..8a9c02b 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1rwdDelay159.py @@ -18,6 +18,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 From 4c976188702fa643d6ef9e3ab538533ab4b9a625 Mon Sep 17 00:00:00 2001 From: han-lab Date: Fri, 10 May 2024 14:25:51 -0700 Subject: [PATCH 10/13] feat: create 2p1 that decreases delay period --- .../curriculums/coupled_baiting_2p1.py | 26 +++++++++---------- .../curriculums/uncoupled_baiting_2p1.py | 22 +++++++--------- .../curriculums/uncoupled_no_baiting_2p1.py | 23 ++++++++-------- 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/code/aind_auto_train/curriculums/coupled_baiting_2p1.py b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py index 0f79ad4..0f4f45d 100644 --- a/code/aind_auto_train/curriculums/coupled_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py @@ -19,8 +19,8 @@ ) curriculum_name = Task.C1B1 -curriculum_version = "2.0" -curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' +curriculum_version = "2.1" +curriculum_description = '''2024-05-09 decrease delay period as we now use much longer early lick punishment''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" task_schema_version = "1.1.0" @@ -60,8 +60,8 @@ ITIBeta=3, # Add a (fixed) small delay period at the beginning # TODO: automate delay period - DelayMin=0.5, - DelayMax=0.5, + DelayMin=0.1, + DelayMax=0.1, DelayBeta=0, # Reward size and reward delay @@ -180,9 +180,8 @@ ITIMax=10, ITIBeta=3, - # Delay 0.5 --> 1.0 - DelayMin=1.0, - DelayMax=1.0, + DelayMin=0.3, + DelayMax=0.3, # -- Within session automation -- # Decrease auto water: unrewarded 5 --> 10, ignored 5 --> 10 @@ -247,9 +246,9 @@ ITIMax=15, ITIBeta=3, - # Delay 1.0 --> 1.5 - DelayMin=1.5, - DelayMax=1.5, + DelayMin=0.5, + DelayMax=0.5, + DelayBeta=0.0, # Decrease autowater number (almost turned off) Unrewarded=15, @@ -317,10 +316,9 @@ ITIMax=30, ITIBeta=3, - # Delay 1.5 --> 2.0 (Bari et al. 2019) - DelayMin=2.0, - DelayMax=2.0, - DelayBeta=0, + DelayMin=1.0, + DelayMax=1.0, + DelayBeta=0.0, # Reward size and reward delay RewardDelay=0.0, diff --git a/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py index eab7c87..54b4a17 100644 --- a/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py @@ -22,8 +22,8 @@ # Note this could be any string, not necessarily one of the Task enums curriculum_name = "Uncoupled Baiting" -curriculum_version = "2.0" -curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' +curriculum_version = "2.1" +curriculum_description = '''2024-05-09 decrease delay period as we now use much longer early lick punishment''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" task_schema_version = "1.1.0" @@ -65,8 +65,8 @@ ITIBeta=3, # Add a (fixed) small delay period at the beginning # TODO: automate delay period - DelayMin=0.5, - DelayMax=0.5, + DelayMin=0.1, + DelayMax=0.1, DelayBeta=0, # Reward size and reward delay @@ -190,9 +190,8 @@ # ITI [1, 7, 3] --> [1, 10, 3] ITIMax=10, - # Delay 0.5 --> 1.0 - DelayMin=1.0, - DelayMax=1.0, + DelayMin=0.3, + DelayMax=0.3, # -- Within session automation -- # Miscs @@ -241,9 +240,8 @@ task=Task.C0B1, UncoupledReward="0.1, 0.4, 0.7", - # Delay 1.0 --> 1.5 - DelayMin=1.5, - DelayMax=1.5, + DelayMin=0.5, + DelayMax=0.5, DelayBeta=0.0, # Final block length for uncoupled task @@ -306,8 +304,8 @@ ITIMax=30.0, ITIBeta=3.0, - DelayMin=2.0, - DelayMax=2.0, + DelayMin=1.0, + DelayMax=1.0, DelayBeta=0.0, RewardDelay=0, diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py index e7c0843..cf49b91 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py @@ -21,8 +21,8 @@ # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 -curriculum_version = "2.0" -curriculum_description = '''2024-04-12 decreased reward size and higher standard for graduation''' +curriculum_version = "2.1" +curriculum_description = '''2024-05-09 decrease delay period as we now use much longer early lick punishment''' task_url = "https://github.com/AllenNeuralDynamics/dynamic-foraging-task" task_schema_version = "1.1.0" @@ -64,8 +64,8 @@ ITIBeta=3, # Add a (fixed) small delay period at the beginning # TODO: automate delay period - DelayMin=0.5, - DelayMax=0.5, + DelayMin=0.1, + DelayMax=0.1, DelayBeta=0, # Reward size and reward delay @@ -189,9 +189,9 @@ # ITI [1, 7, 3] --> [1, 10, 3] ITIMax=10, - # Delay 0.5 --> 1.0 - DelayMin=1.0, - DelayMax=1.0, + # Delay still 0.1 + DelayMin=0.3, + DelayMax=0.3, # -- Within session automation -- # Miscs @@ -240,9 +240,8 @@ task=Task.C0B0, UncoupledReward="0.1, 0.4, 0.7", - # Delay 1.0 --> 1.5 - DelayMin=1.5, - DelayMax=1.5, + DelayMin=0.5, + DelayMax=0.5, DelayBeta=0.0, # Final block length for uncoupled task @@ -303,8 +302,8 @@ ITIMax=30.0, ITIBeta=3.0, - DelayMin=2.0, - DelayMax=2.0, + DelayMin=1.0, + DelayMax=1.0, DelayBeta=0.0, RewardDelay=0, From 1af5c324c02cb9060f90f0cda86f6b76a997fa43 Mon Sep 17 00:00:00 2001 From: hh_itx_win10 Date: Fri, 10 May 2024 14:28:17 -0700 Subject: [PATCH 11/13] chores: add logging --- code/aind_auto_train/curriculums/coupled_baiting_2p1.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py | 2 ++ code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/code/aind_auto_train/curriculums/coupled_baiting_2p1.py b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py index 0f4f45d..338fb3f 100644 --- a/code/aind_auto_train/curriculums/coupled_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/coupled_baiting_2p1.py @@ -17,6 +17,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() curriculum_name = Task.C1B1 curriculum_version = "2.1" diff --git a/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py index 54b4a17..c8a7b00 100644 --- a/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/uncoupled_baiting_2p1.py @@ -19,6 +19,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = "Uncoupled Baiting" diff --git a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py index cf49b91..815c127 100644 --- a/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py +++ b/code/aind_auto_train/curriculums/uncoupled_no_baiting_2p1.py @@ -18,6 +18,8 @@ Task, TrainingStage, DynamicForagingParas, AutoWaterMode, AdvancedBlockMode ) +from aind_auto_train import setup_logging +setup_logging() # Note this could be any string, not necessarily one of the Task enums curriculum_name = Task.C0B0 From f988fe0bbd66518cd2c493c883cddda3f0fbe3a6 Mon Sep 17 00:00:00 2001 From: hh_itx_win10 Date: Fri, 10 May 2024 14:36:13 -0700 Subject: [PATCH 12/13] fix: allow regular expression in curriculum_manager to accept arbitrary version sting --- code/aind_auto_train/curriculum_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/aind_auto_train/curriculum_manager.py b/code/aind_auto_train/curriculum_manager.py index 2ab446f..e4b7a73 100644 --- a/code/aind_auto_train/curriculum_manager.py +++ b/code/aind_auto_train/curriculum_manager.py @@ -56,7 +56,7 @@ def df_curriculums(self) -> pd.DataFrame: schema_version_code_base = curriculum_schemas.Curriculum.model_fields['curriculum_schema_version'].default for f in self.json_files: - match = re.search(r'(.+)_curriculum_v([\d.]+)_schema_v([\d.]+)\.json', + match = re.search(r'(.+)_curriculum_v(.+)_schema_v(.+)\.json', os.path.basename(f)) if match is None: logger.warning( From 0bb7dfe5e5534ee76a63c7f7c88f96ef0ceb4b12 Mon Sep 17 00:00:00 2001 From: hh_itx_win10 Date: Fri, 10 May 2024 14:36:46 -0700 Subject: [PATCH 13/13] ci: bump version --- code/aind_auto_train/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/aind_auto_train/__init__.py b/code/aind_auto_train/__init__.py index 56dc916..30d9708 100644 --- a/code/aind_auto_train/__init__.py +++ b/code/aind_auto_train/__init__.py @@ -1,4 +1,4 @@ -__version__ = "1.0.1" +__version__ = "1.1.0" import logging