def add_mice(self): try: tagreader = TagReader(RFID_serialPort, RFID_doCheckSum, timeOutSecs=RFID_timeout, kind=RFID_kind) except Exception as e: raise e i = 0 print('Scan mice now') while i < 1: try: tag = tagreader.readTag() i += 1 print(tag) except ValueError as e: print(str(e)) tagreader.clearBuffer() SPT_lvl = input('Enter SPT level for new mouse:') SPT_Spout = input('Enter initial SPT spout for new mouse (R/L):') temp = {tag: {'SPT_Pattern': SPT_Spout, 'SPT_level': int(SPT_lvl)}} self.mice_config.update(temp)
values1 = [tag, timestamp, weight_float, 0, 'N', Cage] cur1.execute(insert_statment, values) else: with open(record_filename, 'r') as csv1: reader = csv.reader(csv1) reader1 = list(reader) Baseline_Weight = float(reader1[1][2]) not_valu = round((float(weight_float) - Baseline_Weight) / Baseline_Weight * 100, 1) print(str(not_valu)) if (float(weight_float) - Baseline_Weight) / Baseline_Weight * 100 < -15.0: CO = 'Y' print('Mouse Underweight, Need supplment water') else: CO = 'N' values = [ tag, timestamp, weight_float, round((float(weight_float) - Baseline_Weight) / Baseline_Weight * 100, 1), CO, Cage ] with open(record_filename, "a") as file: file.write(timestamp + "," + str(tag) + "," + str(weight_float) + ',' + str(not_valu) + '%' + ',' + CO + ',' + Cage + "\n") cur1.execute(insert_statment, values) except ValueError as e: print(str(e)) tagReader.clearBuffer() print('Read ' + ' tags')
def htloop (cageSet, tagReader, headFixer, stimulator, expSettings): """ Presents a menu asking user to choose a bit of hardware to test, and runs the tests If a test fails, a dialog is presented asking user to change the pin setup. The modified pinout can be saved, overwriting the configuration in ./AHF_Config.jsn Commands are: t= tagReader: trys to read a tag and, if successful, monitors Tag in Range Pin until tag goes away r = reward solenoid: Opens the reward solenoid for a 1 second duration, then closes it c = contact check: Monitors the head contact pin until contact, and then while contact is maintained f = head Fixer e = Entry beam break p = pistons solenoid: Energizes the pistons for a 2 second duration, and then de-energizes them l = LED: Turns on the brain illumination LED for a 2 second duration, then off h = sHow config settings: Prints out the current pinout in the AHF_CageSet object v = saVe modified config file: Saves the the AHF_CageSet object to the file ./AHF_Config.jsn q = quit: quits the program """ if cageSet.contactPolarity == 'RISING': contactEdge = GPIO.RISING noContactEdge = GPIO.FALLING contactState = GPIO.HIGH noContactState = GPIO.LOW else: contactEdge = GPIO.FALLING noContactEdge = GPIO.RISING contactState = GPIO.LOW noContactState = GPIO.HIGH try: while (True): inputStr = input ('t=tagReader, r=reward solenoid, c=contact check, e= entry beam break, f=head Fixer, l=LED, s=stimulator tester, h=sHow config, v= saVe config, q=quit:') if inputStr == 't': # t for tagreader if tagReader == None: cageSet.serialPort = input ('First, set the tag reader serial port:') try: tagReader = TagReader (cageSet.serialPort, True) inputStr = input ('Do you want to read a tag now?') if inputStr[0] == 'n' or inputStr[0] == "N": continue except IOError as anError: print ('Try setting the serial port again.') tagReader = None if tagReader is not None: try: if (tagReader.serialPort.inWaiting() < 16): print ('No data in serial buffer') tagError = True else: tagID = tagReader.readTag() tagError = False except (IOError, ValueError) as anError: tagError = True if tagError == True: print ('Serial Port Tag-Read Error\n') tagReader.clearBuffer() inputStr = input ('Do you want to change the tag reader serial port (currently ' + cageSet.serialPort + ')?') if inputStr == 'y' or inputStr == "Y": cageSet.serialPort = input ('Enter New Serial Port:') # remake tagReader and open serial port tagReader = TagReader (cageSet.serialPort, True) else: print ("Tag ID =", tagID) # now check Tag-In-Range pin function if (GPIO.input (cageSet.tirPin)== GPIO.LOW): print ('Tag was never registered as being "in range"') tagError = True else: startTime = time() GPIO.wait_for_edge (cageSet.tirPin, GPIO.FALLING, timeout= 10000) if (time () > startTime + 10.0): print ('Tag stayed in range for over 10 seconds') tagError = True else: print ('Tag no longer in range') tagError = False if (tagError == True): inputStr = input ('Do you want to change the tag-in-range Pin (currently ' + str (cageSet.tirPin) + ')?') if inputStr[0] == 'y' or inputStr[0] == "Y": cageSet.tirPin = int (input('Enter New tag-in-range Pin:')) GPIO.setup (cageSet.tirPin, GPIO.IN) elif inputStr == 'r': # r for reward solenoid print ('Reward Solenoid opening for 3 sec') GPIO.output(cageSet.rewardPin, 1) sleep(3.0) GPIO.output(cageSet.rewardPin, 0) inputStr= input('Reward Solenoid closed.\nDo you want to change the Reward Solenoid Pin (currently ' + str (cageSet.rewardPin) + ')?') if inputStr[0] == 'y' or inputStr[0] == "Y": cageSet.rewardPin = int (input('Enter New Reward Solenoid Pin:' )) GPIO.setup (cageSet.rewardPin, GPIO.OUT, initial=GPIO.LOW) elif inputStr == 'c': #c for contact on head fix if GPIO.input (cageSet.contactPin)== contactState: print ('Contact pin already indicates contact.') err=True else: GPIO.wait_for_edge (cageSet.contactPin, contactEdge, 100) if GPIO.input (cageSet.contactPin)== noContactState: print ('No Contact after 10 seconds.') err = True else: print ('Contact Made.') GPIO.wait_for_edge (cageSet.contactPin, noContactEdge, 100) if GPIO.input (cageSet.contactPin)== contactState: print ('Contact maintained for 10 seconds.') err = True else: print ('Contact Broken') err = False if err == True: inputStr= input ('Do you want to change Contact settings (currently pin=' + str (cageSet.contactPin) + ', polarity=' + str(cageSet.contactPolarity) + ', pull up/down =' + str (cageSet.contactPUD) + ')?') if inputStr[0] == 'y' or inputStr[0] == "Y": cageSet.contactPin= int (input ('Enter the GPIO pin connected to the headbar contacts or IR beam-breaker:')) contactInt = int (input ('Enter the contact polarity, 0=FALLING for IR beam-breaker or falling polarity electrical contacts, 1=RISING for rising polarity elctrical contacts:')) if contactInt == 0: cageSet.contactPolarity = 'FALLING' else: cageSet.contactPolarity = 'RISING' contactInt = int (input('Enter desired resistor on contact pin, 0=OFF if external resistor present, else 1=DOWN if rising polarity electrical contact or 2 = UP if IR beam-breaker or falling polarity electrical contacts:')) if contactInt ==0: cageSet.contactPUD = 'OFF' elif contactInt == 1: cageSet.contactPUD = 'DOWN' else: cageSet.contactPUD='UP' GPIO.setup (cageSet.contactPin, GPIO.IN, pull_up_down=getattr (GPIO, "PUD_" + cageSet.contactPUD)) if cageSet.contactPolarity =='RISING': contactEdge = GPIO.RISING noContactEdge = GPIO.FALLING contactState = GPIO.HIGH noContactState = GPIO.LOW else: contactEdge = GPIO.FALLING noContactEdge = GPIO.RISING contactState = GPIO.LOW noContactState = GPIO.HIGH elif inputStr == 'e': # beam break at enty if GPIO.input (cageSet.entryBBpin)== GPIO.LOW: print ('Entry beam break is already broken') err=True else: GPIO.wait_for_edge (cageSet.entryBBpin, GPIO.FALLING, timeout= 10000) if GPIO.input (cageSet.entryBBpin)== GPIO.HIGH: print ('Entry beam not broken after 10 seconds.') err = True else: print ('Entry Beam Broken.') GPIO.wait_for_edge (cageSet.entryBBpin, GPIO.RISING, timeout= 10000) if GPIO.input (cageSet.entryBBpin)== GPIO.LOW: print ('Entry Beam Broken maintained for 10 seconds.') err = True else: print ('Entry Beam Intact Again.') err = False if err == True: inputStr= input ('Do you want to change the Entry Beam Break Pin (currently pin=' + str (cageSet.entryBBpin)+ '?') if inputStr[0] == 'y' or inputStr[0] == "Y": cageSet.entryBBpin= int (input ('Enter the GPIO pin connected to the tube entry IR beam-breaker:')) GPIO.setup (cageSet.entryBBpin, GPIO.IN, pull_up_down=GPIO.PUD_UP) elif inputStr == 'f': # head Fixer, run test from headFixer class headFixer.test(cageSet) elif inputStr == 'l': # l for LED trigger print ('LED turning ON for 2 seconds.') GPIO.output(cageSet.ledPin, 1) sleep (2) GPIO.output(cageSet.ledPin, 0) inputStr=input ('LED turned OFF\nDo you want to change the LED Pin (currently ' + str(cageSet.ledPin) + ')?') if inputStr == 'y' or inputStr == "Y": cageSet.ledPin = int (input('Enter New LED Pin:')) GPIO.setup (cageSet.ledPin, GPIO.OUT, initial = GPIO.LOW) elif inputStr == 's': for i,j in enumerate(expSettings.stimulator): print('\t'+str(i)+': '+str(j)) inputStr = input ('Which stimulator tester would you like to run?') try: stimulator[int(inputStr)].tester(expSettings) except: print('Input is not a valid number!') elif inputStr == 'h': cageSet.show() elif inputStr=='v': cageSet.save() elif inputStr == 'q': break except KeyboardInterrupt: print ("quitting.") finally: if __name__ == '__main__': GPIO.cleanup() # this ensures a clean exit
def main(): """ The main function for the AutoHeadFix program. It initializes or loads settings and configurations, then endlessly loops running entries and head fix trials Ctrl-C is used to enter a menu-driven mode where settings can be altered. """ try: # load general settings for this cage, mostly hardware pinouts # things not expected to change often - there is only one AHFconfig.jsn file, in the enclosing folder cageSettings = AHF_CageSet() #print (cageSettings) # get settings that may vary by experiment, including rewarder, camera parameters, and stimulator # More than one of these files can exist, and the user needs to choose one or make one # we will add some other variables to expSettings so we can pass them as a single argument to functions # logFP, statsFP, dateStr, dayFolderPath, doHeadFix, # configFile can be specified if launched from command line, eg, sudo python3 myconfig or sudo python3 AHFexp_myconfig.jsn configFile = None if argv.__len__() > 1: configFile = argv[1] expSettings = AHF_Settings(configFile) # nextDay starts tomorrow at KDAYSTARTHOUR #nextDay = (int((time() - timezone)/KSECSPERDAY) + 1) * KSECSPERDAY + timezone + (KDAYSTARTHOUR * KSECSPERHOUR) nextDay = ((int( (time() - timezone + localtime().tm_isdst * 3600) / KSECSPERDAY)) * KSECSPERDAY) + timezone - (localtime().tm_isdst * 3600 ) + KSECSPERDAY + KDAYSTARTHOUR # Create folders where the files for today will be stored makeDayFolderPath(expSettings, cageSettings) # initialize mice with zero mice mice = Mice() # make daily Log files and quick stats file makeLogFile(expSettings, cageSettings) makeQuickStatsFile(expSettings, cageSettings, mice) #Generate h5 file to store mouse-individual data makeH5File(expSettings, cageSettings, mice) updateStats(expSettings.statsFP, mice) backup_H5(expSettings, cageSettings) # set up the GPIO pins for each for their respective functionalities. GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(cageSettings.ledPin, GPIO.OUT, initial=GPIO.LOW) # turns on brain illumination LED GPIO.setup(cageSettings.led2Pin, GPIO.OUT, initial=GPIO.LOW) # turns on masking stim LED2 GPIO.setup(cageSettings.tirPin, GPIO.IN) # Tag-in-range output from RFID tag reader GPIO.setup(cageSettings.contactPin, GPIO.IN, pull_up_down=getattr(GPIO, "PUD_" + cageSettings.contactPUD)) if cageSettings.contactPolarity == 'RISING': expSettings.contactEdge = GPIO.RISING expSettings.noContactEdge = GPIO.FALLING expSettings.contactState = GPIO.HIGH expSettings.noContactState = GPIO.LOW else: expSettings.contactEdge = GPIO.FALLING expSettings.noContactEdge = GPIO.RISING expSettings.contactState = GPIO.LOW expSettings.noContactState = GPIO.HIGH # make head fixer - does its own GPIO initialization from info in cageSettings headFixer = AHF_HeadFixer.get_class( cageSettings.headFixer)(cageSettings) # make a rewarder rewarder = AHF_Rewarder(30e-03, cageSettings.rewardPin) rewarder.addToDict('entrance', expSettings.entranceRewardTime) rewarder.addToDict('task', expSettings.taskRewardTime) # make a notifier object if expSettings.hasTextMsg == True: notifier = AHF_Notifier(cageSettings.cageID, expSettings.phoneList) else: notifier = None # make RFID reader tagReader = TagReader(cageSettings.serialPort, False, None) # configure camera camera = AHF_Camera(expSettings.camParamsDict) # make UDP Trigger if expSettings.hasUDP == True: UDPTrigger = AHF_UDPTrig(expSettings.UDPList) print(UDPTrigger) else: UDPTrigger = None # make a lick detector simpleLogger = Simple_Logger(expSettings.logFP) lickDetector = AHF_LickDetector((0, 1), 26, simpleLogger) sleep(1) lickDetector.start_logging() # make stimulator(s) stimulator = [ AHF_Stimulator.get_class(i)(cageSettings, expSettings, rewarder, lickDetector, camera) for i in expSettings.stimulator ] #Stimdict is chosen from the first stimulator expSettings.stimDict = stimulator[0].configDict # Entry beam breaker if cageSettings.hasEntryBB == True: GPIO.setup(cageSettings.entryBBpin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.add_event_detect(cageSettings.entryBBpin, GPIO.BOTH, entryBBCallback) #GPIO.add_event_callback (cageSettings.entryBBpin, entryBBCallback) gTubePanicTime = time() + 25920000 # a month from now. gTubeMaxTime = expSettings.inChamberTimeLimit except Exception as anError: print('Unexpected error starting AutoHeadFix:', str(anError)) raise anError exit(0) try: print('Waiting for a mouse...') while True: #start main loop try: # wait for mouse entry, with occasional timeout to catch keyboard interrupt GPIO.wait_for_edge( cageSettings.tirPin, GPIO.RISING, timeout=kTIMEOUTmS ) # wait for entry based on Tag-in-range pin if (GPIO.input(cageSettings.tirPin) == GPIO.HIGH): try: tag = tagReader.readTag() except (IOError, ValueError): tagReader.clearBuffer() continue entryTime = time() if cageSettings.hasEntryBB == True: GPIO.remove_event_detect(cageSettings.entryBBpin) thisMouse = mice.getMouseFromTag(tag) if thisMouse is None: # try to open mouse config file to initialize mouse data thisMouse = Mouse(tag, 1, 0, 0, 0, 0, 0) mice.addMouse(thisMouse, expSettings.statsFP) writeToLogFile(expSettings.logFP, thisMouse, 'entry') thisMouse.entries += 1 # if we have entrance reward, first wait for entrance reward or first head-fix, which countermands entry reward if thisMouse.entranceRewards < expSettings.maxEntryRewards: giveEntranceReward = True expSettings.doHeadFix = expSettings.propHeadFix > random( ) while GPIO.input( cageSettings.tirPin) == GPIO.HIGH and time( ) < (entryTime + expSettings.entryRewardDelay): GPIO.wait_for_edge(cageSettings.contactPin, expSettings.contactEdge, timeout=kTIMEOUTmS) if (GPIO.input(cageSettings.contactPin) == expSettings.contactState): runTrial(thisMouse, expSettings, cageSettings, rewarder, headFixer, stimulator[thisMouse.stimType], UDPTrigger) giveEntranceReward = False break if (GPIO.input(cageSettings.tirPin) == GPIO.HIGH) and giveEntranceReward == True: thisMouse.reward( rewarder, 'entrance' ) # entrance reward was not countermanded by an early headfix writeToLogFile(expSettings.logFP, thisMouse, 'entryReward') # wait for contacts and run trials till mouse exits or time in chamber exceeded expSettings.doHeadFix = expSettings.propHeadFix > random() while GPIO.input( cageSettings.tirPin) == GPIO.HIGH and time( ) < entryTime + expSettings.inChamberTimeLimit: if (GPIO.input(cageSettings.contactPin) == expSettings.noContactState): GPIO.wait_for_edge(cageSettings.contactPin, expSettings.contactEdge, timeout=kTIMEOUTmS) if (GPIO.input(cageSettings.contactPin) == expSettings.contactState): runTrial(thisMouse, expSettings, cageSettings, rewarder, headFixer, stimulator[thisMouse.stimType], UDPTrigger) expSettings.doHeadFix = expSettings.propHeadFix > random( ) # set doHeadFix for next contact # either mouse left the chamber or has been in chamber too long if GPIO.input(cageSettings.tirPin) == GPIO.HIGH and time( ) > entryTime + expSettings.inChamberTimeLimit: # explictly turn off pistons, though they should be off at end of trial headFixer.releaseMouse() if expSettings.hasTextMsg == True: notifier.notify(thisMouse.tag, (time() - entryTime), True) # wait for mouse to leave chamber, with no timeout, unless it left while we did last 3 lines if GPIO.input(cageSettings.tirPin) == GPIO.HIGH: GPIO.wait_for_edge(cageSettings.tirPin, GPIO.FALLING) if expSettings.hasTextMsg == True: notifier.notify(thisMouse.tag, (time() - entryTime), False) tagReader.clearBuffer() if cageSettings.hasEntryBB == True: #GPIO.setup (cageSettings.entryBBpin, GPIO.IN, pull_up_down = GPIO.PUD_UP) GPIO.add_event_detect(cageSettings.entryBBpin, GPIO.BOTH, entryBBCallback) # after exit, update stats writeToLogFile(expSettings.logFP, thisMouse, 'exit') updateH5File(expSettings, cageSettings, mice, stimulator) updateStats(expSettings.statsFP, mice, thisMouse) # after each exit check for a new day if time() > nextDay: # stop lick logging so we dont write to file when it is closed lickDetector.stop_logging() mice.show() writeToLogFile(expSettings.logFP, None, 'SeshEnd') expSettings.logFP.close() expSettings.statsFP.close() makeDayFolderPath(expSettings, cageSettings) makeLogFile(expSettings, cageSettings) simpleLogger.logFP = expSettings.logFP makeQuickStatsFile(expSettings, cageSettings, mice) for i in stimulator: i.nextDay(expSettings.logFP) nextDay += KSECSPERDAY mice.clear() updateH5File(expSettings, cageSettings, mice, stimulator) updateStats(expSettings.statsFP, mice) backup_H5(expSettings, cageSettings) # reinitialize lick detector because it can lock up if too many licks when not logging lickDetector.__init__((0, 1), 26, simpleLogger) lickDetector.start_logging() print('Waiting for a mouse...') else: # check for entry beam break while idling between trials if cageSettings.hasEntryBB == True and time( ) > gTubePanicTime: print( 'Some one has been in the entrance of this tube for too long' ) # explictly turn off pistons, though they should be off headFixer.releaseMouse() BBentryTime = gTubePanicTime - gTubeMaxTime if expSettings.hasTextMsg == True: notifier.notify( 0, (time() - BBentryTime), True ) # we don't have an RFID for this mouse, so use 0 # wait for mouse to leave chamber while time() > gTubePanicTime: sleep(kTIMEOUTmS / 1000) print( 'looks like some one managed to escape the entrance of this tube' ) if expSettings.hasTextMsg == True: notifier.notify(0, (time() - BBentryTime), False) except KeyboardInterrupt: GPIO.output(cageSettings.ledPin, GPIO.LOW) headFixer.releaseMouse() GPIO.output(cageSettings.rewardPin, GPIO.LOW) lickDetector.stop_logging() if cageSettings.hasEntryBB == True: sleep(1) GPIO.remove_event_detect(cageSettings.entryBBpin) print('removed BB event detect') while True: event = input( 'Enter:\nr to return to head fix trials\nq to quit\nv to run valve control\nh for hardware tester\nm for mice inspection\nc for camera configuration\ne for experiment configuration\n:' ) if event == 'r' or event == "R": lickDetector.start_logging() sleep(1) if cageSettings.hasEntryBB == True: sleep(1) print('Restarting entry bb') GPIO.setup(cageSettings.entryBBpin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.add_event_detect(cageSettings.entryBBpin, GPIO.BOTH, entryBBCallback) break elif event == 'q' or event == 'Q': exit(0) elif event == 'v' or event == "V": valveControl(cageSettings) elif event == 'h' or event == 'H': hardwareTester(cageSettings, tagReader, headFixer, stimulator, expSettings) if cageSettings.contactPolarity == 'RISING': expSettings.contactEdge = GPIO.RISING expSettings.noContactEdge = GPIO.FALLING expSettings.contactState = GPIO.HIGH expSettings.noContactState = GPIO.LOW else: expSettings.contactEdge = GPIO.FALLING expSettings.noContactEdge = GPIO.RISING expSettings.contactState = GPIO.LOW expSettings.noContactState = GPIO.HIGH elif event == 'm' or event == 'M': mice.show() for i, j in enumerate(expSettings.stimulator): print('\t' + str(i) + ': ' + str(j)) inputStr = input( 'Which stimulator-specific inspection method would you like to run?' ) try: stimulator[int(inputStr)].inspect_mice( mice, cageSettings, expSettings) except: print("Stimulator doesn't exist.") updateH5File(expSettings, cageSettings, mice, stimulator) elif event == 'c' or event == 'C': camParams = camera.adjust_config_from_user() elif event == 'e' or event == 'E': modCode = expSettings.edit_from_user() if modCode >= 2: stimulator[modCode - 2] = AHF_Stimulator.get_class( expSettings.stimulator[modCode - 2])( cageSettings, expSettings.stimDict, rewarder, lickDetector, expSettings.logFP, camera) if modCode & 1: for stim in stimulator: stim.change_config(expSettings.stimDict) except Exception as anError: print('AutoHeadFix error:' + str(anError)) raise anError finally: for stim in stimulator: stim.quitting() GPIO.output(cageSettings.ledPin, False) headFixer.releaseMouse() GPIO.output(cageSettings.rewardPin, False) GPIO.cleanup() writeToLogFile(expSettings.logFP, None, 'SeshEnd') expSettings.logFP.close() expSettings.statsFP.close() camera.close() print('AutoHeadFix Stopped')