def session_initialization(self): self.session_start_time = time() self.log_file_path = get_log_file_path(OUTPUT_FOLDER) writeFile(self.log_file_path, '\n%s, ***** Session starts\n'%get_time_stamp()) self.result_file_path = self.log_file_path.replace(".log", ".csv") writeFile(self.result_file_path, self.result_header + "\n-----------------------------------------\n") self.flag_first_feeding = True
def chk_end_feeding(self): if self.feeding_cnt >= MAX_FEEDING_CNT or self.trial_cnt_without_timeout >= MAX_TRIAL_CNT: self.flag_feeding = False # stop feeding process. #sleep(1.5) #ARD_M.send('OPEN_FEEDER') # Leave the feeder open #sleep(0.2) writeFile(self.log_file_path, '%s, Feeding is finished'%get_time_stamp())
def save_movie(command, log_file_path): # OBSOLETE;; saving a movie file on the run tmp_img_dir_path = command.split(",")[1] command = command.split(",")[0] writeFile(log_file_path, '%s, ffmpeg command execution started'%get_time_stamp()) os.system(command) writeFile(log_file_path, '%s, ffmpeg command execution finished'%get_time_stamp()) rmtree(tmp_img_dir_path)
def record_incorrect_button_press(self, arduino_msg): tmp_result_csv = copy(self.result_csv) # Because even if it's a incorrect response, # the cat still can press the correct button again. (Depending on the training phase) # it uses a copy of the self.result_csv to write the incorrect response in the result file. tmp_result_csv = tmp_result_csv.replace("Trial#", "%.3i"%self.trial_cnt) tmp_result_csv = tmp_result_csv.replace("Trial_start_time", get_time_stamp()) if self.chosen_random_snd == SND_FOIL_IDX: tmp_result_csv = tmp_result_csv.replace("Correct_response", "No-motion") else: tmp_result_csv = tmp_result_csv.replace("Correct_response", "%s-press"%BUTTON_TEXT[self.chosen_random_snd]) tmp_result_csv = tmp_result_csv.replace("Response_time", get_time_stamp()) if self.chosen_random_snd == SND_FOIL_IDX: tmp_result_csv = tmp_result_csv.replace("Response", "MOTION") else: tmp_result_csv = tmp_result_csv.replace("Response", "%s-press"%arduino_msg[0]) tmp_result_csv = tmp_result_csv.replace("Correctness", 'INCORRECT') writeFile(self.result_file_path, tmp_result_csv)
def onExit(self, termination = False, msg = None): if msg is not None: print msg writeFile(PROGRAM_LOG_PATH, '\n\n%s, %s'%(get_time_stamp(), msg)) self.main_ai_conn.close() for i in range(NUMBER_OF_CAMERAS): self.main_vi_conn[i].close() self.main_schema_conn.close() self.main_msgB_conn.close() self.ai_conn.close() self.ao_conn.close() for i in range(NUMBER_OF_CAMERAS): self.vi_conn[i].close() self.schema_conn.close() self.msgB_conn.close() if termination: self.ai_p.terminate() self.ao_p.terminate() for i in range(NUMBER_OF_CAMERAS): self.vi_p[i].terminate() self.schema_p.terminate() self.msgB_p.terminate() ### checking log files and generating movie files ui = raw_input("The next process will go through all the log files in the output folder and try to generate movie files(mp4) deleting the temporary image folders.\nProceed? (Y/N)") if ui.strip().upper() == 'Y': uvcInst = uvc.VideoConverter() uvcInst.run() ### taging wave sound files print "-----------------------\n" ui = raw_input("The next process will go through all the wave-sound-files in the output folder and try to tag with proper category names.\nProceed? (Y/N)") if ui.strip().upper() == 'Y': ustInst = ust.WaveFileRecognizer(OUTPUT_PATH) ustInst.run() ### checking MR(Movements Record) files and generating PNG files to show it graphically print "-----------------------\n" ui = raw_input("The next process will go through all the MR(Movements Record) files in the output folder and try to generate PNG picture files drawing the movements.\nProceed? (Y/N)") if ui.strip().upper() == 'Y': umdInst = umd.M_drawer(OUTPUT_PATH) umdInst.run() ### Make folder for each type of files and move print "-----------------------\n" ui = raw_input("Make folder for each type of result files and movie files accordingly.\nProceed? (Y/N)") if ui.strip().upper() == 'Y': umf.run()
def button_familiarization(self): # This is for familiarizing button-press for cats arduino_msg = ARD_M.receive('Button1', 0.1) # Try to receive a 'Button1'-msg for 0.1 second. if arduino_msg == ['Button1', 'HIGH']: #main_ao_conn.send('play_sound:button1') # play a sound for the button1 writeFile(self.log_file_path, '%s, Button1 was pressed'%get_time_stamp()) self.button1_pressed_time = time() self.flag_send_msg_to_vi_conn = True # after certain time, it has to seek for the movement at feeder again if time()-self.button1_pressed_time > 120: # wait for 2 minutes after button is pressed if time()-self.button1_snd_played_time > 10: # 10 sec passed after last button1 snd play if self.flag_send_msg_to_vi_conn == True: AAO.main_vi_conn[1].send('check_motion_at_feeder') self.flag_send_msg_to_vi_conn = False if self.msg_from_vi_conn == "motion_at_feeder": AAO.main_ao_conn.send('play_sound:button1') self.button1_snd_played_time = time() self.flag_send_msg_to_vi_conn = True
def activate_feeder(self): ARD_M.send('FEED') # Activate the feeder writeFile(self.log_file_path, '%s, Feeder activated'%get_time_stamp()) sleep(0.5) ''' ARD_M.send('Query:distance') # investigate the distance to the food level sleep(0.2) distance_to_food = ARD_M.receive('dist_to_food', None) # get the distance-to-food measurements. No timeout-time. ### Convert it(supposed to be 10 measurements) into a list of integers. del_list = [] for i in range(len(distance_to_food)): try: distance_to_food[i] = int(distance_to_food[i]) except: del_list.append(i) for i in range(len(del_list)): distance_to_food.pop(del_list[i]-i) writeFile(self.log_file_path, '%s, Distance measurements to food, %s'%(get_time_stamp(), str(distance_to_food))) distance_to_food = int(median(distance_to_food)) # Record the median value of measurements writeFile(self.log_file_path, '%s, Distance to food, %i cm'%(get_time_stamp(), distance_to_food)) if distance_to_food > 30 or self.feeding_cnt >= MAX_FEEDING_CNT: # The food level is greater than the threshold (in centi-meter) # or the maximum feeding count is reached ''' self.chk_end_feeding()
def send_email(to=[EMAIL_RECEIVER], subject='test', text='test', files=[], server="localhost", log_file_path=''): # send an email msg = MIMEMultipart() msg['From'] = EMAIL_SENDER msg['To'] = COMMASPACE.join(to) msg['Date'] = formatdate(localtime=True) msg['Subject'] = subject msg.attach( MIMEText(text) ) for file in files: part = MIMEBase('application', "octet-stream") part.set_payload( open(file,"rb").read() ) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file)) msg.attach(part) try: mailserver = smtplib.SMTP(server) mailserver.ehlo() mailserver.starttls() mailserver.ehlo() mailserver.login("ohj4", "38321234") mailserver.sendmail(EMAIL_SENDER, to, msg.as_string() ) mailserver.quit() if len(log_file_path) > 0 : writeFile(log_file_path, '\n%s, *** Email, <%s> was sent.\n'%(get_time_stamp(), subject)) except: ''' try: mailserver.quit() except: pass ''' if len(log_file_path) > 0 : writeFile(log_file_path, "Failed to send an email.") pass msg = None mailserver = None
def terminate_trial(self, flag_timeout_record = False): if self.chosen_random_snd >= SND_BUTTON1_IDX: # button-press trial AAO.main_msgB_conn.send('chk_ARD_msg:end') sleep(0.5) if self.trial_correctness != 'NONE': # there was either 'correct' or 'incorrect' response self.trial_cnt += 1 self.trial_cnt_without_timeout += 1 self.chk_end_feeding() elif self.trial_correctness == 'NONE' and self.motion_was_detected == True: # timeout trial self.trial_cnt += 1 self.trial_correctness = 'TIMEOUT' AAO.main_ao_conn.send('play_sound:neg_feedback2') # type 2 negative feedback sound is used to notify the trial is finished with incorrect response if flag_timeout_record == True: self.result_csv = self.result_csv.replace("Response_time", get_time_stamp()) self.result_csv = self.result_csv.replace("Response", "TIMEOUT") self.result_csv = self.result_csv.replace("Correctness", 'TIMEOUT') writeFile(self.result_file_path, self.result_csv) writeFile(self.log_file_path, '%s, %i seconds has passed since the trial started.'%(get_time_stamp(), TRIAL_LENGTH)) else: self.trial_correctness = 'NO_MOTION' writeFile(self.log_file_path, '%s, End of trial.'%(get_time_stamp())) self.feeding_snd_play_time = -1 # end of trial
def record_correct_button_press(self): if self.motion_was_detected == False: self.record_trial_start() self.result_csv = self.result_csv.replace("Response_time", get_time_stamp()) self.result_csv = self.result_csv.replace("Response", "%s-press"%BUTTON_TEXT[self.chosen_random_snd]) self.result_csv = self.result_csv.replace("Correctness", 'CORRECT') writeFile(self.result_file_path, self.result_csv)
def scheduled_feeding(self): curr_time = time() if self.flag_first_feeding == True and curr_time - self.session_start_time > 60 * 2: # seconds * minutes # Feeding hasn't started yet and # feeding starts some seconds(typically 120 sec) after the program started self.flag_first_feeding = False # turn off the flag self.flag_feeding = True # Start feeding self.last_feeding_time = time() self.waiting_time_for_feeding = -1 # At the very beginning, feed at once. if self.flag_feeding: if curr_time - self.last_feeding_time > self.waiting_time_for_feeding: # it's a feeding time ''' ### OBSOLETE ### Simply choose the button with certain probabilities. chosen_number = uniform(0,1) ### 0;SND_NAME_IDX, 1;SND_BUTTON1_IDX, 2;SND_BUTTON2_IDX, 3;SND_BUTTON3_IDX if chosen_number < 0.3333: self.chosen_random_snd = 1 elif 0.3333 <= chosen_number < 0.6666: self.chosen_random_snd = 2 else: self.chosen_random_snd = 3 ''' #self.flag_4th_speaker_test = False #chosen_number = uniform(0,1) #if chosen_number < 1.1: AAO.main_ao_conn.send('4th_speaker_test') self.flag_4th_speaker_test = True ''' chosen_number = uniform(0,1) if chosen_number < 0.3: if chosen_number < 0.15: AAO.main_ao_conn.send('SWS_test') self.flag_SWS_test = True else: AAO.main_ao_conn.send('NVS_test') self.flag_NVS_test = True ''' button_indices = range(SND_BUTTON1_IDX, SND_BUTTON3_IDX+1) # make the list of numbers for the buttons(1~3) if FLAG_BALANCE_CORRECTNESS == True: # if certain button_index has 1 more correct trials than # the button index which has the minimum number of correct trials, # then exclude it, # to balance out that the cat getting the reward from which button. if len(self.past_correct_snd_idx) >= 1: correct_trial_cnt = [] for idx in button_indices: correct_trial_cnt.append(self.past_correct_snd_idx.count(idx)) min_correct_trial_cnt = min(correct_trial_cnt) button_index_removal = [] for i in range(len(button_indices)): if correct_trial_cnt[i] - min_correct_trial_cnt > 0: button_index_removal.append(button_indices[i]) for i in range(len(button_index_removal)): button_indices.remove(button_index_removal[i]) ''' if self.past_correct_snd_idx[0] == self.past_correct_snd_idx[1]: # if the past 2 trials were the same button-trials button_indices.remove(self.past_correct_snd_idx[0]) # get rid of that number from the list ''' ''' ### store the button numbers for the 2 recent trials self.past_correct_snd_idx.append(copy(self.chosen_random_snd)) if len(self.past_correct_snd_idx) > 2: self.past_correct_snd_idx.pop(0) ''' self.chosen_random_snd = choice(button_indices) #self.chosen_random_snd = 2 if self.currMST == []: self.currMST = copy(self.modulated_snd_trials) shuffle(self.currMST) self.flag_SWS_test = False self.flag_NVS_test = False if len(button_indices) > 1: # Only 1 sound left, meaning it should be solved by the cat. # Since the cat can abuse the modified sound to avoid to press certain button, # Modulated sound happens when there're more than one sound is in the choice-list. if self.currMST[0] == 'SWS': AAO.main_ao_conn.send('SWS_test') self.flag_SWS_test = True elif self.currMST[0] == 'NVS': AAO.main_ao_conn.send('NVS_test') self.flag_NVS_test = True self.currMST.pop(0) # very 1st feeding: button3 trial #if self.waiting_time_for_feeding == -1: self.chosen_random_snd = 3 if self.chosen_random_snd == SND_NAME_IDX: AAO.main_ao_conn.send('play_sound:name') # Send a message to play a sound elif SND_NAME_IDX < self.chosen_random_snd: # button (and a foil) #AAO.main_ao_conn.send('play_sound:name') # name call #sleep(3) # name call: 2.5s + pause: 0.5s writeFile(self.log_file_path, '%s, Sound for the trial starts.'%get_time_stamp()) AAO.main_ao_conn.send('play_sound:%s'%BUTTON_TEXT[self.chosen_random_snd]) # play a sound for the button# ### initialization self.motion_was_detected = False self.result_csv = copy(self.result_header) _add_info_txt = '' if self.flag_4th_speaker_test == True: _add_info_txt += '4s_test' if self.flag_SWS_test == True: _add_info_txt += '/SWS' if self.flag_NVS_test == True: _add_info_txt += '/NVS' if _add_info_txt == '': self.result_csv = self.result_csv.replace('Additional_Info', '_') else: self.result_csv = self.result_csv.replace('Additional_Info', _add_info_txt) self.trial_correctness = 'NONE' ''' elif self.chosen_random_snd == 1: writeFile(self.log_file_path, '%s, Trial for <arbitrary_name_00> starts'%get_time_stamp()) AO.main_ao_conn.send('play_sound:arbitrary_name_00') ''' self.flag_process_after_snd_play = True # Initial process after the sound play has to be done self.feeding_snd_play_time = time() self.last_feeding_time = self.feeding_snd_play_time ARD_M.aConn.flushInput() # flush the serial connection self.arduino_msg = "" self.waiting_time_for_feeding = randint(TRIAL_INTERVAL[0], TRIAL_INTERVAL[1])*60 # randomly determine the next feeding-time elapsed_time_after_feeding_snd = time() - self.feeding_snd_play_time if self.feeding_snd_play_time != -1: # feeding sound was already played. if elapsed_time_after_feeding_snd > 1: # wait for 1 second (wait for a bit for sound-playing) if elapsed_time_after_feeding_snd < TRIAL_LENGTH + 1: # it hasn't been TRIAL_LENGTH yet after play # Initial behavior after feeding sound play # ; Send a message to check for the movements around the feeder if self.flag_process_after_snd_play: AAO.main_msgB_conn.send('chk_vm_msg:start') if SND_BUTTON1_IDX <= self.chosen_random_snd <= SND_BUTTON3_IDX: # any button-trial AAO.main_msgB_conn.send('chk_ARD_msg:start') sleep(0.2) self.flag_process_after_snd_play = False if FLAG_RTOI == True: # Trial is repeated on the wrong response if self.trial_correctness == 'INCORRECT': # there was already an incorrect-response if time() - self.incorrect_response_time < FROZEN_TIME_ON_INCORRECT: # FRONZEN_TIME meaning punishment-time is not over yet ### Keep playing the neg_feedback1 for some time if time() - self.incorrect_response_time < 1: AAO.main_ao_conn.send('play_sound:neg_feedback1') sleep(0.6) # length of neg_feedback1 is 0.56 sec. return # exit the function else: if TRIAL_LENGTH - elapsed_time_after_feeding_snd > FROZEN_TIME_ON_INCORRECT-1: # if the left time is long enough (here longer than the punishment time) # play a sound for the button#; (beginning of the same trial again) AAO.main_ao_conn.send('play_sound:%s'%BUTTON_TEXT[self.chosen_random_snd]) self.trial_correctness = 'NONE' ARD_M.aConn.flushInput() # flush the serial connection self.arduino_msg = "" else: self.terminate_trial(flag_timeout_record=True) if self.msg_from_vi_conn == "motion_at_feeder": # there was a motion around the feeder if self.chosen_random_snd == SND_NAME_IDX: # name sound was played self.feeding_cnt += 1 self.activate_feeder() writeFile(self.log_file_path, '%s, Trial for <name> finished'%get_time_stamp()) self.feeding_snd_play_time = -1 elif self.chosen_random_snd == SND_FOIL_IDX: AAO.main_ao_conn.send('play_sound:neg_feedback1') AAO.main_ao_conn.send('play_sound:neg_feedback2') self.incorrect_response_time = time() self.record_incorrect_button_press(['MOTIOIN']) self.trial_correctness = 'INCORRECT' writeFile(self.log_file_path, '%s, Incorrect response(motion detection) on the foil stimulus.'%(get_time_stamp())) if FLAG_RTOI == False: # RTOI: Repeat Trial On Incorrect-response self.terminate_trial() else: # Trial will be repeated ARD_M.send('led_on') # turn the red LED light on (will be automatically off after certain time by Arduino chip itself) elif 0 < self.chosen_random_snd < 4: # button-press trial writeFile(self.log_file_path, '%s, Motion detected at feeder after <%s> sound-play'%(get_time_stamp(), BUTTON_TEXT[self.chosen_random_snd])) if self.motion_was_detected == False: # After playing a stimulus, the motion was detected for the 1st time if self.flag_4th_speaker_test == True: AAO.main_ao_conn.send('4th_speaker_test') if self.flag_SWS_test == True: AAO.main_ao_conn.send('SWS_test') if self.flag_NVS_test == True: AAO.main_ao_conn.send('NVS_test') AAO.main_ao_conn.send('play_sound:%s'%BUTTON_TEXT[self.chosen_random_snd]) # play a sound for the button# self.record_trial_start() self.motion_was_detected = True ''' elif self.chosen_random_snd == 1: # arbitrary_name_00 sound was played writeFile(self.log_file_path, '%s, Motion detected around the feeder after playing <arbitrary_name_00> sound'%get_time_stamp()) AAO.main_ao_conn.send('play_sound:neg_feedback') writeFile(self.log_file_path, '%s, Trial for <arbitrary_name_00> finished'%get_time_stamp()) self.feeding_snd_play_time = -1 ''' if self.chosen_random_snd >= SND_BUTTON1_IDX: # button-press trial if self.arduino_msg != "": # there is some message from Arduino arduino_msg = self.arduino_msg.split(",") if arduino_msg == [BUTTON_TEXT[self.chosen_random_snd], 'HIGH']: # correct button was pressed #AAO.main_ao_conn.send('play_sound:%s'%BUTTON_TEXT[self.chosen_random_snd]) # play a sound for the button# writeFile(self.log_file_path, '%s, %s was pressed.'%(get_time_stamp(), arduino_msg[0])) sleep(0.3) self.feeding_cnt += 1 self.activate_feeder() self.record_correct_button_press() self.trial_correctness = 'CORRECT' self.past_correct_snd_idx.append(copy(self.chosen_random_snd)) # store this button index self.terminate_trial() else: # wrong button was pressed if self.trial_correctness == 'NONE': if self.flag_SWS_test == False and self.flag_NVS_test == False: AAO.main_ao_conn.send('play_sound:neg_feedback1') else: self.activate_feeder() # in SWS or NVS trial, CATOS's response is always positive self.incorrect_response_time = time() self.record_incorrect_button_press(arduino_msg) self.trial_correctness = 'INCORRECT' writeFile(self.log_file_path, '%s, %s was pressed. Incorrect press.'%(get_time_stamp(), arduino_msg[0])) if FLAG_RTOI == False: # RTOI: Repeat Trial On Incorrect-response if self.flag_SWS_test == False and self.flag_NVS_test == False: AAO.main_ao_conn.send('play_sound:neg_feedback2') self.terminate_trial() else: # Trial will be repeated ARD_M.send('led_on') # turn the red LED light on (will be automatically off after certain time by Arduino chip itself) else: # TRIAL_LENGTH passed self.terminate_trial(flag_timeout_record=True)
def schema_run(schema_conn): # Running a schema which AA runs on thought a session writeFile(PROGRAM_LOG_PATH, "%s, ***** Staring of the program.\n\n"%get_time_stamp()) chk_resource_usage(PROGRAM_LOG_PATH) # check the resource (cpu, memory) usage last_chk_resource_time = time() flag_session_changed_to_off = False flag_session_changed_to_on = False while True: if time()-last_chk_resource_time > 60 * 30: # every a half an hour chk_resource_usage(PROGRAM_LOG_PATH) # check the resource (cpu, memory) usage last_chk_resource_time = time() # If the session time is over, archive all the data # If the session time is resumed, update the log-file and csv-result-file. if chk_session_time(SESSION_START_HOUR, SESSION_END_HOUR) == False: if flag_session_changed_to_off == False: # 1st run after finishing the session-time if AAS.feeding_snd_play_time != -1: # if it's middle of a trial AAS.terminate_trial() # terminate it. if flag_session_changed_to_on == True: # The session was on before # If this is True here, this means it's the very 1st time after staring the program. # Therefore, there will be nothing to archive. print '*** The session is over.' uvcInst = uvc.VideoConverter() uvcInst.run() #ustInst = ust.WaveFileRecognizer(OUTPUT_PATH) #ustInst.run() umdInst = umd.M_drawer(OUTPUT_PATH) umdInst.run() folder_name = get_time_stamp()[:10] archive_folder_path = os.path.join('archive', folder_name) umf.run(folder_name, archive_folder_path) print '-------------------------------------------------------------' print 'Archiving process is finished at %s.'%get_time_stamp() print '-------------------------------------------------------------' flag_session_changed_to_off = True flag_session_changed_to_on = False if schema_conn.poll(): # check whether there's any message arrive through the pipe msg = schema_conn.recv() # receive the message if msg == 'q': break sleep(1) continue else: if flag_session_changed_to_on == False: # 1st run after starting the session-time print '-------------------------------------------------------------' print 'Session starts at %s.'%get_time_stamp() print '-------------------------------------------------------------' flag_session_changed_to_off = False flag_session_changed_to_on = True AAS.session_initialization() # Initialize the log-file and result-file msg = "" if AAO.main_msgB_conn.poll(): # any message from message board msg = AAO.main_msgB_conn.recv() # receive AAS.run(msg) ### msg checking for exiting the program if schema_conn.poll(): # check whether there's any message arrive through the pipe msg = schema_conn.recv() # receive the message if msg == 'q': break