class SessionManager(object): sessionmgr_version = Ver('0.0.1') name = '' def __init__(self, **kwargs): if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.sessionmgr_version = Ver(data['sessionmgr_version']) self.name = data['name'] def save_to_dict(self): data = dict() data['sessionmgr_version'] = self.sessionmgr_version.__str__() data['name'] = self.name return data def __repr__(self): return "SessionManager object with name:%s" % (self.name) def check_schedule(self): return False
class NoTimeOff(SessionManager): notimeoff_version = Ver('0.0.1') def __init__(self, **kwargs): super(NoTimeOff, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.notimeoff_version = Ver(data['notimeoff_version']) def save_to_dict(self): data = super(NoTimeOff, self).save_to_dict() data['notimeoff_version'] = self.notimeoff_version.__str__() return data def __repr__(self): return "NoTimeOff object" def check_schedule(self, **kwargs): # Returns keep_doing_trials, secs_remaining_until_state_flip keep_doing_trials = True secs_remaining_until_state_flip = 0 return keep_doing_trials, secs_remaining_until_state_flip
class TimeRange(SessionManager): timerange_version = Ver('0.0.1') time_start = None time_stop = None def __init__(self, **kwargs): super(TimeRange, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.timerange_version = Ver(data['timerange_version']) self.time_start = data['time_start'] self.time_stop = data['time_stop'] def save_to_dict(self): data = super(TimeRange, self).save_to_dict() data['timerange_version'] = self.timerange_version.__str__() data['time_start'] = self.time_start data['time_stop'] = self.time_stop return data def __repr__(self): return "TimeRange object" def check_schedule(self): return NotImplementedError()
def __init__(self): self.ver = Ver('0.0.1') # Feb 28 2014 name = "DemoGratingsProtocol" training_steps = [ TrainingStep( name="DemoGratingStepNum1", trial_manager=gratings.GratingsAFC( name='DemoAFCGratingsTrialManager', deg_per_cycs={ 'L': [0.20], 'R': [0.20] }, durations={ 'L': [1.], 'R': [1.] }, reinforcement_manager=reinfmgr.ConstantReinforcement()), # trial_manager=Gratings(name='DemoAFCGratingsTrialManager', # deg_per_cycs=[0.1], #degrees # orientations=[45,-45,], #degrees # contrasts=[1], # durations=[1], #seconds # radii=[400], #degrees # iti=1, #seconds # itl=0., #inter trial luminance, # ), session_manager=sessmgr.NoTimeOff(), criterion=crit.RepeatIndefinitely()) ] super(DemoAFCGratingsProtocol, self).__init__(training_steps, name=name)
class MinutesPerSession(SessionManager): minutespersession_version = Ver('0.0.1') minutes = None hours_between_sessions = None def __init__(self, **kwargs): super(MinutesPerSession, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.minutespersession_version = Ver(data['minutespersession_version']) self.minutes = data['minutes'] self.hours_between_sessions = data['hours_between_sessions'] def save_to_dict(self): data = super(MinutesPerSession, self).save_to_dict() data[ 'minutespersession_version'] = self.minutespersession_version.__str__( ) data['minutes'] = self.minutes data['hours_between_sessions'] = self.hours_between_sessions return data def __repr__(self): return "MinutesPerSession object, %s minutes with %s hrs between sessions" % ( self.minutes, self.hours_between_sessions) def check_schedule(self): return NotImplementedError()
def __init__(self, trials_per_minute=10, consecutive_minutes=5, name='Unknown'): super(PerformanceCriterion, self).__init__(name) self.ver = Ver('0.0.1') self.trials_per_minute = trials_per_minute self.consecutive_minutes = consecutive_minutes
def __init__(self, num_trials=100, num_trials_mode='global', name='Unknown'): super(NumTrialsDoneCriterion, self).__init__(name) self.ver = Ver('0.0.1') self.num_trials = num_trials self.num_trials_mode = num_trials_mode
def load_from_dict(self, data): self.svbstation_version = Ver(data['svbstation_version']) self.sound_on = data['sound_on'] self.io_type = data['io_type'] self.parallel_port = data['parallel_port'] self.parallel_port_address = data['parallel_port_address'] self.display_name = data['display_name'] self.display_type = data['display_type'] return self
def __init__(self, draw_stim_onset_rect=False, iti=1.0, itl=(0., 0., 0.)): self.ver = Ver('0.0.2') self.draw_stim_onset_rect = draw_stim_onset_rect self.iti = iti if np.isscalar(itl): self.itl = itl * np.asarray( [1, 1, 1]) # inter trial luminance as gray scale else: self.itl = np.asarray(itl) #itl as color
def __init__(self, pct_correct=0.8, num_trials=200, num_trials_mode='global', name='Unknown'): super(PerformanceCriterion, self).__init__(name) self.ver = Ver('0.0.1') self.pct_correct = pct_correct self.num_trials = num_trials self.num_trials_mode = num_trials_mode
def load_from_dict(self, data): self.version = Ver(data['version']) # needed self.server_id = data['server_id'] # needed self.server_data_path = data['server_data_path'] # needed self.creation_time = datetime.datetime.strptime( data['creation_time'], DATETIME_TO_STR) # Month-dd-YYYY::Hr:Min:Sec for sub in data['subjects']: self.subjects.append(Subject.load_from_dict(sub)) for stn in data['stations']: self.stations.append(Station.load_from_dict(stn)) self.assignments = data['assignemnts'] return self
def load_from_dict(self, data): self.station_version = Ver(data['station_version']) self.creation_time = datetime.datetime.strptime( data['creation_time'], DATETIME_TO_STR) self.station_id = data['station_id'] self.station_name = data['station_name'] self.station_path = os.path.join(get_base_path(), 'BCoreData', 'StationData', str(self.station_id)) self.station_location = data['station_location'] self.mac_address = get_mac_address() self.ip_address = get_ip_addr() self.port = get_port() return self
def __init__( self, name, reinforcement_manager=reinfmgr.ConstantReinforcement(), min_run_speed=50, # sets_trigger on arduino run_duration_distribution=2., # seconds iti=1., itl=( 0., 0., 0., ), **kwargs): super(RunForReward, self).__init__(iti=iti, itl=itl) self.ver = Ver('0.0.1') self.reinforcement_manager = reinforcement_manager self.name = name self.run_speed = run_speed self.run_duration_distribution = delay_distribution self._verify_params_ok()
def __init__(self, name='DefaultCC_ConstantDelay_1s', delay_distribution=('Constant', 1.), go_signal=None, response_duration=2., iti=1., itl=( 0., 0., 0., ), **kwargs): super(ClassicalConditioning, self).__init__(iti=iti, itl=itl) self.ver = Ver('0.0.2') self.reinforcement_manager = reinforcement_manager self.name = name self.delay_distribution = delay_distribution self.go_signal = go_signal self.response_duration = response_duration # check if values are ok self._verify_params_ok()
def __init__(self, name='DefaultAuditory_Go_ConstantDelay_2s', reinforcement_manager=reinfmgr.ConstantReinforcement(), delay_distribution=('Constant', 2.), go_signal=None, response_duration=2., iti=1., itl=( 0., 0., 0., ), **kwargs): super(AuditoryGoOnly, self).__init__(iti=iti, itl=itl) self.ver = Ver('0.0.1') self.reinforcement_manager = reinforcement_manager self.name = name self.delay_distribution = delay_distribution self.go_signal = go_signal self.response_duration = response_duration # check if values are ok self._verify_params_ok()
class BServer(object): """ BSERVER keeps track of all the stations that it commands, which subjects are allowed in which station and data storage locations. version : string identifier server_id : string Identifier server_data_path : allowed data storage location server_ip : IPV4 value creation_time : time.time() stations : list of stations subjects : list of subjects assignments : dictionary with keys being subjectID and values being list of stationIDs """ version = Ver('0.0.1') # Feb 5, 2014 server_id = '' server_ip = '' server_data_path = '' creation_time = None stations = [] subjects = [] assignments = dict() server_connection = [] station_connections = [] def __init__(self, **kwargs): if not kwargs: self.creation_time = datetime.datetime.now() elif 'data' in kwargs: self = self.load_from_dict(kwargs['data'], convert=False) else: pass def load_from_dict(self, data): self.version = Ver(data['version']) # needed self.server_id = data['server_id'] # needed self.server_data_path = data['server_data_path'] # needed self.creation_time = datetime.datetime.strptime( data['creation_time'], DATETIME_TO_STR) # Month-dd-YYYY::Hr:Min:Sec for sub in data['subjects']: self.subjects.append(Subject.load_from_dict(sub)) for stn in data['stations']: self.stations.append(Station.load_from_dict(stn)) self.assignments = data['assignemnts'] return self def save_to_dict(self): data = dict() data['version'] = self.version.__str__() data['server_id'] = self.server_id data['server_data_path'] = self.server_data_path data['creation_time'] = datetime.datetime.strftime( self.creation_time, DATETIME_TO_STR) subjects = [] for sub in self.subjects: subjects.append(sub.save_to_dict()) data['subjects'] = subjects stations = [] for stn in self.stations: stations.append(stn.save_to_dict()) data['stations'] = stations data['assignments'] = self.assignments def __repr__(self): return "BServer with id:%s, name:%s, created on:%s)" % ( self.server_id, self.server_name, time.strftime("%b-%d-%Y", self.creation_time)) def run(server, **kwargs): # should expose the ZMQ context. and allow connections raise NotImplementedError() @staticmethod def load(): """ Alias for server.loadServer """ return BServer.load_server() @staticmethod def load_server(): # use standard location for path, # make sure to never modify server here: dbLoc = os.path.join(get_base_path(), 'BCoreData', 'ServerData', 'db.BServer') if os.path.isfile(dbLoc): with open(dbLoc, 'rb') as f: server = json.load(f) print('BServer loaded') else: raise RuntimeError( 'db.Server not found. Ensure it exists before calling loadServer' ) return server def save(self): """ Alias for server.saveServer """ self.save_server() def save_server(self): srcDir = os.path.join(get_base_path(), 'BCoreData', 'ServerData') desDir = os.path.join(get_base_path(), 'BCoreData', 'ServerData', 'backupDBs') if not os.path.isdir(self.server_data_path): # assume that these are never made alone... self._setup_paths() if os.path.isfile(os.path.join(srcDir, 'db.BServer')): # old db exists print(('Old db.Bserver found. moving to backup')) old = BServer() # standardLoad to old des_name = 'db_' + get_time_stamp(old.creation_time) + '.BServer' shutil.copyfile(os.path.join(srcDir, 'db.BServer'), os.path.join(desDir, des_name)) print(('Moved to backup... deleting old copy')) os.remove(os.path.join(srcDir, 'db.BServer')) # there might be some attributes that need to be deleted # delete them here before continuing print(('Cleaning and pickling object')) cleanedBServer = copy.deepcopy(self) cleanedBServer.station_connections = {} with open(os.path.join(srcDir, 'db.BServer'), 'wb') as f: pickle.dump(cleanedBServer, f) def load_backup(self): """ Use this only if you specifically require the deletion of current db.BServer and replacement with an older backup. Only the latest back up is used. """ desDir = os.path.join(get_base_path(), 'BCoreData', 'ServerData') srcDir = os.path.join(get_base_path(), 'BCoreData', 'ServerData', 'backupDBs') # delete the original database os.remove(os.path.join(desDir, 'db.BServer')) # find the latest file in the backupDBs newestBkup = max(os.listdir(srcDir), key=os.path.getctime) shutil.copyfile( os.path.join(srcDir, newestBkup), # source os.path.join(desDir, 'db.BServer') # destination ) # delete the newest backup os.remove(os.path.join(srcDir, newestBkup)) def _setup_paths(server): # create 'BServerData' os.mkdir(os.path.join(get_base_path(), 'BCoreData')) # create 'ServerData','Stations','PermanentTrialRecordStore' in # BServerData os.mkdir(os.path.join(get_base_path(), 'BCoreData', 'ServerData')) os.mkdir(os.path.join(get_base_path(), 'BCoreData', 'StationData')) os.mkdir(os.path.join(get_base_path(), 'BCoreData', 'SubjectData')) os.mkdir(os.path.join(get_base_path(), 'BCoreData', 'ChangeParams')) # create 'replacedDBs' in 'ServerData' os.mkdir( os.path.join(get_base_path(), 'BCoreData', 'ServerData', 'backupDBs')) # create 'Full' and 'Compiled' in 'SubjectData' os.mkdir( os.path.join(get_base_path(), 'BCoreData', 'SubjectData', 'SessionRecords')) os.mkdir( os.path.join(get_base_path(), 'BCoreData', 'SubjectData', 'CompiledTrialRecords')) def add_station(self, new_station): if (new_station.station_id in self.get_station_ids() or new_station.station_name in self.get_station_names()): raise ValueError('Station IDs and Station Names have to be unique') self.stations.append(new_station) # now enable station specific data self.save() def add_subject(self, new_subject): if new_subject in self.subjects: raise ValueError('Cannot add replica of subjects to BServer') self.subjects.append(new_subject) self.save() def change_assignment(self, subject, new_assignment): if subject not in self.subjects: raise ValueError('Cannot change assignment on a subject \ that is not on Bserver') if not (any(new_assignment in self.get_station_ids())): raise ValueError('Cannot assign subject to non existent stations') self.assignments[subject.subject_id] = new_assignment self.save() def get_station_ids(self): station_ids = [] for station in self.stations: station_ids.append(station.station_id) return station_ids def get_station_names(self): station_names = [] for station in self.stations: station_names.append(station.station_name) return station_names def get_subject_ids(self): subject_ids = [] for subject in self.subjects: subject_ids.append(subject.subject_id) return subject_ids
def __init__(self): self.ver = Ver('0.0.1') name = 'DemoNoStimulusProtocol'
class StandardKeyboardStation(StandardVisionBehaviorStation): """ STANDARDKEYBOARDSTATION(SKBS) defines a subclass of STANDARDVISIONBEHAVIORSTATION(SVBS). It defines a station with a standard display, sounds settings which can only be turned on or off, three sensor pins [connected to the keyboard]. Only allows stand alone running Attributes allowed are: station_id : numeric ID to be sent to STATION station_path : DO NOT SEND - STATION WILL SET IT display : dictionary containing details about the display unit soundOn : True/False For the StandardKeyboardStation: K+1 : Left Sensor K+2 : Center Sensor K+3 : Right Sensor K+Q : Quit """ skstation_version = Ver('0.0.1') def __init__(self, **kwargs): super(StandardKeyboardStation, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.skstation_version = Ver(data['skstation_version']) return self def save_to_dict(self): data = super(StandardKeyboardStation, self).save_to_dict() data['skstation_version'] = self.skstation_version return data def __repr__(self): return "StandardKeyboardStation object with id:%s, location:%s and ip:%s" % ( self.station_id, self.station_location, self.ip_address) @property def num_ports(self): return 3 def read_ports(self): key = psychopy.event.getKeys(keyList=['1', '2', '3', 'k']) ports = np.asarray([False, False, False]) if key: if not key[0] in self._key_pressed: self._key_pressed.append(key[0]) if 'k' in self._key_pressed and '1' in self._key_pressed: ports = np.bitwise_or(ports, [True, False, False]) psychopy.event.clearEvents() print(self._key_pressed) self._key_pressed.remove('k') self._key_pressed.remove('1') if 'k' in self._key_pressed and '2' in self._key_pressed: ports = np.bitwise_or(ports, [False, True, False]) psychopy.event.clearEvents() print(self._key_pressed) self._key_pressed.remove('k') self._key_pressed.remove('2') if 'k' in self._key_pressed and '3' in self._key_pressed: ports = np.bitwise_or(ports, [False, False, True]) psychopy.event.clearEvents() print(self._key_pressed) self._key_pressed.remove('k') self._key_pressed.remove('3') return self.get_ports()[ports] def open_valve(self, valve): print('Opening valve', valve) def close_valve(self, valve): print('Closing valve', valve) def flush_valves(self, dur=1): pass def close_all_valves(self): print('Closing all valves') def initialize(self): self.initialize_display(display=self.display) self.initialize_sounds() self.close_all_valves()
def load_from_dict(self, data): self.notimeoff_version = Ver(data['notimeoff_version'])
def __init__(self, name='DefaultProtocol'): self.ver = Ver('0.0.1') # Feb 28 2014 self.name = name
def load_from_dict(self, data): self.sessionmgr_version = Ver(data['sessionmgr_version']) self.name = data['name']
def load_from_dict(self, data): self.timerange_version = Ver(data['timerange_version']) self.time_start = data['time_start'] self.time_stop = data['time_stop']
class Station(object): """ STATION contains all the relevant details and interfaces to run trials from a particular station. This is an abstract class. Do not instantiate. stationID : numeric ID stationPath : string path to data storage location MACAddress : unique mac address for the processor/ethernet card. string identifier """ _subject = None _key_pressed = [] _sounds = {} _stims = {} _clocks = {} _parallel_port_conn = None creation_time = '' station_version = Ver('0.0.1') station_id = None station_name = '' station_path = '' station_location = None def __init__(self, **kwargs): if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data']) else: pass def load_from_dict(self, data): self.station_version = Ver(data['station_version']) self.creation_time = datetime.datetime.strptime( data['creation_time'], DATETIME_TO_STR) self.station_id = data['station_id'] self.station_name = data['station_name'] self.station_path = os.path.join(get_base_path(), 'BCoreData', 'StationData', str(self.station_id)) self.station_location = data['station_location'] self.mac_address = get_mac_address() self.ip_address = get_ip_addr() self.port = get_port() return self def save_to_dict(self): data = dict() data['station_version'] = self.station_version.__str__() data['station_id'] = self.station_id data['station_name'] = self.station_name data['station_location'] = self.station_location data['creation_time'] = datetime.datetime.strftime( self.creation_time, DATETIME_TO_STR) return data def __repr__(self): return "Station object with id:%s, location:%s and ip:%s" % ( self.station_id, self.station_location, self.ip_address) def register(self): # pass def _setup_paths(self): if not os.path.isdir(self.station_path): os.makedirs(self.station_path) def do_trials(self, **kwargs): raise NotImplementedError('Run doTrials() on a subclass') def initialize_sounds(self): self._sounds['trial_start_sound'] = psychopy.sound.Sound(440, stereo=0, secs=1., hamming=True) self._sounds['request_sound'] = psychopy.sound.Sound(493.88, stereo=0, secs=1., hamming=True) self._sounds['stim_start_sound'] = psychopy.sound.Sound(493.88, stereo=0, secs=1., hamming=True) self._sounds['go_sound'] = psychopy.sound.Sound(493.88, stereo=0, secs=1., hamming=True) self._sounds['keep_going_sound'] = psychopy.sound.Sound(493.88, stereo=0, secs=1., hamming=True) self._sounds['request_sound'] = psychopy.sound.Sound(493.88, stereo=0, secs=1., hamming=True) self._sounds['correct_sound'] = psychopy.sound.Sound(523.25, stereo=0, secs=1., hamming=True) self._sounds['reward_sound'] = psychopy.sound.Sound(523.25, stereo=0, secs=1., hamming=True) self._sounds['trial_end_sound'] = psychopy.sound.Sound(523.25, stereo=0, secs=1., hamming=True) sampleRate, secs, f_punishment = (44100, 2, [370, 440]) nSamples = int(secs * sampleRate) phase = 2 * np.pi * np.linspace(0.0, 1.0, nSamples) val = np.full_like(phase, 0.) for f in f_punishment: val += np.sin(f * phase) val = np.matlib.repmat(val, 2, 1) self._sounds['punishment_sound'] = psychopy.sound.Sound(val.T, hamming=True) val = 0.5 * np.random.randn(1, nSamples) val = np.matlib.repmat(val, 2, 1) self._sounds['try_something_else'] = psychopy.sound.Sound(val.T, hamming=True) self._sounds['trial_end_sound'] = psychopy.sound.Sound(587.33, stereo=0, secs=1., hamming=True) def _rewind_sounds(self, time=0.): for sound in self._sounds: self._sounds[sound].seek(time) def decache(self): """ Remove session specific details. ideal for pickling """ self._key_pressed = None self._sounds = None self._stims = None self._clocks = None
def load_from_dict(self, data): self.minutespersession_version = Ver(data['minutespersession_version']) self.minutes = data['minutes'] self.hours_between_sessions = data['hours_between_sessions']
class StandardVisionBehaviorStation(Station): """ STANDARDVISIONBEHAVIORSTATION(SVBS) defines a subclass of STATION. It defines a station with a standard display, a parallel port for i/o with standard pin-out settings, sounds settings which can only be turned on or off, three valve pins, three sensor pins. Only allows stand alone running Attributes allowed are: station_id : numeric ID to be sent to STATION station_path : DO NOT SEND - STATION WILL SET IT display : dictionary containing details about the display unit soundOn : True/False parallelPort : dictionary containing details about the parallel port For the StandardVisualBehaviorStation, with Rev 2/3 breakout boards ("The Bomb"), only certain ports are used and for specific purposes: Pin 2 : Right Reward Valve Pin 3 : Center Reward Valve Pin 4 : Left Reward Valve Pin 5 : LED1 Pin 6 : eyePuff Pin 7 : LED2 Pin 8 : indexPulse Pin 9 : framePulse Pin 10 : Center Response Sensor Pin 12 : Right Response Sensor Pin 13 : Left Response Sensor While, these values are not hard coded here, use these values if you want your system to work :) Use these defaults unless you know what you are doing parallel_port = {} parallel_port['right_valve'] = 2 parallel_port['center_valve'] = 3 parallel_port['left_valve'] = 4 parallel_port['valve_pins'] = (2, 3, 4) parallel_port['center_port'] = 10 parallel_port['right_port'] = 12 parallel_port['left_port'] = 13 parallel_port['port_pins'] = (12, 10, 13) parallel_port['index_pin'] = 8 parallel_port['frame_pin'] = 9 parallel_port['led_0'] = 5 parallel_port['led_1'] = 7 """ _window = None _session = None _server_conn = None svbstation_version = Ver('0.0.1') sound_on = False io_type = '' parallel_port = None parallel_port_address = '' display_name = '' display_type = '' display = None def __init__(self, **kwargs): super(StandardVisionBehaviorStation, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass self.display = self.get_display() self.parallel_port = self.get_parport_mappings() def load_from_dict(self, data): self.svbstation_version = Ver(data['svbstation_version']) self.sound_on = data['sound_on'] self.io_type = data['io_type'] self.parallel_port = data['parallel_port'] self.parallel_port_address = data['parallel_port_address'] self.display_name = data['display_name'] self.display_type = data['display_type'] return self def save_to_dict(self): data = super(StandardVisionBehaviorStation, self).save_to_dict() data['svbstation_version'] = self.svbstation_version data['sound_on'] = self.sound_on data['io_type'] = self.io_type data['parallel_port'] = self.parallel_port data['parallel_port_address'] = self.parallel_port_address data['display_name'] = self.display_name data['display_type'] = self.display_type return data def __repr__(self): return "StandardVisionBehaviorStation object with id:%s, location:%s and ip:%s" % ( self.station_id, self.station_location, self.ip_address) def get_display(self): return displays.StandardDisplay() def get_parport_mappings(self): if self.parallel_port == 'standardVisionBehaviorDefault': print( 'STANDARDVISIONBEHAVIORSTATION:INITIALIZE_PARALLEL_PORT::setting parallelport to standardVisionBehaviorDefault' ) pPort = {} pPort['right_valve'] = 2 pPort['center_valve'] = 3 pPort['left_valve'] = 4 pPort['valve_pins'] = [2, 3, 4] pPort['center_port'] = 10 pPort['right_port'] = 12 pPort['left_port'] = 13 pPort['port_pins'] = [13, 10, 12] pPort['index_pin'] = 8 pPort['frame_pin'] = 9 pPort['trial_pin'] = 6 pPort['led_0'] = 5 pPort['led_1'] = 7 return pPort elif self.parallel_port == 'standardHeadfixBehaviorDefault': print( 'STANDARDVISIONBEHAVIORSTATION:INITIALIZE_PARALLEL_PORT::setting parallelport to standardVisionHeadfixDefault' ) pPort = {} pPort['reward_valve'] = 3 pPort['valve_pins'] = [ 3, ] pPort['response_port'] = 10 pPort['running_port'] = 13 pPort['port_pins'] = [ 10, ] pPort['index_pin'] = 8 pPort['frame_pin'] = 9 pPort['trial_pin'] = 6 pPort['led_0'] = 5 pPort['led_1'] = 7 return pPort else: return None # need to write code that checks if allowable def initialize(self): self.initialize_display(display=self.display) self.initialize_sounds() self.initialize_parallel_port() self.close_all_valves() def run(self): self.connect_to_server() run_trials = False while True: # look for data from server msg = self.get_server_msg() quit = False if run_trials and ~quit: # get info anout session self.get_session() sub = self._session['subject'] tR = self._session['trial_record'] cR = self._session['compiled_record'] prot = self._session['protocol'] trial_num = self._session['trial_num'] def initialize_display(self, display=displays.StandardDisplay()): self._window = psychopy.visual.Window(color=(0., 0., 0.), fullscr=True, winType='pyglet', allowGUI=False, units='deg', screen=0, viewScale=None, waitBlanking=True, allowStencil=True, monitor=display) self._window.flip() def initialize_parallel_port(self): self._parallel_port_conn = psychopy.parallel.ParallelPort( address=self.parallel_port_address) self.close_all_valves() def connect_to_server(self): """ This is a somewhat complicated handshake. Initially, the station acts as a server exposing its IP::port to the server. Since the server knows this IP::port it can create a client connection easily. Upon connection, BServer(currently client) sends a connection info for a separate connection(BServer will reserve the space for this connection) to the station and the station will connect to the BServer now as a client. This way new stations can be added to the server without any station-side code modification. BServer can dynamically manage its resources. Along with threaded TCP server connections on the server side, this should provide scalable, TCP communications with the server """ self._server_conn = TCPServerConnection(ipaddr=self.ip_address, port=self.port) self._server_conn.start() server_connection_details = self._server_conn.recvData() # use server_connection_details to connect to the BServer as a client print( 'STANDARDVISIONBEHAVIORSTATION:CONNECT_TO_SERVER::Closing connection as server...' ) self._server_conn.stop() self._server_conn = BehaviorClientConnection( ipaddr=server_connection_details['ipaddr'], port=server_connection_details['port']) print( 'STANDARDVISIONBEHAVIORSTATION:CONNECT_TO_SERVER::Starting connection as client...' ) self._server_conn.start() @property def subject(self): return self._subject @subject.setter def subject(self, value): self._subject = value @property def session(self): return self._session @session.setter def session(self, value): self._session = value def get_ports(self): return np.asarray(['left_port', 'center_port', 'right_port']) @property def num_ports(self): if self.parallel_port: return len(self.parallel_port['port_pins']) else: return 0 def add_subject(self, sub): self.subject = sub #if sub.subject_id in self.get_subjects(): # RuntimeError("STATION:STANDARDVISIONBEHAVIORSTATION:ADD_SUBJECT:Subject "+ sub.subject_id + " already in station. Cannot add twice") # #print("STATION:STANDARDVISIONBEHAVIORSTATION:ADD_SUBJECT: Adding subject_id " + sub.subject_id +" to station_id " + str(self.station_id)) #self.subjects.append(sub) def remove_subject(self, sub): self.subject = None #if sub.subject_id not in self.get_subjects(): # RuntimeError("STATION:STANDARDVISIONBEHAVIORSTATION:ADD_SUBJECT:Subject "+ sub.subject_id + " not in station. Cannot remove.") #print("STATION:STANDARDVISIONBEHAVIORSTATION:REMOVE_SUBJECT: Removing subject_id " + sub.subject_id +" from station_id " + str(self.station_id)) #idx = [i for (i,x) in enumerate(self.get_subjects()) if x==sub.subject_id] #self.subjects = self.subjects[:idx[0]]+self.subjects[idx[0]+1:] def close_all_valves(self): val = list('{0:08b}'.format(self._parallel_port_conn.readData())) for valve in self.parallel_port['valve_pins']: val[1 - valve] = '0' self._parallel_port_conn.setData(int(''.join(val), 2)) def read_ports(self): out = [False, False, False] port_names = ['left_port', 'center_port', 'right_port'] for i, port in enumerate(self.parallel_port['port_pins']): out[i] = self._parallel_port_conn.readPin(port) active_ports = [x for x, y in zip(port_names, out) if not y] return active_ports def open_valve(self, valve): valve_pin = self.parallel_port[valve] self.set_pin_on(valve_pin) def close_valve(self, valve): valve_pin = self.parallel_port[valve] self.set_pin_off(valve_pin) def flush_valves(self, dur=1): val = list('{0:08b}'.format(self._parallel_port_conn.readData())) for valve in self.parallel_port['valve_pins']: val[1 - valve] = '1' self._parallel_port_conn.setData(int(''.join(val), 2)) time.sleep(dur) for valve in self.parallel_port['valve_pins']: val[1 - valve] = '0' self._parallel_port_conn.setData(int(''.join(val), 2)) def set_index_pin_on(self): index_pin = self.parallel_port['index_pin'] self.set_pin_on(index_pin) def set_index_pin_off(self): index_pin = self.parallel_port['index_pin'] self.set_pin_off(index_pin) def set_frame_pin_on(self): frame_pin = self.parallel_port['frame_pin'] self.set_pin_on(frame_pin) def set_frame_pin_off(self): frame_pin = self.parallel_port['frame_pin'] self.set_pin_off(frame_pin) def set_trial_pin_on(self): trial_pin = self.parallel_port['trial_pin'] self.set_pin_on(trial_pin) def set_trial_pin_off(self): trial_pin = self.parallel_port['trial_pin'] self.set_pin_off(trial_pin) def set_pin_on(self, pin): if pin < 2 or pin > 9: ValueError('Cannot deal with this') val = list('{0:08b}'.format(self._parallel_port_conn.readData())) val[1 - pin] = '1' self._parallel_port_conn.setData(int(''.join(val), 2)) def set_pin_off(self, pin): if pin < 2 or pin > 9: ValueError('Cannot deal with this') val = list('{0:08b}'.format(self._parallel_port_conn.readData())) val[1 - pin] = '0' self._parallel_port_conn.setData(int(''.join(val), 2)) def get_display_size(self): pass def get_session(self): """ Connect to BServer and request session details to be loaded """ self._session = self._server_conn.client_to_server( self._server_conn.SESSION_REQUESTED) def decache(self): """ Remove session specific details. ideal for pickling """ self._window = None self._session = None self._server_conn = None self._parallel_port_conn = None self._clocks = None def do_trials(self, **kwargs): # first step in the running of trials. called directly by station # or through the BServer if __debug__: pass self.initialize() # get the compiled_records for the animal. Compiled records will contain all the information that will be used in # the course of running the experiment. If some stimulus parameter for a given trial is dependent on something in # the previous trial, please add it to compiled records compiled_record = self.subject.load_compiled_records() quit = False # session starts here session_record = [] # just a list of tRs session_number = compiled_record["session_number"][-1] + 1 # setup the clocks self._clocks['session_clock'] = psychopy.core.MonotonicClock() self._clocks['trial_clock'] = psychopy.core.Clock() session_start_time = psychopy.core.getAbsTime() while not quit: # it loops in here every trial trial_record = {} # just assign relevant details here trial_record["session_start_time"] = session_start_time trial_record[ "trial_number"] = compiled_record["trial_number"][-1] + 1 trial_record["session_number"] = session_number trial_record["station_id"] = self.station_id trial_record["station_version_number"] = self.ver.__str__() trial_record["station_name"] = self.station_name trial_record["num_ports_in_station"] = self.num_ports trial_record["trial_start_time"] = self._clocks[ 'session_clock'].getTime() # doTrial - only trial_record will be returned as its type will be changed trial_record, quit = self.subject.do_trial( station=self, trial_record=trial_record, compiled_record=compiled_record, quit=quit) trial_record["trial_stop_time"] = self._clocks[ 'session_clock'].getTime() # update sessionRecord and compiledRecord compiled_record = compile_records(compiled_record, trial_record) session_record.append(trial_record) # save session records self.subject.save_session_records(session_record) # save compiled records self.subject.save_compiled_records(compiled_record) self.decache() def close_session(self, **kwargs): print("STANDARDVISIONBEHAVIORSTATION:CLOSE_SESSION::Closing Session") def close_window(self): self._window.close() def check_manual_quit(self): key = psychopy.event.getKeys(keyList=['k', 'q']) if key: if not key[0] in self._key_pressed: self._key_pressed.append(key[0]) if 'k' in self._key_pressed and 'q' in self._key_pressed: psychopy.event.clearEvents() return True else: return False def read_kb(self): key, modifier = event.getKeys(keyList=['1', '2', '3', 'k'], modifier=True) ports = np.asarray([False, False, False]) if key: if not key[0] in self._key_pressed: self._key_pressed.append(key[0]) if 'k' in self._key_pressed and '1' in self._key_pressed: self._key_pressed.remove('k') self._key_pressed.remove('1') if 'k' in self._key_pressed and '2' in self._key_pressed: ports = np.bitwise_or(ports, [False, True, False]) psychopy.event.clearEvents() print(self._key_pressed) self._key_pressed.remove('k') self._key_pressed.remove('2') if 'k' in self._key_pressed and '3' in self._key_pressed: ports = np.bitwise_or(ports, [False, False, True]) psychopy.event.clearEvents() print(self._key_pressed) self._key_pressed.remove('k') self._key_pressed.remove('3') return self.get_ports()[ports]
def __init__(self, name='Unknown'): self.name = name self.ver = Ver('0.0.1')
class StandardVisionHeadfixStation(StandardVisionBehaviorStation): """ STANDARDVISIONHEADFIXSTATION(SVHS) defines a subclass of SVBS. It defines a station with a standard display, a parallel port for i/o with standard pin-out settings, sounds settings which can only be turned on or off, one valve pins, one sensor pins. Only allows stand alone running Attributes allowed are: station_id : numeric ID to be sent to STATION station_path : DO NOT SEND - STATION WILL SET IT display : dictionary containing details about the display unit soundOn : True/False parallelPort : dictionary containing details about the parallel port For the StandardVisualBehaviorStation, with Rev 2/3 breakout boards ("The Bomb"), only certain ports are used and for specific purposes: Pin 3 : Center Reward Valve Pin 8 : indexPulse Pin 9 : framePulse Pin 10 : Center Response Sensor While, these values are not hard coded here, use these values if you want your system to work :) Use these defaults unless you know what you are doing parallel_port = {} parallel_port['center_valve'] = 3 parallel_port['valve_pins'] = (3) parallel_port['center_port'] = 10 parallel_port['port_pins'] = (10) parallel_port['index_pin'] = 8 parallel_port['frame_pin'] = 9 parallel_port['led_0'] = 5 parallel_port['led_1'] = 7 """ svhfstation_version = Ver('0.0.1') def __init__(self, **kwargs): super(StandardVisionHeadfixStation, self).__init__(**kwargs) if not kwargs: pass elif 'data' in kwargs: self = self.load_from_dict(kwargs['data]']) else: pass def load_from_dict(self, data): self.svhfstation_version = Ver(data['svhfstation_version']) return self def save_to_dict(self): data = super(StandardVisionHeadfixStation, self).save_to_dict() data['svhfstation_version'] = self.svhfstation_version return data def __repr__(self): return "StandardVisionHeadfixStation object with id:%s, location:%s and ip:%s" % ( self.station_id, self.station_location, self.ip_address) def get_ports(self): return np.asarray(['response_port']) def read_ports(self): port_names = ['response_port'] if self._parallel_port_conn.readPin( self.parallel_port['port_pins'][0]): return [] # when the lick port is high then it is empty. else: return ['response_port' ] # when the lick port is low, then there is licking def open_valve(self, valve): valve_pin = self.parallel_port[valve] self.set_pin_on(valve_pin) def close_valve(self, valve): valve_pin = self.parallel_port[valve] self.set_pin_off(valve_pin) def close_all_valves(self): self.close_valve('reward_valve')
def __init__(self, name='Unknown'): self.ver = Ver('0.0.1') super(RepeatIndefinitely, self).__init__(name)
def load_from_dict(self, data): self.skstation_version = Ver(data['skstation_version']) return self
def __init__(self, name, trial_manager, session_manager, criterion): self.ver = Ver('0.0.1') self.name = name self.trial_manager = trial_manager self.session_manager = session_manager self.criterion = criterion