diff --git a/README.md b/README.md index 70ab553..c01f1ff 100755 --- a/README.md +++ b/README.md @@ -1,2 +1,25 @@ # RPi4_behavior_boxes BehavBox is a system with Raspberry Pi computers that is sufficient to provide a foundation of constructing animal behavior training and experiment. + +# Quick Start +in task_protocol, you could find all the task examples. Each task has its run file, task file, task information file and an example of session_information file. + +To start running a task file, you need to first create a session_information pathway and session_information file in a path (suggested) in the home directory and outside of the git repo since you would have to configure and changes the file everyday for training purposes. + +After configure the session_information path and input the appropriate path leading to the exact session_information of the date, you could do python3 run_x_task.py to start running the task. + +# Example +To start running the task `headfixed_task.py` +1. Setup and configure the 'session_information_year-month-date.py' file: +first, create the experimental_data directory in the home directory path:
+`$ mkdir ~/experimental_data`
+second, create all the necessary subdirectories for the specific task:
+`$ mkdir ~/experimental_data/headfixed_task`
+`$ mkdir ~/experimental_data/headfixed_task/session_info`
+then, copy the session_information example file corresponding to the specific task:
+`$ cp ~/RPi4_behavbior_boxes/task_protocol/headfixed_task/session_info_headfixed_independent_reward.py ~/experimental_data/headfixed_task/session_info`
+2. Modify the newly created session_info file:
+`$ sudo nano ~/experimental_data/headfixed_task/session_info_headfixed_independent_reward.py`
+**KEEP IN MIND** after configuring the session_information to manually change the field manual date to the day of the experiment session (the day of the experiment), and the name of the session_info file from `session_info_headfixed_independent_reward.py` to `session_info_year-month-date.py`. Otherwise, an error would occur when running the task file. +3. After setting up the session_info file, run the task:
+`$ python3 ~/RPi4_behavior_boxes/task_protocol/headfixed_task/run_headfixed_task.py` \ No newline at end of file diff --git a/picamera_library_modified/picamera.egg-info/dependency_links.txt b/debug/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from picamera_library_modified/picamera.egg-info/dependency_links.txt rename to debug/__init__.py diff --git a/calibrate.py b/debug/calibrate.py similarity index 100% rename from calibrate.py rename to debug/calibrate.py diff --git a/camera_test.py b/debug/camera_test.py similarity index 100% rename from camera_test.py rename to debug/camera_test.py diff --git a/control_preview.py b/debug/control_preview.py similarity index 100% rename from control_preview.py rename to debug/control_preview.py diff --git a/debug/generate_reward_trajectory.py b/debug/generate_reward_trajectory.py new file mode 100644 index 0000000..4d2cbed --- /dev/null +++ b/debug/generate_reward_trajectory.py @@ -0,0 +1,45 @@ +def cumsum_positive(input_list): + for index in range(len(input_list)): + if index == 0 and input_list[index]<0: + input_list[index] = -input_list[index] + elif input_list[index]+input_list[index-1]<0: + input_list[index] = input_list[index] - input_list[index-1] + else: + input_list[index] = input_list[index] + input_list[index-1] + return input_list + +def generate_reward_trajectory(scale=0.5, offset=3.0, change_point=20, ntrials=200): + # initial reward (need to be random) + rewards_L = [1] + rewards_R = [1] + for a in np.arange(np.round(ntrials / change_point)): + temp = np.random.randn(change_point) * scale + # temp = np.random.uniform(low=0.0, high=10, size=(change_point,)) + + # print("ay o" + str(temp)) + # while temp < 0: + # temp = np.random.randn(change_point) * scale + rewards_L.append(cumsum_positive(temp) + offset) + temp = np.random.randn(change_point) * scale + # temp = np.random.uniform(low=0.0, high=10, size=(change_point,)) + # while temp < 0: + # temp = np.random.randn(change_point) * scale + rewards_R.append(cumsum_positive(temp) + offset) + rewards_L = np.hstack(rewards_L) + rewards_R = np.hstack(rewards_R) + # plt.plot(rewards_L,'b');plt.plot(rewards_R,'r--') + reward_LR = [rewards_L, rewards_R] + reward_LR = np.transpose(np.array(reward_LR)) + reward_LR = reward_LR[0:ntrials, :] + # print(reward_LR) + return reward_LR + +# from reward_distribution import generate_reward_trajectory +scale = 0.5 +offset = 3.0 +change_point = 20 +ntrials = 100 + +reward_distribution_list = generate_reward_trajectory(scale, offset, change_point, ntrials) + +print(reward_distribution_list) \ No newline at end of file diff --git a/mounting_hard_drive.txt b/debug/mounting_hard_drive.txt similarity index 100% rename from mounting_hard_drive.txt rename to debug/mounting_hard_drive.txt diff --git a/press_button.py b/debug/press_button.py similarity index 100% rename from press_button.py rename to debug/press_button.py diff --git a/pump_debug.py b/debug/pump_debug.py similarity index 70% rename from pump_debug.py rename to debug/pump_debug.py index 946f369..dc0beda 100755 --- a/pump_debug.py +++ b/debug/pump_debug.py @@ -1,6 +1,9 @@ # pump_debug.py: it's for testing the pump class and the pump itself import sys import time +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') from behavbox import Pump # from fake_session_info import fake_session_info side = str(sys.argv[1]) diff --git a/pygame_debug.py b/debug/pygame_debug.py similarity index 100% rename from pygame_debug.py rename to debug/pygame_debug.py diff --git a/record_treadmill.py b/debug/record_treadmill.py similarity index 100% rename from record_treadmill.py rename to debug/record_treadmill.py diff --git a/record_video.py b/debug/record_video.py similarity index 100% rename from record_video.py rename to debug/record_video.py diff --git a/debug/reward_distribution.py b/debug/reward_distribution.py new file mode 100644 index 0000000..8a066b2 --- /dev/null +++ b/debug/reward_distribution.py @@ -0,0 +1,24 @@ +import numpy as np + +def generate_reward_trajectory(scale=0.5, offset=3.0, change_point=20, ntrials=200): + # initial reward (need to be random) + rewards_L = [1] + rewards_R = [1] + for a in np.arange(np.round(ntrials/change_point)): + temp = np.random.randn(change_point)*scale + rewards_L.append(np.cumsum(temp, axis=-1) + offset) + temp = np.random.randn(change_point)*scale + rewards_R.append(np.cumsum(temp, axis=-1) + offset) + rewards_L=np.hstack(rewards_L) + rewards_R=np.hstack(rewards_R) + #plt.plot(rewards_L,'b');plt.plot(rewards_R,'r--') + reward_LR = [rewards_L, rewards_R] + reward_LR = np.transpose(np.array(reward_LR)) + reward_LR = reward_LR[0:ntrials,:] + print(reward_LR) + return reward_LR +# generate_reward_trajectory() +# session_information['reward']['scale'] +# session_information['reward']['offset'] +# session_information['reward']['change_point'] +# session_information['reward']['ntrials'] \ No newline at end of file diff --git a/debug/syringe_pump_pygame_debug.py b/debug/syringe_pump_pygame_debug.py new file mode 100644 index 0000000..14cfaed --- /dev/null +++ b/debug/syringe_pump_pygame_debug.py @@ -0,0 +1,93 @@ +import pygame +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') +from behavbox import Pump +import numpy as np + +class Pump(object): + def __init__(self, session_info): + self.pump1 = LED(19) + self.pump2 = LED(20) + self.pump3 = LED(21) + self.pump4 = LED(7) + self.pump_air = LED(8) + self.pump_vacuum = LED(25) + self.reward_list = [] # a list of tuple (pump_x, reward_amount) with information of reward history for data + # visualization + + def reward(self, which_pump, reward_size): + # import coefficient from the session_information + coefficient_p1 = [0.13, 0] + coefficient_p2 = [0.13, 0] + coefficient_p3 = [0.13, 0] + coefficient_p4 = [0.13, 0] + duration_air = 1 + duration_vac = 1 + + if which_pump == "1": + duration = round((coefficient_p1[0] * (reward_size / 1000) + coefficient_p1[1]), 5) # linear function + self.pump1.blink(duration, 0.1, 1) + self.reward_list.append(("pump1_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump1_reward(reward_coeff: " + str(coefficient_p1) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "2": + duration = round((coefficient_p2[0] * (reward_size / 1000) + coefficient_p2[1]), 5) # linear function + self.pump2.blink(duration, 0.1, 1) + self.reward_list.append(("pump2_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump2_reward(reward_coeff: " + str(coefficient_p2) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "3": + duration = round((coefficient_p3[0] * (reward_size / 1000) + coefficient_p3[1]), 5) # linear function + self.pump3.blink(duration, 0.1, 1) + self.reward_list.append(("pump3_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump3_reward(reward_coeff: " + str(coefficient_p3) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "4": + duration = round((coefficient_p4[0] * (reward_size / 1000) + coefficient_p4[1]), 5) # linear function + self.pump4.blink(duration, 0.1, 1) + self.reward_list.append(("pump4_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump4_reward(reward_coeff: " + str(coefficient_p4) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "air_puff": + self.pump_air.blink(duration_air, 0.1, 1) + self.reward_list.append(("air_puff", reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump4_reward_" + str(reward_size)) + elif which_pump == "vacuum": + self.pump_vacuum.blink(duration_vac, 0.1, 1) + logging.info(";" + str(time.time()) + ";[reward];pump_vacuum" + str(duration_vac)) +try: + pump = Pump() + pygame.init() + DISPLAYSURF = pygame.display.set_mode((200, 200)) + pygame.display.set_caption("pygame debugging") +except Exception as error_message: + print(str(error_message)) + +run = True +reward_size = float(input("Input reward_size: ")) + +while run: + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: + run = False + if event.type == pygame.KEYDOWN: + # print("KeyDown: " + str(event.type) + "\n") + if event.key == pygame.K_q: + print("Q down: syringe pump 1") + pump.reward("1", reward_size) + if event.key == pygame.K_w: + print("W down: syringe pump 2") + pump.reward("2", reward_size) + if event.key == pygame.K_e: + print("E down: syringe pump 3") + pump.reward("3", reward_size) + if event.key == pygame.K_r: + print("R down: syringe pump 4") + pump.reward("4", reward_size) + if event.key == pygame.K_a: + print("A down: air puff on") + pump.reward("air_puff", reward_size) + if event.key == pygame.K_s: + print("S down: vacuum on") + pump.reward("vacuum", 1) \ No newline at end of file diff --git a/treadmill_debug.py b/debug/treadmill_debug.py similarity index 100% rename from treadmill_debug.py rename to debug/treadmill_debug.py diff --git a/environment/__init__.py b/environment/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/environment/__init__.py @@ -0,0 +1 @@ + diff --git a/essential/ADC/__init__.py b/essential/ADC/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/ADC/__init__.py @@ -0,0 +1 @@ + diff --git a/ADC/readme.md b/essential/ADC/readme.md similarity index 100% rename from ADC/readme.md rename to essential/ADC/readme.md diff --git a/ADS1x15.py b/essential/ADS1x15.py similarity index 100% rename from ADS1x15.py rename to essential/ADS1x15.py diff --git a/FlipperOutput.py b/essential/FlipperOutput.py similarity index 100% rename from FlipperOutput.py rename to essential/FlipperOutput.py diff --git a/essential/RTC/__init__.py b/essential/RTC/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/RTC/__init__.py @@ -0,0 +1 @@ + diff --git a/RTC/readme.md b/essential/RTC/readme.md similarity index 100% rename from RTC/readme.md rename to essential/RTC/readme.md diff --git a/Treadmill.py b/essential/Treadmill.py similarity index 100% rename from Treadmill.py rename to essential/Treadmill.py diff --git a/essential/__init__.py b/essential/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/__init__.py @@ -0,0 +1 @@ + diff --git a/behavbox.py b/essential/behavbox.py similarity index 69% rename from behavbox.py rename to essential/behavbox.py index caeb719..d8aebf2 100755 --- a/behavbox.py +++ b/essential/behavbox.py @@ -104,13 +104,33 @@ def __init__(self, session_info): # there is a DIO6, but that is the same pin as the camera strobe ############################################################################################### - # IR detection - for nosepoke detection + # IR detection - for nosepoke + ############################################################################################### + self.IR_rx1 = Button(5, None, True) # None, True inverts the signal so poke=True, no-poke=False + self.IR_rx2 = Button(6, None, True) + self.IR_rx3 = Button(12, None, True) + self.IR_rx4 = Button(13, None, True) # (optional, reserved for future use + self.IR_rx5 = Button(16, None, True) # (optional, reserved for future use + + # link nosepoke event detections to callbacks + self.IR_rx1.when_pressed = self.IR_1_entry + self.IR_rx2.when_pressed = self.IR_2_entry + self.IR_rx3.when_pressed = self.IR_3_entry + self.IR_rx4.when_pressed = self.IR_4_entry + self.IR_rx5.when_pressed = self.IR_5_entry + self.IR_rx1.when_released = self.IR_1_exit + self.IR_rx2.when_released = self.IR_2_exit + self.IR_rx3.when_released = self.IR_3_exit + self.IR_rx4.when_released = self.IR_4_exit + self.IR_rx5.when_released = self.IR_5_exit + ############################################################################################### + # close circuit detection - for ground pin circuit lick detection ############################################################################################### self.lick1 = Button(26, None, True) self.lick2 = Button(27, None, True) self.lick3 = Button(15, None, True) - self.reserved_rx1 = Button(13, None, True) # for mitch - self.reserved_rx2 = Button(16, None, True) # for mitch + #self.reserved_rx1 = Button(13, None, True) # for mitch + #self.reserved_rx2 = Button(16, None, True) # for mitch # # # link nosepoke event detections to callbacks self.lick1.when_pressed = self.left_exit @@ -121,10 +141,10 @@ def __init__(self, session_info): self.lick2.when_released = self.right_entry self.lick3.when_released = self.center_entry - self.reserved_rx1.when_pressed = self.reserved_rx1_pressed - self.reserved_rx2.when_pressed = self.reserved_rx2_pressed - self.reserved_rx1.when_released = self.reserved_rx1_released - self.reserved_rx2.when_released = self.reserved_rx2_released + # self.reserved_rx1.when_pressed = self.reserved_rx1_pressed + # self.reserved_rx2.when_pressed = self.reserved_rx2_pressed + # self.reserved_rx1.when_released = self.reserved_rx1_released + # self.reserved_rx2.when_released = self.reserved_rx2_released ############################################################################################### # sound: audio board DIO - pins sending TTL to the Tsunami soundboard via SMA connectors @@ -142,7 +162,7 @@ def __init__(self, session_info): ############################################################################################### # pump: trigger signal output to a driver board induce the solenoid valve to deliver reward ############################################################################################### - self.pump = Pump() + self.pump = Pump(self.session_info) ############################################################################################### # flipper strobe signal (previously called camera strobe signal) @@ -260,39 +280,42 @@ def check_keybd(self): self.keyboard_active = False elif event.key == pygame.K_1: self.left_entry() + self.left_IR_entry() logging.info(";" + str(time.time()) + ";[action];key_pressed_left_entry()") elif event.key == pygame.K_2: self.center_entry() + self.center_IR_entry() logging.info(";" + str(time.time()) + ";[action];key_pressed_center_entry()") elif event.key == pygame.K_3: self.right_entry() + self.right_IR_entry() logging.info(";" + str(time.time()) + ";[action];key_pressed_right_entry()") - elif event.key == pygame.K_4: - self.reserved_rx1_pressed() - logging.info(";" + str(time.time()) + ";[action];key_pressed_reserved_rx1_pressed()") - elif event.key == pygame.K_5: - self.reserved_rx2_pressed() - logging.info(";" + str(time.time()) + ";[action];key_pressed_reserved_rx2_pressed()") + # elif event.key == pygame.K_4: + # self.reserved_rx1_pressed() + # logging.info(";" + str(time.time()) + ";[action];key_pressed_reserved_rx1_pressed()") + # elif event.key == pygame.K_5: + # self.reserved_rx2_pressed() + # logging.info(";" + str(time.time()) + ";[action];key_pressed_reserved_rx2_pressed()") elif event.key == pygame.K_q: # print("Q down: syringe pump 1 moves") - logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump1") - self.pump.reward("1", 5) + # logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump1") + self.pump.reward("key_1", self.session_info["key_reward_amount"]) elif event.key == pygame.K_w: # print("W down: syringe pump 2 moves") - logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump2") - self.pump.reward("2", 5) + # logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump2") + self.pump.reward("key_2", self.session_info["key_reward_amount"]) elif event.key == pygame.K_e: # print("E down: syringe pump 3 moves") - logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump3") - self.pump.reward("3", 5) + # logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump3") + self.pump.reward("key_3", self.session_info["key_reward_amount"]) elif event.key == pygame.K_r: # print("R down: syringe pump 4 moves") - logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump4") - self.pump.reward("4", 5) + # logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump4") + self.pump.reward("key_4", self.session_info["key_reward_amount"]) elif event.key == pygame.K_t: # print("T down: vacuum on") - logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump_vacuum") - self.pump.reward("vacuum", 1) + # logging.info(";" + str(time.time()) + ";[reward];key_pressed_pump_vacuum") + self.pump.reward("key_vacuum", 1) elif event.type == pygame.KEYUP: if event.key == pygame.K_1: self.left_exit() @@ -455,27 +478,65 @@ def right_exit(self): self.interact_list.append((time.time(), "right_exit")) logging.info(";" + str(time.time()) + ";[action];right_exit") - def reserved_rx1_pressed(self): - self.event_list.append("reserved_rx1_pressed") - self.interact_list.append((time.time(), "reserved_rx1_pressed")) - logging.info(";" + str(time.time()) + ";[action];reserved_rx1_pressed") - - def reserved_rx2_pressed(self): - self.event_list.append("reserved_rx2_pressed") - self.interact_list.append((time.time(), "reserved_rx2_pressed")) - logging.info(";" + str(time.time()) + ";[action];reserved_rx2_pressed") - - def reserved_rx1_released(self): - self.event_list.append("reserved_rx1_released") - self.interact_list.append((time.time(), "reserved_rx1_released")) - logging.info(";" + str(time.time()) + ";[action];reserved_rx1_released") - - def reserved_rx2_released(self): - self.event_list.append("reserved_rx2_released") - self.interact_list.append((time.time(), "reserved_rx2_released")) - logging.info(";" + str(time.time()) + ";[action];reserved_rx2_released") - - + # def reserved_rx1_pressed(self): + # self.event_list.append("reserved_rx1_pressed") + # self.interact_list.append((time.time(), "reserved_rx1_pressed")) + # logging.info(";" + str(time.time()) + ";[action];reserved_rx1_pressed") + # + # def reserved_rx2_pressed(self): + # self.event_list.append("reserved_rx2_pressed") + # self.interact_list.append((time.time(), "reserved_rx2_pressed")) + # logging.info(";" + str(time.time()) + ";[action];reserved_rx2_pressed") + # + # def reserved_rx1_released(self): + # self.event_list.append("reserved_rx1_released") + # self.interact_list.append((time.time(), "reserved_rx1_released")) + # logging.info(";" + str(time.time()) + ";[action];reserved_rx1_released") + # + # def reserved_rx2_released(self): + # self.event_list.append("reserved_rx2_released") + # self.interact_list.append((time.time(), "reserved_rx2_released")) + # logging.info(";" + str(time.time()) + ";[action];reserved_rx2_released") + def IR_1_entry(self): + self.event_list.append("IR_1_entry") + logging.info(str(time.time()) + ", IR_1_entry") + + def IR_2_entry(self): + self.event_list.append("IR_2_entry") + logging.info(str(time.time()) + ", IR_2_entry") + + def IR_3_entry(self): + self.event_list.append("IR_3_entry") + logging.info(str(time.time()) + ", IR_3_entry") + + def IR_4_entry(self): + self.event_list.append("IR_4_entry") + logging.info(str(time.time()) + ", IR_4_entry") + + def IR_5_entry(self): + self.event_list.append("IR_5_entry") + logging.info(str(time.time()) + ", IR_5_entry") + + def IR_1_exit(self): + self.event_list.append("IR_1_exit") + logging.info(str(time.time()) + ", IR_1_exit") + + def IR_2_exit(self): + self.event_list.append("IR_2_exit") + # self.cueLED2.off() + logging.info(str(time.time()) + ", IR_2_exit") + + def IR_3_exit(self): + self.event_list.append("IR_3_exit") + logging.info(str(time.time()) + ", IR_3_exit") + + def IR_4_exit(self): + self.event_list.append("IR_4_exit") + logging.info(str(time.time()) + ", IR_4_exit") + + def IR_5_exit(self): + self.event_list.append("IR_5_exit") + logging.info(str(time.time()) + ", IR_5_exit") # this is for the cue LEDs. BoxLED.value is the intensity value (PWM duty cycle, from 0 to 1) # currently. BoxLED.set_value is the saved intensity value that determines how bright the @@ -491,7 +552,8 @@ def on( class Pump(object): - def __init__(self): + def __init__(self, session_info): + self.session_info = session_info self.pump1 = LED(19) self.pump2 = LED(20) self.pump3 = LED(21) @@ -502,44 +564,73 @@ def __init__(self): # visualization def reward(self, which_pump, reward_size): - # coefficient_fit = np.array([8.78674242e-04, 7.33609848e-02, 1.47535000e+00]) # further calibration is needed - # coefficient_1 = coefficient_fit[-1] - # coefficient_2 = coefficient_fit[-2] - # coefficient_3 = coefficient_fit[-3] - reward_size - tube_fit = 0.11609 # ml/s - # discriminant = coefficient_2 ** 2 - 4 * coefficient_1 * coefficient_3 - # # find solution, i.e. duration of pulse, by calculating the solution for the quadratic equation - # solution = np.array([(-coefficient_2 + np.sqrt(discriminant)) / (2 * coefficient_1), - # (-coefficient_2 - np.sqrt(discriminant)) / (2 * coefficient_1)]) - - # With two solution, get the positive value - # solution_positive = solution[(solution > 0).nonzero()[0][0]] - # round to the second decimal - # duration = round(solution_positive, 3) * (10**-3) - - duration = round((reward_size/1000)/tube_fit, 3) - duration_vacuum = 0.5 + # import coefficient from the session_information + coefficient_p1 = self.session_info["calibration_coefficient"]['1'] + coefficient_p2 = self.session_info["calibration_coefficient"]['2'] + coefficient_p3 = self.session_info["calibration_coefficient"]['3'] + coefficient_p4 = self.session_info["calibration_coefficient"]['4'] + duration_air = self.session_info['air_duration'] + duration_vac = self.session_info["vacuum_duration"] if which_pump == "1": + duration = round((coefficient_p1[0] * (reward_size / 1000) + coefficient_p1[1]), 5) # linear function self.pump1.blink(duration, 0.1, 1) self.reward_list.append(("pump1_reward", reward_size)) - logging.info(";" + str(time.time()) + ";[reward];pump1_reward_" + str(reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump1_reward(reward_coeff: " + str(coefficient_p1) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") elif which_pump == "2": + duration = round((coefficient_p2[0] * (reward_size / 1000) + coefficient_p2[1]), 5) # linear function self.pump2.blink(duration, 0.1, 1) self.reward_list.append(("pump2_reward", reward_size)) - logging.info(";" + str(time.time()) + ";[reward];pump2_reward_" + str(reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump2_reward(reward_coeff: " + str(coefficient_p2) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") elif which_pump == "3": + duration = round((coefficient_p3[0] * (reward_size / 1000) + coefficient_p3[1]), 5) # linear function self.pump3.blink(duration, 0.1, 1) self.reward_list.append(("pump3_reward", reward_size)) - logging.info(";" + str(time.time()) + ";[reward];pump3_reward_" + str(reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump3_reward(reward_coeff: " + str(coefficient_p3) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") elif which_pump == "4": + duration = round((coefficient_p4[0] * (reward_size / 1000) + coefficient_p4[1]), 5) # linear function self.pump4.blink(duration, 0.1, 1) self.reward_list.append(("pump4_reward", reward_size)) - logging.info(";" + str(time.time()) + ";[reward];pump4_reward_" + str(reward_size)) + logging.info(";" + str(time.time()) + ";[reward];pump4_reward(reward_coeff: " + str(coefficient_p4) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") elif which_pump == "air_puff": - self.pump_air.blink(duration, 0.1, 1) + self.pump_air.blink(duration_air, 0.1, 1) self.reward_list.append(("air_puff", reward_size)) logging.info(";" + str(time.time()) + ";[reward];pump4_reward_" + str(reward_size)) elif which_pump == "vacuum": - self.pump_vacuum.blink(duration_vacuum, 0.1, 1) - logging.info(";" + str(time.time()) + ";[reward];pump_vacuum") \ No newline at end of file + self.pump_vacuum.blink(duration_vac, 0.1, 1) + logging.info(";" + str(time.time()) + ";[reward];pump_vacuum" + str(duration_vac)) + elif which_pump == "key_1": + duration = round((coefficient_p1[0] * (reward_size / 1000) + coefficient_p1[1]), 5) # linear function + self.pump1.blink(duration, 0.1, 1) + self.reward_list.append(("pump1_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[key];pump1_reward(reward_coeff: " + str(coefficient_p1) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "key_2": + duration = round((coefficient_p2[0] * (reward_size / 1000) + coefficient_p2[1]), 5) # linear function + self.pump2.blink(duration, 0.1, 1) + self.reward_list.append(("pump2_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[key];pump2_reward(reward_coeff: " + str(coefficient_p2) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "key_3": + duration = round((coefficient_p3[0] * (reward_size / 1000) + coefficient_p3[1]), 5) # linear function + self.pump3.blink(duration, 0.1, 1) + self.reward_list.append(("pump3_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[key];pump3_reward(reward_coeff: " + str(coefficient_p3) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "key_4": + duration = round((coefficient_p4[0] * (reward_size / 1000) + coefficient_p4[1]), 5) # linear function + self.pump4.blink(duration, 0.1, 1) + self.reward_list.append(("pump4_reward", reward_size)) + logging.info(";" + str(time.time()) + ";[key];pump4_reward(reward_coeff: " + str(coefficient_p4) + + ", reward_amount: " + str(reward_size) + "duration: " + str(duration) + ")") + elif which_pump == "key_air_puff": + self.pump_air.blink(duration_air, 0.1, 1) + self.reward_list.append(("air_puff", reward_size)) + logging.info(";" + str(time.time()) + ";[key];pump4_reward_" + str(reward_size)) + elif which_pump == "key_vacuum": + self.pump_vacuum.blink(duration_vac, 0.1, 1) + logging.info(";" + str(time.time()) + ";[key];pump_vacuum" + str(duration_vac)) \ No newline at end of file diff --git a/camera/Video-Capture-Behavior.py b/essential/camera/Video-Capture-Behavior.py similarity index 100% rename from camera/Video-Capture-Behavior.py rename to essential/camera/Video-Capture-Behavior.py diff --git a/essential/camera/__init__.py b/essential/camera/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/camera/__init__.py @@ -0,0 +1 @@ + diff --git a/camera/camera_sync,record b/essential/camera/camera_sync,record similarity index 100% rename from camera/camera_sync,record rename to essential/camera/camera_sync,record diff --git a/camera/camera_sync,record.py b/essential/camera/camera_sync,record.py similarity index 100% rename from camera/camera_sync,record.py rename to essential/camera/camera_sync,record.py diff --git a/camera/readme.md b/essential/camera/readme.md similarity index 100% rename from camera/readme.md rename to essential/camera/readme.md diff --git a/picamera_library_modified/LICENSE.txt b/essential/picamera_library_modified/LICENSE.txt similarity index 100% rename from picamera_library_modified/LICENSE.txt rename to essential/picamera_library_modified/LICENSE.txt diff --git a/picamera_library_modified/MANIFEST.in b/essential/picamera_library_modified/MANIFEST.in similarity index 100% rename from picamera_library_modified/MANIFEST.in rename to essential/picamera_library_modified/MANIFEST.in diff --git a/picamera_library_modified/Makefile b/essential/picamera_library_modified/Makefile similarity index 100% rename from picamera_library_modified/Makefile rename to essential/picamera_library_modified/Makefile diff --git a/picamera_library_modified/README.rst b/essential/picamera_library_modified/README.rst similarity index 100% rename from picamera_library_modified/README.rst rename to essential/picamera_library_modified/README.rst diff --git a/picamera_library_modified/build/lib/picamera/__init__.py b/essential/picamera_library_modified/build/lib/picamera/__init__.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/__init__.py rename to essential/picamera_library_modified/build/lib/picamera/__init__.py diff --git a/picamera_library_modified/build/lib/picamera/array.py b/essential/picamera_library_modified/build/lib/picamera/array.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/array.py rename to essential/picamera_library_modified/build/lib/picamera/array.py diff --git a/picamera_library_modified/build/lib/picamera/bcm_host.py b/essential/picamera_library_modified/build/lib/picamera/bcm_host.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/bcm_host.py rename to essential/picamera_library_modified/build/lib/picamera/bcm_host.py diff --git a/picamera_library_modified/build/lib/picamera/camera.py b/essential/picamera_library_modified/build/lib/picamera/camera.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/camera.py rename to essential/picamera_library_modified/build/lib/picamera/camera.py diff --git a/picamera_library_modified/build/lib/picamera/color.py b/essential/picamera_library_modified/build/lib/picamera/color.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/color.py rename to essential/picamera_library_modified/build/lib/picamera/color.py diff --git a/picamera_library_modified/build/lib/picamera/display.py b/essential/picamera_library_modified/build/lib/picamera/display.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/display.py rename to essential/picamera_library_modified/build/lib/picamera/display.py diff --git a/picamera_library_modified/build/lib/picamera/encoders.py b/essential/picamera_library_modified/build/lib/picamera/encoders.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/encoders.py rename to essential/picamera_library_modified/build/lib/picamera/encoders.py diff --git a/picamera_library_modified/build/lib/picamera/exc.py b/essential/picamera_library_modified/build/lib/picamera/exc.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/exc.py rename to essential/picamera_library_modified/build/lib/picamera/exc.py diff --git a/picamera_library_modified/build/lib/picamera/frames.py b/essential/picamera_library_modified/build/lib/picamera/frames.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/frames.py rename to essential/picamera_library_modified/build/lib/picamera/frames.py diff --git a/picamera_library_modified/build/lib/picamera/mmal.py b/essential/picamera_library_modified/build/lib/picamera/mmal.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/mmal.py rename to essential/picamera_library_modified/build/lib/picamera/mmal.py diff --git a/picamera_library_modified/build/lib/picamera/mmalobj.py b/essential/picamera_library_modified/build/lib/picamera/mmalobj.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/mmalobj.py rename to essential/picamera_library_modified/build/lib/picamera/mmalobj.py diff --git a/picamera_library_modified/build/lib/picamera/renderers.py b/essential/picamera_library_modified/build/lib/picamera/renderers.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/renderers.py rename to essential/picamera_library_modified/build/lib/picamera/renderers.py diff --git a/picamera_library_modified/build/lib/picamera/streams.py b/essential/picamera_library_modified/build/lib/picamera/streams.py similarity index 100% rename from picamera_library_modified/build/lib/picamera/streams.py rename to essential/picamera_library_modified/build/lib/picamera/streams.py diff --git a/picamera_library_modified/coverage.cfg b/essential/picamera_library_modified/coverage.cfg similarity index 100% rename from picamera_library_modified/coverage.cfg rename to essential/picamera_library_modified/coverage.cfg diff --git a/picamera_library_modified/debian/changelog b/essential/picamera_library_modified/debian/changelog similarity index 100% rename from picamera_library_modified/debian/changelog rename to essential/picamera_library_modified/debian/changelog diff --git a/picamera_library_modified/debian/clean b/essential/picamera_library_modified/debian/clean similarity index 100% rename from picamera_library_modified/debian/clean rename to essential/picamera_library_modified/debian/clean diff --git a/picamera_library_modified/debian/compat b/essential/picamera_library_modified/debian/compat similarity index 100% rename from picamera_library_modified/debian/compat rename to essential/picamera_library_modified/debian/compat diff --git a/picamera_library_modified/debian/control b/essential/picamera_library_modified/debian/control similarity index 100% rename from picamera_library_modified/debian/control rename to essential/picamera_library_modified/debian/control diff --git a/picamera_library_modified/debian/copyright b/essential/picamera_library_modified/debian/copyright similarity index 100% rename from picamera_library_modified/debian/copyright rename to essential/picamera_library_modified/debian/copyright diff --git a/picamera_library_modified/debian/docs b/essential/picamera_library_modified/debian/docs similarity index 100% rename from picamera_library_modified/debian/docs rename to essential/picamera_library_modified/debian/docs diff --git a/picamera_library_modified/debian/python-picamera-docs.doc-base b/essential/picamera_library_modified/debian/python-picamera-docs.doc-base similarity index 100% rename from picamera_library_modified/debian/python-picamera-docs.doc-base rename to essential/picamera_library_modified/debian/python-picamera-docs.doc-base diff --git a/picamera_library_modified/debian/python-picamera-docs.docs b/essential/picamera_library_modified/debian/python-picamera-docs.docs similarity index 100% rename from picamera_library_modified/debian/python-picamera-docs.docs rename to essential/picamera_library_modified/debian/python-picamera-docs.docs diff --git a/picamera_library_modified/debian/rules b/essential/picamera_library_modified/debian/rules similarity index 100% rename from picamera_library_modified/debian/rules rename to essential/picamera_library_modified/debian/rules diff --git a/picamera_library_modified/debian/source/format b/essential/picamera_library_modified/debian/source/format similarity index 100% rename from picamera_library_modified/debian/source/format rename to essential/picamera_library_modified/debian/source/format diff --git a/picamera_library_modified/debian/source/options b/essential/picamera_library_modified/debian/source/options similarity index 100% rename from picamera_library_modified/debian/source/options rename to essential/picamera_library_modified/debian/source/options diff --git a/picamera_library_modified/dist/picamera-1.13-py3.7.egg b/essential/picamera_library_modified/dist/picamera-1.13-py3.7.egg similarity index 100% rename from picamera_library_modified/dist/picamera-1.13-py3.7.egg rename to essential/picamera_library_modified/dist/picamera-1.13-py3.7.egg diff --git a/picamera_library_modified/docs/Makefile b/essential/picamera_library_modified/docs/Makefile similarity index 100% rename from picamera_library_modified/docs/Makefile rename to essential/picamera_library_modified/docs/Makefile diff --git a/picamera_library_modified/docs/_static/style_override.css b/essential/picamera_library_modified/docs/_static/style_override.css similarity index 100% rename from picamera_library_modified/docs/_static/style_override.css rename to essential/picamera_library_modified/docs/_static/style_override.css diff --git a/picamera_library_modified/docs/api_array.rst b/essential/picamera_library_modified/docs/api_array.rst similarity index 100% rename from picamera_library_modified/docs/api_array.rst rename to essential/picamera_library_modified/docs/api_array.rst diff --git a/picamera_library_modified/docs/api_camera.rst b/essential/picamera_library_modified/docs/api_camera.rst similarity index 100% rename from picamera_library_modified/docs/api_camera.rst rename to essential/picamera_library_modified/docs/api_camera.rst diff --git a/picamera_library_modified/docs/api_color.rst b/essential/picamera_library_modified/docs/api_color.rst similarity index 100% rename from picamera_library_modified/docs/api_color.rst rename to essential/picamera_library_modified/docs/api_color.rst diff --git a/picamera_library_modified/docs/api_encoders.rst b/essential/picamera_library_modified/docs/api_encoders.rst similarity index 100% rename from picamera_library_modified/docs/api_encoders.rst rename to essential/picamera_library_modified/docs/api_encoders.rst diff --git a/picamera_library_modified/docs/api_exc.rst b/essential/picamera_library_modified/docs/api_exc.rst similarity index 100% rename from picamera_library_modified/docs/api_exc.rst rename to essential/picamera_library_modified/docs/api_exc.rst diff --git a/picamera_library_modified/docs/api_mmalobj.rst b/essential/picamera_library_modified/docs/api_mmalobj.rst similarity index 100% rename from picamera_library_modified/docs/api_mmalobj.rst rename to essential/picamera_library_modified/docs/api_mmalobj.rst diff --git a/picamera_library_modified/docs/api_renderers.rst b/essential/picamera_library_modified/docs/api_renderers.rst similarity index 100% rename from picamera_library_modified/docs/api_renderers.rst rename to essential/picamera_library_modified/docs/api_renderers.rst diff --git a/picamera_library_modified/docs/api_streams.rst b/essential/picamera_library_modified/docs/api_streams.rst similarity index 100% rename from picamera_library_modified/docs/api_streams.rst rename to essential/picamera_library_modified/docs/api_streams.rst diff --git a/picamera_library_modified/docs/changelog.rst b/essential/picamera_library_modified/docs/changelog.rst similarity index 100% rename from picamera_library_modified/docs/changelog.rst rename to essential/picamera_library_modified/docs/changelog.rst diff --git a/picamera_library_modified/docs/conf.py b/essential/picamera_library_modified/docs/conf.py similarity index 100% rename from picamera_library_modified/docs/conf.py rename to essential/picamera_library_modified/docs/conf.py diff --git a/picamera_library_modified/docs/deprecated.rst b/essential/picamera_library_modified/docs/deprecated.rst similarity index 100% rename from picamera_library_modified/docs/deprecated.rst rename to essential/picamera_library_modified/docs/deprecated.rst diff --git a/picamera_library_modified/docs/development.rst b/essential/picamera_library_modified/docs/development.rst similarity index 100% rename from picamera_library_modified/docs/development.rst rename to essential/picamera_library_modified/docs/development.rst diff --git a/picamera_library_modified/docs/encoder_classes.dot b/essential/picamera_library_modified/docs/encoder_classes.dot similarity index 100% rename from picamera_library_modified/docs/encoder_classes.dot rename to essential/picamera_library_modified/docs/encoder_classes.dot diff --git a/picamera_library_modified/docs/examples/array_capture_py2.py b/essential/picamera_library_modified/docs/examples/array_capture_py2.py similarity index 100% rename from picamera_library_modified/docs/examples/array_capture_py2.py rename to essential/picamera_library_modified/docs/examples/array_capture_py2.py diff --git a/picamera_library_modified/docs/examples/array_capture_py3.py b/essential/picamera_library_modified/docs/examples/array_capture_py3.py similarity index 100% rename from picamera_library_modified/docs/examples/array_capture_py3.py rename to essential/picamera_library_modified/docs/examples/array_capture_py3.py diff --git a/picamera_library_modified/docs/examples/bayer_array.py b/essential/picamera_library_modified/docs/examples/bayer_array.py similarity index 100% rename from picamera_library_modified/docs/examples/bayer_array.py rename to essential/picamera_library_modified/docs/examples/bayer_array.py diff --git a/picamera_library_modified/docs/examples/bayer_data.py b/essential/picamera_library_modified/docs/examples/bayer_data.py similarity index 100% rename from picamera_library_modified/docs/examples/bayer_data.py rename to essential/picamera_library_modified/docs/examples/bayer_data.py diff --git a/picamera_library_modified/docs/examples/capture_client.py b/essential/picamera_library_modified/docs/examples/capture_client.py similarity index 100% rename from picamera_library_modified/docs/examples/capture_client.py rename to essential/picamera_library_modified/docs/examples/capture_client.py diff --git a/picamera_library_modified/docs/examples/capture_server.py b/essential/picamera_library_modified/docs/examples/capture_server.py similarity index 100% rename from picamera_library_modified/docs/examples/capture_server.py rename to essential/picamera_library_modified/docs/examples/capture_server.py diff --git a/picamera_library_modified/docs/examples/circular_record1.py b/essential/picamera_library_modified/docs/examples/circular_record1.py similarity index 100% rename from picamera_library_modified/docs/examples/circular_record1.py rename to essential/picamera_library_modified/docs/examples/circular_record1.py diff --git a/picamera_library_modified/docs/examples/circular_record2.py b/essential/picamera_library_modified/docs/examples/circular_record2.py similarity index 100% rename from picamera_library_modified/docs/examples/circular_record2.py rename to essential/picamera_library_modified/docs/examples/circular_record2.py diff --git a/picamera_library_modified/docs/examples/color_detect.py b/essential/picamera_library_modified/docs/examples/color_detect.py similarity index 100% rename from picamera_library_modified/docs/examples/color_detect.py rename to essential/picamera_library_modified/docs/examples/color_detect.py diff --git a/picamera_library_modified/docs/examples/consistent_capture.py b/essential/picamera_library_modified/docs/examples/consistent_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/consistent_capture.py rename to essential/picamera_library_modified/docs/examples/consistent_capture.py diff --git a/picamera_library_modified/docs/examples/custom_encoders.py b/essential/picamera_library_modified/docs/examples/custom_encoders.py similarity index 100% rename from picamera_library_modified/docs/examples/custom_encoders.py rename to essential/picamera_library_modified/docs/examples/custom_encoders.py diff --git a/picamera_library_modified/docs/examples/custom_outputs_count.py b/essential/picamera_library_modified/docs/examples/custom_outputs_count.py similarity index 100% rename from picamera_library_modified/docs/examples/custom_outputs_count.py rename to essential/picamera_library_modified/docs/examples/custom_outputs_count.py diff --git a/picamera_library_modified/docs/examples/custom_outputs_motion_analysis.py b/essential/picamera_library_modified/docs/examples/custom_outputs_motion_analysis.py similarity index 100% rename from picamera_library_modified/docs/examples/custom_outputs_motion_analysis.py rename to essential/picamera_library_modified/docs/examples/custom_outputs_motion_analysis.py diff --git a/picamera_library_modified/docs/examples/custom_outputs_motion_detector.py b/essential/picamera_library_modified/docs/examples/custom_outputs_motion_detector.py similarity index 100% rename from picamera_library_modified/docs/examples/custom_outputs_motion_detector.py rename to essential/picamera_library_modified/docs/examples/custom_outputs_motion_detector.py diff --git a/picamera_library_modified/docs/examples/file_capture.py b/essential/picamera_library_modified/docs/examples/file_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/file_capture.py rename to essential/picamera_library_modified/docs/examples/file_capture.py diff --git a/picamera_library_modified/docs/examples/file_record.py b/essential/picamera_library_modified/docs/examples/file_record.py similarity index 100% rename from picamera_library_modified/docs/examples/file_record.py rename to essential/picamera_library_modified/docs/examples/file_record.py diff --git a/picamera_library_modified/docs/examples/gesture_detect.py b/essential/picamera_library_modified/docs/examples/gesture_detect.py similarity index 100% rename from picamera_library_modified/docs/examples/gesture_detect.py rename to essential/picamera_library_modified/docs/examples/gesture_detect.py diff --git a/picamera_library_modified/docs/examples/image_overlay_array.py b/essential/picamera_library_modified/docs/examples/image_overlay_array.py similarity index 100% rename from picamera_library_modified/docs/examples/image_overlay_array.py rename to essential/picamera_library_modified/docs/examples/image_overlay_array.py diff --git a/picamera_library_modified/docs/examples/image_overlay_file.py b/essential/picamera_library_modified/docs/examples/image_overlay_file.py similarity index 100% rename from picamera_library_modified/docs/examples/image_overlay_file.py rename to essential/picamera_library_modified/docs/examples/image_overlay_file.py diff --git a/picamera_library_modified/docs/examples/led_control.py b/essential/picamera_library_modified/docs/examples/led_control.py similarity index 100% rename from picamera_library_modified/docs/examples/led_control.py rename to essential/picamera_library_modified/docs/examples/led_control.py diff --git a/picamera_library_modified/docs/examples/mmal_clock_splitter.py b/essential/picamera_library_modified/docs/examples/mmal_clock_splitter.py similarity index 100% rename from picamera_library_modified/docs/examples/mmal_clock_splitter.py rename to essential/picamera_library_modified/docs/examples/mmal_clock_splitter.py diff --git a/picamera_library_modified/docs/examples/mmal_crosshair.py b/essential/picamera_library_modified/docs/examples/mmal_crosshair.py similarity index 100% rename from picamera_library_modified/docs/examples/mmal_crosshair.py rename to essential/picamera_library_modified/docs/examples/mmal_crosshair.py diff --git a/picamera_library_modified/docs/examples/motion_data1.py b/essential/picamera_library_modified/docs/examples/motion_data1.py similarity index 100% rename from picamera_library_modified/docs/examples/motion_data1.py rename to essential/picamera_library_modified/docs/examples/motion_data1.py diff --git a/picamera_library_modified/docs/examples/motion_data2.py b/essential/picamera_library_modified/docs/examples/motion_data2.py similarity index 100% rename from picamera_library_modified/docs/examples/motion_data2.py rename to essential/picamera_library_modified/docs/examples/motion_data2.py diff --git a/picamera_library_modified/docs/examples/motion_data3.py b/essential/picamera_library_modified/docs/examples/motion_data3.py similarity index 100% rename from picamera_library_modified/docs/examples/motion_data3.py rename to essential/picamera_library_modified/docs/examples/motion_data3.py diff --git a/picamera_library_modified/docs/examples/motion_data4.py b/essential/picamera_library_modified/docs/examples/motion_data4.py similarity index 100% rename from picamera_library_modified/docs/examples/motion_data4.py rename to essential/picamera_library_modified/docs/examples/motion_data4.py diff --git a/picamera_library_modified/docs/examples/multi_res_record.py b/essential/picamera_library_modified/docs/examples/multi_res_record.py similarity index 100% rename from picamera_library_modified/docs/examples/multi_res_record.py rename to essential/picamera_library_modified/docs/examples/multi_res_record.py diff --git a/picamera_library_modified/docs/examples/multiproc_camera.py b/essential/picamera_library_modified/docs/examples/multiproc_camera.py similarity index 100% rename from picamera_library_modified/docs/examples/multiproc_camera.py rename to essential/picamera_library_modified/docs/examples/multiproc_camera.py diff --git a/picamera_library_modified/docs/examples/night_capture.py b/essential/picamera_library_modified/docs/examples/night_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/night_capture.py rename to essential/picamera_library_modified/docs/examples/night_capture.py diff --git a/picamera_library_modified/docs/examples/opencv_capture.py b/essential/picamera_library_modified/docs/examples/opencv_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/opencv_capture.py rename to essential/picamera_library_modified/docs/examples/opencv_capture.py diff --git a/picamera_library_modified/docs/examples/pil_capture.py b/essential/picamera_library_modified/docs/examples/pil_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/pil_capture.py rename to essential/picamera_library_modified/docs/examples/pil_capture.py diff --git a/picamera_library_modified/docs/examples/rapid_capture_generator.py b/essential/picamera_library_modified/docs/examples/rapid_capture_generator.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_capture_generator.py rename to essential/picamera_library_modified/docs/examples/rapid_capture_generator.py diff --git a/picamera_library_modified/docs/examples/rapid_capture_mjpeg.py b/essential/picamera_library_modified/docs/examples/rapid_capture_mjpeg.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_capture_mjpeg.py rename to essential/picamera_library_modified/docs/examples/rapid_capture_mjpeg.py diff --git a/picamera_library_modified/docs/examples/rapid_capture_sequence.py b/essential/picamera_library_modified/docs/examples/rapid_capture_sequence.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_capture_sequence.py rename to essential/picamera_library_modified/docs/examples/rapid_capture_sequence.py diff --git a/picamera_library_modified/docs/examples/rapid_capture_threading.py b/essential/picamera_library_modified/docs/examples/rapid_capture_threading.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_capture_threading.py rename to essential/picamera_library_modified/docs/examples/rapid_capture_threading.py diff --git a/picamera_library_modified/docs/examples/rapid_capture_yield.py b/essential/picamera_library_modified/docs/examples/rapid_capture_yield.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_capture_yield.py rename to essential/picamera_library_modified/docs/examples/rapid_capture_yield.py diff --git a/picamera_library_modified/docs/examples/rapid_streaming.py b/essential/picamera_library_modified/docs/examples/rapid_streaming.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_streaming.py rename to essential/picamera_library_modified/docs/examples/rapid_streaming.py diff --git a/picamera_library_modified/docs/examples/rapid_streaming_mjpeg.py b/essential/picamera_library_modified/docs/examples/rapid_streaming_mjpeg.py similarity index 100% rename from picamera_library_modified/docs/examples/rapid_streaming_mjpeg.py rename to essential/picamera_library_modified/docs/examples/rapid_streaming_mjpeg.py diff --git a/picamera_library_modified/docs/examples/record_and_capture.py b/essential/picamera_library_modified/docs/examples/record_and_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/record_and_capture.py rename to essential/picamera_library_modified/docs/examples/record_and_capture.py diff --git a/picamera_library_modified/docs/examples/record_client.py b/essential/picamera_library_modified/docs/examples/record_client.py similarity index 100% rename from picamera_library_modified/docs/examples/record_client.py rename to essential/picamera_library_modified/docs/examples/record_client.py diff --git a/picamera_library_modified/docs/examples/record_sequence.py b/essential/picamera_library_modified/docs/examples/record_sequence.py similarity index 100% rename from picamera_library_modified/docs/examples/record_sequence.py rename to essential/picamera_library_modified/docs/examples/record_sequence.py diff --git a/picamera_library_modified/docs/examples/record_server.py b/essential/picamera_library_modified/docs/examples/record_server.py similarity index 100% rename from picamera_library_modified/docs/examples/record_server.py rename to essential/picamera_library_modified/docs/examples/record_server.py diff --git a/picamera_library_modified/docs/examples/record_server_pi.py b/essential/picamera_library_modified/docs/examples/record_server_pi.py similarity index 100% rename from picamera_library_modified/docs/examples/record_server_pi.py rename to essential/picamera_library_modified/docs/examples/record_server_pi.py diff --git a/picamera_library_modified/docs/examples/resize_capture.py b/essential/picamera_library_modified/docs/examples/resize_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/resize_capture.py rename to essential/picamera_library_modified/docs/examples/resize_capture.py diff --git a/picamera_library_modified/docs/examples/rgb_capture1.py b/essential/picamera_library_modified/docs/examples/rgb_capture1.py similarity index 100% rename from picamera_library_modified/docs/examples/rgb_capture1.py rename to essential/picamera_library_modified/docs/examples/rgb_capture1.py diff --git a/picamera_library_modified/docs/examples/rgb_capture2.py b/essential/picamera_library_modified/docs/examples/rgb_capture2.py similarity index 100% rename from picamera_library_modified/docs/examples/rgb_capture2.py rename to essential/picamera_library_modified/docs/examples/rgb_capture2.py diff --git a/picamera_library_modified/docs/examples/split_record.py b/essential/picamera_library_modified/docs/examples/split_record.py similarity index 100% rename from picamera_library_modified/docs/examples/split_record.py rename to essential/picamera_library_modified/docs/examples/split_record.py diff --git a/picamera_library_modified/docs/examples/stream_capture.py b/essential/picamera_library_modified/docs/examples/stream_capture.py similarity index 100% rename from picamera_library_modified/docs/examples/stream_capture.py rename to essential/picamera_library_modified/docs/examples/stream_capture.py diff --git a/picamera_library_modified/docs/examples/stream_capture_close.py b/essential/picamera_library_modified/docs/examples/stream_capture_close.py similarity index 100% rename from picamera_library_modified/docs/examples/stream_capture_close.py rename to essential/picamera_library_modified/docs/examples/stream_capture_close.py diff --git a/picamera_library_modified/docs/examples/stream_record.py b/essential/picamera_library_modified/docs/examples/stream_record.py similarity index 100% rename from picamera_library_modified/docs/examples/stream_record.py rename to essential/picamera_library_modified/docs/examples/stream_record.py diff --git a/picamera_library_modified/docs/examples/text_overlay.py b/essential/picamera_library_modified/docs/examples/text_overlay.py similarity index 100% rename from picamera_library_modified/docs/examples/text_overlay.py rename to essential/picamera_library_modified/docs/examples/text_overlay.py diff --git a/picamera_library_modified/docs/examples/text_overlay_scroll.py b/essential/picamera_library_modified/docs/examples/text_overlay_scroll.py similarity index 100% rename from picamera_library_modified/docs/examples/text_overlay_scroll.py rename to essential/picamera_library_modified/docs/examples/text_overlay_scroll.py diff --git a/picamera_library_modified/docs/examples/text_overlay_timestamp.py b/essential/picamera_library_modified/docs/examples/text_overlay_timestamp.py similarity index 100% rename from picamera_library_modified/docs/examples/text_overlay_timestamp.py rename to essential/picamera_library_modified/docs/examples/text_overlay_timestamp.py diff --git a/picamera_library_modified/docs/examples/timelapse1.py b/essential/picamera_library_modified/docs/examples/timelapse1.py similarity index 100% rename from picamera_library_modified/docs/examples/timelapse1.py rename to essential/picamera_library_modified/docs/examples/timelapse1.py diff --git a/picamera_library_modified/docs/examples/timelapse2.py b/essential/picamera_library_modified/docs/examples/timelapse2.py similarity index 100% rename from picamera_library_modified/docs/examples/timelapse2.py rename to essential/picamera_library_modified/docs/examples/timelapse2.py diff --git a/picamera_library_modified/docs/examples/web_streaming.py b/essential/picamera_library_modified/docs/examples/web_streaming.py similarity index 100% rename from picamera_library_modified/docs/examples/web_streaming.py rename to essential/picamera_library_modified/docs/examples/web_streaming.py diff --git a/picamera_library_modified/docs/examples/weird_outputs.py b/essential/picamera_library_modified/docs/examples/weird_outputs.py similarity index 100% rename from picamera_library_modified/docs/examples/weird_outputs.py rename to essential/picamera_library_modified/docs/examples/weird_outputs.py diff --git a/picamera_library_modified/docs/examples/yuv_capture1.py b/essential/picamera_library_modified/docs/examples/yuv_capture1.py similarity index 100% rename from picamera_library_modified/docs/examples/yuv_capture1.py rename to essential/picamera_library_modified/docs/examples/yuv_capture1.py diff --git a/picamera_library_modified/docs/examples/yuv_capture2.py b/essential/picamera_library_modified/docs/examples/yuv_capture2.py similarity index 100% rename from picamera_library_modified/docs/examples/yuv_capture2.py rename to essential/picamera_library_modified/docs/examples/yuv_capture2.py diff --git a/picamera_library_modified/docs/examples/yuv_capture3.py b/essential/picamera_library_modified/docs/examples/yuv_capture3.py similarity index 100% rename from picamera_library_modified/docs/examples/yuv_capture3.py rename to essential/picamera_library_modified/docs/examples/yuv_capture3.py diff --git a/picamera_library_modified/docs/examples/yuv_capture4.py b/essential/picamera_library_modified/docs/examples/yuv_capture4.py similarity index 100% rename from picamera_library_modified/docs/examples/yuv_capture4.py rename to essential/picamera_library_modified/docs/examples/yuv_capture4.py diff --git a/picamera_library_modified/docs/faq.rst b/essential/picamera_library_modified/docs/faq.rst similarity index 100% rename from picamera_library_modified/docs/faq.rst rename to essential/picamera_library_modified/docs/faq.rst diff --git a/picamera_library_modified/docs/fov.rst b/essential/picamera_library_modified/docs/fov.rst similarity index 100% rename from picamera_library_modified/docs/fov.rst rename to essential/picamera_library_modified/docs/fov.rst diff --git a/picamera_library_modified/docs/images/bayer_bytes.pdf b/essential/picamera_library_modified/docs/images/bayer_bytes.pdf similarity index 100% rename from picamera_library_modified/docs/images/bayer_bytes.pdf rename to essential/picamera_library_modified/docs/images/bayer_bytes.pdf diff --git a/picamera_library_modified/docs/images/bayer_bytes.png b/essential/picamera_library_modified/docs/images/bayer_bytes.png similarity index 100% rename from picamera_library_modified/docs/images/bayer_bytes.png rename to essential/picamera_library_modified/docs/images/bayer_bytes.png diff --git a/picamera_library_modified/docs/images/bayer_bytes.svg b/essential/picamera_library_modified/docs/images/bayer_bytes.svg similarity index 100% rename from picamera_library_modified/docs/images/bayer_bytes.svg rename to essential/picamera_library_modified/docs/images/bayer_bytes.svg diff --git a/picamera_library_modified/docs/images/bayer_pattern.pdf b/essential/picamera_library_modified/docs/images/bayer_pattern.pdf similarity index 100% rename from picamera_library_modified/docs/images/bayer_pattern.pdf rename to essential/picamera_library_modified/docs/images/bayer_pattern.pdf diff --git a/picamera_library_modified/docs/images/bayer_pattern.png b/essential/picamera_library_modified/docs/images/bayer_pattern.png similarity index 100% rename from picamera_library_modified/docs/images/bayer_pattern.png rename to essential/picamera_library_modified/docs/images/bayer_pattern.png diff --git a/picamera_library_modified/docs/images/bayer_pattern.svg b/essential/picamera_library_modified/docs/images/bayer_pattern.svg similarity index 100% rename from picamera_library_modified/docs/images/bayer_pattern.svg rename to essential/picamera_library_modified/docs/images/bayer_pattern.svg diff --git a/picamera_library_modified/docs/images/camera_architecture.pdf b/essential/picamera_library_modified/docs/images/camera_architecture.pdf similarity index 100% rename from picamera_library_modified/docs/images/camera_architecture.pdf rename to essential/picamera_library_modified/docs/images/camera_architecture.pdf diff --git a/picamera_library_modified/docs/images/camera_architecture.png b/essential/picamera_library_modified/docs/images/camera_architecture.png similarity index 100% rename from picamera_library_modified/docs/images/camera_architecture.png rename to essential/picamera_library_modified/docs/images/camera_architecture.png diff --git a/picamera_library_modified/docs/images/camera_architecture.svg b/essential/picamera_library_modified/docs/images/camera_architecture.svg similarity index 100% rename from picamera_library_modified/docs/images/camera_architecture.svg rename to essential/picamera_library_modified/docs/images/camera_architecture.svg diff --git a/picamera_library_modified/docs/images/camera_layout.pdf b/essential/picamera_library_modified/docs/images/camera_layout.pdf similarity index 100% rename from picamera_library_modified/docs/images/camera_layout.pdf rename to essential/picamera_library_modified/docs/images/camera_layout.pdf diff --git a/picamera_library_modified/docs/images/camera_layout.png b/essential/picamera_library_modified/docs/images/camera_layout.png similarity index 100% rename from picamera_library_modified/docs/images/camera_layout.png rename to essential/picamera_library_modified/docs/images/camera_layout.png diff --git a/picamera_library_modified/docs/images/camera_layout.svg b/essential/picamera_library_modified/docs/images/camera_layout.svg similarity index 100% rename from picamera_library_modified/docs/images/camera_layout.svg rename to essential/picamera_library_modified/docs/images/camera_layout.svg diff --git a/picamera_library_modified/docs/images/enable_camera.png b/essential/picamera_library_modified/docs/images/enable_camera.png similarity index 100% rename from picamera_library_modified/docs/images/enable_camera.png rename to essential/picamera_library_modified/docs/images/enable_camera.png diff --git a/picamera_library_modified/docs/images/encoder_classes.pdf b/essential/picamera_library_modified/docs/images/encoder_classes.pdf similarity index 100% rename from picamera_library_modified/docs/images/encoder_classes.pdf rename to essential/picamera_library_modified/docs/images/encoder_classes.pdf diff --git a/picamera_library_modified/docs/images/encoder_classes.png b/essential/picamera_library_modified/docs/images/encoder_classes.png similarity index 100% rename from picamera_library_modified/docs/images/encoder_classes.png rename to essential/picamera_library_modified/docs/images/encoder_classes.png diff --git a/picamera_library_modified/docs/images/encoder_classes.svg b/essential/picamera_library_modified/docs/images/encoder_classes.svg similarity index 100% rename from picamera_library_modified/docs/images/encoder_classes.svg rename to essential/picamera_library_modified/docs/images/encoder_classes.svg diff --git a/picamera_library_modified/docs/images/good_connection.jpg b/essential/picamera_library_modified/docs/images/good_connection.jpg similarity index 100% rename from picamera_library_modified/docs/images/good_connection.jpg rename to essential/picamera_library_modified/docs/images/good_connection.jpg diff --git a/picamera_library_modified/docs/images/good_connection.xcf b/essential/picamera_library_modified/docs/images/good_connection.xcf similarity index 100% rename from picamera_library_modified/docs/images/good_connection.xcf rename to essential/picamera_library_modified/docs/images/good_connection.xcf diff --git a/picamera_library_modified/docs/images/gpu_architecture.pdf b/essential/picamera_library_modified/docs/images/gpu_architecture.pdf similarity index 100% rename from picamera_library_modified/docs/images/gpu_architecture.pdf rename to essential/picamera_library_modified/docs/images/gpu_architecture.pdf diff --git a/picamera_library_modified/docs/images/gpu_architecture.png b/essential/picamera_library_modified/docs/images/gpu_architecture.png similarity index 100% rename from picamera_library_modified/docs/images/gpu_architecture.png rename to essential/picamera_library_modified/docs/images/gpu_architecture.png diff --git a/picamera_library_modified/docs/images/gpu_architecture.svg b/essential/picamera_library_modified/docs/images/gpu_architecture.svg similarity index 100% rename from picamera_library_modified/docs/images/gpu_architecture.svg rename to essential/picamera_library_modified/docs/images/gpu_architecture.svg diff --git a/picamera_library_modified/docs/images/image_protocol.pdf b/essential/picamera_library_modified/docs/images/image_protocol.pdf similarity index 100% rename from picamera_library_modified/docs/images/image_protocol.pdf rename to essential/picamera_library_modified/docs/images/image_protocol.pdf diff --git a/picamera_library_modified/docs/images/image_protocol.png b/essential/picamera_library_modified/docs/images/image_protocol.png similarity index 100% rename from picamera_library_modified/docs/images/image_protocol.png rename to essential/picamera_library_modified/docs/images/image_protocol.png diff --git a/picamera_library_modified/docs/images/image_protocol.svg b/essential/picamera_library_modified/docs/images/image_protocol.svg similarity index 100% rename from picamera_library_modified/docs/images/image_protocol.svg rename to essential/picamera_library_modified/docs/images/image_protocol.svg diff --git a/picamera_library_modified/docs/images/jpeg_capture_pipeline.dot b/essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.dot similarity index 100% rename from picamera_library_modified/docs/images/jpeg_capture_pipeline.dot rename to essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.dot diff --git a/picamera_library_modified/docs/images/jpeg_capture_pipeline.pdf b/essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.pdf similarity index 100% rename from picamera_library_modified/docs/images/jpeg_capture_pipeline.pdf rename to essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.pdf diff --git a/picamera_library_modified/docs/images/jpeg_capture_pipeline.png b/essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.png similarity index 100% rename from picamera_library_modified/docs/images/jpeg_capture_pipeline.png rename to essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.png diff --git a/picamera_library_modified/docs/images/jpeg_capture_pipeline.svg b/essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.svg similarity index 100% rename from picamera_library_modified/docs/images/jpeg_capture_pipeline.svg rename to essential/picamera_library_modified/docs/images/jpeg_capture_pipeline.svg diff --git a/picamera_library_modified/docs/images/jpeg_encode_pipeline.dot b/essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.dot similarity index 100% rename from picamera_library_modified/docs/images/jpeg_encode_pipeline.dot rename to essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.dot diff --git a/picamera_library_modified/docs/images/jpeg_encode_pipeline.pdf b/essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.pdf similarity index 100% rename from picamera_library_modified/docs/images/jpeg_encode_pipeline.pdf rename to essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.pdf diff --git a/picamera_library_modified/docs/images/jpeg_encode_pipeline.png b/essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.png similarity index 100% rename from picamera_library_modified/docs/images/jpeg_encode_pipeline.png rename to essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.png diff --git a/picamera_library_modified/docs/images/jpeg_encode_pipeline.svg b/essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.svg similarity index 100% rename from picamera_library_modified/docs/images/jpeg_encode_pipeline.svg rename to essential/picamera_library_modified/docs/images/jpeg_encode_pipeline.svg diff --git a/picamera_library_modified/docs/images/pi_zero_assembled.jpg b/essential/picamera_library_modified/docs/images/pi_zero_assembled.jpg similarity index 100% rename from picamera_library_modified/docs/images/pi_zero_assembled.jpg rename to essential/picamera_library_modified/docs/images/pi_zero_assembled.jpg diff --git a/picamera_library_modified/docs/images/pi_zero_pieces.jpg b/essential/picamera_library_modified/docs/images/pi_zero_pieces.jpg similarity index 100% rename from picamera_library_modified/docs/images/pi_zero_pieces.jpg rename to essential/picamera_library_modified/docs/images/pi_zero_pieces.jpg diff --git a/picamera_library_modified/docs/images/picamera_pipeline.dot b/essential/picamera_library_modified/docs/images/picamera_pipeline.dot similarity index 100% rename from picamera_library_modified/docs/images/picamera_pipeline.dot rename to essential/picamera_library_modified/docs/images/picamera_pipeline.dot diff --git a/picamera_library_modified/docs/images/picamera_pipeline.pdf b/essential/picamera_library_modified/docs/images/picamera_pipeline.pdf similarity index 100% rename from picamera_library_modified/docs/images/picamera_pipeline.pdf rename to essential/picamera_library_modified/docs/images/picamera_pipeline.pdf diff --git a/picamera_library_modified/docs/images/picamera_pipeline.png b/essential/picamera_library_modified/docs/images/picamera_pipeline.png similarity index 100% rename from picamera_library_modified/docs/images/picamera_pipeline.png rename to essential/picamera_library_modified/docs/images/picamera_pipeline.png diff --git a/picamera_library_modified/docs/images/picamera_pipeline.svg b/essential/picamera_library_modified/docs/images/picamera_pipeline.svg similarity index 100% rename from picamera_library_modified/docs/images/picamera_pipeline.svg rename to essential/picamera_library_modified/docs/images/picamera_pipeline.svg diff --git a/picamera_library_modified/docs/images/preview_pipeline.dot b/essential/picamera_library_modified/docs/images/preview_pipeline.dot similarity index 100% rename from picamera_library_modified/docs/images/preview_pipeline.dot rename to essential/picamera_library_modified/docs/images/preview_pipeline.dot diff --git a/picamera_library_modified/docs/images/preview_pipeline.pdf b/essential/picamera_library_modified/docs/images/preview_pipeline.pdf similarity index 100% rename from picamera_library_modified/docs/images/preview_pipeline.pdf rename to essential/picamera_library_modified/docs/images/preview_pipeline.pdf diff --git a/picamera_library_modified/docs/images/preview_pipeline.png b/essential/picamera_library_modified/docs/images/preview_pipeline.png similarity index 100% rename from picamera_library_modified/docs/images/preview_pipeline.png rename to essential/picamera_library_modified/docs/images/preview_pipeline.png diff --git a/picamera_library_modified/docs/images/preview_pipeline.svg b/essential/picamera_library_modified/docs/images/preview_pipeline.svg similarity index 100% rename from picamera_library_modified/docs/images/preview_pipeline.svg rename to essential/picamera_library_modified/docs/images/preview_pipeline.svg diff --git a/picamera_library_modified/docs/images/rgb_capture_pipeline.dot b/essential/picamera_library_modified/docs/images/rgb_capture_pipeline.dot similarity index 100% rename from picamera_library_modified/docs/images/rgb_capture_pipeline.dot rename to essential/picamera_library_modified/docs/images/rgb_capture_pipeline.dot diff --git a/picamera_library_modified/docs/images/rgb_capture_pipeline.pdf b/essential/picamera_library_modified/docs/images/rgb_capture_pipeline.pdf similarity index 100% rename from picamera_library_modified/docs/images/rgb_capture_pipeline.pdf rename to essential/picamera_library_modified/docs/images/rgb_capture_pipeline.pdf diff --git a/picamera_library_modified/docs/images/rgb_capture_pipeline.png b/essential/picamera_library_modified/docs/images/rgb_capture_pipeline.png similarity index 100% rename from picamera_library_modified/docs/images/rgb_capture_pipeline.png rename to essential/picamera_library_modified/docs/images/rgb_capture_pipeline.png diff --git a/picamera_library_modified/docs/images/rgb_capture_pipeline.svg b/essential/picamera_library_modified/docs/images/rgb_capture_pipeline.svg similarity index 100% rename from picamera_library_modified/docs/images/rgb_capture_pipeline.svg rename to essential/picamera_library_modified/docs/images/rgb_capture_pipeline.svg diff --git a/picamera_library_modified/docs/images/sensor_area_1.png b/essential/picamera_library_modified/docs/images/sensor_area_1.png similarity index 100% rename from picamera_library_modified/docs/images/sensor_area_1.png rename to essential/picamera_library_modified/docs/images/sensor_area_1.png diff --git a/picamera_library_modified/docs/images/sensor_area_1.xcf b/essential/picamera_library_modified/docs/images/sensor_area_1.xcf similarity index 100% rename from picamera_library_modified/docs/images/sensor_area_1.xcf rename to essential/picamera_library_modified/docs/images/sensor_area_1.xcf diff --git a/picamera_library_modified/docs/images/sensor_area_2.png b/essential/picamera_library_modified/docs/images/sensor_area_2.png similarity index 100% rename from picamera_library_modified/docs/images/sensor_area_2.png rename to essential/picamera_library_modified/docs/images/sensor_area_2.png diff --git a/picamera_library_modified/docs/images/sensor_area_2.xcf b/essential/picamera_library_modified/docs/images/sensor_area_2.xcf similarity index 100% rename from picamera_library_modified/docs/images/sensor_area_2.xcf rename to essential/picamera_library_modified/docs/images/sensor_area_2.xcf diff --git a/picamera_library_modified/docs/images/still_port_capture.pdf b/essential/picamera_library_modified/docs/images/still_port_capture.pdf similarity index 100% rename from picamera_library_modified/docs/images/still_port_capture.pdf rename to essential/picamera_library_modified/docs/images/still_port_capture.pdf diff --git a/picamera_library_modified/docs/images/still_port_capture.png b/essential/picamera_library_modified/docs/images/still_port_capture.png similarity index 100% rename from picamera_library_modified/docs/images/still_port_capture.png rename to essential/picamera_library_modified/docs/images/still_port_capture.png diff --git a/picamera_library_modified/docs/images/still_port_capture.svg b/essential/picamera_library_modified/docs/images/still_port_capture.svg similarity index 100% rename from picamera_library_modified/docs/images/still_port_capture.svg rename to essential/picamera_library_modified/docs/images/still_port_capture.svg diff --git a/picamera_library_modified/docs/images/still_raw_capture.pdf b/essential/picamera_library_modified/docs/images/still_raw_capture.pdf similarity index 100% rename from picamera_library_modified/docs/images/still_raw_capture.pdf rename to essential/picamera_library_modified/docs/images/still_raw_capture.pdf diff --git a/picamera_library_modified/docs/images/still_raw_capture.png b/essential/picamera_library_modified/docs/images/still_raw_capture.png similarity index 100% rename from picamera_library_modified/docs/images/still_raw_capture.png rename to essential/picamera_library_modified/docs/images/still_raw_capture.png diff --git a/picamera_library_modified/docs/images/still_raw_capture.svg b/essential/picamera_library_modified/docs/images/still_raw_capture.svg similarity index 100% rename from picamera_library_modified/docs/images/still_raw_capture.svg rename to essential/picamera_library_modified/docs/images/still_raw_capture.svg diff --git a/picamera_library_modified/docs/images/versions.pdf b/essential/picamera_library_modified/docs/images/versions.pdf similarity index 100% rename from picamera_library_modified/docs/images/versions.pdf rename to essential/picamera_library_modified/docs/images/versions.pdf diff --git a/picamera_library_modified/docs/images/versions.png b/essential/picamera_library_modified/docs/images/versions.png similarity index 100% rename from picamera_library_modified/docs/images/versions.png rename to essential/picamera_library_modified/docs/images/versions.png diff --git a/picamera_library_modified/docs/images/versions.svg b/essential/picamera_library_modified/docs/images/versions.svg similarity index 100% rename from picamera_library_modified/docs/images/versions.svg rename to essential/picamera_library_modified/docs/images/versions.svg diff --git a/picamera_library_modified/docs/images/video_fullfov_record.pdf b/essential/picamera_library_modified/docs/images/video_fullfov_record.pdf similarity index 100% rename from picamera_library_modified/docs/images/video_fullfov_record.pdf rename to essential/picamera_library_modified/docs/images/video_fullfov_record.pdf diff --git a/picamera_library_modified/docs/images/video_fullfov_record.png b/essential/picamera_library_modified/docs/images/video_fullfov_record.png similarity index 100% rename from picamera_library_modified/docs/images/video_fullfov_record.png rename to essential/picamera_library_modified/docs/images/video_fullfov_record.png diff --git a/picamera_library_modified/docs/images/video_fullfov_record.svg b/essential/picamera_library_modified/docs/images/video_fullfov_record.svg similarity index 100% rename from picamera_library_modified/docs/images/video_fullfov_record.svg rename to essential/picamera_library_modified/docs/images/video_fullfov_record.svg diff --git a/picamera_library_modified/docs/images/video_port_capture.pdf b/essential/picamera_library_modified/docs/images/video_port_capture.pdf similarity index 100% rename from picamera_library_modified/docs/images/video_port_capture.pdf rename to essential/picamera_library_modified/docs/images/video_port_capture.pdf diff --git a/picamera_library_modified/docs/images/video_port_capture.png b/essential/picamera_library_modified/docs/images/video_port_capture.png similarity index 100% rename from picamera_library_modified/docs/images/video_port_capture.png rename to essential/picamera_library_modified/docs/images/video_port_capture.png diff --git a/picamera_library_modified/docs/images/video_port_capture.svg b/essential/picamera_library_modified/docs/images/video_port_capture.svg similarity index 100% rename from picamera_library_modified/docs/images/video_port_capture.svg rename to essential/picamera_library_modified/docs/images/video_port_capture.svg diff --git a/picamera_library_modified/docs/images/video_port_record.pdf b/essential/picamera_library_modified/docs/images/video_port_record.pdf similarity index 100% rename from picamera_library_modified/docs/images/video_port_record.pdf rename to essential/picamera_library_modified/docs/images/video_port_record.pdf diff --git a/picamera_library_modified/docs/images/video_port_record.png b/essential/picamera_library_modified/docs/images/video_port_record.png similarity index 100% rename from picamera_library_modified/docs/images/video_port_record.png rename to essential/picamera_library_modified/docs/images/video_port_record.png diff --git a/picamera_library_modified/docs/images/video_port_record.svg b/essential/picamera_library_modified/docs/images/video_port_record.svg similarity index 100% rename from picamera_library_modified/docs/images/video_port_record.svg rename to essential/picamera_library_modified/docs/images/video_port_record.svg diff --git a/picamera_library_modified/docs/images/yuv420.pdf b/essential/picamera_library_modified/docs/images/yuv420.pdf similarity index 100% rename from picamera_library_modified/docs/images/yuv420.pdf rename to essential/picamera_library_modified/docs/images/yuv420.pdf diff --git a/picamera_library_modified/docs/images/yuv420.png b/essential/picamera_library_modified/docs/images/yuv420.png similarity index 100% rename from picamera_library_modified/docs/images/yuv420.png rename to essential/picamera_library_modified/docs/images/yuv420.png diff --git a/picamera_library_modified/docs/images/yuv420.svg b/essential/picamera_library_modified/docs/images/yuv420.svg similarity index 100% rename from picamera_library_modified/docs/images/yuv420.svg rename to essential/picamera_library_modified/docs/images/yuv420.svg diff --git a/picamera_library_modified/docs/index.rst b/essential/picamera_library_modified/docs/index.rst similarity index 100% rename from picamera_library_modified/docs/index.rst rename to essential/picamera_library_modified/docs/index.rst diff --git a/picamera_library_modified/docs/install.rst b/essential/picamera_library_modified/docs/install.rst similarity index 100% rename from picamera_library_modified/docs/install.rst rename to essential/picamera_library_modified/docs/install.rst diff --git a/picamera_library_modified/docs/license.rst b/essential/picamera_library_modified/docs/license.rst similarity index 100% rename from picamera_library_modified/docs/license.rst rename to essential/picamera_library_modified/docs/license.rst diff --git a/picamera_library_modified/docs/quickstart.rst b/essential/picamera_library_modified/docs/quickstart.rst similarity index 100% rename from picamera_library_modified/docs/quickstart.rst rename to essential/picamera_library_modified/docs/quickstart.rst diff --git a/picamera_library_modified/docs/recipes1.rst b/essential/picamera_library_modified/docs/recipes1.rst similarity index 100% rename from picamera_library_modified/docs/recipes1.rst rename to essential/picamera_library_modified/docs/recipes1.rst diff --git a/picamera_library_modified/docs/recipes2.rst b/essential/picamera_library_modified/docs/recipes2.rst similarity index 100% rename from picamera_library_modified/docs/recipes2.rst rename to essential/picamera_library_modified/docs/recipes2.rst diff --git a/picamera_library_modified/picamera.egg-info/PKG-INFO b/essential/picamera_library_modified/picamera.egg-info/PKG-INFO similarity index 100% rename from picamera_library_modified/picamera.egg-info/PKG-INFO rename to essential/picamera_library_modified/picamera.egg-info/PKG-INFO diff --git a/picamera_library_modified/picamera.egg-info/SOURCES.txt b/essential/picamera_library_modified/picamera.egg-info/SOURCES.txt similarity index 100% rename from picamera_library_modified/picamera.egg-info/SOURCES.txt rename to essential/picamera_library_modified/picamera.egg-info/SOURCES.txt diff --git a/essential/picamera_library_modified/picamera.egg-info/dependency_links.txt b/essential/picamera_library_modified/picamera.egg-info/dependency_links.txt new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/essential/picamera_library_modified/picamera.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/picamera_library_modified/picamera.egg-info/requires.txt b/essential/picamera_library_modified/picamera.egg-info/requires.txt similarity index 100% rename from picamera_library_modified/picamera.egg-info/requires.txt rename to essential/picamera_library_modified/picamera.egg-info/requires.txt diff --git a/picamera_library_modified/picamera.egg-info/top_level.txt b/essential/picamera_library_modified/picamera.egg-info/top_level.txt similarity index 100% rename from picamera_library_modified/picamera.egg-info/top_level.txt rename to essential/picamera_library_modified/picamera.egg-info/top_level.txt diff --git a/picamera_library_modified/picamera/__init__.py b/essential/picamera_library_modified/picamera/__init__.py similarity index 100% rename from picamera_library_modified/picamera/__init__.py rename to essential/picamera_library_modified/picamera/__init__.py diff --git a/picamera_library_modified/picamera/array.py b/essential/picamera_library_modified/picamera/array.py similarity index 100% rename from picamera_library_modified/picamera/array.py rename to essential/picamera_library_modified/picamera/array.py diff --git a/picamera_library_modified/picamera/bcm_host.py b/essential/picamera_library_modified/picamera/bcm_host.py similarity index 100% rename from picamera_library_modified/picamera/bcm_host.py rename to essential/picamera_library_modified/picamera/bcm_host.py diff --git a/picamera_library_modified/picamera/camera.py b/essential/picamera_library_modified/picamera/camera.py similarity index 100% rename from picamera_library_modified/picamera/camera.py rename to essential/picamera_library_modified/picamera/camera.py diff --git a/picamera_library_modified/picamera/color.py b/essential/picamera_library_modified/picamera/color.py similarity index 100% rename from picamera_library_modified/picamera/color.py rename to essential/picamera_library_modified/picamera/color.py diff --git a/picamera_library_modified/picamera/display.py b/essential/picamera_library_modified/picamera/display.py similarity index 100% rename from picamera_library_modified/picamera/display.py rename to essential/picamera_library_modified/picamera/display.py diff --git a/picamera_library_modified/picamera/encoders.py b/essential/picamera_library_modified/picamera/encoders.py similarity index 100% rename from picamera_library_modified/picamera/encoders.py rename to essential/picamera_library_modified/picamera/encoders.py diff --git a/picamera_library_modified/picamera/exc.py b/essential/picamera_library_modified/picamera/exc.py similarity index 100% rename from picamera_library_modified/picamera/exc.py rename to essential/picamera_library_modified/picamera/exc.py diff --git a/picamera_library_modified/picamera/frames.py b/essential/picamera_library_modified/picamera/frames.py similarity index 100% rename from picamera_library_modified/picamera/frames.py rename to essential/picamera_library_modified/picamera/frames.py diff --git a/picamera_library_modified/picamera/mmal.py b/essential/picamera_library_modified/picamera/mmal.py similarity index 100% rename from picamera_library_modified/picamera/mmal.py rename to essential/picamera_library_modified/picamera/mmal.py diff --git a/picamera_library_modified/picamera/mmalobj.py b/essential/picamera_library_modified/picamera/mmalobj.py similarity index 100% rename from picamera_library_modified/picamera/mmalobj.py rename to essential/picamera_library_modified/picamera/mmalobj.py diff --git a/picamera_library_modified/picamera/renderers.py b/essential/picamera_library_modified/picamera/renderers.py similarity index 100% rename from picamera_library_modified/picamera/renderers.py rename to essential/picamera_library_modified/picamera/renderers.py diff --git a/picamera_library_modified/picamera/streams.py b/essential/picamera_library_modified/picamera/streams.py similarity index 100% rename from picamera_library_modified/picamera/streams.py rename to essential/picamera_library_modified/picamera/streams.py diff --git a/picamera_library_modified/py32dev_requirements.txt b/essential/picamera_library_modified/py32dev_requirements.txt similarity index 100% rename from picamera_library_modified/py32dev_requirements.txt rename to essential/picamera_library_modified/py32dev_requirements.txt diff --git a/picamera_library_modified/rtd_requirements.txt b/essential/picamera_library_modified/rtd_requirements.txt similarity index 100% rename from picamera_library_modified/rtd_requirements.txt rename to essential/picamera_library_modified/rtd_requirements.txt diff --git a/picamera_library_modified/setup.py b/essential/picamera_library_modified/setup.py similarity index 100% rename from picamera_library_modified/setup.py rename to essential/picamera_library_modified/setup.py diff --git a/picamera_library_modified/tests/conftest.py b/essential/picamera_library_modified/tests/conftest.py similarity index 100% rename from picamera_library_modified/tests/conftest.py rename to essential/picamera_library_modified/tests/conftest.py diff --git a/picamera_library_modified/tests/test_array.py b/essential/picamera_library_modified/tests/test_array.py similarity index 100% rename from picamera_library_modified/tests/test_array.py rename to essential/picamera_library_modified/tests/test_array.py diff --git a/picamera_library_modified/tests/test_attr.py b/essential/picamera_library_modified/tests/test_attr.py similarity index 100% rename from picamera_library_modified/tests/test_attr.py rename to essential/picamera_library_modified/tests/test_attr.py diff --git a/picamera_library_modified/tests/test_capture.py b/essential/picamera_library_modified/tests/test_capture.py similarity index 100% rename from picamera_library_modified/tests/test_capture.py rename to essential/picamera_library_modified/tests/test_capture.py diff --git a/picamera_library_modified/tests/test_exc.py b/essential/picamera_library_modified/tests/test_exc.py similarity index 100% rename from picamera_library_modified/tests/test_exc.py rename to essential/picamera_library_modified/tests/test_exc.py diff --git a/picamera_library_modified/tests/test_misc.py b/essential/picamera_library_modified/tests/test_misc.py similarity index 100% rename from picamera_library_modified/tests/test_misc.py rename to essential/picamera_library_modified/tests/test_misc.py diff --git a/picamera_library_modified/tests/test_record.py b/essential/picamera_library_modified/tests/test_record.py similarity index 100% rename from picamera_library_modified/tests/test_record.py rename to essential/picamera_library_modified/tests/test_record.py diff --git a/picamera_library_modified/tests/test_streams.py b/essential/picamera_library_modified/tests/test_streams.py similarity index 100% rename from picamera_library_modified/tests/test_streams.py rename to essential/picamera_library_modified/tests/test_streams.py diff --git a/picamera_library_modified/tests/verify.py b/essential/picamera_library_modified/tests/verify.py similarity index 100% rename from picamera_library_modified/tests/verify.py rename to essential/picamera_library_modified/tests/verify.py diff --git a/pygame_matplotlib/__init__.py b/essential/pygame_matplotlib/__init__.py similarity index 100% rename from pygame_matplotlib/__init__.py rename to essential/pygame_matplotlib/__init__.py diff --git a/pygame_matplotlib/backend_pygame.py b/essential/pygame_matplotlib/backend_pygame.py similarity index 100% rename from pygame_matplotlib/backend_pygame.py rename to essential/pygame_matplotlib/backend_pygame.py diff --git a/pygame_matplotlib/gui_window.py b/essential/pygame_matplotlib/gui_window.py similarity index 100% rename from pygame_matplotlib/gui_window.py rename to essential/pygame_matplotlib/gui_window.py diff --git a/essential/scripts/__init__.py b/essential/scripts/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/scripts/__init__.py @@ -0,0 +1 @@ + diff --git a/scripts/root_crontab.sh b/essential/scripts/root_crontab.sh similarity index 100% rename from scripts/root_crontab.sh rename to essential/scripts/root_crontab.sh diff --git a/scripts/user_crontab.sh b/essential/scripts/user_crontab.sh similarity index 100% rename from scripts/user_crontab.sh rename to essential/scripts/user_crontab.sh diff --git a/essential/sound/001-beep.wav b/essential/sound/001-beep.wav new file mode 100644 index 0000000..4959964 Binary files /dev/null and b/essential/sound/001-beep.wav differ diff --git a/essential/sound/002-buzz.wav b/essential/sound/002-buzz.wav new file mode 100644 index 0000000..428916f Binary files /dev/null and b/essential/sound/002-buzz.wav differ diff --git a/essential/sound/003-buzz.wav b/essential/sound/003-buzz.wav new file mode 100644 index 0000000..428916f Binary files /dev/null and b/essential/sound/003-buzz.wav differ diff --git a/essential/sound/004-white-noise-44-1-16bit.wav b/essential/sound/004-white-noise-44-1-16bit.wav new file mode 100644 index 0000000..f0d50a8 Binary files /dev/null and b/essential/sound/004-white-noise-44-1-16bit.wav differ diff --git a/syringe_pump_c_code/main.c b/essential/syringe_pump_c_code/main.c similarity index 100% rename from syringe_pump_c_code/main.c rename to essential/syringe_pump_c_code/main.c diff --git a/syringe_pump_c_code/main.py b/essential/syringe_pump_c_code/main.py similarity index 100% rename from syringe_pump_c_code/main.py rename to essential/syringe_pump_c_code/main.py diff --git a/syringe_pump_c_code/main.so b/essential/syringe_pump_c_code/main.so similarity index 100% rename from syringe_pump_c_code/main.so rename to essential/syringe_pump_c_code/main.so diff --git a/syringe_pump_c_code/readme.md b/essential/syringe_pump_c_code/readme.md similarity index 100% rename from syringe_pump_c_code/readme.md rename to essential/syringe_pump_c_code/readme.md diff --git a/treadmill/Bounce2-master (1).zip b/essential/treadmill/Bounce2-master (1).zip similarity index 100% rename from treadmill/Bounce2-master (1).zip rename to essential/treadmill/Bounce2-master (1).zip diff --git a/treadmill/Treadmill.ino b/essential/treadmill/Treadmill.ino similarity index 100% rename from treadmill/Treadmill.ino rename to essential/treadmill/Treadmill.ino diff --git a/treadmill/Treadmill_20200302.ino b/essential/treadmill/Treadmill_20200302.ino similarity index 100% rename from treadmill/Treadmill_20200302.ino rename to essential/treadmill/Treadmill_20200302.ino diff --git a/treadmill/Treadmill_20211112.ino b/essential/treadmill/Treadmill_20211112.ino similarity index 100% rename from treadmill/Treadmill_20211112.ino rename to essential/treadmill/Treadmill_20211112.ino diff --git a/essential/treadmill/__init__.py b/essential/treadmill/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/treadmill/__init__.py @@ -0,0 +1 @@ + diff --git a/treadmill/digitalWriteFast-master (1).zip b/essential/treadmill/digitalWriteFast-master (1).zip similarity index 100% rename from treadmill/digitalWriteFast-master (1).zip rename to essential/treadmill/digitalWriteFast-master (1).zip diff --git a/treadmill/readme.md b/essential/treadmill/readme.md similarity index 100% rename from treadmill/readme.md rename to essential/treadmill/readme.md diff --git a/treadmill/treadmill_current.ino b/essential/treadmill/treadmill_current.ino similarity index 100% rename from treadmill/treadmill_current.ino rename to essential/treadmill/treadmill_current.ino diff --git a/treadmill_distance.ino b/essential/treadmill/treadmill_distance.ino similarity index 100% rename from treadmill_distance.ino rename to essential/treadmill/treadmill_distance.ino diff --git a/treadmill_i2c.py b/essential/treadmill/treadmill_i2c.py similarity index 100% rename from treadmill_i2c.py rename to essential/treadmill/treadmill_i2c.py diff --git a/video_acquisition/README.md b/essential/video_acquisition/README.md similarity index 100% rename from video_acquisition/README.md rename to essential/video_acquisition/README.md diff --git a/video_acquisition/StartAcquisition_gpio.py b/essential/video_acquisition/StartAcquisition_gpio.py similarity index 100% rename from video_acquisition/StartAcquisition_gpio.py rename to essential/video_acquisition/StartAcquisition_gpio.py diff --git a/video_acquisition/VideoCapture.py b/essential/video_acquisition/VideoCapture.py similarity index 100% rename from video_acquisition/VideoCapture.py rename to essential/video_acquisition/VideoCapture.py diff --git a/essential/video_acquisition/__init__.py b/essential/video_acquisition/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/video_acquisition/__init__.py @@ -0,0 +1 @@ + diff --git a/video_acquisition/control_acquisition.py b/essential/video_acquisition/control_acquisition.py similarity index 100% rename from video_acquisition/control_acquisition.py rename to essential/video_acquisition/control_acquisition.py diff --git a/video_acquisition/killrecording.py b/essential/video_acquisition/killrecording.py similarity index 100% rename from video_acquisition/killrecording.py rename to essential/video_acquisition/killrecording.py diff --git a/video_acquisition/start_acquisition.py b/essential/video_acquisition/start_acquisition.py similarity index 100% rename from video_acquisition/start_acquisition.py rename to essential/video_acquisition/start_acquisition.py diff --git a/video_acquisition/start_acquisition_old.py b/essential/video_acquisition/start_acquisition_old.py similarity index 100% rename from video_acquisition/start_acquisition_old.py rename to essential/video_acquisition/start_acquisition_old.py diff --git a/start_preview.py b/essential/video_acquisition/start_preview.py similarity index 100% rename from start_preview.py rename to essential/video_acquisition/start_preview.py diff --git a/video_acquisition/stop_acquisition.sh b/essential/video_acquisition/stop_acquisition.sh similarity index 100% rename from video_acquisition/stop_acquisition.sh rename to essential/video_acquisition/stop_acquisition.sh diff --git a/stop_preview.sh b/essential/video_acquisition/stop_preview.sh similarity index 100% rename from stop_preview.sh rename to essential/video_acquisition/stop_preview.sh diff --git a/stop_video b/essential/video_acquisition/stop_video similarity index 100% rename from stop_video rename to essential/video_acquisition/stop_video diff --git a/essential/visual_stimuli/__init__.py b/essential/visual_stimuli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/essential/visual_stimuli/__init__.py @@ -0,0 +1 @@ + diff --git a/visual_stimuli/readme.md b/essential/visual_stimuli/readme.md similarity index 100% rename from visual_stimuli/readme.md rename to essential/visual_stimuli/readme.md diff --git a/visual_stimuli/vstest.py b/essential/visual_stimuli/vstest.py similarity index 100% rename from visual_stimuli/vstest.py rename to essential/visual_stimuli/vstest.py diff --git a/visualstim.py b/essential/visualstim.py similarity index 100% rename from visualstim.py rename to essential/visualstim.py diff --git a/behavbox_v2.py b/obsolete/behavbox_v2.py similarity index 100% rename from behavbox_v2.py rename to obsolete/behavbox_v2.py diff --git a/fake_session_info.py b/obsolete/fake_session_info.py similarity index 100% rename from fake_session_info.py rename to obsolete/fake_session_info.py diff --git a/headfixed2FC_task.py b/obsolete/headfixed2FC_task_old.py similarity index 93% rename from headfixed2FC_task.py rename to obsolete/headfixed2FC_task_old.py index 9b28b8a..996b29b 100644 --- a/headfixed2FC_task.py +++ b/obsolete/headfixed2FC_task_old.py @@ -123,8 +123,8 @@ def __init__(self, **kwargs): # name and session_info should be provided as kwa self.wrong_choice_error = False self.multiple_choice_error = False self.error_repeat = False - self.reward_time_start = None # for reward_available state time keeping purpose - self.reward_time = 10 # sec. could be incorporate into the session_info; available time for reward + self.reward_time_start = None # for reward_available state time keeping purpose + self.reward_time = 10 # sec. could be incorporate into the session_info; available time for reward self.reward_times_up = False self.block_count = 0 @@ -160,6 +160,7 @@ def __init__(self, **kwargs): # name and session_info should be provided as kwa # session_statistics self.total_reward = 0 self.correct_trial_in_block = 0 + ######################################################################## # functions called when state transitions occur ######################################################################## @@ -205,7 +206,6 @@ def run(self): self.restart() # first detect the lick signal: cue_state = self.current_card[0] - # side_choice = self.current_card[2] side_mice = None if self.event_name == "left_entry": side_mice = 'left' @@ -222,34 +222,35 @@ def run(self): if cue_state == 'all': side_choice = side_mice if side_choice == 'left': - reward_size = self.current_card[2][0] + left_reward = self.session_info['reward_size'][self.current_card[2][0]] + reward_size = random.uniform(left_reward - self.session_info['reward_deviation'], + left_reward + self.session_info['reward_deviation']) pump_num = self.current_card[3][0] elif side_choice == 'right': - reward_size = self.current_card[2][1] + right_reward = self.session_info['reward_size'][self.current_card[2][1]] + reward_size = random.uniform(right_reward - self.session_info['reward_deviation'], + right_reward + self.session_info['reward_deviation']) pump_num = self.current_card[3][1] else: side_choice = self.current_card[1] - reward_size = self.current_card[2] + forced_reward = self.session_info['reward_size'][self.current_card[2]] + reward_size = random.uniform(forced_reward - self.session_info['reward_deviation'], + forced_reward + self.session_info['reward_deviation']) pump_num = self.current_card[3] if side_mice == side_choice: # if the animal chose correctly print("Number of lick detected: " + str(self.lick_count)) if self.lick_count == 0: # if this is the first lick - # self.side_mice_buffer = side_mice - self.pump.reward(pump_num, self.session_info["reward_size"][reward_size]) + self.pump.reward(pump_num, reward_size) self.total_reward += 1 self.correct_trial_in_block += 1 self.reward_time_start = time.time() print("Reward time start" + str(self.reward_time_start)) self.lick_count += 1 - elif self.side_mice_buffer: if self.lick_count == 0: self.check_cue('sound2') self.wrong_choice_error = True self.restart() - #else: # wrong side - wrong_choice error - # self.multiple_choice_error = True - # self.restart() # look for keystrokes self.box.check_keybd() @@ -331,11 +332,6 @@ def exit_reward_available(self): self.error_repeat = True self.error_list.append('wrong_choice_error') self.wrong_choice_error = False - #elif self.multiple_choice_error: - # logging.info(";" + str(time.time()) + ";[error];multiple_choice_error;" + str(self.error_repeat)) - # self.error_repeat = False - # self.error_list.append('multiple_choice_error') - # self.multiple_choice_error = False elif self.lick_count == 0: logging.info(";" + str(time.time()) + ";[error];no_choice_error;" + str(self.error_repeat)) self.error_repeat = True @@ -360,16 +356,13 @@ def check_cue(self, cue): # self.LED_blink = True self.box.cueLED2.on() logging.info(";" + str(time.time()) + ";[cue];cueLED_R_on;" + str(self.error_repeat)) - elif cue =='all': - #self.box.cueLED1.blink(0.2, 0.1) + elif cue == 'all': self.box.cueLED1.on() self.box.cueLED2.on() logging.info(";" + str(time.time()) + ";[cue];LED_L+R_on; " + str(self.error_repeat)) def cue_off(self, cue): if cue == 'all': - #self.box.sound1.off() - #self.box.sound2.off() self.box.cueLED1.off() self.box.cueLED2.off() elif cue == 'sound1': @@ -380,7 +373,6 @@ def cue_off(self, cue): logging.info(";" + str(time.time()) + ";[cue];cue_sound2_off;" + str(self.error_repeat)) elif cue == 'LED_L': self.box.cueLED1.off() - #self.LED_blink = False logging.info(";" + str(time.time()) + ";[cue];cueLED1_off;" + str(self.error_repeat)) elif cue == 'LED_R': self.box.cueLED2.off() @@ -406,8 +398,6 @@ def update_plot_error(self): ticks = range(len(counts)) fig, ax = plt.subplots(1, 1, ) ax.bar(ticks, counts, align='center', tick_label=labels) - # plt.xticks(ticks, labels) - # plt.title(session_name) ax = plt.gca() ax.set_xticks(ticks, labels) ax.set_xticklabels(labels=labels, rotation=70) diff --git a/headfixed_task.py b/obsolete/headfixed_task_old.py similarity index 100% rename from headfixed_task.py rename to obsolete/headfixed_task_old.py diff --git a/lick_task.py b/obsolete/lick_task.py similarity index 100% rename from lick_task.py rename to obsolete/lick_task.py diff --git a/pump_task.py b/obsolete/pump_task.py similarity index 100% rename from pump_task.py rename to obsolete/pump_task.py diff --git a/record_run_test.py b/obsolete/record_run_test.py similarity index 100% rename from record_run_test.py rename to obsolete/record_run_test.py diff --git a/run_flip_task.py b/obsolete/run_flip_task.py similarity index 100% rename from run_flip_task.py rename to obsolete/run_flip_task.py diff --git a/run_headfixed2FC_task.py b/obsolete/run_headfixed2FC_task.py similarity index 100% rename from run_headfixed2FC_task.py rename to obsolete/run_headfixed2FC_task.py diff --git a/run_headfixed_task.py b/obsolete/run_headfixed_task.py similarity index 100% rename from run_headfixed_task.py rename to obsolete/run_headfixed_task.py diff --git a/run_lick_task.py b/obsolete/run_lick_task.py similarity index 100% rename from run_lick_task.py rename to obsolete/run_lick_task.py diff --git a/run_season_task.py b/obsolete/run_season_task.py similarity index 100% rename from run_season_task.py rename to obsolete/run_season_task.py diff --git a/run_soyoun_task.py b/obsolete/run_soyoun_task.py similarity index 100% rename from run_soyoun_task.py rename to obsolete/run_soyoun_task.py diff --git a/run_visualization_task.py b/obsolete/run_visualization_task.py similarity index 100% rename from run_visualization_task.py rename to obsolete/run_visualization_task.py diff --git a/run_walk_task.py b/obsolete/run_walk_task.py similarity index 100% rename from run_walk_task.py rename to obsolete/run_walk_task.py diff --git a/session_info_headfixed.py b/obsolete/session_info_headfixed.py similarity index 100% rename from session_info_headfixed.py rename to obsolete/session_info_headfixed.py diff --git a/session_info_headfixed2FC.py b/obsolete/session_info_headfixed2FC.py similarity index 85% rename from session_info_headfixed2FC.py rename to obsolete/session_info_headfixed2FC.py index 54c165c..8136923 100644 --- a/session_info_headfixed2FC.py +++ b/obsolete/session_info_headfixed2FC.py @@ -55,6 +55,7 @@ session_info['choice'] = ['right', 'left'] # lick port session_info['reward'] = ['small', 'large'] # reward size session_info['reward_size'] = {'small': 5, 'large': 10} +session_info['reward_deviation'] = 1 if session_info['phase'] == 1: session_info['reward_size'] = {'small': 10, 'large': 10} @@ -74,3 +75,14 @@ session_info['consecutive_control'] = False if session_info['consecutive_control']: session_info['consecutive_max'] = 3 + +session_info["calibration_coefficient"] = {} + +session_info["calibration_coefficient"]['1'] = [0.13, 0] # highest power first +session_info["calibration_coefficient"]['2'] = [0.13, 0] +session_info["calibration_coefficient"]['3'] = [0.13, 0.0] +session_info["calibration_coefficient"]['4'] = [0.13, 0.0] + +session_info['air_duration'] = 0 +session_info["vacuum_duration"] = 1 +session_info["key_reward_amount"] = 5 \ No newline at end of file diff --git a/session_info_walk.py b/obsolete/session_info_walk.py similarity index 100% rename from session_info_walk.py rename to obsolete/session_info_walk.py diff --git a/soyoun_task.py b/obsolete/soyoun_task.py similarity index 100% rename from soyoun_task.py rename to obsolete/soyoun_task.py diff --git a/task_information_headfixed.py b/obsolete/task_information_headfixed.py similarity index 100% rename from task_information_headfixed.py rename to obsolete/task_information_headfixed.py diff --git a/task_information_headfixed2FC.py b/obsolete/task_information_headfixed2FC.py similarity index 100% rename from task_information_headfixed2FC.py rename to obsolete/task_information_headfixed2FC.py diff --git a/task_information_lick.py b/obsolete/task_information_lick.py similarity index 100% rename from task_information_lick.py rename to obsolete/task_information_lick.py diff --git a/task_information_phase_1.py b/obsolete/task_information_phase_1.py similarity index 100% rename from task_information_phase_1.py rename to obsolete/task_information_phase_1.py diff --git a/test_session_info.py b/obsolete/test_session_info.py similarity index 100% rename from test_session_info.py rename to obsolete/test_session_info.py diff --git a/testing_visualstim.py b/obsolete/testing_visualstim.py similarity index 100% rename from testing_visualstim.py rename to obsolete/testing_visualstim.py diff --git a/visualization_task.py b/obsolete/visualization_task.py similarity index 100% rename from visualization_task.py rename to obsolete/visualization_task.py diff --git a/walk_task.py b/obsolete/walk_task.py similarity index 100% rename from walk_task.py rename to obsolete/walk_task.py diff --git a/syringe_pump_pygame_debug.py b/syringe_pump_pygame_debug.py deleted file mode 100644 index a2dfbcc..0000000 --- a/syringe_pump_pygame_debug.py +++ /dev/null @@ -1,38 +0,0 @@ -import pygame -from behavbox import Pump -import numpy as np -try: - pump = Pump() - pygame.init() - DISPLAYSURF = pygame.display.set_mode((200, 200)) - pygame.display.set_caption("pygame debugging") -except Exception as error_message: - print(str(error_message)) - -run = True -reward_size = float(input("Input reward_size: ")) - -while run: - for event in pygame.event.get(): - if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: - run = False - if event.type == pygame.KEYDOWN: - # print("KeyDown: " + str(event.type) + "\n") - if event.key == pygame.K_q: - print("Q down: syringe pump 1") - pump.reward("1", reward_size) - if event.key == pygame.K_w: - print("W down: syringe pump 2") - pump.reward("2", reward_size) - if event.key == pygame.K_e: - print("E down: syringe pump 3") - pump.reward("3", reward_size) - if event.key == pygame.K_r: - print("R down: syringe pump 4") - pump.reward("4", reward_size) - if event.key == pygame.K_a: - print("A down: air puff on") - pump.reward("air_puff", reward_size) - if event.key == pygame.K_s: - print("S down: vacuum on") - pump.reward("vacuum", 1) \ No newline at end of file diff --git a/EFO_task/EFO_task.py b/task_protocol/EFO_task/EFO_task.py similarity index 98% rename from EFO_task/EFO_task.py rename to task_protocol/EFO_task/EFO_task.py index 4eaddd7..5b86cde 100644 --- a/EFO_task/EFO_task.py +++ b/task_protocol/EFO_task/EFO_task.py @@ -26,7 +26,9 @@ } ) # all modules above this line will have logging disabled - +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') import behavbox # adding timing capability to the state machine diff --git a/task_protocol/EFO_task/__init__.py b/task_protocol/EFO_task/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/task_protocol/EFO_task/__init__.py @@ -0,0 +1 @@ + diff --git a/task_protocol/__init__.py b/task_protocol/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/task_protocol/__init__.py @@ -0,0 +1 @@ + diff --git a/task_protocol/headfixed_task/__init__.py b/task_protocol/headfixed_task/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/task_protocol/headfixed_task/__init__.py @@ -0,0 +1 @@ + diff --git a/task_protocol/headfixed_task/headfixed_independent_reward_task.py b/task_protocol/headfixed_task/headfixed_independent_reward_task.py new file mode 100644 index 0000000..9484671 --- /dev/null +++ b/task_protocol/headfixed_task/headfixed_independent_reward_task.py @@ -0,0 +1,471 @@ +# python3: headfixed_task.py +""" +author: tian qiu & Soyoun Kim +date: 2023-02-16 +name: headfixed2FC_task.py +goal: model_free reinforcement learning behavioral training task structure +description: + an updated test version of headfixed_task.py & add foraging reward condition + +""" +import importlib +from transitions import Machine +from transitions import State +from transitions.extensions.states import add_state_features, Timeout +import pysistence, collections +from icecream import ic +import logging +import time +from datetime import datetime +import os +from gpiozero import PWMLED, LED, Button +from colorama import Fore, Style +import logging.config +from time import sleep +import random +import threading +import matplotlib +import matplotlib.pyplot as plt +import matplotlib.figure as fg +import numpy as np + +logging.config.dictConfig( + { + "version": 1, + "disable_existing_loggers": True, + } +) +# all modules above this line will have logging disabled + +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') +import behavbox + + +# adding timing capability to the state machine +@add_state_features(Timeout) +class TimedStateMachine(Machine): + pass + + +class HeadfixedIndependentRewardTask(object): + # Define states. States where the animals is waited to make their decision + + def __init__(self, **kwargs): # name and session_info should be provided as kwargs + + # if no name or session, make fake ones (for testing purposes) + if kwargs.get("name", None) is None: + self.name = "name" + print( + Fore.RED + + Style.BRIGHT + + "Warning: no name supplied; making fake one" + + Style.RESET_ALL + ) + else: + self.name = kwargs.get("name", None) + + if kwargs.get("session_info", None) is None: + print( + Fore.RED + + Style.BRIGHT + + "Warning: no session_info supplied; making fake one" + + Style.RESET_ALL + ) + from fake_session_info import fake_session_info + + self.session_info = fake_session_info + else: + self.session_info = kwargs.get("session_info", None) + ic(self.session_info) + + # initialize the state machine + self.states = [ + State(name='standby', + on_enter=["enter_standby"], + on_exit=["exit_standby"]), + Timeout(name="initiate", + on_enter=["enter_initiate"], + on_exit=["exit_initiate"], + timeout=self.session_info["initiation_timeout"], + on_timeout=["restart"]), + Timeout(name='cue_state', + on_enter=["enter_cue_state"], + on_exit=["exit_cue_state"], + timeout=self.session_info["cue_timeout"], + on_timeout=["restart"]), + Timeout(name='reward_available', + on_enter=["enter_reward_available"], + on_exit=["exit_reward_available"], + timeout=self.session_info["wait_for_choice"], + on_timeout=["restart"]) + ] + self.transitions = [ + ['start_trial', 'standby', 'initiate'], + ['start_cue', 'initiate', 'cue_state'], + ['evaluate_reward', 'cue_state', 'reward_available'], + ['restart', ['initiate', 'cue_state', 'reward_available'], 'standby'] + ] + + self.machine = TimedStateMachine( + model=self, + states=self.states, + transitions=self.transitions, + initial='standby' + ) + self.trial_running = False + + # trial statistics + self.correct_trial_number = 0 + self.actual_trial_number = 0 + self.error_count = 0 + self.error_list = [] + self.early_lick_error = False + self.initiate_error = False + self.cue_state_error = False + self.wrong_choice_error = True + self.multiple_choice_error = False + self.error_repeat = False + + self.pump_num = None + self.reward_size = None + self.current_reward = None + self.reward_check = False + self.reward_size_offset = self.session_info['reward_size_offset'] + + self.block_count = 0 + self.blocknumber = self.session_info["block_number"] + self.current_card = None + self.left_poke_count = 0 + self.right_poke_count = 0 + self.timeline_left_poke = [] + self.left_poke_count_list = [] + self.timeline_right_poke = [] + self.right_poke_count_list = [] + self.event_name = "" + # initialize behavior box + self.box = behavbox.BehavBox(self.session_info) + self.pump = self.box.pump + + self.treadmill = self.box.treadmill + + self.distance_initiation = self.session_info['treadmill_setup']['distance_initiation'] + self.distance_cue = self.session_info['treadmill_setup']['distance_cue'] + self.distance_buffer = None + self.distance_diff = 0 + + # for foragaing parameters + self.side_choice = None # whether free choice is left or right + self.cue_state = None + + # for refining the lick detection + self.lick_count = 0 + self.side_mice_buffer = None + self.LED_blink = False + try: + self.lick_threshold = self.session_info["lick_threshold"] + except: + print("No lick_threshold defined in session_info. Therefore, default defined as 2 \n") + self.lick_threshold = 1 + + # session_statistics + self.total_reward = 0 + + ######################################################################## + # functions called when state transitions occur + ######################################################################## + def run(self): + if self.box.event_list: + self.event_name = self.box.event_list.popleft() + else: + self.event_name = "" + # there can only be lick during the reward available state + # if lick detected prior to reward available state + # the trial will restart and transition to standby + if self.event_name is "left_entry" or self.event_name == "right_entry": + # print("EVENT NAME !!!!!! " + self.event_name) + if self.state == "reward_available" or self.state == "standby" or self.state == "initiate": + pass + else: + self.early_lick_error = True + self.error_repeat = True + self.restart() + if self.state == "standby": + pass + elif self.state == "initiate": + self.distance_diff = self.get_distance() - self.distance_buffer + if self.distance_diff >= self.distance_initiation: + self.initiate_error = False + self.start_cue() + else: + self.initiate_error = True + elif self.state == "cue_state": + self.distance_diff = self.get_distance() - self.distance_buffer + if self.distance_diff >= self.distance_cue: + self.cue_state_error = False + self.evaluate_reward() + else: + self.cue_state_error = True + elif self.state == "reward_available": + cue_state = self.current_card[0] + side_mice = None + if self.event_name == "left_entry": + side_mice = 'left' + self.left_poke_count += 1 + self.left_poke_count_list.append(self.left_poke_count) + self.timeline_left_poke.append(time.time()) + elif self.event_name == "right_entry": + side_mice = 'right' + self.right_poke_count += 1 + self.right_poke_count_list.append(self.right_poke_count) + self.timeline_right_poke.append(time.time()) + if side_mice: + self.side_mice_buffer = side_mice + self.cue_state = cue_state # cue state for foraging + if cue_state == 'all': + side_choice = side_mice + if side_choice == 'left': + self.pump_num = self.current_card[2][0] + self.reward_size = self.current_reward[0] + print("self.current_reward[0]: " + str(self.current_reward[0])) + elif side_choice == 'right': + self.pump_num = self.current_card[2][1] + self.reward_size = self.current_reward[1] + print("self.current_reward[0]: " + str(self.current_reward[1])) + elif cue_state == 'LED_L': + side_choice = self.current_card[1] + self.pump_num = self.current_card[2] + self.reward_size = self.current_reward[0] + elif cue_state == 'LED_R': + side_choice = self.current_card[1] + self.pump_num = self.current_card[2] + self.reward_size = self.current_reward[1] + print("!!!!!!!!CUE_STATE: " + str(cue_state)) + if side_mice == side_choice: # if the animal chose correctly + self.side_mice_buffer = side_mice + if side_mice == side_choice: # if the animal chose correctly + if self.lick_count == 0: # if this is the first lick + self.side_choice = side_choice # foraging task + self.wrong_choice_error = False + self.reward_check = True + self.lick_count += 1 + self.restart() + elif self.side_mice_buffer: + if self.lick_count == 0: + self.wrong_choice_error = True + self.lick_count += 1 + self.restart() + + # look for keystrokes + self.box.check_keybd() + + def enter_standby(self): + logging.info(";" + str(time.time()) + ";[transition];enter_standby;" + str(self.error_repeat)) + self.update_plot_choice() + # self.update_plot_error() + self.trial_running = False + # self.reward_error = False + if self.early_lick_error: + self.error_list.append("early_lick_error") + logging.info(";" + str(time.time()) + ";[error];early_lick_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.early_lick_error = False + print(str(time.time()) + ", Total reward up till current session: " + str(self.total_reward)) + logging.info(";" + str(time.time()) + ";[trial];trial_" + str(self.actual_trial_number) + ";" + str(self.error_repeat)) + + def exit_standby(self): + logging.info(";" + str(time.time()) + ";[transition];exit_standby;" + str(self.error_repeat)) + self.lick_count = 0 + self.side_mice_buffer = None + self.box.event_list.clear() + pass + + def enter_initiate(self): + # print("!!!!!!!!!!!event name is " + self.event_name) # for debugging purposes + # check error_repeat + logging.info(";" + str(time.time()) + ";[transition];enter_initiate;" + str(self.error_repeat)) + self.check_cue('sound1') + self.trial_running = True + # wait for treadmill signal and process the treadmill signal + self.distance_buffer = self.get_distance() + logging.info( + ";" + str(time.time()) + ";[treadmill];" + str(self.distance_buffer) + ";" + str(self.error_repeat)) + + def exit_initiate(self): + # check the flag to see whether to shuffle or keep the original card + logging.info(";" + str(time.time()) + ";[transition];exit_initiate;" + str(self.error_repeat)) + print("EVENT NAME: " + str(self.box.event_list)) + self.cue_off('sound1') + if self.initiate_error: + self.error_list.append('initiate_error') + self.error_repeat = True + logging.info(";" + str(time.time()) + ";[error];initiate_error;" + str(self.error_repeat)) + self.error_count += 1 + + def enter_cue_state(self): + logging.info(";" + str(time.time()) + ";[transition];enter_cue_state;" + str(self.error_repeat)) + # turn on the cue according to the current card + self.check_cue(self.current_card[0]) + # wait for treadmill signal and process the treadmill signal + self.distance_buffer = self.get_distance() + logging.info( + ";" + str(time.time()) + ";[treadmill];" + str(self.distance_buffer) + ";" + str(self.error_repeat)) + + def exit_cue_state(self): + logging.info(";" + str(time.time()) + ";[transition];exit_cue_state;" + str(self.error_repeat)) + self.cue_off(self.current_card[0]) + if not self.early_lick_error: + if self.cue_state_error: + self.check_cue("sound2") + self.error_list.append('cue_state_error') + self.error_repeat = True + logging.info(";" + str(time.time()) + ";[error];cue_state_error;" + str(self.error_repeat)) + self.error_count += 1 + self.cue_state_error = False + + def enter_reward_available(self): + logging.info(";" + str(time.time()) + ";[transition];enter_reward_available;" + str(self.error_repeat)) + print(str(time.time()) + ", " + str(self.actual_trial_number) + ", cue_state distance satisfied") + + def exit_reward_available(self): + logging.info(";" + str(time.time()) + ";[transition];exit_reward_available;" + str(self.error_repeat)) + if self.lick_count == 0: + logging.info(";" + str(time.time()) + ";[error];no_choice_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.error_repeat = True + self.error_count += 1 + self.error_list.append('no_choice_error') + elif self.wrong_choice_error: + logging.info(";" + str(time.time()) + ";[error];wrong_choice_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.error_repeat = True + self.error_count += 1 + self.error_list.append('wrong_choice_error') + elif self.reward_check: + logging.info(";" + str(time.time()) + ";[error];correct_trial;" + str(self.error_repeat)) + self.pump.reward(self.pump_num, self.reward_size) + self.error_repeat = False + self.total_reward += 1 + self.reward_check = False + self.error_list.append('correct_trial') + self.pump_num = None + self.reward_size = None + self.wrong_choice_error = False + + + def check_cue(self, cue): + if cue == 'sound1': + logging.info(";" + str(time.time()) + ";[cue];cue_sound1_on;" + str(self.error_repeat)) + self.box.sound1.on() + if cue == 'sound2': + logging.info(";" + str(time.time()) + ";[cue];cue_sound2_on;" + str(self.error_repeat)) + self.box.sound2.blink(1, 0.1, 1) + elif cue == 'LED_L': + self.box.cueLED1.on() + logging.info(";" + str(time.time()) + ";[cue];cueLED_L_on;" + str(self.error_repeat)) + elif cue == 'LED_R': + self.box.cueLED2.on() + logging.info(";" + str(time.time()) + ";[cue];cueLED_R_on;" + str(self.error_repeat)) + elif cue == 'all': + self.box.cueLED1.on() + self.box.cueLED2.on() + logging.info(";" + str(time.time()) + ";[cue];LED_L+R_on; " + str(self.error_repeat)) + + def cue_off(self, cue): + if cue == 'all': + self.box.cueLED1.off() + self.box.cueLED2.off() + elif cue == 'sound1': + self.box.sound1.off() + logging.info(";" + str(time.time()) + ";[cue];cue_sound1_off;" + str(self.error_repeat)) + elif cue == 'sound2': + self.box.sound2.off() + logging.info(";" + str(time.time()) + ";[cue];cue_sound2_off;" + str(self.error_repeat)) + elif cue == 'LED_L': + self.box.cueLED1.off() + logging.info(";" + str(time.time()) + ";[cue];cueLED1_off;" + str(self.error_repeat)) + elif cue == 'LED_R': + self.box.cueLED2.off() + logging.info(";" + str(time.time()) + ";[cue];cueLED2_off;" + str(self.error_repeat)) + + def get_distance(self): + try: + distance = self.treadmill.distance_cm + except Exception as e: + logging.info(";" + str(time.time()) + ";[system_error];" + str(e) + ";" + str(self.error_repeat)) + self.treadmill = self.box.treadmill + distance = self.treadmill.distance_cm + return distance + + def update_plot(self): + fig, axes = plt.subplots(1, 1, ) + axes.plot([1, 2], [1, 2], color='green', label='test') + self.box.check_plot(fig) + + def update_plot_error(self): + error_event = self.error_list + labels, counts = np.unique(error_event, return_counts=True) + ticks = range(len(counts)) + fig, ax = plt.subplots(1, 1, ) + ax.bar(ticks, counts, align='center', tick_label=labels) + ax = plt.gca() + ax.set_xticks(ticks, labels) + ax.set_xticklabels(labels=labels, rotation=70) + + self.box.check_plot(fig) + + def update_plot_choice(self, save_fig=False): + trajectory_left = self.left_poke_count_list + time_left = self.timeline_left_poke + trajectory_right = self.right_poke_count_list + time_right = self.timeline_right_poke + fig, ax = plt.subplots(1, 1, ) + print(type(fig)) + + ax.plot(time_left, trajectory_left, color='b', marker="o", label='left_lick_trajectory') + ax.plot(time_right, trajectory_right, color='r', marker="o", label='right_lick_trajectory') + if save_fig: + plt.savefig(self.session_info['basedir'] + "/" + self.session_info['basename'] + "/" + \ + self.session_info['basename'] + "_choice_plot" + '.png') + self.box.check_plot(fig) + + def integrate_plot(self, save_fig=False): + + fig, ax = plt.subplots(2, 1) + + trajectory_left = self.left_poke_count_list + time_left = self.timeline_left_poke + trajectory_right = self.right_poke_count_list + time_right = self.timeline_right_poke + print(type(fig)) + + ax[0].plot(time_left, trajectory_left, color='b', marker="o", label='left_lick_trajectory') + ax[0].plot(time_right, trajectory_right, color='r', marker="o", label='right_lick_trajectory') + + error_event = self.error_list + labels, counts = np.unique(error_event, return_counts=True) + ticks = range(len(counts)) + ax[1].bar(ticks, counts, align='center', tick_label=labels) + # plt.xticks(ticks, labels) + # plt.title(session_name) + ax[1] = plt.gca() + ax[1].set_xticks(ticks, labels) + ax[1].set_xticklabels(labels=labels, rotation=70) + + if save_fig: + plt.savefig(self.session_info['basedir'] + "/" + self.session_info['basename'] + "/" + \ + self.session_info['basename'] + "_summery" + '.png') + self.box.check_plot(fig) + + ######################################################################## + # methods to start and end the behavioral session + ######################################################################## + + def start_session(self): + ic("TODO: start video") + self.box.video_start() + + def end_session(self): + ic("TODO: stop video") + self.update_plot_choice(save_fig=True) + self.box.video_stop() \ No newline at end of file diff --git a/task_protocol/headfixed_task/headfixed_task.py b/task_protocol/headfixed_task/headfixed_task.py new file mode 100644 index 0000000..76c6da0 --- /dev/null +++ b/task_protocol/headfixed_task/headfixed_task.py @@ -0,0 +1,470 @@ +# python3: headfixed_task.py +""" +author: tian qiu & Soyoun Kim +date: 2023-02-16 +name: headfixed2FC_task.py +goal: model_free reinforcement learning behavioral training task structure +description: + an updated test version of headfixed_task.py & add foraging reward condition + +""" +import importlib +from transitions import Machine +from transitions import State +from transitions.extensions.states import add_state_features, Timeout +import pysistence, collections +from icecream import ic +import logging +import time +from datetime import datetime +import os +from gpiozero import PWMLED, LED, Button +from colorama import Fore, Style +import logging.config +from time import sleep +import random +import threading +import matplotlib +import matplotlib.pyplot as plt +import matplotlib.figure as fg +import numpy as np + +logging.config.dictConfig( + { + "version": 1, + "disable_existing_loggers": True, + } +) +# all modules above this line will have logging disabled +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') +import behavbox + + +# adding timing capability to the state machine +@add_state_features(Timeout) +class TimedStateMachine(Machine): + pass + + +class HeadfixedTask(object): + # Define states. States where the animals is waited to make their decision + + def __init__(self, **kwargs): # name and session_info should be provided as kwargs + + # if no name or session, make fake ones (for testing purposes) + if kwargs.get("name", None) is None: + self.name = "name" + print( + Fore.RED + + Style.BRIGHT + + "Warning: no name supplied; making fake one" + + Style.RESET_ALL + ) + else: + self.name = kwargs.get("name", None) + + if kwargs.get("session_info", None) is None: + print( + Fore.RED + + Style.BRIGHT + + "Warning: no session_info supplied; making fake one" + + Style.RESET_ALL + ) + from fake_session_info import fake_session_info + + self.session_info = fake_session_info + else: + self.session_info = kwargs.get("session_info", None) + ic(self.session_info) + + # initialize the state machine + self.states = [ + State(name='standby', + on_enter=["enter_standby"], + on_exit=["exit_standby"]), + Timeout(name="initiate", + on_enter=["enter_initiate"], + on_exit=["exit_initiate"], + timeout=self.session_info["initiation_timeout"], + on_timeout=["restart"]), + Timeout(name='cue_state', + on_enter=["enter_cue_state"], + on_exit=["exit_cue_state"], + timeout=self.session_info["cue_timeout"], + on_timeout=["restart"]), + Timeout(name='reward_available', + on_enter=["enter_reward_available"], + on_exit=["exit_reward_available"], + timeout=self.session_info["wait_for_choice"], + on_timeout=["restart"]) + ] + self.transitions = [ + ['start_trial', 'standby', 'initiate'], + ['start_cue', 'initiate', 'cue_state'], + ['evaluate_reward', 'cue_state', 'reward_available'], + ['restart', ['initiate', 'cue_state', 'reward_available'], 'standby'] + ] + + self.machine = TimedStateMachine( + model=self, + states=self.states, + transitions=self.transitions, + initial='standby' + ) + self.trial_running = False + + # trial statistics + self.correct_trial_number = 0 + self.actual_trial_number = 0 + self.error_count = 0 + self.error_list = [] + self.early_lick_error = False + self.initiate_error = False + self.cue_state_error = False + self.wrong_choice_error = True + self.multiple_choice_error = False + self.error_repeat = False + + self.pump_num = None + self.reward_size = None + self.current_reward = None + self.reward_check = False + self.reward_size_offset = self.session_info['reward_size_offset'] + + self.block_count = 0 + self.blocknumber = self.session_info["block_number"] + self.current_card = None + self.left_poke_count = 0 + self.right_poke_count = 0 + self.timeline_left_poke = [] + self.left_poke_count_list = [] + self.timeline_right_poke = [] + self.right_poke_count_list = [] + self.event_name = "" + # initialize behavior box + self.box = behavbox.BehavBox(self.session_info) + self.pump = self.box.pump + + self.treadmill = self.box.treadmill + + self.distance_initiation = self.session_info['treadmill_setup']['distance_initiation'] + self.distance_cue = self.session_info['treadmill_setup']['distance_cue'] + self.distance_buffer = None + self.distance_diff = 0 + + # for foragaing parameters + self.side_choice = None # whether free choice is left or right + self.cue_state = None + + # for refining the lick detection + self.lick_count = 0 + self.side_mice_buffer = None + self.LED_blink = False + try: + self.lick_threshold = self.session_info["lick_threshold"] + except: + print("No lick_threshold defined in session_info. Therefore, default defined as 2 \n") + self.lick_threshold = 1 + + # session_statistics + self.total_reward = 0 + + ######################################################################## + # functions called when state transitions occur + ######################################################################## + def run(self): + if self.box.event_list: + self.event_name = self.box.event_list.popleft() + else: + self.event_name = "" + # there can only be lick during the reward available state + # if lick detected prior to reward available state + # the trial will restart and transition to standby + if self.event_name is "left_entry" or self.event_name == "right_entry": + # print("EVENT NAME !!!!!! " + self.event_name) + if self.state == "reward_available" or self.state == "standby" or self.state == "initiate": + pass + else: + self.early_lick_error = True + self.error_repeat = True + self.restart() + if self.state == "standby": + pass + elif self.state == "initiate": + self.distance_diff = self.get_distance() - self.distance_buffer + if self.distance_diff >= self.distance_initiation: + self.initiate_error = False + self.start_cue() + else: + self.initiate_error = True + elif self.state == "cue_state": + self.distance_diff = self.get_distance() - self.distance_buffer + if self.distance_diff >= self.distance_cue: + self.cue_state_error = False + self.evaluate_reward() + else: + self.cue_state_error = True + elif self.state == "reward_available": + cue_state = self.current_card[0] + side_mice = None + if self.event_name == "left_entry": + side_mice = 'left' + self.left_poke_count += 1 + self.left_poke_count_list.append(self.left_poke_count) + self.timeline_left_poke.append(time.time()) + elif self.event_name == "right_entry": + side_mice = 'right' + self.right_poke_count += 1 + self.right_poke_count_list.append(self.right_poke_count) + self.timeline_right_poke.append(time.time()) + if side_mice: + self.side_mice_buffer = side_mice + self.cue_state = cue_state # cue state for foraging + if cue_state == 'all': + side_choice = side_mice + if side_choice == 'left': + self.pump_num = self.current_card[2][0] + self.reward_size = self.current_reward[0] + print("self.current_reward[0]: " + str(self.current_reward[0])) + elif side_choice == 'right': + self.pump_num = self.current_card[2][1] + self.reward_size = self.current_reward[1] + print("self.current_reward[0]: " + str(self.current_reward[1])) + elif cue_state == 'LED_L': + side_choice = self.current_card[1] + self.pump_num = self.current_card[2] + self.reward_size = self.current_reward[0] + elif cue_state == 'LED_R': + side_choice = self.current_card[1] + self.pump_num = self.current_card[2] + self.reward_size = self.current_reward[1] + print("!!!!!!!!CUE_STATE: " + str(cue_state)) + if side_mice == side_choice: # if the animal chose correctly + self.side_mice_buffer = side_mice + if side_mice == side_choice: # if the animal chose correctly + if self.lick_count == 0: # if this is the first lick + self.side_choice = side_choice # foraging task + self.wrong_choice_error = False + self.reward_check = True + self.lick_count += 1 + self.restart() + elif self.side_mice_buffer: + if self.lick_count == 0: + self.wrong_choice_error = True + self.lick_count += 1 + self.restart() + + # look for keystrokes + self.box.check_keybd() + + def enter_standby(self): + logging.info(";" + str(time.time()) + ";[transition];enter_standby;" + str(self.error_repeat)) + self.update_plot_choice() + # self.update_plot_error() + self.trial_running = False + # self.reward_error = False + if self.early_lick_error: + self.error_list.append("early_lick_error") + logging.info(";" + str(time.time()) + ";[error];early_lick_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.early_lick_error = False + print(str(time.time()) + ", Total reward up till current session: " + str(self.total_reward)) + logging.info(";" + str(time.time()) + ";[trial];trial_" + str(self.actual_trial_number) + ";" + str(self.error_repeat)) + + def exit_standby(self): + logging.info(";" + str(time.time()) + ";[transition];exit_standby;" + str(self.error_repeat)) + self.lick_count = 0 + self.side_mice_buffer = None + self.box.event_list.clear() + pass + + def enter_initiate(self): + # print("!!!!!!!!!!!event name is " + self.event_name) # for debugging purposes + # check error_repeat + logging.info(";" + str(time.time()) + ";[transition];enter_initiate;" + str(self.error_repeat)) + self.check_cue('sound1') + self.trial_running = True + # wait for treadmill signal and process the treadmill signal + self.distance_buffer = self.get_distance() + logging.info( + ";" + str(time.time()) + ";[treadmill];" + str(self.distance_buffer) + ";" + str(self.error_repeat)) + + def exit_initiate(self): + # check the flag to see whether to shuffle or keep the original card + logging.info(";" + str(time.time()) + ";[transition];exit_initiate;" + str(self.error_repeat)) + print("EVENT NAME: " + str(self.box.event_list)) + self.cue_off('sound1') + if self.initiate_error: + self.error_list.append('initiate_error') + self.error_repeat = True + logging.info(";" + str(time.time()) + ";[error];initiate_error;" + str(self.error_repeat)) + self.error_count += 1 + + def enter_cue_state(self): + logging.info(";" + str(time.time()) + ";[transition];enter_cue_state;" + str(self.error_repeat)) + # turn on the cue according to the current card + self.check_cue(self.current_card[0]) + # wait for treadmill signal and process the treadmill signal + self.distance_buffer = self.get_distance() + logging.info( + ";" + str(time.time()) + ";[treadmill];" + str(self.distance_buffer) + ";" + str(self.error_repeat)) + + def exit_cue_state(self): + logging.info(";" + str(time.time()) + ";[transition];exit_cue_state;" + str(self.error_repeat)) + self.cue_off(self.current_card[0]) + if not self.early_lick_error: + if self.cue_state_error: + self.check_cue("sound2") + self.error_list.append('cue_state_error') + self.error_repeat = True + logging.info(";" + str(time.time()) + ";[error];cue_state_error;" + str(self.error_repeat)) + self.error_count += 1 + self.cue_state_error = False + + def enter_reward_available(self): + logging.info(";" + str(time.time()) + ";[transition];enter_reward_available;" + str(self.error_repeat)) + print(str(time.time()) + ", " + str(self.actual_trial_number) + ", cue_state distance satisfied") + + def exit_reward_available(self): + logging.info(";" + str(time.time()) + ";[transition];exit_reward_available;" + str(self.error_repeat)) + if self.lick_count == 0: + logging.info(";" + str(time.time()) + ";[error];no_choice_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.error_repeat = True + self.error_count += 1 + self.error_list.append('no_choice_error') + elif self.wrong_choice_error: + logging.info(";" + str(time.time()) + ";[error];wrong_choice_error;" + str(self.error_repeat)) + self.check_cue('sound2') + self.error_repeat = True + self.error_count += 1 + self.error_list.append('wrong_choice_error') + elif self.reward_check: + logging.info(";" + str(time.time()) + ";[error];correct_trial;" + str(self.error_repeat)) + self.pump.reward(self.pump_num, self.reward_size) + self.error_repeat = False + self.total_reward += 1 + self.reward_check = False + self.error_list.append('correct_trial') + self.pump_num = None + self.reward_size = None + self.wrong_choice_error = False + + + def check_cue(self, cue): + if cue == 'sound1': + logging.info(";" + str(time.time()) + ";[cue];cue_sound1_on;" + str(self.error_repeat)) + self.box.sound1.on() + if cue == 'sound2': + logging.info(";" + str(time.time()) + ";[cue];cue_sound2_on;" + str(self.error_repeat)) + self.box.sound2.blink(1, 0.1, 1) + elif cue == 'LED_L': + self.box.cueLED1.on() + logging.info(";" + str(time.time()) + ";[cue];cueLED_L_on;" + str(self.error_repeat)) + elif cue == 'LED_R': + self.box.cueLED2.on() + logging.info(";" + str(time.time()) + ";[cue];cueLED_R_on;" + str(self.error_repeat)) + elif cue == 'all': + self.box.cueLED1.on() + self.box.cueLED2.on() + logging.info(";" + str(time.time()) + ";[cue];LED_L+R_on; " + str(self.error_repeat)) + + def cue_off(self, cue): + if cue == 'all': + self.box.cueLED1.off() + self.box.cueLED2.off() + elif cue == 'sound1': + self.box.sound1.off() + logging.info(";" + str(time.time()) + ";[cue];cue_sound1_off;" + str(self.error_repeat)) + elif cue == 'sound2': + self.box.sound2.off() + logging.info(";" + str(time.time()) + ";[cue];cue_sound2_off;" + str(self.error_repeat)) + elif cue == 'LED_L': + self.box.cueLED1.off() + logging.info(";" + str(time.time()) + ";[cue];cueLED1_off;" + str(self.error_repeat)) + elif cue == 'LED_R': + self.box.cueLED2.off() + logging.info(";" + str(time.time()) + ";[cue];cueLED2_off;" + str(self.error_repeat)) + + def get_distance(self): + try: + distance = self.treadmill.distance_cm + except Exception as e: + logging.info(";" + str(time.time()) + ";[system_error];" + str(e) + ";" + str(self.error_repeat)) + self.treadmill = self.box.treadmill + distance = self.treadmill.distance_cm + return distance + + def update_plot(self): + fig, axes = plt.subplots(1, 1, ) + axes.plot([1, 2], [1, 2], color='green', label='test') + self.box.check_plot(fig) + + def update_plot_error(self): + error_event = self.error_list + labels, counts = np.unique(error_event, return_counts=True) + ticks = range(len(counts)) + fig, ax = plt.subplots(1, 1, ) + ax.bar(ticks, counts, align='center', tick_label=labels) + ax = plt.gca() + ax.set_xticks(ticks, labels) + ax.set_xticklabels(labels=labels, rotation=70) + + self.box.check_plot(fig) + + def update_plot_choice(self, save_fig=False): + trajectory_left = self.left_poke_count_list + time_left = self.timeline_left_poke + trajectory_right = self.right_poke_count_list + time_right = self.timeline_right_poke + fig, ax = plt.subplots(1, 1, ) + print(type(fig)) + + ax.plot(time_left, trajectory_left, color='b', marker="o", label='left_lick_trajectory') + ax.plot(time_right, trajectory_right, color='r', marker="o", label='right_lick_trajectory') + if save_fig: + plt.savefig(self.session_info['basedir'] + "/" + self.session_info['basename'] + "/" + \ + self.session_info['basename'] + "_choice_plot" + '.png') + self.box.check_plot(fig) + + def integrate_plot(self, save_fig=False): + + fig, ax = plt.subplots(2, 1) + + trajectory_left = self.left_poke_count_list + time_left = self.timeline_left_poke + trajectory_right = self.right_poke_count_list + time_right = self.timeline_right_poke + print(type(fig)) + + ax[0].plot(time_left, trajectory_left, color='b', marker="o", label='left_lick_trajectory') + ax[0].plot(time_right, trajectory_right, color='r', marker="o", label='right_lick_trajectory') + + error_event = self.error_list + labels, counts = np.unique(error_event, return_counts=True) + ticks = range(len(counts)) + ax[1].bar(ticks, counts, align='center', tick_label=labels) + # plt.xticks(ticks, labels) + # plt.title(session_name) + ax[1] = plt.gca() + ax[1].set_xticks(ticks, labels) + ax[1].set_xticklabels(labels=labels, rotation=70) + + if save_fig: + plt.savefig(self.session_info['basedir'] + "/" + self.session_info['basename'] + "/" + \ + self.session_info['basename'] + "_summery" + '.png') + self.box.check_plot(fig) + + ######################################################################## + # methods to start and end the behavioral session + ######################################################################## + + def start_session(self): + ic("TODO: start video") + self.box.video_start() + + def end_session(self): + ic("TODO: stop video") + self.update_plot_choice(save_fig=True) + self.box.video_stop() \ No newline at end of file diff --git a/task_protocol/headfixed_task/run_headfixed_independent_reward_task.py b/task_protocol/headfixed_task/run_headfixed_independent_reward_task.py new file mode 100644 index 0000000..1957312 --- /dev/null +++ b/task_protocol/headfixed_task/run_headfixed_independent_reward_task.py @@ -0,0 +1,265 @@ +#!/usr/bin/env -S ipython3 -i +# run_headfixed2FC_task.py +""" +author: tian qiu & Soyoun Kim +date: 2023-02-16 +name: run_headfixed_independent_reward_task.py +goal: model_free reinforcement learning behavioral training run task file +description: + an updated test version of run_headfixed_task.py & add foraging task + +""" +import random +import numpy as np +from transitions import Machine +from transitions import State +from icecream import ic +import logging +from datetime import datetime +import os +import logging.config +import pysistence, collections +import socket +import importlib +import colorama +import warnings +import scipy.io, pickle +import pygame +from colorama import Fore, Style +import time +from time import sleep + +debug_enable = False + +# all modules above this line will have logging disabled +logging.config.dictConfig({ + 'version': 1, + 'disable_existing_loggers': True, +}) + +if debug_enable: + # enabling debugger + from IPython import get_ipython + + ipython = get_ipython() + ipython.magic("pdb on") + ipython.magic("xmode Verbose") + +# import your task class here +from headfixed_independent_reward_task import HeadfixedIndependentRewardTask + +try: + # load in session_info file, check that dates are correct, put in automatic + # time and date stamps for when the experiment was run + + datestr = datetime.now().strftime("%Y-%m-%d") + timestr = datetime.now().strftime('%H%M%S') + full_module_name = 'session_info_' + datestr + + import sys + + session_info_path = '/home/pi/experiment_info/headfixed_independent_reward_task/session_info' + sys.path.insert(0, session_info_path) + tempmod = importlib.import_module(full_module_name) + session_info = tempmod.session_info + mouse_info = tempmod.mouse_info + + session_info['date'] = datestr + session_info['time'] = timestr + session_info['datetime'] = session_info['date'] + '_' + session_info['time'] + session_info['basename'] = session_info['mouse_name'] + '_' + session_info['datetime'] + session_info['dir_name'] = session_info['basedir'] + "/" + session_info['basename'] + + if session_info['manual_date'] != session_info['date']: # check if file is updated + print('wrong date!!') + raise RuntimeError('manual_date field in session_info file is not updated') + + # make data directory and initialize logfile + os.makedirs(session_info['dir_name']) + os.chdir(session_info['dir_name']) + session_info['file_basename'] = session_info['dir_name'] + '/' + session_info['basename'] + + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s.%(msecs)03d,[%(levelname)s],%(message)s", + datefmt=('%H:%M:%S'), + handlers=[ + logging.FileHandler(session_info['file_basename'] + '.log'), + logging.StreamHandler() # sends copy of log output to screen + ] + ) + + from task_information_independent_reward import TaskInformation + task_information = TaskInformation() + # print("Imported task_information_headfixed: " + str(task_information.name)) + task = HeadfixedIndependentRewardTask(name="headfixed_independent_reward_task", session_info=session_info) + + + def cumsum_positive(input_list): + for index in range(len(input_list)): + if index == 0 and input_list[index] < 0: + input_list[index] = -input_list[index] + elif input_list[index] + input_list[index - 1] < 0: + input_list[index] = input_list[index] - input_list[index - 1] + else: + input_list[index] = input_list[index] + input_list[index - 1] + return input_list + + def generate_reward_trajectory(scale=0.5, offset=3.0, change_point=20, ntrials=200): + # initial reward (need to be random) + rewards_L = [1] + rewards_R = [1] + for a in np.arange(np.round(ntrials / change_point)): + temp = np.random.randn(change_point) * scale + rewards_L.append(cumsum_positive(temp) + offset) + temp = np.random.randn(change_point) * scale + rewards_R.append(cumsum_positive(temp) + offset) + rewards_L = np.hstack(rewards_L) + rewards_R = np.hstack(rewards_R) + # plt.plot(rewards_L,'b');plt.plot(rewards_R,'r--') + reward_LR = [rewards_L, rewards_R] + reward_LR = np.transpose(np.array(reward_LR)) + reward_LR = reward_LR[0:ntrials, :] + # print(reward_LR) + return reward_LR + + def generate_sine_wave(increment, period_width, amplitude_offset, amplitude_scale, deviation, session_length): # for training purpose only + session_start = random.uniform(0, period_width) + session_end = session_start + session_length + value_input = np.arange(session_start, session_end, increment) + + sine_output = (np.sin((np.pi / period_width) * value_input) + amplitude_offset) * amplitude_scale + negative_sine_output = (np.sin((np.pi / period_width) * -value_input) + amplitude_offset) * amplitude_scale + left_side_reward = np.random.normal(sine_output, deviation) + right_side_reward = np.random.normal(negative_sine_output, deviation) + reward_list = list(zip(left_side_reward, right_side_reward)) + return reward_list + + if session_info['phase'] == "independent_reward": + # from reward_distribution import generate_reward_trajectory + scale = session_info['independent_reward']['scale'] + offset = session_info['independent_reward']['offset'] + change_point = session_info['independent_reward']['change_point'] + ntrials = session_info['independent_reward']['ntrials'] + reward_distribution_list = generate_reward_trajectory(scale, offset, change_point, ntrials) + elif session_info['phase'] == "forced_choice": + reward_size = session_info['reward_size'] + elif session_info['phase'] == "sine_reward": + session_length = session_info["sine_reward"]["session_length"] + increment = session_info["sine_reward"]["increment"] + period_width = session_info["sine_reward"]["period_width"] + amplitude_offset = session_info["sine_reward"]["amplitude_offset"] + amplitude_scale = session_info["sine_reward"]["amplitude_scale"] + deviation = session_info["sine_reward"]["deviation"] + reward_distribution_list = generate_sine_wave(increment, period_width, amplitude_offset, + amplitude_scale, deviation, session_length) + elif session_info['phase'] == 'foraging_reward': + offset = session_info['foraging_reward']['offset'] + max_reward = session_info['foraging_reward']['max_reward'] + increment = session_info['foraging_reward']['increment'] + reward_distribution = (3,3) + + + first_trial_of_the_session = True + + # # you can change various parameters if you want + # task.machine.states['cue'].timeout = 2 + + # start session + task.start_session() + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + sleep(10) + # loop over trials + # Set a timer + t_minute = int(input("Enter the time in minutes: ")) # wll add in the session info + t_end = time.time() + 60 * t_minute + while time.time() < t_end: # time check + if task.error_repeat: # error repeat check + task.error_repeat = False + print("punishment_time_out: " + str(session_info["punishment_timeout"])) + sleep(session_info["punishment_timeout"]) + print("Trial " + str(task.actual_trial_number) + " \n") + task.actual_trial_number += 1 + print("*******************************\n") + print("*error_repeat trial* \n" + + " - Current card condition: \n" + + "*******************************\n" + + "*reward_side: " + str(task.current_card[0]) + "\n" + + "*reward_size: " + str(task.current_reward)[1:-1] + "\n") + else: + if not first_trial_of_the_session: + print("reward_time_out: " + str(session_info["reward_timeout"])) + sleep(session_info["reward_timeout"]) + else: + first_trial_of_the_session = False + # setup the beginning of a new trial + task.error_count = 0 # reset the error count if previous trial is correct + print("Trial " + str(task.actual_trial_number) + " \n") + task.correct_trial_number += 1 + task.actual_trial_number += 1 + print("*******************************\n") + # acquire new reward contingency and cue association + #print("fraction " + str(session_info['fraction']) + " \n") + task.current_card = task_information.draw_card(session_info['phase'], session_info['fraction']) + if session_info['phase'] == "independent_reward": + task.current_reward = reward_distribution_list[task.correct_trial_number] + float(task.reward_size_offset) + elif session_info['phase'] == "forced_choice": + task.current_reward = session_info['reward_size'] + elif session_info['phase'] == "sine_reward": + task.current_reward = reward_distribution_list[task.correct_trial_number] + elif session_info['phase'] == 'foraging_reward': + reward_L = reward_distribution[0] + reward_R = reward_distribution[1] + task.current_reward = reward_distribution + if task.cue_state == 'all': + if task.side_choice == 'left': + reward_L = reward_L - increment + reward_R = reward_R + increment + if reward_L < 0: + reward_L = 0 + if reward_R > max_reward: + reward_R = max_reward + elif task.side_choice == 'right': + reward_R = reward_R - increment + reward_L = reward_L + increment + if reward_R < 0: + reward_R = 0 + if reward_L > max_reward: + reward_L = max_reward + reward_distribution = (reward_L, reward_R) + task.current_reward = reward_distribution + + + logging.info(";" + str(time.time()) + ";[condition];current_card_" + str(task.current_card) + + ";current_reward_" + str(task.current_reward)[1:-1]) + + print(" - Current card condition: \n" + + "*******************************\n" + + "*reward_side: " + str(task.current_card[0]) + "\n" + + "*reward_size: " + str(task.current_reward)[1:-1] + "\n") + logging.info(";" + str(time.time()) + ";[transition];start_trial()") + task.start_trial() # initiate the time state machine, start_trial() is a trigger + while task.trial_running: + task.run() # run command trigger additional functions outside of the state machine + print("error_count: " + str(task.error_count)) + raise SystemExit + +# graceful exit +except (KeyboardInterrupt, SystemExit): + print(Fore.RED + Style.BRIGHT + 'Exiting now...' + Style.RESET_ALL) + ic('about to call end_session()') + task.end_session() + ic('just called end_session()') + # save dicts to disk + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + pygame.quit() + +# exit because of error +except RuntimeError as ex: + print(Fore.RED + Style.BRIGHT + 'ERROR: Exiting now' + Style.RESET_ALL) + # save dicts to disk + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + task.end_session() \ No newline at end of file diff --git a/task_protocol/headfixed_task/run_headfixed_task.py b/task_protocol/headfixed_task/run_headfixed_task.py new file mode 100644 index 0000000..be08437 --- /dev/null +++ b/task_protocol/headfixed_task/run_headfixed_task.py @@ -0,0 +1,265 @@ +#!/usr/bin/env -S ipython3 -i +# run_headfixed2FC_task.py +""" +author: tian qiu & Soyoun Kim +date: 2023-02-16 +name: run_headfixed_independent_reward_task.py +goal: model_free reinforcement learning behavioral training run task file +description: + an updated test version of run_headfixed_task.py & add foraging task + +""" +import random +import numpy as np +from transitions import Machine +from transitions import State +from icecream import ic +import logging +from datetime import datetime +import os +import logging.config +import pysistence, collections +import socket +import importlib +import colorama +import warnings +import scipy.io, pickle +import pygame +from colorama import Fore, Style +import time +from time import sleep + +debug_enable = False + +# all modules above this line will have logging disabled +logging.config.dictConfig({ + 'version': 1, + 'disable_existing_loggers': True, +}) + +if debug_enable: + # enabling debugger + from IPython import get_ipython + + ipython = get_ipython() + ipython.magic("pdb on") + ipython.magic("xmode Verbose") + +# import your task class here +from headfixed_task import HeadfixedTask + +try: + # load in session_info file, check that dates are correct, put in automatic + # time and date stamps for when the experiment was run + + datestr = datetime.now().strftime("%Y-%m-%d") + timestr = datetime.now().strftime('%H%M%S') + full_module_name = 'session_info_' + datestr + + import sys + + session_info_path = '/home/pi/experiment_info/headfixed_task/session_info' + sys.path.insert(0, session_info_path) + tempmod = importlib.import_module(full_module_name) + session_info = tempmod.session_info + mouse_info = tempmod.mouse_info + + session_info['date'] = datestr + session_info['time'] = timestr + session_info['datetime'] = session_info['date'] + '_' + session_info['time'] + session_info['basename'] = session_info['mouse_name'] + '_' + session_info['datetime'] + session_info['dir_name'] = session_info['basedir'] + "/" + session_info['basename'] + + if session_info['manual_date'] != session_info['date']: # check if file is updated + print('wrong date!!') + raise RuntimeError('manual_date field in session_info file is not updated') + + # make data directory and initialize logfile + os.makedirs(session_info['dir_name']) + os.chdir(session_info['dir_name']) + session_info['file_basename'] = session_info['dir_name'] + '/' + session_info['basename'] + + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s.%(msecs)03d,[%(levelname)s],%(message)s", + datefmt=('%H:%M:%S'), + handlers=[ + logging.FileHandler(session_info['file_basename'] + '.log'), + logging.StreamHandler() # sends copy of log output to screen + ] + ) + + from task_information_independent_reward import TaskInformation + task_information = TaskInformation() + # print("Imported task_information_headfixed: " + str(task_information.name)) + task = HeadfixedTask(name="headfixed_task", session_info=session_info) + + + def cumsum_positive(input_list): + for index in range(len(input_list)): + if index == 0 and input_list[index] < 0: + input_list[index] = -input_list[index] + elif input_list[index] + input_list[index - 1] < 0: + input_list[index] = input_list[index] - input_list[index - 1] + else: + input_list[index] = input_list[index] + input_list[index - 1] + return input_list + + def generate_reward_trajectory(scale=0.5, offset=3.0, change_point=20, ntrials=200): + # initial reward (need to be random) + rewards_L = [1] + rewards_R = [1] + for a in np.arange(np.round(ntrials / change_point)): + temp = np.random.randn(change_point) * scale + rewards_L.append(cumsum_positive(temp) + offset) + temp = np.random.randn(change_point) * scale + rewards_R.append(cumsum_positive(temp) + offset) + rewards_L = np.hstack(rewards_L) + rewards_R = np.hstack(rewards_R) + # plt.plot(rewards_L,'b');plt.plot(rewards_R,'r--') + reward_LR = [rewards_L, rewards_R] + reward_LR = np.transpose(np.array(reward_LR)) + reward_LR = reward_LR[0:ntrials, :] + # print(reward_LR) + return reward_LR + + def generate_sine_wave(increment, period_width, amplitude_offset, amplitude_scale, deviation, session_length): # for training purpose only + session_start = random.uniform(0, period_width) + session_end = session_start + session_length + value_input = np.arange(session_start, session_end, increment) + + sine_output = (np.sin((np.pi / period_width) * value_input) + amplitude_offset) * amplitude_scale + negative_sine_output = (np.sin((np.pi / period_width) * -value_input) + amplitude_offset) * amplitude_scale + left_side_reward = np.random.normal(sine_output, deviation) + right_side_reward = np.random.normal(negative_sine_output, deviation) + reward_list = list(zip(left_side_reward, right_side_reward)) + return reward_list + + if session_info['phase'] == "independent_reward": + # from reward_distribution import generate_reward_trajectory + scale = session_info['independent_reward']['scale'] + offset = session_info['independent_reward']['offset'] + change_point = session_info['independent_reward']['change_point'] + ntrials = session_info['independent_reward']['ntrials'] + reward_distribution_list = generate_reward_trajectory(scale, offset, change_point, ntrials) + elif session_info['phase'] == "forced_choice": + reward_size = session_info['reward_size'] + elif session_info['phase'] == "sine_reward": + session_length = session_info["sine_reward"]["session_length"] + increment = session_info["sine_reward"]["increment"] + period_width = session_info["sine_reward"]["period_width"] + amplitude_offset = session_info["sine_reward"]["amplitude_offset"] + amplitude_scale = session_info["sine_reward"]["amplitude_scale"] + deviation = session_info["sine_reward"]["deviation"] + reward_distribution_list = generate_sine_wave(increment, period_width, amplitude_offset, + amplitude_scale, deviation, session_length) + elif session_info['phase'] == 'foraging_reward': + offset = session_info['foraging_reward']['offset'] + max_reward = session_info['foraging_reward']['max_reward'] + increment = session_info['foraging_reward']['increment'] + reward_distribution = (3,3) + + + first_trial_of_the_session = True + + # # you can change various parameters if you want + # task.machine.states['cue'].timeout = 2 + + # start session + task.start_session() + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + sleep(10) + # loop over trials + # Set a timer + t_minute = int(input("Enter the time in minutes: ")) # wll add in the session info + t_end = time.time() + 60 * t_minute + while time.time() < t_end: # time check + if task.error_repeat: # error repeat check + task.error_repeat = False + print("punishment_time_out: " + str(session_info["punishment_timeout"])) + sleep(session_info["punishment_timeout"]) + print("Trial " + str(task.actual_trial_number) + " \n") + task.actual_trial_number += 1 + print("*******************************\n") + print("*error_repeat trial* \n" + + " - Current card condition: \n" + + "*******************************\n" + + "*reward_side: " + str(task.current_card[0]) + "\n" + + "*reward_size: " + str(task.current_reward)[1:-1] + "\n") + else: + if not first_trial_of_the_session: + print("reward_time_out: " + str(session_info["reward_timeout"])) + sleep(session_info["reward_timeout"]) + else: + first_trial_of_the_session = False + # setup the beginning of a new trial + task.error_count = 0 # reset the error count if previous trial is correct + print("Trial " + str(task.actual_trial_number) + " \n") + task.correct_trial_number += 1 + task.actual_trial_number += 1 + print("*******************************\n") + # acquire new reward contingency and cue association + #print("fraction " + str(session_info['fraction']) + " \n") + task.current_card = task_information.draw_card(session_info['phase'], session_info['fraction']) + if session_info['phase'] == "independent_reward": + task.current_reward = reward_distribution_list[task.correct_trial_number] + float(task.reward_size_offset) + elif session_info['phase'] == "forced_choice": + task.current_reward = session_info['reward_size'] + elif session_info['phase'] == "sine_reward": + task.current_reward = reward_distribution_list[task.correct_trial_number] + elif session_info['phase'] == 'foraging_reward': + reward_L = reward_distribution[0] + reward_R = reward_distribution[1] + task.current_reward = reward_distribution + if task.cue_state == 'all': + if task.side_choice == 'left': + reward_L = reward_L - increment + reward_R = reward_R + increment + if reward_L < 0: + reward_L = 0 + if reward_R > max_reward: + reward_R = max_reward + elif task.side_choice == 'right': + reward_R = reward_R - increment + reward_L = reward_L + increment + if reward_R < 0: + reward_R = 0 + if reward_L > max_reward: + reward_L = max_reward + reward_distribution = (reward_L, reward_R) + task.current_reward = reward_distribution + + + logging.info(";" + str(time.time()) + ";[condition];current_card_" + str(task.current_card) + + ";current_reward_" + str(task.current_reward)[1:-1]) + + print(" - Current card condition: \n" + + "*******************************\n" + + "*reward_side: " + str(task.current_card[0]) + "\n" + + "*reward_size: " + str(task.current_reward)[1:-1] + "\n") + logging.info(";" + str(time.time()) + ";[transition];start_trial()") + task.start_trial() # initiate the time state machine, start_trial() is a trigger + while task.trial_running: + task.run() # run command trigger additional functions outside of the state machine + print("error_count: " + str(task.error_count)) + raise SystemExit + +# graceful exit +except (KeyboardInterrupt, SystemExit): + print(Fore.RED + Style.BRIGHT + 'Exiting now...' + Style.RESET_ALL) + ic('about to call end_session()') + task.end_session() + ic('just called end_session()') + # save dicts to disk + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + pygame.quit() + +# exit because of error +except RuntimeError as ex: + print(Fore.RED + Style.BRIGHT + 'ERROR: Exiting now' + Style.RESET_ALL) + # save dicts to disk + scipy.io.savemat(session_info['file_basename'] + '_session_info.mat', {'session_info': session_info}) + pickle.dump(session_info, open(session_info['file_basename'] + '_session_info.pkl', "wb")) + task.end_session() \ No newline at end of file diff --git a/task_protocol/headfixed_task/session_info_headfixed_independent_reward.py b/task_protocol/headfixed_task/session_info_headfixed_independent_reward.py new file mode 100644 index 0000000..4c4bbf1 --- /dev/null +++ b/task_protocol/headfixed_task/session_info_headfixed_independent_reward.py @@ -0,0 +1,130 @@ +from datetime import datetime +import os +import pysistence, collections +import socket +import pandas as pd +import numpy as np + +# defining immutable mouse dict (once defined for a mouse, NEVER EDIT IT) +mouse_info = pysistence.make_dict({'mouse_name': 'test', + 'fake_field': 'fake_info', + }) + +# Information for this session (the user should edit this each session) +session_info = collections.OrderedDict() +session_info['mouse_info'] = mouse_info +session_info['mouse_name'] = mouse_info['mouse_name'] + +session_info['basedir'] = '/home/pi/buffer' +session_info['external_storage'] = '/mnt/hd' +session_info['flipper_filename'] = '/home/pi/buffer/flipper_timestamp' +# for actual data save to this dir: +# session_info['basedir'] = '/home/pi/video' +session_info['weight'] = 0.0 +session_info['manual_date'] = '2023-07-13' +session_info['box_name'] = socket.gethostname() +session_info['block_number'] = 1 # 1 (left large) or 2 (right large) which block starts + +session_info['config'] = 'headfixed2FC' + +# behavior parameters +session_info['timeout_length'] = 5 # in seconds +session_info["lick_threshold"] = 1 +# visual stimulus +session_info["visual_stimulus"] = False + +session_info['config'] = 'headfixed2FC' +session_info['treadmill_setup'] = {} +session_info['treadmill'] = True +session_info['fraction'] = 0.3 # 0.3, 0.5,0.7,1 # free choice fraction 1 for all free choice +session_info['phase'] = 'foraging_reward' # 'forced_choice', 'sine_reward' + + + +if session_info['treadmill']: + session_info['treadmill_setup']['distance_cue'] = 5 # cm + session_info['treadmill_setup']['distance_initiation'] = 10 # cm +else: + session_info['treadmill_setup'] = None + +session_info['error_repeat'] = True +if session_info['error_repeat']: + session_info['error_max'] = 3 + +# condition setup +session_info['cue'] = ['LED_L', 'LED_R', 'all'] +# session_info['state'] = ['block1', 'block2'] # +session_info['choice'] = ['right', 'left'] # lick port +session_info['air_duration'] = 0 +session_info["vacuum_duration"] = 1 + +""" solenoid calibration information configuration """ + +solenoid_coeff = None +def get_coefficient(): + df_calibration = pd.read_csv("~/experiment_info/calibration_info/calibration.csv") + pump_coefficient = {} + + for pump_num in range(1, 5): + df_pump = df_calibration[df_calibration['pump_number'] == pump_num] + mg_per_pulse = df_pump['weight_fluid'].div(df_pump['iteration']) + on_time = df_pump['on_time'] + + fit_calibration = np.polyfit(mg_per_pulse, on_time, 1) # output with highest power first + pump_coefficient[str(pump_num)] = fit_calibration + return pump_coefficient + +try: + solenoid_coeff = get_coefficient() +except Exception as e: + print(e) + +session_info["calibration_coefficient"] = {} + +if solenoid_coeff: + session_info["calibration_coefficient"]['1'] = solenoid_coeff["1"] + session_info["calibration_coefficient"]['2'] = solenoid_coeff["2"] + session_info["calibration_coefficient"]['3'] = solenoid_coeff["3"] + session_info["calibration_coefficient"]['4'] = solenoid_coeff["4"] +else: + print("No coefficients, generate the default") + # solenoid valve linear fit coefficient for each pump + session_info["calibration_coefficient"]['1'] = [0.13, 0] # highest power first + session_info["calibration_coefficient"]['2'] = [0.13, 0] + session_info["calibration_coefficient"]['3'] = [0.13, 0.0] + session_info["calibration_coefficient"]['4'] = [0.13, 0.0] + +# define timeout during each condition +session_info['initiation_timeout'] = 120 # s +session_info['cue_timeout'] = 120 +session_info['wait_for_choice'] = 60 +session_info['reward_timeout'] = 1 +session_info["punishment_timeout"] = 3 + +session_info["key_reward_amount"] = 2 +session_info['reward_size_offset'] = 2 +session_info['reward_size'] = (5, 5) + +if session_info["phase"] == 'independent_reward': + session_info['independent_reward'] = {} + session_info['independent_reward']['scale'] = 0.5 + session_info['independent_reward']['offset'] = 3.0 + session_info['independent_reward']['change_point'] = 20 + session_info['independent_reward']['ntrials'] = 1000 +elif session_info["phase"] == 'sine_reward': + session_info["sine_reward"] = {} + session_info["sine_reward"]["increment"] = 1 + session_info["sine_reward"]["period_width"] = 40 + session_info["sine_reward"]["amplitude_offset"] = 2 + session_info["sine_reward"]["amplitude_scale"] = 3 + session_info["sine_reward"]["deviation"] = 0 +elif session_info['phase'] == 'foraging_reward': + session_info["foraging_reward"] = {} + session_info["foraging_reward"]["increment"] = 0.25 + session_info["foraging_reward"]["offset"] = 3 + session_info["foraging_reward"]["max_reward"] = 10 + + +session_info['consecutive_control'] = False +if session_info['consecutive_control']: + session_info['consecutive_max'] = 3 \ No newline at end of file diff --git a/task_protocol/headfixed_task/session_info_headfixed_task.py b/task_protocol/headfixed_task/session_info_headfixed_task.py new file mode 100644 index 0000000..5b8795d --- /dev/null +++ b/task_protocol/headfixed_task/session_info_headfixed_task.py @@ -0,0 +1,131 @@ +from datetime import datetime +import os +import pysistence, collections +import socket +import pandas as pd +import numpy as np + +# defining immutable mouse dict (once defined for a mouse, NEVER EDIT IT) +mouse_info = pysistence.make_dict({'mouse_name': 'test', + 'fake_field': 'fake_info', + }) + +# Information for this session (the user should edit this each session) +session_info = collections.OrderedDict() +session_info['mouse_info'] = mouse_info +session_info['mouse_name'] = mouse_info['mouse_name'] + +session_info['basedir'] = '/home/pi/buffer' +session_info['external_storage'] = '/mnt/hd' +session_info['flipper_filename'] = '/home/pi/buffer/flipper_timestamp' +# for actual data save to this dir: +# session_info['basedir'] = '/home/pi/video' +session_info['weight'] = 0.0 +session_info['manual_date'] = '2023-07-13' +session_info['box_name'] = socket.gethostname() +session_info['block_number'] = 1 # 1 (left large) or 2 (right large) which block starts + +session_info['config'] = 'headfixed2FC' + +# behavior parameters +session_info['timeout_length'] = 5 # in seconds +session_info["lick_threshold"] = 1 +# visual stimulus +session_info["visual_stimulus"] = False + +session_info['config'] = 'headfixed2FC' +session_info['treadmill_setup'] = {} +session_info['treadmill'] = True +session_info['fraction'] = 0.3 # 0.3, 0.5,0.7,1 # free choice fraction 1 for all free choice +session_info['phase'] = 'foraging_reward' # 'forced_choice', 'sine_reward' + + + +if session_info['treadmill']: + session_info['treadmill_setup']['distance_cue'] = 5 # cm + session_info['treadmill_setup']['distance_initiation'] = 10 # cm +else: + session_info['treadmill_setup'] = None + +session_info['error_repeat'] = True +if session_info['error_repeat']: + session_info['error_max'] = 3 + +# condition setup +session_info['cue'] = ['LED_L', 'LED_R', 'all'] +# session_info['state'] = ['block1', 'block2'] # +session_info['choice'] = ['right', 'left'] # lick port +session_info['air_duration'] = 0 +session_info["vacuum_duration"] = 1 + +""" solenoid calibration information configuration """ + +solenoid_coeff = None +def get_coefficient(): + df_calibration = pd.read_csv("~/experiment_info/calibration_info/calibration.csv") + pump_coefficient = {} + + for pump_num in range(1, 5): + df_pump = df_calibration[df_calibration['pump_number'] == pump_num] + mg_per_pulse = df_pump['weight_fluid'].div(df_pump['iteration']) + on_time = df_pump['on_time'] + + fit_calibration = np.polyfit(mg_per_pulse, on_time, 1) # output with highest power first + pump_coefficient[str(pump_num)] = fit_calibration + return pump_coefficient + +try: + solenoid_coeff = get_coefficient() +except Exception as e: + print(e) + +session_info["calibration_coefficient"] = {} + +if solenoid_coeff: + session_info["calibration_coefficient"]['1'] = solenoid_coeff["1"] + session_info["calibration_coefficient"]['2'] = solenoid_coeff["2"] + session_info["calibration_coefficient"]['3'] = solenoid_coeff["3"] + session_info["calibration_coefficient"]['4'] = solenoid_coeff["4"] +else: + print("No coefficients, generate the default") + # solenoid valve linear fit coefficient for each pump + session_info["calibration_coefficient"]['1'] = [0.13, 0] # highest power first + session_info["calibration_coefficient"]['2'] = [0.13, 0] + session_info["calibration_coefficient"]['3'] = [0.13, 0.0] + session_info["calibration_coefficient"]['4'] = [0.13, 0.0] + +# define timeout during each condition +session_info['initiation_timeout'] = 120 # s +session_info['cue_timeout'] = 120 +session_info['wait_for_choice'] = 60 +session_info['reward_timeout'] = 1 +session_info["punishment_timeout"] = 3 + +session_info["key_reward_amount"] = 2 +session_info['reward_size_offset'] = 2 +session_info['reward_size'] = (5, 5) + +if session_info["phase"] == 'independent_reward': + session_info['independent_reward'] = {} + session_info['independent_reward']['scale'] = 0.5 + session_info['independent_reward']['offset'] = 3.0 + session_info['independent_reward']['change_point'] = 20 + session_info['independent_reward']['ntrials'] = 1000 +elif session_info["phase"] == 'sine_reward': + session_info["sine_reward"] = {} + session_info["sine_reward"]["increment"] = 1 + session_info["sine_reward"]["period_width"] = 40 + session_info["sine_reward"]["amplitude_offset"] = 2 + session_info["sine_reward"]["amplitude_scale"] = 3 + session_info["sine_reward"]["deviation"] = 0 +elif session_info['phase'] == 'foraging_reward': + session_info["foraging_reward"] = {} + session_info["foraging_reward"]["increment"] = 0.25 + session_info["foraging_reward"]["offset"] = 3 + session_info["foraging_reward"]["max_reward"] = 10 + + +session_info['consecutive_control'] = False +if session_info['consecutive_control']: + session_info['consecutive_max'] = 3 + diff --git a/task_protocol/headfixed_task/task_information_headfixed.py b/task_protocol/headfixed_task/task_information_headfixed.py new file mode 100644 index 0000000..ddcf184 --- /dev/null +++ b/task_protocol/headfixed_task/task_information_headfixed.py @@ -0,0 +1,46 @@ +import random + + +class TaskInformation(object): + def __init__(self, **kwargs): + self.name = "model_based_reinforcement_learning_task" + self.deck = [('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ] + + def draw_card(self, phase="independent_reward", fraction=0.5): + row_start = 0 + row_end = len(self.deck)-1 + + if phase == 'forced_choice': + row_end = 1 + elif phase == 'free_choice': + row_start = 9 + elif phase == 'forced_choice_left': + row_end = 0 + elif phase == 'forced_choice_right': + row_start = 1 + row_end = 1 + else: + if fraction == 0.5: + row_start = 8 + row_end = 11 + elif fraction == 0.7: + row_start = 6 + elif fraction == 0.3: + row_end = 13 + elif fraction == 1: + row_start = 11 + + card = self.deck[random.randint(row_start, row_end)] + return card + +# print(TaskInformation().draw_card()) diff --git a/task_protocol/headfixed_task/task_information_independent_reward.py b/task_protocol/headfixed_task/task_information_independent_reward.py new file mode 100644 index 0000000..a423b6d --- /dev/null +++ b/task_protocol/headfixed_task/task_information_independent_reward.py @@ -0,0 +1,46 @@ +import random + + +class TaskInformation(object): + def __init__(self, **kwargs): + self.name = "model_based_reinforcement_learning_task" + self.deck = [('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('LED_L', 'left', '1'), ('LED_R', 'right', '2'), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ('all', ('left', 'right'), ('1', '2')), ('all', ('left', 'right'), ('1', '2')), + ] + + def draw_card(self, phase="independent_reward", fraction=0.5): + row_start = 0 + row_end = len(self.deck)-1 + + if phase == 'forced_choice': + row_end = 1 + elif phase == 'free_choice': + row_start = 9 + elif phase == 'forced_choice_left': + row_end = 0 + elif phase == 'forced_choice_right': + row_start = 1 + row_end = 1 + else: + if fraction == 0.5: + row_start = 8 + row_end = 11 + elif fraction == 0.7: + row_start = 6 + elif fraction == 0.3: + row_end = 13 + elif fraction == 1: + row_start = 11 + + card = self.deck[random.randint(row_start, row_end)] + return card + +# print(TaskInformation().draw_card()) \ No newline at end of file diff --git a/task_protocol/kelly_task/__init__.py b/task_protocol/kelly_task/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/task_protocol/kelly_task/__init__.py @@ -0,0 +1 @@ + diff --git a/kelly_record_task.py b/task_protocol/kelly_task/kelly_record_task.py similarity index 93% rename from kelly_record_task.py rename to task_protocol/kelly_task/kelly_record_task.py index 1440cce..a149eb8 100755 --- a/kelly_record_task.py +++ b/task_protocol/kelly_task/kelly_record_task.py @@ -15,7 +15,9 @@ ) # all modules above this line will have logging disabled -# import behavbox_test +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') import behavbox class KellyRecordTask(object): def __init__(self, **kwargs): # name and session_info should be provided as kwargs diff --git a/kelly_task.py b/task_protocol/kelly_task/kelly_task.py similarity index 98% rename from kelly_task.py rename to task_protocol/kelly_task/kelly_task.py index 73cae35..f3ce1f1 100755 --- a/kelly_task.py +++ b/task_protocol/kelly_task/kelly_task.py @@ -17,7 +17,9 @@ } ) # all modules above this line will have logging disabled - +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') import behavbox # adding timing capability to the state machine diff --git a/run_kelly_task.py b/task_protocol/kelly_task/run_kelly_task.py similarity index 100% rename from run_kelly_task.py rename to task_protocol/kelly_task/run_kelly_task.py diff --git a/run_record_task.py b/task_protocol/kelly_task/run_record_task.py similarity index 100% rename from run_record_task.py rename to task_protocol/kelly_task/run_record_task.py diff --git a/session_info_year-month-date.py b/task_protocol/kelly_task/session_info_year-month-date.py similarity index 100% rename from session_info_year-month-date.py rename to task_protocol/kelly_task/session_info_year-month-date.py diff --git a/task_protocol/self_admin_task/__init__.py b/task_protocol/self_admin_task/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/task_protocol/self_admin_task/__init__.py @@ -0,0 +1 @@ + diff --git a/remi_self_admin_task.py b/task_protocol/self_admin_task/remi_self_admin_task.py similarity index 99% rename from remi_self_admin_task.py rename to task_protocol/self_admin_task/remi_self_admin_task.py index 5b28f8e..76db1a1 100644 --- a/remi_self_admin_task.py +++ b/task_protocol/self_admin_task/remi_self_admin_task.py @@ -46,7 +46,9 @@ } ) # all modules above this line will have logging disabled - +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') import behavbox # import ivsa_syringe_pump # I will need to add the ivsa_syringe_pump class to the behavbox code diff --git a/run_remi_self_admin_task.py b/task_protocol/self_admin_task/run_remi_self_admin_task.py similarity index 100% rename from run_remi_self_admin_task.py rename to task_protocol/self_admin_task/run_remi_self_admin_task.py diff --git a/run_self_admin_task.py b/task_protocol/self_admin_task/run_self_admin_task.py similarity index 100% rename from run_self_admin_task.py rename to task_protocol/self_admin_task/run_self_admin_task.py diff --git a/self_admin_task.py b/task_protocol/self_admin_task/self_admin_task.py similarity index 99% rename from self_admin_task.py rename to task_protocol/self_admin_task/self_admin_task.py index fec7a43..1f04a15 100644 --- a/self_admin_task.py +++ b/task_protocol/self_admin_task/self_admin_task.py @@ -36,7 +36,9 @@ } ) # all modules above this line will have logging disabled - +# updated with reorganization (on 7/11/2023) +import sys +sys.path.insert(0,'/home/pi/RPi4_behavior_boxes/essential') import behavbox diff --git a/session_info_self_admin.py b/task_protocol/self_admin_task/session_info_self_admin.py similarity index 100% rename from session_info_self_admin.py rename to task_protocol/self_admin_task/session_info_self_admin.py diff --git a/treadmill_20211115.ino b/treadmill_20211115.ino deleted file mode 100644 index 31e5267..0000000 --- a/treadmill_20211115.ino +++ /dev/null @@ -1,145 +0,0 @@ -// when the treadmil encoder is located in the front -// include rev output for stablity -//#include -#include -#define VERSION "20211112" -// ===== VERSIONS ====== -#define MAXSPEED 1000.0f // maximum speed for dac out (mm/sec) -#define MAXDACVOLTS 2.5f // DAC ouput voltage at maximum speed -#define MAXDACCNTS 4095.0f // maximum dac value -//float maxDACval = MAXDACVOLTS * MAXDACCNTS / 3.3; // limit dac output to max allowed -float maxDACval = MAXDACVOLTS * MAXDACCNTS / 3.3 / 2; // limit dac output to max allowed // JR edit 5/28/19 make in both directions -#define encAPin 0 -#define encBPin 1 -#define dacPin A14 -//#define idxPin 2 // not use d here - -// counts per rotation of treadmill encoder wheel -// 200 counts per rev -// 1.03" per rev -// so - 1.03 * 25.4 * pi / 200 /1000 = microns/cnt -#define MM_PER_COUNT 410950 // actually 1/10^6mm per count since we divide by usecs -#define DIST_PER_COUNT ((float)MM_PER_COUNT/1000000.0) -//(float)0.41095 -#define SPEED_TIMEOUT 50000 // if we don't move in this many microseconds assume we are stopped -static float runSpeed = 0; -static float lastSpeed = 0; -volatile uint32_t lastUsecs; -volatile uint32_t thisUsecs; -volatile uint32_t encoderUsecs; -volatile float distance = 0; -int counts = 0; // net count - -int countAdj = 0; // 0-250 and 0-50 for negative 50-250 for positive -//int rev = 0;//count revolution -#define FW 1 -#define BW -1 -int dir = FW; -// ------------------------------------------ -// interrupt routine for ENCODER_A rising edge -// --------------------------------------------- -void encoderInt() -{ - int ENCA = digitalRead(encAPin); // always update output - int ENCB = digitalRead(encBPin); - if (ENCA == ENCB ) // figure out the direction - { - Serial.print('F'); - dir = FW; - thisUsecs = micros(); - encoderUsecs = thisUsecs - lastUsecs; - lastUsecs = thisUsecs; - runSpeed = (float)MM_PER_COUNT / encoderUsecs; - distance += DIST_PER_COUNT; - counts += 1; - } - else - { - Serial.print('B'); - dir = BW; - thisUsecs = micros(); - encoderUsecs = thisUsecs - lastUsecs; - lastUsecs = thisUsecs; - runSpeed = (float)MM_PER_COUNT / encoderUsecs* -1; - distance -= DIST_PER_COUNT; - counts -= 1; - } -} -void setup() -{ - //Serial.begin(115200); - //Serial2.begin(115200); - Serial.begin(19200); - Serial2.begin(19200); - //while ( !Serial); // if no serial USB is connected, may need to comment this out - pinMode(encAPin, INPUT_PULLUP); // sets the digital pin as input - pinMode(encBPin, INPUT_PULLUP); // sets the digital pin as input - analogWriteResolution(12); - - Serial.print("Treadmill Interface V: "); - Serial.println(VERSION); - Serial.println("distance,speed"); - Serial.println(maxDACval); - - Wire.begin(8); - Wire.setSDA(18); - Wire.setSCL(19); - Wire.onRequest(sendData); - - lastUsecs = micros(); - attachInterrupt(encAPin, encoderInt, RISING); // check encoder every A pin rising edge -} -void loop() -{ - noInterrupts(); - uint32_t now = micros(); - uint32_t lastU = lastUsecs; - if ( (now > lastU) && ((now - lastU) > SPEED_TIMEOUT) ) - { // now should never be < lastUsecs, but sometiems it is - // I question if noInterupts works - runSpeed = 0; - } - interrupts(); - if ( runSpeed != lastSpeed ) - { - lastSpeed = runSpeed; - // float dacval = runSpeed / MAXSPEED * maxDACval; - float dacval = (.5 + runSpeed / MAXSPEED) * maxDACval; - if ( dacval < 0 ) dacval = 0; - if ( dacval > maxDACval) dacval = maxDACval; -// Serial.print(distance); - countAdj = counts+50; - if (countAdj>250) - { - counts=1; - countAdj = 51; - } - if (counts<-50){ - counts = -50; - countAdj = 0; - } - Serial.print(countAdj); - Serial.print(","); - Serial.println(runSpeed); - int a=(uint16_t)dacval-730; - analogWrite(A14, (uint16_t) dacval); - Serial.println("iiiiiiiiiiiiiii"); - Serial.println(a); -// Wire.onRequest(sendData); //for debug purpose -// Wire.write(counts); //for transmitting the count as data - Serial2.write(counts);//Serial2.write(a); - } -// Serial.println(distance);d -} - -void sendData() -{ -// long Dst = distance; -// long Spd = runSpeed; -// long data = (Dst << 8) | Spd; -// Wire.write(data); -// Serial.println(data); - Wire.write(counts); //for transmitting the count as data -// Wire.write("iiiiiiiiiiiiiii"); -// Wire.write(a); -} \ No newline at end of file