class GUI(object): """ simple gui to demostrate live inejction of the spike io script. """ def __init__(self, n_neurons): """ creates the gui :return: """ self._started = False # Set up the live connection for sending and receiving spikes self.live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self.live_spikes_connection.add_start_callback( "spike_injector_forward", self.send_input_forward) root = tk.Tk() root.title("Injecting Spikes GUI") label = tk.Label(root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self.neuron_id = tk.Spinbox( root, from_=0, to=n_neurons - 1, textvariable=neuron_id_value) self.neuron_id.pack() pop_label_value = tk.StringVar() self.pop_label = tk.Spinbox( root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self.pop_label.pack() button = tk.Button(root, text='Inject', width=25, command=self.inject_spike) button.pack() root.mainloop() # Create a sender of packets for the forward population def send_input_forward(self, pop_label, _): """ records that stuff has started on the spinnaker machine :param pop_label: label :param _: dont care :return: """ self._started = True # add a gui with a button and scroll list def inject_spike(self): """ is set off when inject is pressed, takes the vlaues from the spin boxes and fires a spike in. :return: """ print "injecting with neuron_id {} to pop {}".format( self.neuron_id.get(), self.pop_label.get()) if self._started: self.live_spikes_connection.send_spike(str(self.pop_label.get()), int(self.neuron_id.get()))
def setupSpikeReceiver(self, network=None): print "\tSetting up Spike Receiver..." networkLabels = [] for pop in network: ExternalDevices.activate_live_output_for(pop[1], database_notify_host="localhost", database_notify_port_num=19996) networkLabels.append(pop[1].label) liveConnection = SpynnakerLiveSpikesConnection(receive_labels=networkLabels, local_port=19996, send_labels=None) for label in networkLabels: liveConnection.add_receive_callback(label, self.plotReceivedSpike)
def __init__(self, pop_labels): self._length_sender = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=pop_labels) self._len = 0.95 self._dlen = 0.0 self._go_on = True for label in pop_labels: self._length_sender.add_start_callback(label, self.send_input_spindle) self._count = 0
def setupSpikeInjectors(retinaLeft=None, retinaRight=None): print "Setting up Spike Injectors for Retina Left and Retina Right..." retinaLabels = [] for popL, popR in zip(retinaLeft, retinaRight): retinaLabels.append(popL.label) retinaLabels.append(popR.label) liveConnection = SpynnakerLiveSpikesConnection(receive_labels=None, local_port=19999, send_labels=retinaLabels) from retinaSpikeInjector import startInjecting liveConnection.add_start_callback(retinaLabels[0], startInjecting) return liveConnection
def setupSpikeReceiver(network=None): print "Setting up Spike Receiver..." networkLabels = [] for pop in network: ExternalDevices.activate_live_output_for(pop[1], database_notify_host="localhost", database_notify_port_num=19996, board_address='10.162.177.122') networkLabels.append(pop[1].label) if not useCVisualiser: liveConnection = SpynnakerLiveSpikesConnection(receive_labels=networkLabels, local_port=19996, send_labels=None) for label in networkLabels: liveConnection.add_receive_callback(label, receiveSpike) return liveConnection
class GUI(object): """ Simple gui to demostrate live inejction of the spike io script. """ def __init__(self, n_neurons, ready): self._n_neurons = n_neurons # Set up the live connection for sending and receiving spikes self._live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self._live_spikes_connection.add_start_callback( "spike_injector_forward", self.start) self._root = tk.Tk() self._root.title("Injecting Spikes GUI") label = tk.Label(self._root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self._neuron_id = tk.Spinbox( self._root, from_=0, to=self._n_neurons - 1, textvariable=neuron_id_value) self._neuron_id.pack() pop_label_value = tk.StringVar() self._pop_label = tk.Spinbox( self._root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self._pop_label.pack() self._button = tk.Button( self._root, text='Inject', width=25, command=self.inject_spike, state="disabled") self._button.pack() ready.set() self._root.mainloop() def start(self, pop_label, connection): self._button["state"] = "normal" def inject_spike(self): neuron_id = int(self._neuron_id.get()) label = str(self._pop_label.get()) print "injecting with neuron_id {} to pop {}".format(neuron_id, label) self._live_spikes_connection.send_spike(label, neuron_id)
def __init__(self, n_neurons): """ creates the gui :return: """ self._started = False # Set up the live connection for sending and receiving spikes self.live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self.live_spikes_connection.add_start_callback( "spike_injector_forward", self.send_input_forward) root = tk.Tk() root.title("Injecting Spikes GUI") label = tk.Label(root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self.neuron_id = tk.Spinbox( root, from_=0, to=n_neurons - 1, textvariable=neuron_id_value) self.neuron_id.pack() pop_label_value = tk.StringVar() self.pop_label = tk.Spinbox( root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self.pop_label.pack() button = tk.Button(root, text='Inject', width=25, command=self.inject_spike) button.pack() root.mainloop()
def __init__(self, n_neurons, ready): self._n_neurons = n_neurons # Set up the live connection for sending and receiving spikes self._live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self._live_spikes_connection.add_start_callback( "spike_injector_forward", self.start) self._root = tk.Tk() self._root.title("Injecting Spikes GUI") label = tk.Label(self._root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self._neuron_id = tk.Spinbox( self._root, from_=0, to=self._n_neurons - 1, textvariable=neuron_id_value) self._neuron_id.pack() pop_label_value = tk.StringVar() self._pop_label = tk.Spinbox( self._root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self._pop_label.pack() self._button = tk.Button( self._root, text='Inject', width=25, command=self.inject_spike, state="disabled") self._button.pack() ready.set() self._root.mainloop()
class SpindleLengthSender(object): def __init__(self, pop_labels): self._length_sender = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=pop_labels) self._len = 0.95 self._dlen = 0.0 self._go_on = True for label in pop_labels: self._length_sender.add_start_callback(label, self.send_input_spindle) self._count = 0 def len_to_intlist(self): l = list() l.append(int(math.trunc(self._len))) l.append(int((self._len - math.trunc(self._len)) * 1000)) l.append(int(math.trunc(self._dlen))) l.append(int((self._dlen - math.trunc(self._dlen)) * 1000)) return l def stop(self): self._go_on = False def generate_new_length(self): if self._count < 110: self._len = 0.95 self._dlen = 0.0 elif self._count < 220: self._len += (1.08 - 0.95) / 110 self._dlen = (1.08 - 0.95) / 1.1 else: self._len = 1.08 self._dlen = 0.0 self._count += 1 def send_input_spindle(self, label, sender): while self._go_on: self.generate_new_length() sender.send_spikes(label, self.len_to_intlist()) time.sleep(0.01)
def __init__(self, n_neurons): """ creates the gui :return: """ self._started = False # Set up the live connection for sending and receiving spikes self.live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self.live_spikes_connection.add_start_callback( "spike_injector_forward", self.send_input_forward) root = tk.Tk() root.title("Injecting Spikes GUI") label = tk.Label(root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self.neuron_id = tk.Spinbox(root, from_=0, to=n_neurons - 1, textvariable=neuron_id_value) self.neuron_id.pack() pop_label_value = tk.StringVar() self.pop_label = tk.Spinbox(root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self.pop_label.pack() button = tk.Button(root, text='Inject', width=25, command=self.inject_spike) button.pack() root.mainloop()
def setupVisualiser(network=None, retinaLeft=None, retinaRight=None): print "Setting up Visualiser..." global retinaThreads, disparityThread, logFile logFile = open("dipsarities.txt", 'w') print "\tSetting up Spike Receiver..." networkLabels = [] for pop in network: ExternalDevices.activate_live_output_for(pop[1], database_notify_host="localhost", database_notify_port_num=19996) networkLabels.append(pop[1].label) liveConnection_receiver = SpynnakerLiveSpikesConnection(receive_labels=networkLabels, local_port=19996, send_labels=None) disparityThread = spike_plotter() for label in networkLabels: liveConnection_receiver.add_receive_callback(label, disparityThread.plotReceivedSpike) disparityThread.start() print "\tSetting up Spike Injectors for Retina Left and Retina Right..." retinaLabels = [] for popL, popR in zip(retinaLeft, retinaRight): retinaLabels.append(popL[1].label) retinaLabels.append(popR[1].label) liveConnection_sender = SpynnakerLiveSpikesConnection(receive_labels=None, local_port=19999, send_labels=retinaLabels) bg_col=pygame.Color(230,230,230,0) on_col=pygame.Color(10,220,10,0) off_col=pygame.Color(220,10,10,0) retinaThreads[ports[0]] = dvs_reader(port=ports[0], colors = {"bg": bg_col, "on": on_col, "off": off_col}, label="RetL", liveConnection=liveConnection_sender) retinaThreads[ports[1]] = dvs_reader(port=ports[1], colors = {"bg": bg_col, "on": on_col, "off": off_col}, label="RetR", liveConnection=liveConnection_sender) liveConnection_sender.add_start_callback(retinaLabels[0], startInjecting) panelsDrawer = Thread(target=setupPanels) panelsDrawer.start()
# Activate the sending of live spikes ExternalDevices.activate_live_output_for(pop_forward, database_notify_host="localhost", database_notify_port_num=19996) # Create a sender of packets for the forward population def send_input_forward(label, sender): print "Sending forward spike for neuron 0" sender.send_spike(label, 0) # if not using the c visualiser, then a new spynnaker live spikes connection # is created to define that there are python code which receives the # outputted spikes. live_spikes_connection = SpynnakerLiveSpikesConnection( local_port=19996, send_labels=["spike_injector_forward"]) # Set up callbacks to occur at the start of simulation live_spikes_connection.add_start_callback("spike_injector_forward", send_input_forward) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes() # If there are spikes, plot using matplotlib if len(spikes_forward) != 0: pylab.figure() if len(spikes_forward) != 0: pylab.plot([i[1] for i in spikes_forward], [i[0] for i in spikes_forward], "b.") pylab.ylabel('neuron id') pylab.xlabel('Time/ms')
def __init__(self): # initial call to set up the front end (pynn requirement) Frontend.setup(timestep=1.0, min_delay=1.0, max_delay=144.0) use_c_visualiser = True use_spike_injector = True # neurons per population and the length of runtime in ms for the # simulation, as well as the expected weight each spike will contain self.n_neurons = 100 # set up gui p = None if use_spike_injector: from multiprocessing import Process from multiprocessing import Event ready = Event() p = Process(target=GUI, args=[self.n_neurons, ready]) p.start() ready.wait() # different runtimes for demostration purposes run_time = None if not use_c_visualiser and not use_spike_injector: run_time = 1000 elif use_c_visualiser and not use_spike_injector: run_time = 10000 elif use_c_visualiser and use_spike_injector: run_time = 100000 elif not use_c_visualiser and use_spike_injector: run_time = 10000 weight_to_spike = 2.0 # neural parameters of the IF_curr model used to respond to injected # spikes. # (cell params for a synfire chain) cell_params_lif = {'cm': 0.25, 'i_offset': 0.0, 'tau_m': 20.0, 'tau_refrac': 2.0, 'tau_syn_E': 5.0, 'tau_syn_I': 5.0, 'v_reset': -70.0, 'v_rest': -65.0, 'v_thresh': -50.0 } ################################## # Parameters for the injector population. This is the minimal set of # parameters required, which is for a set of spikes where the key is # not important. Note that a virtual key *will* be assigned to the # population, and that spikes sent which do not match this virtual key # will be dropped; however, if spikes are sent using 16-bit keys, they # will automatically be made to match the virtual key. The virtual # key assigned can be obtained from the database. ################################## cell_params_spike_injector = { # The port on which the spiNNaker machine should listen for # packets. Packets to be injected should be sent to this port on # the spiNNaker machine 'port': 12345 } ################################## # Parameters for the injector population. Note that each injector # needs to be given a different port. The virtual key is assigned # here, rather than being allocated later. As with the above, spikes # injected need to match this key, and this will be done automatically # with 16-bit keys. ################################## cell_params_spike_injector_with_key = { # The port on which the spiNNaker machine should listen for # packets. Packets to be injected should be sent to this port on # the spiNNaker machine 'port': 12346, # This is the base key to be used for the injection, which is used # to allow the keys to be routed around the spiNNaker machine. # This assignment means that 32-bit keys must have the high-order # 16-bit set to 0x7; This will automatically be prepended to # 16-bit keys. 'virtual_key': 0x70000 } # create synfire populations (if cur exp) pop_forward = Frontend.Population( self.n_neurons, Frontend.IF_curr_exp, cell_params_lif, label='pop_forward') pop_backward = Frontend.Population( self.n_neurons, Frontend.IF_curr_exp, cell_params_lif, label='pop_backward') # Create injection populations injector_forward = None injector_backward = None if use_spike_injector: injector_forward = Frontend.Population( self.n_neurons, ExternalDevices.SpikeInjector, cell_params_spike_injector_with_key, label='spike_injector_forward') injector_backward = Frontend.Population( self.n_neurons, ExternalDevices.SpikeInjector, cell_params_spike_injector, label='spike_injector_backward') else: spike_times = [] for _ in range(0, self.n_neurons): spike_times.append([]) spike_times[0] = [0] spike_times[20] = [(run_time / 100) * 20] spike_times[40] = [(run_time / 100) * 40] spike_times[60] = [(run_time / 100) * 60] spike_times[80] = [(run_time / 100) * 80] cell_params_forward = {'spike_times': spike_times} spike_times_backwards = [] for _ in range(0, self.n_neurons): spike_times_backwards.append([]) spike_times_backwards[0] = [(run_time / 100) * 80] spike_times_backwards[20] = [(run_time / 100) * 60] spike_times_backwards[40] = [(run_time / 100) * 40] spike_times_backwards[60] = [(run_time / 100) * 20] spike_times_backwards[80] = [0] cell_params_backward = {'spike_times': spike_times_backwards} injector_forward = Frontend.Population( self.n_neurons, Frontend.SpikeSourceArray, cell_params_forward, label='spike_injector_forward') injector_backward = Frontend.Population( self.n_neurons, Frontend.SpikeSourceArray, cell_params_backward, label='spike_injector_backward') # Create a connection from the injector into the populations Frontend.Projection( injector_forward, pop_forward, Frontend.OneToOneConnector(weights=weight_to_spike)) Frontend.Projection( injector_backward, pop_backward, Frontend.OneToOneConnector(weights=weight_to_spike)) # Synfire chain connections where each neuron is connected to its next # neuron # NOTE: there is no recurrent connection so that each chain stops once # it reaches the end loop_forward = list() loop_backward = list() for i in range(0, self.n_neurons - 1): loop_forward.append((i, (i + 1) % self.n_neurons, weight_to_spike, 3)) loop_backward.append(((i + 1) % self.n_neurons, i, weight_to_spike, 3)) Frontend.Projection(pop_forward, pop_forward, Frontend.FromListConnector(loop_forward)) Frontend.Projection(pop_backward, pop_backward, Frontend.FromListConnector(loop_backward)) # record spikes from the synfire chains so that we can read off valid # results in a safe way afterwards, and verify the behavior pop_forward.record() pop_backward.record() # Activate the sending of live spikes ExternalDevices.activate_live_output_for( pop_forward, database_notify_host="localhost", database_notify_port_num=19996) ExternalDevices.activate_live_output_for( pop_backward, database_notify_host="localhost", database_notify_port_num=19996) if not use_c_visualiser: # if not using the c visualiser, then a new spynnaker live spikes # connection is created to define that there are python code which # receives the outputted spikes. live_spikes_connection_receive = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward", "pop_backward"], local_port=19999, send_labels=None) # Set up callbacks to occur when spikes are received live_spikes_connection_receive.add_receive_callback( "pop_forward", receive_spikes) live_spikes_connection_receive.add_receive_callback( "pop_backward", receive_spikes) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes() spikes_backward = pop_backward.getSpikes() # If there are spikes, plot using matplotlib if len(spikes_forward) != 0 or len(spikes_backward) != 0: pylab.figure() if len(spikes_forward) != 0: pylab.plot([i[1] for i in spikes_forward], [i[0] for i in spikes_forward], "b.") if len(spikes_backward) != 0: pylab.plot([i[1] for i in spikes_backward], [i[0] for i in spikes_backward], "r.") pylab.ylabel('neuron id') pylab.xlabel('Time/ms') pylab.title('spikes') pylab.show() else: print "No spikes received" # Clear data structures on spiNNaker to leave the machine in a clean # state for future executions Frontend.end() if use_spike_injector: p.join()
class ExternalDvsEmulatorDevice(ReverseIpTagMultiCastSource, AbstractProvidesOutgoingConstraints, ): MODE_128 = "128" MODE_64 = "64" MODE_32 = "32" MODE_16 = "16" UP_POLARITY = "UP" DOWN_POLARITY = "DOWN" MERGED_POLARITY = "MERGED" RECTIFIED_POLARITY = "RECTIFIED_POLARITY" POLARITY_DICT = {UP_POLARITY: uint8(0), DOWN_POLARITY: uint8(1), MERGED_POLARITY: uint8(2), RECTIFIED_POLARITY: uint8(3), 0: UP_POLARITY, 1: DOWN_POLARITY, 2: MERGED_POLARITY, 3: RECTIFIED_POLARITY} OUTPUT_RATE = "RATE" OUTPUT_TIME = "TIME" OUTPUT_TIME_BIN = "TIME_BIN" OUTPUT_TIME_BIN_THR = "TIME_BIN_THR" def __init__(self, n_neurons, machine_time_step, timescale_factor, database_socket, label, port=12345, virtual_key=None, spikes_per_second=0, ring_buffer_sigma=None, device_id=0, fps=60, mode="128", scale_img=True, polarity="MERGED", inhibition = False, inh_area_width = 2, threshold=12, adaptive_threshold = False, min_threshold=6, max_threshold=168, threshold_delta_down = 2, threshold_delta_up = 12, output_type="TIME", num_bits_per_spike=4, history_weight=0.99, save_spikes=None, run_time_ms=None, local_port=19876): """ :param device_id: int for webcam modes, or string for video file :param mode: The retina "mode" :param retina_key: The value of the top 16-bits of the key :param polarity: The "polarity" of the retina data :param machine_time_step: The time step of the simulation :param timescale_factor: The timescale factor of the simulation :param label: The label for the population :param n_neurons: The number of neurons in the population """ fixed_n_neurons = n_neurons if mode == ExternalDvsEmulatorDevice.MODE_128 or \ mode == ExternalDvsEmulatorDevice.MODE_64 or \ mode == ExternalDvsEmulatorDevice.MODE_32 or \ mode == ExternalDvsEmulatorDevice.MODE_16: self._out_res = int(mode) self._res_2x = self._out_res*2 else: raise exceptions.SpynnakerException("the model does not " "recongise this mode") if (polarity == ExternalDvsEmulatorDevice.UP_POLARITY or polarity == ExternalDvsEmulatorDevice.DOWN_POLARITY or polarity == ExternalDvsEmulatorDevice.RECTIFIED_POLARITY): fixed_n_neurons = self._out_res**2 else: fixed_n_neurons = 2*(self._out_res**2) if fixed_n_neurons != n_neurons and n_neurons is not None: logger.warn("The specified number of neurons for the DVS emulator" " device has been ignored {} will be used instead" .format(fixed_n_neurons)) self._video_source = None self._device_id = device_id self._is_virtual_cam = False self._polarity = polarity self._polarity_n = ExternalDvsEmulatorDevice.POLARITY_DICT[polarity] self._global_max = int16(0) self._output_type = output_type self._raw_frame = None self._gray_frame = None self._tmp_frame = None self._ref_frame = 128*np.ones((self._out_res, self._out_res), dtype=int16) self._curr_frame = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes_frame = np.zeros((self._out_res, self._out_res, 3), dtype=uint8) self._diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._abs_diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes = np.zeros((self._out_res, self._out_res), dtype=int16) self._adaptive_threshold = adaptive_threshold self._thresh_matrix = None if adaptive_threshold: self._thresh_matrix = np.zeros((self._out_res, self._out_res), dtype=int16) self._threshold_delta_down = int16(threshold_delta_down) self._threshold_delta_up = int16(threshold_delta_up) self._max_threshold = int16(max_threshold) self._min_threshold = int16(min_threshold) self._up_spikes = None self._down_spikes = None self._spikes_lists = None self._threshold = int16(threshold) self._data_shift = uint8(np.log2(self._out_res)) self._up_down_shift = uint8(2*self._data_shift) self._data_mask = uint8(self._out_res - 1) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: self._num_bins = 8 #8-bit images don't need more elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._num_bins = 6 #should be enough? else: self._num_bins = int(1000./fps) self._num_bits_per_spike = min(num_bits_per_spike, self._num_bins) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN or \ self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._log2_table = gs.generate_log2_table(self._num_bits_per_spike, self._num_bins) else: self._log2_table = gs.generate_log2_table(self._num_bits_per_spike, 8) #stupid hack, compatibility issues self._scale_img = scale_img self._img_height = 0 self._img_height_crop_u = 0 self._img_height_crop_b = 0 self._img_width = 0 self._img_width_crop_l = 0 self._img_width_crop_r = 0 self._img_ratio = 0. self._img_scaled_width = 0 self._scaled_width = 0 self._fps = fps self._max_time_ms = 0 self._time_per_frame = 0. self._time_per_spike_pack_ms = 0 self._get_sizes = True self._scale_changed = False self._running = True self._label = label self._n_neurons = fixed_n_neurons self._local_port = local_port self._inh_area_width = inh_area_width self._inhibition = inhibition self._inh_coords = gs.generate_inh_coords(self._out_res, self._out_res, inh_area_width) self._history_weight = history_weight self._run_time_ms = run_time_ms ################################################################ if spinn_version == "2015.005": ReverseIpTagMultiCastSource.__init__(self, n_neurons=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, port=self._local_port, label=self._label, virtual_key=virtual_key) else: ReverseIpTagMultiCastSource.__init__(self, n_keys=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, label=self._label, receive_port=self._local_port, virtual_key=virtual_key) AbstractProvidesOutgoingConstraints.__init__(self) print("number of neurons for webcam = %d"%self._n_neurons) self._live_conn = SpynnakerLiveSpikesConnection(send_labels = [self._label, ], local_port = self._local_port) def init(label, n_neurons, run_time_ms, machine_timestep_ms): print("Sending %d neuron sources from %s"%(n_neurons, label)) self._live_conn.add_init_callback(self._label, init) self._live_conn.add_start_callback(self._label, self.run) self._sender = None self._save_spikes = save_spikes def get_outgoing_edge_constraints(self, partitioned_edge, graph_mapper): constraints = ReverseIpTagMultiCastSource\ .get_outgoing_edge_constraints( self, partitioned_edge, graph_mapper) constraints.append(KeyAllocatorContiguousRangeContraint()) return constraints def get_number_of_mallocs_used_by_dsg(self, vertex_slice, in_edges): mallocs = \ ReverseIpTagMultiCastSource.get_number_of_mallocs_used_by_dsg( self, vertex_slice, in_edges) if config.getboolean("SpecExecution", "specExecOnHost"): return 1 else: return mallocs def __del__(self): self._running = False def stop(self): self.__del__() def run(self, label, sender): self._label = label self._sender = sender if self._run_time_ms is None: max_run_time_s = self.no_machine_time_steps/float(self.machine_time_step) - 0.5 else: max_run_time_s = self._run_time_ms/1000. self.acquire_device() spike_queue = Queue() spike_emmision_proc = Process(target=self.send_spikes, args=(spike_queue,)) spike_emmision_proc.start() img_queue = Queue() #~ spike_gen_proc = Process(target=self.process_frame, args=(img_queue,)) spike_gen_proc = Process(target=self.process_frame, args=(img_queue, spike_queue)) spike_gen_proc.start() grab_times = [] start_time = 0. app_start_time = time.time() app_curr_time = time.time() first_frame = True frame_time = 0. while self._running: start_time = time.time() valid_frame = self.grab_frame() grab_times.append(time.time() - start_time) if not valid_frame: self._running = False # send the minimum difference value once to synchronize time-based # decoding on the receiver end if self._output_type != ExternalDvsEmulatorDevice.OUTPUT_RATE and \ first_frame == True: first_frame = False self._curr_frame[:] = 128 + self._threshold + 1 #half range of vals + thresh + 1 img_queue.put(self._curr_frame) app_curr_time = time.time() if app_curr_time - app_start_time > max_run_time_s: self._running = False frame_time = time.time() - start_time if frame_time < self._time_per_frame: time.sleep(self._time_per_frame - frame_time) print("webcam runtime ", app_curr_time - app_start_time) img_queue.put(None) spike_gen_proc.join() spike_queue.put(None) spike_emmision_proc.join() if self._video_source is not None: self._video_source.release() cv2.destroyAllWindows() def process_frame(self, img_queue, spike_queue): label = self._label spikes_frame = self._spikes_frame cv2.namedWindow (label) cv2.startWindowThread() res2x = self._res_2x spike_list = [] # gen_times = [] # compose_times = [] # transform_times = [] # ref_up_times = [] lists = None while True: image = img_queue.get() if image is None or not self._running: break # start_time = time.time() self.generate_spikes(image) # gen_times.append(time.time()-start_time) # start_time = time.time() self.update_reference() # ref_up_times.append(time.time()-start_time) # start_time = time.time() lists = self.transform_spikes() # transform_times.append(time.time() - start_time) spike_queue.put(lists) if self._save_spikes is not None: spike_list.append(lists) # start_time = time.time() self.compose_output_frame() # compose_times.append(time.time()-start_time) cv2.imshow( label, cv2.resize(spikes_frame, (res2x, res2x)) ) if cv2.waitKey(1) & 0xFF == ord('q'):#\ #or not sender.isAlive(): self._running = False break #continue # print("gen times") # print(np.array(gen_times).mean()) # print("update ref times") # print(np.array(ref_up_times).mean()) # print("transform times") # print(np.array(transform_times).mean()) # print("compose times") # print(np.array(compose_times).mean()) cv2.destroyAllWindows() cv2.waitKey(1) if self._save_spikes is not None: #print spike_list print("attempting to save spike_list") pickle.dump( spike_list, open(self._save_spikes, "wb") ) def send_spikes(self, spike_queue): sender = self._sender while True: spikes = spike_queue.get() if spikes is None or not self._running: break self.emit_spikes(sender, spikes) def acquire_device(self): if isinstance(self._device_id, VirtualCam): self._video_source = self._device_id self._is_virtual_cam = True else: self._video_source = cv2.VideoCapture(self._device_id) if not self._video_source.isOpened(): self._video_source.open() try: self._video_source.set(cv2.CAP_PROP_FRAME_WIDTH, 320) self._video_source.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) except: pass try: self._video_source.set(cv2.CAP_PROP_FPS, self._fps) except: self._fps = self._video_source.get(cv2.CAP_PROP_FPS) self._max_time_ms = int16((1./self._fps)*1000) self._time_per_frame = 1./self._fps self._time_per_spike_pack_ms = self.calculate_time_per_pack() def grab_frame(self): #~ start_time = time.time() if self._is_virtual_cam: valid_frame, self._curr_frame[:] = self._video_source.read(self._ref_frame) return True else: if self._raw_frame is None or self._scale_changed: valid_frame, self._raw_frame = self._video_source.read() else: valid_frame, self._raw_frame[:] = self._video_source.read() #~ end_time = time.time() #~ print("Time to capture frame = ", end_time - start_time) if not valid_frame: return False #~ start_time = time.time() if self._gray_frame is None or self._scale_changed: self._gray_frame = cv2.convertColor(self._raw_frame, cv2.COLOR_BGR2GRAY).astype(int16) else: self._gray_frame[:] = cv2.convertColor(self._raw_frame, cv2.COLOR_BGR2GRAY) #~ end_time = time.time() #~ print("Time to convert to grayscale = ", end_time - start_time) #~ start_time = time.time() if self._get_sizes or self._scale_changed: self._get_sizes = False self._scale_changed = False self._img_height, self._img_width = self._gray_frame.shape self._img_ratio = float(self._img_width)/float(self._img_height) self._img_scaled_width = int(float(self._out_res)*self._img_ratio) if self._scale_img: diff = self._img_scaled_width - self._out_res self._img_width_crop_l = diff//2 self._img_width_crop_r = self._img_width_crop_l + self._out_res else: diff = self._img_width - self._out_res self._img_width_crop_l = diff//2 self._img_width_crop_r = self._img_width_crop_l + self._out_res diff = self._img_height - self._out_res self._img_height_crop_u = diff//2 self._img_height_crop_b = self._img_height_crop_u + self._out_res self._tmp_frame = np.zeros((self._out_res, self._img_scaled_width)) #~ end_time = time.time() #~ print("Time to calculate sizes = ", end_time - start_time) #~ start_time = time.time() if self._scale_img: self._tmp_frame[:] = cv2.resize(self._gray_frame, (self._img_scaled_width, self._out_res), interpolation=cv2.INTER_NN) self._curr_frame[:] = self._tmp_frame[:, self._img_width_crop_l: self._img_width_crop_r] else: self._curr_frame[:] = self._gray_frame[self._img_height_crop_u: self._img_height_crop_b, self._img_width_crop_l: self._img_width_crop_r] #~ end_time = time.time() #~ print("Time to scale frame = ", end_time - start_time) return True def emit_spikes(self, sender, lists): lbl = self._label max_time_s = self._time_per_spike_pack_ms/1000. #~ lists = self._spikes_lists send_spikes = sender.send_spikes #from generate_spikes.pyx (cython) if lists is not None: for spike_pack in lists: start_time = time.time() send_spikes(lbl, spike_pack, send_full_keys=False) elapsed_time = time.time() - start_time if elapsed_time < max_time_s: time.sleep(max_time_s - elapsed_time) def generate_spikes(self, image): self._curr_frame = image curr_frame = self._curr_frame #~ curr_frame = image ref_frame = self._ref_frame diff = self._diff abs_diff = self._abs_diff spikes = self._spikes img_w = self._out_res inh_w = self._inh_area_width inhibition = self._inhibition inh_coords = self._inh_coords threshold = self._threshold if self._adaptive_threshold: thresh_mat = self._thresh_matrix #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = gs.thresholded_difference_adpt(curr_frame, ref_frame, thresh_mat) else: #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = gs.thresholded_difference(curr_frame, ref_frame, threshold) if inhibition: spikes[:] = gs.local_inhibition(spikes, abs_diff, inh_coords, img_w, img_w, inh_w) def update_reference(self): abs_diff = self._abs_diff spikes = self._spikes ref_frame = self._ref_frame min_thresh = self._min_threshold max_thresh = self._max_threshold threshold = self._threshold max_time_ms = self._max_time_ms history_weight = self._history_weight num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits-1] #no values for 0-bit encoding if self._adaptive_threshold: thresh_mat = self._thresh_matrix thresh_delta_down = self._threshold_delta_down thresh_delta_up = self._threshold_delta_up ref_frame[:], thresh_mat[:] = gs.update_reference_rate_adpt(abs_diff, spikes, ref_frame, thresh_mat, min_thresh, max_thresh, thresh_delta_down, thresh_delta_up, max_time_ms, history_weight) else: if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: ref_frame[:] = gs.update_reference_rate(abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: ref_frame[:] = gs.update_reference_time_thresh(abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: ref_frame[:] = gs.update_reference_time_binary_raw(abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: ref_frame[:] = gs.update_reference_time_binary_thresh(abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) def transform_spikes(self): data_shift = self._data_shift up_down_shift = self._up_down_shift data_mask = self._data_mask polarity = self._polarity_n spikes = self._spikes threshold = self._threshold max_thresh = self._max_threshold #~ lists = self._spikes_lists max_time_ms = self._max_time_ms abs_diff = self._abs_diff num_bins = self._num_bins num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits - 1] dn_spks, up_spks, g_max = gs.split_spikes(spikes, abs_diff, polarity) lists = None #from generate_spikes.pyx (cython) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: lists = gs.make_spike_lists_rate(up_spks, dn_spks, g_max, threshold, up_down_shift, data_shift, data_mask, max_time_ms) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: lists = gs.make_spike_lists_time(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, num_bins, max_time_ms, threshold, max_thresh) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: lists = gs.make_spike_lists_time_bin(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, threshold, max_thresh, num_bins, log2_table) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: lists = gs.make_spike_lists_time_bin_thr(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, threshold, max_thresh, num_bins, log2_table) return lists def compose_output_frame(self): curr_frame = self._curr_frame spikes_frame = self._spikes_frame spikes = self._spikes width = self._out_res height = self._out_res polarity = self._polarity_n #from generate_spikes.pyx (cython) spikes_frame[:] = gs.render_frame(spikes=spikes, curr_frame=curr_frame, width=width, height=height, polarity=polarity) def calculate_time_per_pack(self): time_per_pack = 0 if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: time_per_pack = 1 elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: time_per_pack = (self._max_time_ms)// \ (min(self._max_time_ms, self._max_threshold//self._min_threshold + 1)) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: time_per_pack = (self._max_time_ms)//(8) #raw difference value could be 8-bit else: time_per_pack = (self._max_time_ms)//(self._num_bits_per_spike + 1) return time_per_pack
# Activate the sending of live spikes ExternalDevices.activate_live_output_for(pop_forward, database_notify_host="localhost", database_notify_port_num=19996) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print "Received spike at time", time, "from", label, "-", neuron_id # if not using the c visualiser, then a new spynnaker live spikes connection # is created to define that there are python code which receives the # outputted spikes. live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward"], local_port=19996, send_labels=None) # Set up callbacks to occur when spikes are received live_spikes_connection.add_receive_callback("pop_forward", receive_spikes) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes() # If there are spikes, plot using matplotlib if len(spikes_forward) != 0: pylab.figure() if len(spikes_forward) != 0: pylab.plot([i[1] for i in spikes_forward], [i[0] for i in spikes_forward], "b.") pylab.ylabel('neuron id') pylab.xlabel('Time/ms') pylab.title('spikes')
} pop_forward = Frontend.Population(n_neurons, Frontend.IF_curr_exp, cell_params_lif, label="pop_forward") pop_forward.record() injector_forward = Frontend.Population( n_neurons, ExternalDevices.SpikeInjector, cell_params_spike_injector, label="spike_injector_forward" ) Frontend.Projection(injector_forward, pop_forward, Frontend.OneToOneConnector(weights=weight_to_spike)) live_spikes_connection_send = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=board_port, send_labels=["spike_injector_forward"] ) live_spikes_connection_send.add_init_callback("spike_injector_forward", init_pop) live_spikes_connection_send.add_start_callback("spike_injector_forward", send_input_forward) Frontend.run(run_time) spikes_forward = pop_forward.getSpikes() sorted_spikes = sorted(spikes_forward, key=lambda x: x[1]) for i in range(len(sorted_spikes) - 1): print sorted_spikes[i][1], ", ", sorted_spikes[i][0], ", ", sorted_spikes[i + 1][1] - sorted_spikes[i][1]
tNext = retinasSpikes[index+1][0] if r == 1: send_spike_retina("ret_right", liveConnectionRetina) else: send_spike_retina("ret_left", liveConnectionRetina) time.sleep((tNext - t)/1000.0) def init_thread(label, sender): if label == "ret_left": sender_thread = Thread(target=threadLeft_run, args=(sender,)) sender_thread.start() else: sender_thread = Thread(target=threadRight_run, args=(sender,)) sender_thread.start() live_spikes_connection_receiver = SpynnakerLiveSpikesConnection(receive_labels=["collector", "inh_left", "inh_right"], local_port=19996, send_labels=None) live_spikes_connection_receiver.add_receive_callback("collector", receive_spike_cell) live_spikes_connection_receiver.add_receive_callback("inh_left", receive_spike_cell) live_spikes_connection_receiver.add_receive_callback("inh_right", receive_spike_cell) live_spikes_connection_sender = SpynnakerLiveSpikesConnection(receive_labels=None, local_port=19999, send_labels=["ret_right", "ret_left"]) # Set up callbacks to occur at the start of simulation # live_spikes_connection_sender.add_start_callback("ret_left", init_thread) live_spikes_connection_sender.add_start_callback("ret_right", init_thread) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_collector = collector.getSpikes() print "Spikes count collector: ", len(spikes_collector)
class ExternalDvsEmulatorDevice( ReverseIpTagMultiCastSource, AbstractProvidesOutgoingConstraints, ): MODE_128 = "128" MODE_64 = "64" MODE_32 = "32" MODE_16 = "16" UP_POLARITY = "UP" DOWN_POLARITY = "DOWN" MERGED_POLARITY = "MERGED" RECTIFIED_POLARITY = "RECTIFIED_POLARITY" POLARITY_DICT = { UP_POLARITY: uint8(0), DOWN_POLARITY: uint8(1), MERGED_POLARITY: uint8(2), RECTIFIED_POLARITY: uint8(3), 0: UP_POLARITY, 1: DOWN_POLARITY, 2: MERGED_POLARITY, 3: RECTIFIED_POLARITY } OUTPUT_RATE = "RATE" OUTPUT_TIME = "TIME" OUTPUT_TIME_BIN = "TIME_BIN" OUTPUT_TIME_BIN_THR = "TIME_BIN_THR" def __init__(self, n_neurons, machine_time_step, timescale_factor, database_socket, label, port=12345, virtual_key=None, spikes_per_second=0, ring_buffer_sigma=None, device_id=0, fps=60, mode="128", scale_img=True, polarity="MERGED", inhibition=False, inh_area_width=2, threshold=12, adaptive_threshold=False, min_threshold=6, max_threshold=168, threshold_delta_down=2, threshold_delta_up=12, output_type="TIME", num_bits_per_spike=4, history_weight=0.99, save_spikes=None, run_time_ms=None, local_port=19876): """ :param device_id: int for webcam modes, or string for video file :param mode: The retina "mode" :param retina_key: The value of the top 16-bits of the key :param polarity: The "polarity" of the retina data :param machine_time_step: The time step of the simulation :param timescale_factor: The timescale factor of the simulation :param label: The label for the population :param n_neurons: The number of neurons in the population """ fixed_n_neurons = n_neurons if mode == ExternalDvsEmulatorDevice.MODE_128 or \ mode == ExternalDvsEmulatorDevice.MODE_64 or \ mode == ExternalDvsEmulatorDevice.MODE_32 or \ mode == ExternalDvsEmulatorDevice.MODE_16: self._out_res = int(mode) self._res_2x = self._out_res * 2 else: raise exceptions.SpynnakerException("the model does not " "recongise this mode") if (polarity == ExternalDvsEmulatorDevice.UP_POLARITY or polarity == ExternalDvsEmulatorDevice.DOWN_POLARITY or polarity == ExternalDvsEmulatorDevice.RECTIFIED_POLARITY): fixed_n_neurons = self._out_res**2 else: fixed_n_neurons = 2 * (self._out_res**2) if fixed_n_neurons != n_neurons and n_neurons is not None: logger.warn( "The specified number of neurons for the DVS emulator" " device has been ignored {} will be used instead".format( fixed_n_neurons)) self._video_source = None self._device_id = device_id self._is_virtual_cam = False self._polarity = polarity self._polarity_n = ExternalDvsEmulatorDevice.POLARITY_DICT[polarity] self._global_max = int16(0) self._output_type = output_type self._raw_frame = None self._gray_frame = None self._tmp_frame = None self._ref_frame = 128 * np.ones( (self._out_res, self._out_res), dtype=int16) self._curr_frame = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes_frame = np.zeros((self._out_res, self._out_res, 3), dtype=uint8) self._diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._abs_diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes = np.zeros((self._out_res, self._out_res), dtype=int16) self._adaptive_threshold = adaptive_threshold self._thresh_matrix = None if adaptive_threshold: self._thresh_matrix = np.zeros((self._out_res, self._out_res), dtype=int16) self._threshold_delta_down = int16(threshold_delta_down) self._threshold_delta_up = int16(threshold_delta_up) self._max_threshold = int16(max_threshold) self._min_threshold = int16(min_threshold) self._up_spikes = None self._down_spikes = None self._spikes_lists = None self._threshold = int16(threshold) self._data_shift = uint8(np.log2(self._out_res)) self._up_down_shift = uint8(2 * self._data_shift) self._data_mask = uint8(self._out_res - 1) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: self._num_bins = 8 #8-bit images don't need more elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._num_bins = 6 #should be enough? else: self._num_bins = int(1000. / fps) self._num_bits_per_spike = min(num_bits_per_spike, self._num_bins) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN or \ self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._log2_table = gs.generate_log2_table(self._num_bits_per_spike, self._num_bins) else: self._log2_table = gs.generate_log2_table( self._num_bits_per_spike, 8) #stupid hack, compatibility issues self._scale_img = scale_img self._img_height = 0 self._img_height_crop_u = 0 self._img_height_crop_b = 0 self._img_width = 0 self._img_width_crop_l = 0 self._img_width_crop_r = 0 self._img_ratio = 0. self._img_scaled_width = 0 self._scaled_width = 0 self._fps = fps self._max_time_ms = 0 self._time_per_frame = 0. self._time_per_spike_pack_ms = 0 self._get_sizes = True self._scale_changed = False self._running = True self._label = label self._n_neurons = fixed_n_neurons self._local_port = local_port self._inh_area_width = inh_area_width self._inhibition = inhibition self._inh_coords = gs.generate_inh_coords(self._out_res, self._out_res, inh_area_width) self._history_weight = history_weight self._run_time_ms = run_time_ms ################################################################ if spinn_version == "2015.005": ReverseIpTagMultiCastSource.__init__( self, n_neurons=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, port=self._local_port, label=self._label, virtual_key=virtual_key) else: ReverseIpTagMultiCastSource.__init__( self, n_keys=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, label=self._label, receive_port=self._local_port, virtual_key=virtual_key) AbstractProvidesOutgoingConstraints.__init__(self) print("number of neurons for webcam = %d" % self._n_neurons) self._live_conn = SpynnakerLiveSpikesConnection( send_labels=[ self._label, ], local_port=self._local_port) def init(label, n_neurons, run_time_ms, machine_timestep_ms): print("Sending %d neuron sources from %s" % (n_neurons, label)) self._live_conn.add_init_callback(self._label, init) self._live_conn.add_start_callback(self._label, self.run) self._sender = None self._save_spikes = save_spikes def get_outgoing_edge_constraints(self, partitioned_edge, graph_mapper): constraints = ReverseIpTagMultiCastSource\ .get_outgoing_edge_constraints( self, partitioned_edge, graph_mapper) constraints.append(KeyAllocatorContiguousRangeContraint()) return constraints def get_number_of_mallocs_used_by_dsg(self, vertex_slice, in_edges): mallocs = \ ReverseIpTagMultiCastSource.get_number_of_mallocs_used_by_dsg( self, vertex_slice, in_edges) if config.getboolean("SpecExecution", "specExecOnHost"): return 1 else: return mallocs def __del__(self): self._running = False def stop(self): self.__del__() def run(self, label, sender): self._label = label self._sender = sender if self._run_time_ms is None: max_run_time_s = self.no_machine_time_steps / float( self.machine_time_step) - 0.5 else: max_run_time_s = self._run_time_ms / 1000. self.acquire_device() spike_queue = Queue() spike_emmision_proc = Process(target=self.send_spikes, args=(spike_queue, )) spike_emmision_proc.start() img_queue = Queue() #~ spike_gen_proc = Process(target=self.process_frame, args=(img_queue,)) spike_gen_proc = Process(target=self.process_frame, args=(img_queue, spike_queue)) spike_gen_proc.start() grab_times = [] start_time = 0. app_start_time = time.time() app_curr_time = time.time() first_frame = True frame_time = 0. while self._running: start_time = time.time() valid_frame = self.grab_frame() grab_times.append(time.time() - start_time) if not valid_frame: self._running = False # send the minimum difference value once to synchronize time-based # decoding on the receiver end if self._output_type != ExternalDvsEmulatorDevice.OUTPUT_RATE and \ first_frame == True: first_frame = False self._curr_frame[:] = 128 + self._threshold + 1 #half range of vals + thresh + 1 img_queue.put(self._curr_frame) app_curr_time = time.time() if app_curr_time - app_start_time > max_run_time_s: self._running = False frame_time = time.time() - start_time if frame_time < self._time_per_frame: time.sleep(self._time_per_frame - frame_time) print("webcam runtime ", app_curr_time - app_start_time) img_queue.put(None) spike_gen_proc.join() spike_queue.put(None) spike_emmision_proc.join() if self._video_source is not None: self._video_source.release() cv2.destroyAllWindows() def process_frame(self, img_queue, spike_queue): label = self._label spikes_frame = self._spikes_frame cv2.namedWindow(label) cv2.startWindowThread() res2x = self._res_2x spike_list = [] # gen_times = [] # compose_times = [] # transform_times = [] # ref_up_times = [] lists = None while True: image = img_queue.get() if image is None or not self._running: break # start_time = time.time() self.generate_spikes(image) # gen_times.append(time.time()-start_time) # start_time = time.time() self.update_reference() # ref_up_times.append(time.time()-start_time) # start_time = time.time() lists = self.transform_spikes() # transform_times.append(time.time() - start_time) spike_queue.put(lists) if self._save_spikes is not None: spike_list.append(lists) # start_time = time.time() self.compose_output_frame() # compose_times.append(time.time()-start_time) cv2.imshow(label, cv2.resize(spikes_frame, (res2x, res2x))) if cv2.waitKey(1) & 0xFF == ord('q'): #\ #or not sender.isAlive(): self._running = False break #continue # print("gen times") # print(np.array(gen_times).mean()) # print("update ref times") # print(np.array(ref_up_times).mean()) # print("transform times") # print(np.array(transform_times).mean()) # print("compose times") # print(np.array(compose_times).mean()) cv2.destroyAllWindows() cv2.waitKey(1) if self._save_spikes is not None: #print spike_list print("attempting to save spike_list") pickle.dump(spike_list, open(self._save_spikes, "wb")) def send_spikes(self, spike_queue): sender = self._sender while True: spikes = spike_queue.get() if spikes is None or not self._running: break self.emit_spikes(sender, spikes) def acquire_device(self): if isinstance(self._device_id, VirtualCam): self._video_source = self._device_id self._is_virtual_cam = True else: self._video_source = cv2.VideoCapture(self._device_id) if not self._video_source.isOpened(): self._video_source.open() try: self._video_source.set(cv2.CAP_PROP_FRAME_WIDTH, 320) self._video_source.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) except: pass try: self._video_source.set(cv2.CAP_PROP_FPS, self._fps) except: self._fps = self._video_source.get(cv2.CAP_PROP_FPS) self._max_time_ms = int16((1. / self._fps) * 1000) self._time_per_frame = 1. / self._fps self._time_per_spike_pack_ms = self.calculate_time_per_pack() def grab_frame(self): #~ start_time = time.time() if self._is_virtual_cam: valid_frame, self._curr_frame[:] = self._video_source.read( self._ref_frame) return True else: if self._raw_frame is None or self._scale_changed: valid_frame, self._raw_frame = self._video_source.read() else: valid_frame, self._raw_frame[:] = self._video_source.read() #~ end_time = time.time() #~ print("Time to capture frame = ", end_time - start_time) if not valid_frame: return False #~ start_time = time.time() if self._gray_frame is None or self._scale_changed: self._gray_frame = cv2.convertColor( self._raw_frame, cv2.COLOR_BGR2GRAY).astype(int16) else: self._gray_frame[:] = cv2.convertColor(self._raw_frame, cv2.COLOR_BGR2GRAY) #~ end_time = time.time() #~ print("Time to convert to grayscale = ", end_time - start_time) #~ start_time = time.time() if self._get_sizes or self._scale_changed: self._get_sizes = False self._scale_changed = False self._img_height, self._img_width = self._gray_frame.shape self._img_ratio = float(self._img_width) / float( self._img_height) self._img_scaled_width = int( float(self._out_res) * self._img_ratio) if self._scale_img: diff = self._img_scaled_width - self._out_res self._img_width_crop_l = diff // 2 self._img_width_crop_r = self._img_width_crop_l + self._out_res else: diff = self._img_width - self._out_res self._img_width_crop_l = diff // 2 self._img_width_crop_r = self._img_width_crop_l + self._out_res diff = self._img_height - self._out_res self._img_height_crop_u = diff // 2 self._img_height_crop_b = self._img_height_crop_u + self._out_res self._tmp_frame = np.zeros( (self._out_res, self._img_scaled_width)) #~ end_time = time.time() #~ print("Time to calculate sizes = ", end_time - start_time) #~ start_time = time.time() if self._scale_img: self._tmp_frame[:] = cv2.resize( self._gray_frame, (self._img_scaled_width, self._out_res), interpolation=cv2.INTER_NN) self._curr_frame[:] = self._tmp_frame[:, self._img_width_crop_l: self._img_width_crop_r] else: self._curr_frame[:] = self._gray_frame[ self._img_height_crop_u:self._img_height_crop_b, self._img_width_crop_l:self._img_width_crop_r] #~ end_time = time.time() #~ print("Time to scale frame = ", end_time - start_time) return True def emit_spikes(self, sender, lists): lbl = self._label max_time_s = self._time_per_spike_pack_ms / 1000. #~ lists = self._spikes_lists send_spikes = sender.send_spikes #from generate_spikes.pyx (cython) if lists is not None: for spike_pack in lists: start_time = time.time() send_spikes(lbl, spike_pack, send_full_keys=False) elapsed_time = time.time() - start_time if elapsed_time < max_time_s: time.sleep(max_time_s - elapsed_time) def generate_spikes(self, image): self._curr_frame = image curr_frame = self._curr_frame #~ curr_frame = image ref_frame = self._ref_frame diff = self._diff abs_diff = self._abs_diff spikes = self._spikes img_w = self._out_res inh_w = self._inh_area_width inhibition = self._inhibition inh_coords = self._inh_coords threshold = self._threshold if self._adaptive_threshold: thresh_mat = self._thresh_matrix #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = gs.thresholded_difference_adpt( curr_frame, ref_frame, thresh_mat) else: #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = gs.thresholded_difference( curr_frame, ref_frame, threshold) if inhibition: spikes[:] = gs.local_inhibition(spikes, abs_diff, inh_coords, img_w, img_w, inh_w) def update_reference(self): abs_diff = self._abs_diff spikes = self._spikes ref_frame = self._ref_frame min_thresh = self._min_threshold max_thresh = self._max_threshold threshold = self._threshold max_time_ms = self._max_time_ms history_weight = self._history_weight num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits - 1] #no values for 0-bit encoding if self._adaptive_threshold: thresh_mat = self._thresh_matrix thresh_delta_down = self._threshold_delta_down thresh_delta_up = self._threshold_delta_up ref_frame[:], thresh_mat[:] = gs.update_reference_rate_adpt( abs_diff, spikes, ref_frame, thresh_mat, min_thresh, max_thresh, thresh_delta_down, thresh_delta_up, max_time_ms, history_weight) else: if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: ref_frame[:] = gs.update_reference_rate( abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: ref_frame[:] = gs.update_reference_time_thresh( abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: ref_frame[:] = gs.update_reference_time_binary_raw( abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: ref_frame[:] = gs.update_reference_time_binary_thresh( abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) def transform_spikes(self): data_shift = self._data_shift up_down_shift = self._up_down_shift data_mask = self._data_mask polarity = self._polarity_n spikes = self._spikes threshold = self._threshold max_thresh = self._max_threshold #~ lists = self._spikes_lists max_time_ms = self._max_time_ms abs_diff = self._abs_diff num_bins = self._num_bins num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits - 1] dn_spks, up_spks, g_max = gs.split_spikes(spikes, abs_diff, polarity) lists = None #from generate_spikes.pyx (cython) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: lists = gs.make_spike_lists_rate(up_spks, dn_spks, g_max, threshold, up_down_shift, data_shift, data_mask, max_time_ms) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: lists = gs.make_spike_lists_time(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, num_bins, max_time_ms, threshold, max_thresh) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: lists = gs.make_spike_lists_time_bin(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, threshold, max_thresh, num_bins, log2_table) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: lists = gs.make_spike_lists_time_bin_thr(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, threshold, max_thresh, num_bins, log2_table) return lists def compose_output_frame(self): curr_frame = self._curr_frame spikes_frame = self._spikes_frame spikes = self._spikes width = self._out_res height = self._out_res polarity = self._polarity_n #from generate_spikes.pyx (cython) spikes_frame[:] = gs.render_frame(spikes=spikes, curr_frame=curr_frame, width=width, height=height, polarity=polarity) def calculate_time_per_pack(self): time_per_pack = 0 if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_RATE: time_per_pack = 1 elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME: time_per_pack = (self._max_time_ms)// \ (min(self._max_time_ms, self._max_threshold//self._min_threshold + 1)) elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: time_per_pack = (self._max_time_ms) // ( 8) #raw difference value could be 8-bit else: time_per_pack = (self._max_time_ms) // (self._num_bits_per_spike + 1) return time_per_pack
print_condition.acquire() print "Sending forward spike for neuron 0" print_condition.release() sender.send_spike(label, 0) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print_condition.acquire() print "Received spike at time", time, "from", label, "-", neuron_id print_condition.release() if neuron_id == 0 and label== "pop_backward_parrot": live_spikes_connection.send_spike("spike_injector_forward", 0) elif neuron_id == 99 and label== "pop_forward_parrot": live_spikes_connection.send_spike("spike_injector_forward", 1) # Set up the live connection for sending spikes live_spikes_connection = SpynnakerLiveSpikesConnection( local_port=19996, send_labels=["spike_injector_forward"]) # Set up the live connection for sending spikes to closed loop live_spikes_connection_receiver = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward_parrot", "pop_backward_parrot"], local_port=19995) # Set up callbacks to occur at the start of simulation live_spikes_connection.add_start_callback("spike_injector_forward", send_input_forward) # Set up callbacks to occur when spikes are received live_spikes_connection_receiver.add_receive_callback("pop_forward_parrot", receive_spikes) live_spikes_connection_receiver.add_receive_callback("pop_backward_parrot", receive_spikes) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes()
# record spikes from the synfire chains so that we can read off valid results # in a safe way afterwards, and verify the behavior pop_forward.record() # Activate the sending of live spikes ExternalDevices.activate_live_output_for( pop_forward, database_notify_host="localhost", database_notify_port_num=19996) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print "Received spike at time", time, "from", label, "-", neuron_id # if not using the c visualiser, then a new spynnaker live spikes connection # is created to define that there are python code which receives the # outputted spikes. live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward"], local_port=19996, send_labels=None) # Set up callbacks to occur when spikes are received live_spikes_connection.add_receive_callback("pop_forward", receive_spikes) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes() # If there are spikes, plot using matplotlib if len(spikes_forward) != 0: pylab.figure() if len(spikes_forward) != 0: pylab.plot([i[1] for i in spikes_forward], [i[0] for i in spikes_forward], "b.") pylab.ylabel('neuron id') pylab.xlabel('Time/ms')
add_spikes(full_input_spikes, input_spikes[n][in_id], silence=period_length*2) input_layer = {} #~ for i in xrange(len(input_spikes)): #~ input_layer[i] = sim.Population(img_neurons, sim.SpikeSourceArray, #~ {"spike_times": input_spikes[i]}, #~ structure=grid) input_layer[in_id] = sim.Population(img_neurons, inj_cell_type, inj_cell_params, label="spike_injector") live_spikes_connection_send = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=["spike_injector"]) live_spikes_connection_send.add_start_callback("spike_injector", send_input) #~ input_layer[in_id] = sim.Population(img_neurons, sim.SpikeSourceArray, #~ {"spike_times": input_spikes[in_id]} #~ ) learn_layer = {} learn_layer['exc'] = sim.Population(num_exc+1, neuron_model, cell_params_izk_exc, label="Learn layer - exc") learn_layer['inh'] = sim.Population(num_inh+1, neuron_model, cell_params_izk_inh, label="Learn layer - inh")
def _connect_spike_sources(self, retinae=None, verbose=False): if verbose: print "INFO: Connecting Spike Sources to Network." global _retina_proj_l, _retina_proj_r # left is 0--dimensionRetinaY-1; right is dimensionRetinaY--dimensionRetinaY*2-1 connListRetLBlockerL = [] connListRetLBlockerR = [] connListRetRBlockerL = [] connListRetRBlockerR = [] for y in range(0, self.dim_y): connListRetLBlockerL.append( (y, y, self.cell_params['synaptic']['wSaB'], self.cell_params['synaptic']['dSaB'])) connListRetLBlockerR.append( (y, y + self.dim_y, self.cell_params['synaptic']['wSzB'], self.cell_params['synaptic']['dSzB'])) connListRetRBlockerL.append( (y, y, self.cell_params['synaptic']['wSzB'], self.cell_params['synaptic']['dSzB'])) connListRetRBlockerR.append( (y, y + self.dim_y, self.cell_params['synaptic']['wSaB'], self.cell_params['synaptic']['dSaB'])) retinaLeft = retinae['left'].pixel_columns retinaRight = retinae['right'].pixel_columns pixel = 0 for row in _retina_proj_l: for pop in row: ps.Projection(retinaLeft[pixel], self.network[pop][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wSC'], delays=self.cell_params['synaptic']['dSC']), target='excitatory') ps.Projection(retinaLeft[pixel], self.network[pop][0], ps.FromListConnector(connListRetLBlockerL), target='excitatory') ps.Projection(retinaLeft[pixel], self.network[pop][0], ps.FromListConnector(connListRetLBlockerR), target='inhibitory') pixel += 1 pixel = 0 for col in _retina_proj_r: for pop in col: ps.Projection(retinaRight[pixel], self.network[pop][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wSC'], delays=self.cell_params['synaptic']['dSC']), target='excitatory') ps.Projection(retinaRight[pixel], self.network[pop][0], ps.FromListConnector(connListRetRBlockerR), target='excitatory') ps.Projection(retinaRight[pixel], self.network[pop][0], ps.FromListConnector(connListRetRBlockerL), target='inhibitory') pixel += 1 # configure for the live input streaming if desired if not (retinae['left'].use_prerecorded_input and retinae['right'].use_prerecorded_input): from spynnaker_external_devices_plugin.pyNN.connections.spynnaker_live_spikes_connection import \ SpynnakerLiveSpikesConnection all_retina_labels = retinaLeft.labels + retinaRight.labels self.live_connection_sender = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=all_retina_labels) # this callback will be executed right after simulation.run() has been called. If simply a while True # is put there, the main thread will stuck there and will not complete the simulation. # One solution might be to start a thread/process which runs a "while is_running:" loop unless the main thread # sets the "is_running" to False. self.live_connection_sender.add_start_callback( all_retina_labels[0], self.start_injecting) import DVSReader as dvs # the port numbers might well be wrong self.dvs_stream_left = dvs.DVSReader( port=0, label=retinaLeft.label, live_connection=self.live_connection_sender) self.dvs_stream_right = dvs.DVSReader( port=1, label=retinaRight.label, live_connection=self.live_connection_sender) # start the threads, i.e. start reading from the DVS. However, nothing will be sent to the SNN. # See start_injecting self.dvs_stream_left.start() self.dvs_stream_right.start()
class GUI(object): """ simple gui to demostrate live inejction of the spike io script. """ def __init__(self, n_neurons): """ creates the gui :return: """ self._started = False # Set up the live connection for sending and receiving spikes self.live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19996, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation self.live_spikes_connection.add_start_callback( "spike_injector_forward", self.send_input_forward) root = tk.Tk() root.title("Injecting Spikes GUI") label = tk.Label(root, fg="dark green") label.pack() neuron_id_value = tk.IntVar() self.neuron_id = tk.Spinbox(root, from_=0, to=n_neurons - 1, textvariable=neuron_id_value) self.neuron_id.pack() pop_label_value = tk.StringVar() self.pop_label = tk.Spinbox(root, textvariable=pop_label_value, values=("spike_injector_forward", "spike_injector_backward")) self.pop_label.pack() button = tk.Button(root, text='Inject', width=25, command=self.inject_spike) button.pack() root.mainloop() # Create a sender of packets for the forward population def send_input_forward(self, pop_label, _): """ records that stuff has started on the spinnaker machine :param pop_label: label :param _: dont care :return: """ self._started = True # add a gui with a button and scroll list def inject_spike(self): """ is set off when inject is pressed, takes the vlaues from the spin boxes and fires a spike in. :return: """ print "injecting with neuron_id {} to pop {}".format( self.neuron_id.get(), self.pop_label.get()) if self._started: self.live_spikes_connection.send_spike(str(self.pop_label.get()), int(self.neuron_id.get()))
# Create a connection from the injector into the populations Frontend.Projection(injector, pop, Frontend.OneToOneConnector(weights=weight_to_spike)) # Activate the sending of live spikes ExternalDevices.activate_live_output_for( pop, database_notify_host="localhost", database_notify_port_num=19996) # Set up the live connection for sending spikes live_spikes_connection_send = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=["spike_injector"]) # Set up callbacks to occur at initialisation live_spikes_connection_send.add_init_callback( "spike_injector", init_pop) live_spikes_connection_receive = SpynnakerLiveSpikesConnection( receive_labels=["pop"], local_port=19996, send_labels=None)
def __init__(self, n_neurons_source=None, Spike_Source_Class=None, Spike_Sink_Class=None, output_population=None, ros_topic_send='to_spinnaker', ros_topic_recv='from_spinnaker', clk_rate=1000, ros_output_rate=10, benchmark=False): # Members self.n_neurons = n_neurons_source if n_neurons_source is not None else 1 self._Spike_Source_Class = Spike_Source_Class self._Spike_Sink_Class = Spike_Sink_Class self.interface_id = self._instance_counter.next() self._output_population = output_population self.send_topic = ros_topic_send self.recv_topic = ros_topic_recv self._clk_rate = clk_rate # in Hz self._ros_output_rate = ros_output_rate # Hz self._benchmark = benchmark self._injector_label = 'injector{}'.format(self.interface_id) spike_injector_port = 12345 + self.interface_id local_port = 19999 + self.interface_id local_recv_port = 17895 self._database_notify_port = local_port self._queue_ros_spinnaker = Queue() self._queue_spinnaker_ros = Queue() # My own "population" data structures to send and receive spikes, initialized later. self._spike_source = None self._spike_sink = None send_labels = [self._injector_label] rcv_labels = None self.sender_active = n_neurons_source is not None and self._Spike_Source_Class is not None self.receiver_active = self._output_population is not None and self._Spike_Sink_Class is not None if self.receiver_active: rcv_labels = [self._output_population.label] self._spike_injector_population = pynn.Population(size=self.n_neurons, cellclass=ExternalDevices.SpikeInjector, cellparams={'port': spike_injector_port, 'database_notify_port_num':local_port}, label=self._injector_label) self._spinnaker_connection = LiveSpikesConnection(receive_labels=rcv_labels, local_port=local_port, send_labels=send_labels) self._spinnaker_connection.add_start_callback(self._injector_label, self._init_ros_node) # spinnaker thread! if self.receiver_active: self._spinnaker_connection.add_receive_callback(self._output_population.label, self._incoming_spike_callback) ExternalDevices.activate_live_output_for(self._output_population, port=local_recv_port+self.interface_id, database_notify_port_num=self._database_notify_port)
print "Sending backward spike", real_id print_condition.release() sender.send_spike(label, real_id) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print_condition.acquire() print "Received spike at time", time, "from", label, "-", neuron_id print_condition.release() # Set up the live connection for sending spikes live_spikes_connection_send = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at the start of simulation live_spikes_connection_send.add_start_callback("spike_injector_forward", send_input_forward) live_spikes_connection_send.add_start_callback("spike_injector_backward", send_input_backward) if not using_c_vis: # if not using the c visualiser, then a new spynnaker live spikes connection # is created to define that there are python code which receives the # outputted spikes. live_spikes_connection_receive = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward", "pop_backward"], local_port=19996,
def __init__(self, n_neurons, machine_time_step, timescale_factor, label, images=None, port=12345, virtual_key=None, spikes_per_second=0, ring_buffer_sigma=None, database_socket=None, behaviour="SACCADE", max_saccade_distance=1, frames_per_microsaccade = 1, frames_per_saccade = 29, #~30 total_on_time_ms = 1000, inter_off_time_ms = 100, background_gray = 0, fps=90, mode="128", scale_img=True, polarity="MERGED", inhibition = False, inh_area_width = 2, threshold=12, adaptive_threshold = False, min_threshold=6, max_threshold=168, threshold_delta_down = 2, threshold_delta_up = 12, output_type="TIME", num_bits_per_spike=5, history_weight=0.99, save_spikes=None, local_port=19876): """ :param device_id: int for webcam modes, or string for video file :param mode: The retina "mode" :param retina_key: The value of the top 16-bits of the key :param polarity: The "polarity" of the retina data :param machine_time_step: The time step of the simulation :param timescale_factor: The timescale factor of the simulation :param label: The label for the population :param n_neurons: The number of neurons in the population """ self._loaded_idx = 0 self._total_images = 0 self._image_list = self.get_images_paths(images) fixed_n_neurons = n_neurons if mode == ExternalImageDvsEmulatorDevice.MODE_128 or \ mode == ExternalImageDvsEmulatorDevice.MODE_64 or \ mode == ExternalImageDvsEmulatorDevice.MODE_32 or \ mode == ExternalImageDvsEmulatorDevice.MODE_16: self._out_res = int(mode) else: raise exceptions.SpynnakerException("the model does not " "recongise this mode") if (polarity == ExternalImageDvsEmulatorDevice.UP_POLARITY or polarity == ExternalImageDvsEmulatorDevice.DOWN_POLARITY): fixed_n_neurons = self._out_res**2 else: fixed_n_neurons = 2*(self._out_res**2) if fixed_n_neurons != n_neurons and n_neurons is not None: logger.warn("The specified number of neurons for the DVS emulator" " device has been ignored {} will be used instead" .format(fixed_n_neurons)) self._center_x = 0 self._center_y = 0 self._max_saccade_distance = max_saccade_distance self._frames_per_microsaccade = frames_per_microsaccade self._frames_per_saccade = frames_per_saccade self._traverse_speed = (self._out_res*2.)/((total_on_time_ms/1000.)*fps) self._behaviour = behaviour self._total_on_time_ms = total_on_time_ms self._inter_off_time_ms = inter_off_time_ms self._background_gray = background_gray self._polarity = polarity self._polarity_n = ExternalImageDvsEmulatorDevice.POLARITY_DICT[polarity] self._global_max = int16(0) self._output_type = output_type self._raw_frame = None self._gray_frame = None self._tmp_frame = None self._ref_frame = 128*numpy.ones((self._out_res, self._out_res), dtype=int16) self._curr_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._moved_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._silence_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._spikes_frame = numpy.zeros((self._out_res, self._out_res, 3), dtype=uint8) self._diff = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._abs_diff = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._spikes = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._adaptive_threshold = adaptive_threshold self._thresh_matrix = None if adaptive_threshold: self._thresh_matrix = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._threshold_delta_down = int16(threshold_delta_down) self._threshold_delta_up = int16(threshold_delta_up) self._max_threshold = int16(max_threshold) self._min_threshold = int16(min_threshold) self._up_spikes = None self._down_spikes = None self._spikes_lists = None self._threshold = int16(threshold) self._data_shift = uint8(numpy.log2(self._out_res)) self._up_down_shift = uint8(2*self._data_shift) self._data_mask = uint8(self._out_res - 1) if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN: self._num_bins = 8 #8-bit images don't need more elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._num_bins = 6 #should be enough? else: self._num_bins = int(1000./fps) self._num_bits_per_spike = min(num_bits_per_spike, self._num_bins) if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN or \ self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._log2_table = generate_log2_table(self._num_bits_per_spike, self._num_bins) else: self._log2_table = generate_log2_table(self._num_bits_per_spike, 8) #stupid hack, compatibility issues self._scale_img = scale_img self._img_height = 0 self._img_height_crop_u = 0 self._img_height_crop_b = 0 self._img_width = 0 self._img_width_crop_l = 0 self._img_width_crop_r = 0 self._img_ratio = 0. self._img_scaled_width = 0 self._scaled_width = 0 self._fps = fps self._half_frame = fps/2 self._max_time_ms = int16((1./fps)*1000) self._time_per_spike_pack_ms = self.calculate_time_per_pack() self._get_sizes = True self._scale_changed = False self._running = True self._label = label self._n_neurons = fixed_n_neurons self._local_port = local_port self._inh_area_width = inh_area_width self._inhibition = inhibition self._history_weight = history_weight ################################################################ if spinn_version == "2015.005": ReverseIpTagMultiCastSource.__init__(self, n_neurons=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, port=self._local_port, label=self._label, virtual_key=virtual_key) else: ReverseIpTagMultiCastSource.__init__(self, n_keys=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, label=self._label, receive_port=self._local_port, virtual_key=virtual_key) AbstractProvidesOutgoingConstraints.__init__(self) print "number of neurons for webcam = %d"%self._n_neurons self._live_conn = SpynnakerLiveSpikesConnection(send_labels = [self._label, ], local_port = self._local_port) def init(label, n_neurons, run_time_ms, machine_timestep_ms): print("Sending %d neuron sources from %s"%(n_neurons, label)) self._live_conn.add_init_callback(self._label, init) self._live_conn.add_start_callback(self._label, self.run) self._sender = None self._save_spikes = save_spikes self._spike_list = []
def __init__(self, n_neurons, machine_time_step, timescale_factor, database_socket, label, port=12345, virtual_key=None, spikes_per_second=0, ring_buffer_sigma=None, device_id=0, fps=60, mode="128", scale_img=True, polarity="MERGED", inhibition=False, inh_area_width=2, threshold=12, adaptive_threshold=False, min_threshold=6, max_threshold=168, threshold_delta_down=2, threshold_delta_up=12, output_type="TIME", num_bits_per_spike=4, history_weight=0.99, save_spikes=None, run_time_ms=None, local_port=19876): """ :param device_id: int for webcam modes, or string for video file :param mode: The retina "mode" :param retina_key: The value of the top 16-bits of the key :param polarity: The "polarity" of the retina data :param machine_time_step: The time step of the simulation :param timescale_factor: The timescale factor of the simulation :param label: The label for the population :param n_neurons: The number of neurons in the population """ fixed_n_neurons = n_neurons if mode == ExternalDvsEmulatorDevice.MODE_128 or \ mode == ExternalDvsEmulatorDevice.MODE_64 or \ mode == ExternalDvsEmulatorDevice.MODE_32 or \ mode == ExternalDvsEmulatorDevice.MODE_16: self._out_res = int(mode) self._res_2x = self._out_res * 2 else: raise exceptions.SpynnakerException("the model does not " "recongise this mode") if (polarity == ExternalDvsEmulatorDevice.UP_POLARITY or polarity == ExternalDvsEmulatorDevice.DOWN_POLARITY or polarity == ExternalDvsEmulatorDevice.RECTIFIED_POLARITY): fixed_n_neurons = self._out_res**2 else: fixed_n_neurons = 2 * (self._out_res**2) if fixed_n_neurons != n_neurons and n_neurons is not None: logger.warn( "The specified number of neurons for the DVS emulator" " device has been ignored {} will be used instead".format( fixed_n_neurons)) self._video_source = None self._device_id = device_id self._is_virtual_cam = False self._polarity = polarity self._polarity_n = ExternalDvsEmulatorDevice.POLARITY_DICT[polarity] self._global_max = int16(0) self._output_type = output_type self._raw_frame = None self._gray_frame = None self._tmp_frame = None self._ref_frame = 128 * np.ones( (self._out_res, self._out_res), dtype=int16) self._curr_frame = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes_frame = np.zeros((self._out_res, self._out_res, 3), dtype=uint8) self._diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._abs_diff = np.zeros((self._out_res, self._out_res), dtype=int16) self._spikes = np.zeros((self._out_res, self._out_res), dtype=int16) self._adaptive_threshold = adaptive_threshold self._thresh_matrix = None if adaptive_threshold: self._thresh_matrix = np.zeros((self._out_res, self._out_res), dtype=int16) self._threshold_delta_down = int16(threshold_delta_down) self._threshold_delta_up = int16(threshold_delta_up) self._max_threshold = int16(max_threshold) self._min_threshold = int16(min_threshold) self._up_spikes = None self._down_spikes = None self._spikes_lists = None self._threshold = int16(threshold) self._data_shift = uint8(np.log2(self._out_res)) self._up_down_shift = uint8(2 * self._data_shift) self._data_mask = uint8(self._out_res - 1) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN: self._num_bins = 8 #8-bit images don't need more elif self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._num_bins = 6 #should be enough? else: self._num_bins = int(1000. / fps) self._num_bits_per_spike = min(num_bits_per_spike, self._num_bins) if self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN or \ self._output_type == ExternalDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._log2_table = gs.generate_log2_table(self._num_bits_per_spike, self._num_bins) else: self._log2_table = gs.generate_log2_table( self._num_bits_per_spike, 8) #stupid hack, compatibility issues self._scale_img = scale_img self._img_height = 0 self._img_height_crop_u = 0 self._img_height_crop_b = 0 self._img_width = 0 self._img_width_crop_l = 0 self._img_width_crop_r = 0 self._img_ratio = 0. self._img_scaled_width = 0 self._scaled_width = 0 self._fps = fps self._max_time_ms = 0 self._time_per_frame = 0. self._time_per_spike_pack_ms = 0 self._get_sizes = True self._scale_changed = False self._running = True self._label = label self._n_neurons = fixed_n_neurons self._local_port = local_port self._inh_area_width = inh_area_width self._inhibition = inhibition self._inh_coords = gs.generate_inh_coords(self._out_res, self._out_res, inh_area_width) self._history_weight = history_weight self._run_time_ms = run_time_ms ################################################################ if spinn_version == "2015.005": ReverseIpTagMultiCastSource.__init__( self, n_neurons=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, port=self._local_port, label=self._label, virtual_key=virtual_key) else: ReverseIpTagMultiCastSource.__init__( self, n_keys=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, label=self._label, receive_port=self._local_port, virtual_key=virtual_key) AbstractProvidesOutgoingConstraints.__init__(self) print("number of neurons for webcam = %d" % self._n_neurons) self._live_conn = SpynnakerLiveSpikesConnection( send_labels=[ self._label, ], local_port=self._local_port) def init(label, n_neurons, run_time_ms, machine_timestep_ms): print("Sending %d neuron sources from %s" % (n_neurons, label)) self._live_conn.add_init_callback(self._label, init) self._live_conn.add_start_callback(self._label, self.run) self._sender = None self._save_spikes = save_spikes
while n < neuronCount: sender.send_spike("med", n, send_full_keys=False) n += 1 counter_sent += neuronCount # time.sleep(0.007) print time.time() def init(label, sender): pass sender_thread = Thread(target=th_run, args=(sender,)) sender_thread.start() ExternalDevices.activate_live_output_for(source, database_notify_host="localhost",database_notify_port_num=19996) live_spikes_connection_receiver = SpynnakerLiveSpikesConnection(receive_labels=["src"], local_port=19996, send_labels=None) live_spikes_connection_receiver.add_receive_callback("src", receive_spike_cell) live_spikes_connection_sender = SpynnakerLiveSpikesConnection(receive_labels=None, local_port=19999, send_labels=["med"]) live_spikes_connection_sender.add_start_callback("med", init) Frontend.run(run_time) # Retrieve spikes from the synfire chain population # print "Spikes count source:", len(source.getSpikes()) # print "Spikes count collector_ssa:", len(collector_ssa.getSpikes()) # print collector_ssa.getSpikes()[:20] # print "Spikes count collector_inj:", len(collector_inj.getSpikes()) print counter_received, counter_sent # print collector_inj.getSpikes()[:20]
print_condition.acquire() print "Sending backward spike", real_id print_condition.release() sender.send_spike(label, real_id) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print_condition.acquire() print "Received spike at time", time, "from", label, "-", neuron_id print_condition.release() # Set up the live connection for sending spikes live_spikes_connection_send = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=["spike_injector_forward", "spike_injector_backward"]) # Set up callbacks to occur at initialisation live_spikes_connection_send.add_init_callback( "spike_injector_forward", init_pop) live_spikes_connection_send.add_init_callback( "spike_injector_backward", init_pop) # Set up callbacks to occur at the start of simulation live_spikes_connection_send.add_start_callback( "spike_injector_forward", send_input_forward) live_spikes_connection_send.add_start_callback( "spike_injector_backward", send_input_backward) live_spikes_connection_receive = None
class CooperativeNetwork(object): def __init__(self, retinae=None, max_disparity=0, cell_params=None, record_spikes=True, record_v=False, experiment_name="Experiment", verbose=True): # IMPORTANT NOTE: This implementation assumes min_disparity = 0 assert retinae['left'] is not None and retinae['right'] is not None, \ "ERROR: Retinas are not initialised! Creating Network Failed." dx = retinae['left'].dim_x assert dx > max_disparity >= 0, "ERROR: Maximum Disparity Constant is illegal!" self.max_disparity = max_disparity self.min_disparity = 0 self.size = (2 * (dx - self.min_disparity) * (self.max_disparity - self.min_disparity + 1) - (self.max_disparity - self.min_disparity + 1)**2 + self.max_disparity - self.min_disparity + 1) / 2 self.dim_x = dx self.dim_y = retinae['left'].dim_y # check this assertion before the actual network generation, since the former # might take very long to complete. assert retinae['left'].dim_x == retinae['right'].dim_x and \ retinae['left'].dim_y == retinae['right'].dim_y, \ "ERROR: Left and Right retina dimensions are not matching. Connecting Spike Sources to Network Failed." # TODO: make parameter values dependent on the simulation time step # (for the case 0.1 it is not tested completely and should serve more like an example) # the notation for the synaptic parameters is as follows: # B blocker, C collector, S spike source, (2, 4) # w weight, d delay, (1) # a one's own, z other, (3) # i inhibition, e excitation (5) # If B is before C than the connection is from B to C. # Example: dSaB would mean a dealy from a spike source to the one's own blocker neuron, and # wSzB would be the weight from a spike source to the heterolateral blocker neuron. params = {'neural': dict(), 'synaptic': dict(), 'topological': dict()} simulation_time_step = 0.2 if simulation_time_step == 0.2: params['neural'] = { 'tau_E': 2.0, 'tau_I': 2.0, 'tau_mem': 2.07, 'v_reset_blocker': -84.0, 'v_reset_collector': -90.0 } # why -90.0? w = 18.0 params['synaptic'] = { 'wBC': w, # -20.5: negative won't work. However keep in mind that it is inhibitory! 'dBC': simulation_time_step, 'wSC': w, 'dSC': 1.6, 'wSaB': w, 'dSaB': simulation_time_step, 'wSzB': w, # same story here 'dSzB': simulation_time_step, 'wCCi': w, # and again 'dCCi': simulation_time_step, 'wCCo': w / 3, # and again 'dCCo': simulation_time_step, 'wCCe': 1.8, 'dCCe': simulation_time_step } params['topological'] = { 'radius_e': 1, 'radius_i': max(self.dim_x, self.dim_y) } elif simulation_time_step == 0.1: params['neural'] = { 'tau_E': 1.0, 'tau_I': 1.0, 'tau_mem': 1.07, 'v_reset_blocker': -92.0, 'v_reset_collector': -102.0 } params['synaptic'] = { 'wBC': 39.5, #weight should be positive numbers, indicated as inhibitory synapses (if necessary)! 'dBC': simulation_time_step, 'wSC': 39.5, 'dSC': 0.8, 'wSaB': 49.5, 'dSaB': simulation_time_step, 'wSzB': 39.5, # same here 'dSzB': simulation_time_step, 'wCCi': 50.0, # and here 'dCCi': simulation_time_step, 'wCCe': 4.0, 'dCCe': simulation_time_step } params['topological'] = { 'radius_e': 1, 'radius_i': max(self.dim_x, self.dim_y) } self.cell_params = params if cell_params is None else cell_params self.network = self._create_network(record_spikes=record_spikes, record_v=record_v, verbose=verbose) self._connect_spike_sources(retinae=retinae, verbose=verbose) self.experiment_name = experiment_name.replace(" ", "_") def _create_network(self, record_spikes=False, record_v=False, verbose=False): print( "INFO: Creating Cooperative Network of size {0} (in microensembles)." .format(self.size)) # if record_spikes: # from pyNN.spiNNaker import record network = [] neural_params = self.cell_params['neural'] for x in range(0, self.size): blocker_columns = ps.Population( self.dim_y * 2, ps.IF_curr_exp, { 'tau_syn_E': neural_params['tau_E'], 'tau_syn_I': neural_params['tau_I'], 'tau_m': neural_params['tau_mem'], 'v_reset': neural_params['v_reset_blocker'] }, label="Blocker {0}".format(x)) collector_column = ps.Population( self.dim_y, ps.IF_curr_exp, { 'tau_syn_E': neural_params['tau_E'], 'tau_syn_I': neural_params['tau_I'], 'tau_m': neural_params['tau_mem'], 'v_reset': neural_params['v_reset_collector'] }, label="Collector {0}".format(x)) if record_spikes: collector_column.record() # records only the spikes if record_v: collector_column.record_v( ) # records the membrane potential -- very resource demanding! blocker_columns.record_v() network.append((blocker_columns, collector_column)) self._interconnect_neurons(network, verbose=verbose) if self.dim_x > 1: self._interconnect_neurons_inhexc(network, verbose) else: global _retina_proj_l, _retina_proj_r, same_disparity_indices _retina_proj_l = [[0]] _retina_proj_r = [[0]] same_disparity_indices = [[0]] return network def _interconnect_neurons(self, network, verbose=False): assert network is not None, \ "ERROR: Network is not initialised! Interconnecting failed." synaptic_params = self.cell_params['synaptic'] # generate connectivity list: 0 untill dimensionRetinaY-1 for the left # and dimensionRetinaY till dimensionRetinaY*2 - 1 for the right connList = [] for y in range(0, self.dim_y): connList.append( (y, y, synaptic_params['wBC'], synaptic_params['dBC'])) connList.append((y + self.dim_y, y, synaptic_params['wBC'], synaptic_params['dBC'])) # connect the inhibitory neurons to the cell output neurons if verbose: print "INFO: Interconnecting Neurons. This may take a while." for ensemble in network: ps.Projection(ensemble[0], ensemble[1], ps.FromListConnector(connList), target='inhibitory') def _interconnect_neurons_inhexc(self, network, verbose=False): assert network is not None, \ "ERROR: Network is not initialised! Interconnecting for inhibitory and excitatory patterns failed." if verbose and self.cell_params['topological']['radius_i'] < self.dim_x: print "WARNING: Bad radius of inhibition. Uniquness constraint cannot be satisfied." if verbose and 0 <= self.cell_params['topological'][ 'radius_e'] > self.dim_x: print "WARNING: Bad radius of excitation. " # create lists with inhibitory along the Retina Right projective line nbhoodInhL = [] nbhoodInhR = [] nbhoodExcX = [] nbhoodEcxY = [] # used for the triangular form of the matrix in order to remain within the square if verbose: print "INFO: Generating inhibitory and excitatory connectivity patterns." # generate rows limiter = self.max_disparity - self.min_disparity + 1 ensembleIndex = 0 while ensembleIndex < len(network): if ensembleIndex / (self.max_disparity - self.min_disparity + 1) > \ (self.dim_x - self.min_disparity) - (self.max_disparity - self.min_disparity) - 1: limiter -= 1 if limiter == 0: break nbhoodInhL.append( [ensembleIndex + disp for disp in range(0, limiter)]) ensembleIndex += limiter ensembleIndex = len(network) # generate columns nbhoodInhR = [[x] for x in nbhoodInhL[0]] shiftGlob = 0 for x in nbhoodInhL[1:]: shiftGlob += 1 shift = 0 for e in x: if (shift + 1) % (self.max_disparity - self.min_disparity + 1) == 0: nbhoodInhR.append([e]) else: nbhoodInhR[shift + shiftGlob].append(e) shift += 1 # generate all diagonals for diag in map(None, *nbhoodInhL): sublist = [] for elem in diag: if elem is not None: sublist.append(elem) nbhoodExcX.append(sublist) # generate all y-axis excitation for x in range(0, self.dim_y): for e in range(1, self.cell_params['topological']['radius_e'] + 1): if x + e < self.dim_y: nbhoodEcxY.append( (x, x + e, self.cell_params['synaptic']['wCCe'], self.cell_params['synaptic']['dCCe'])) if x - e >= 0: nbhoodEcxY.append( (x, x - e, self.cell_params['synaptic']['wCCe'], self.cell_params['synaptic']['dCCe'])) # Store these lists as global parameters as they can be used to quickly match the spiking collector neuron # with the corresponding pixel xy coordinates (same_disparity_indices) # TODO: think of a better way to encode pixels: closed form formula would be perfect # These are also used when connecting the spike sources to the network! (retina_proj_l, retina_proj_r) global _retina_proj_l, _retina_proj_r, same_disparity_indices _retina_proj_l = nbhoodInhL _retina_proj_r = nbhoodInhR same_disparity_indices = nbhoodExcX if verbose: print "INFO: Connecting neurons for internal excitation and inhibition." for row in nbhoodInhL: for pop in row: for nb in row: if nb != pop: ps.Projection( network[pop][1], network[nb][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wCCi'], delays=self.cell_params['synaptic']['dCCi']), target='inhibitory') for col in nbhoodInhR: for pop in col: for nb in col: if nb != pop: ps.Projection( network[pop][1], network[nb][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wCCi'], delays=self.cell_params['synaptic']['dCCi']), target='inhibitory') for diag in nbhoodExcX: for pop in diag: for nb in range( 1, self.cell_params['topological']['radius_e'] + 1): if diag.index(pop) + nb < len(diag): ps.Projection( network[pop][1], network[diag[diag.index(pop) + nb]][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wCCe'], delays=self.cell_params['synaptic']['dCCe']), target='excitatory') if diag.index(pop) - nb >= 0: ps.Projection( network[pop][1], network[diag[diag.index(pop) - nb]][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wCCe'], delays=self.cell_params['synaptic']['dCCe']), target='excitatory') for ensemble in network: ps.Projection(ensemble[1], ensemble[1], ps.FromListConnector(nbhoodEcxY), target='excitatory') def _connect_spike_sources(self, retinae=None, verbose=False): if verbose: print "INFO: Connecting Spike Sources to Network." global _retina_proj_l, _retina_proj_r # left is 0--dimensionRetinaY-1; right is dimensionRetinaY--dimensionRetinaY*2-1 connListRetLBlockerL = [] connListRetLBlockerR = [] connListRetRBlockerL = [] connListRetRBlockerR = [] for y in range(0, self.dim_y): connListRetLBlockerL.append( (y, y, self.cell_params['synaptic']['wSaB'], self.cell_params['synaptic']['dSaB'])) connListRetLBlockerR.append( (y, y + self.dim_y, self.cell_params['synaptic']['wSzB'], self.cell_params['synaptic']['dSzB'])) connListRetRBlockerL.append( (y, y, self.cell_params['synaptic']['wSzB'], self.cell_params['synaptic']['dSzB'])) connListRetRBlockerR.append( (y, y + self.dim_y, self.cell_params['synaptic']['wSaB'], self.cell_params['synaptic']['dSaB'])) retinaLeft = retinae['left'].pixel_columns retinaRight = retinae['right'].pixel_columns pixel = 0 for row in _retina_proj_l: for pop in row: ps.Projection(retinaLeft[pixel], self.network[pop][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wSC'], delays=self.cell_params['synaptic']['dSC']), target='excitatory') ps.Projection(retinaLeft[pixel], self.network[pop][0], ps.FromListConnector(connListRetLBlockerL), target='excitatory') ps.Projection(retinaLeft[pixel], self.network[pop][0], ps.FromListConnector(connListRetLBlockerR), target='inhibitory') pixel += 1 pixel = 0 for col in _retina_proj_r: for pop in col: ps.Projection(retinaRight[pixel], self.network[pop][1], ps.OneToOneConnector( weights=self.cell_params['synaptic']['wSC'], delays=self.cell_params['synaptic']['dSC']), target='excitatory') ps.Projection(retinaRight[pixel], self.network[pop][0], ps.FromListConnector(connListRetRBlockerR), target='excitatory') ps.Projection(retinaRight[pixel], self.network[pop][0], ps.FromListConnector(connListRetRBlockerL), target='inhibitory') pixel += 1 # configure for the live input streaming if desired if not (retinae['left'].use_prerecorded_input and retinae['right'].use_prerecorded_input): from spynnaker_external_devices_plugin.pyNN.connections.spynnaker_live_spikes_connection import \ SpynnakerLiveSpikesConnection all_retina_labels = retinaLeft.labels + retinaRight.labels self.live_connection_sender = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=all_retina_labels) # this callback will be executed right after simulation.run() has been called. If simply a while True # is put there, the main thread will stuck there and will not complete the simulation. # One solution might be to start a thread/process which runs a "while is_running:" loop unless the main thread # sets the "is_running" to False. self.live_connection_sender.add_start_callback( all_retina_labels[0], self.start_injecting) import DVSReader as dvs # the port numbers might well be wrong self.dvs_stream_left = dvs.DVSReader( port=0, label=retinaLeft.label, live_connection=self.live_connection_sender) self.dvs_stream_right = dvs.DVSReader( port=1, label=retinaRight.label, live_connection=self.live_connection_sender) # start the threads, i.e. start reading from the DVS. However, nothing will be sent to the SNN. # See start_injecting self.dvs_stream_left.start() self.dvs_stream_right.start() def start_injecting(self): # start injecting into the SNN self.dvs_stream_left.start_injecting = True self.dvs_stream_right.start_injecting = True def get_network_dimensions(self): parameters = { 'size': self.size, 'dim_x': self.dim_x, 'dim_y': self.dim_y, 'min_d': self.min_disparity, 'max_d': self.max_disparity } return parameters """ this method returns (and saves) a full list of spike times with the corresponding pixel location and disparities.""" def get_spikes(self, sort_by_time=True, save_spikes=True): global same_disparity_indices, _retina_proj_l spikes_per_population = [x[1].getSpikes() for x in self.network] spikes = list() # for each column population in the network, find the x,y coordinates corresponding to the neuron # and the disparity. Then write them in the list and sort it by the timestamp value. for col_index, col in enumerate(spikes_per_population, 0): # it is 0-indexed # find the disparity disp = self.min_disparity for d in range(0, self.max_disparity + 1): if col_index in same_disparity_indices[d]: disp = d + self.min_disparity break # for each spike in the population extract the timestamp and x,y coordinates for spike in col: x_coord = 0 for p in range(0, self.dim_x): if col_index in _retina_proj_l[p]: x_coord = p break y_coord = int(spike[0]) spikes.append((round(spike[1], 1), x_coord + 1, y_coord + 1, disp)) # pixel coordinates are 1-indexed if sort_by_time: spikes.sort(key=lambda x: x[0]) if save_spikes: if not os.path.exists("./spikes"): os.makedirs("./spikes") i = 0 while os.path.exists("./spikes/{0}_{1}_spikes.dat".format( self.experiment_name, i)): i += 1 with open( './spikes/{0}_{1}_spikes.dat'.format( self.experiment_name, i), 'w') as fs: self._write_preamble(fs) fs.write( "### DATA FORMAT ###\n" "# Description: All spikes from the Collector Neurons are recorded. The disparity is inferred " "from the Neuron ID. The disparity is calculated with the left camera as reference." "The timestamp is dependent on the simulation parameters (simulation timestep).\n" "# Each row contains: " "Time -- x-coordinate -- y-coordinate -- disparity\n" "### DATA START ###\n") for s in spikes: fs.write( str(s[0]) + " " + str(s[1]) + " " + str(s[2]) + " " + str(s[3]) + "\n") fs.write("### DATA END ###") fs.close() return spikes """ this method returns the accumulated spikes for each disparity as a list. It is not very useful except when the disparity sorting and formatting in the more general one get_spikes is not needed.""" def get_accumulated_disparities(self, sort_by_disparity=True, save_spikes=True): if sort_by_disparity: global same_disparity_indices spikes_per_disparity_map = [] for d in range(0, self.max_disparity - self.min_disparity + 1): collector_cells = [ self.network[x][1] for x in same_disparity_indices[d] ] spikes_per_disparity_map.append( sum([ sum(x.get_spike_counts().values()) for x in collector_cells ])) if save_spikes: if not os.path.exists("./spikes"): os.makedirs("./spikes") i = 0 while os.path.exists("./spikes/{0}_{1}_disp.dat".format( self.experiment_name, i)): i += 1 with open( './spikes/{0}_{1}_disp.dat'.format( self.experiment_name, i), 'w') as fd: self._write_preamble(fd) for s in spikes_per_disparity_map: fd.write(str(s) + "\n") fd.close() return spikes_per_disparity_map else: # this is pretty useless. maybe it should be removed in the future all_spikes = sum( sum(x[1].get_spikes_count().values() for x in self.network)) return all_spikes """ this method returns a list containing the membrane potential of all neural populations sorted by id.""" def get_v(self, save_v=True): voltages = { "collector_v": [x[1].get_v() for x in self.network], "blockers_v": [x[0].get_v() for x in self.network] } if save_v: if not os.path.exists("./membrane_potentials"): os.makedirs("./membrane_potentials") i = 0 while os.path.exists( "./membrane_potentials/{0}_{1}_vmem.dat".format( self.experiment_name, i)): i += 1 with open( './membrane_potentials/{0}_{1}_vmem.dat'.format( self.experiment_name, i), 'w') as fv: self._write_preamble(fv) fv.write( "### DATA FORMAT ###\n" "# Description: First all Blocker Populations are being printed. " "Then all Collector populations. Both are sorted by Population ID (i.e. order of creation). " "Each Blocker/Collector Population lists all neurons, sorted by Neuron ID. " "There are two times more Blocker than Collector Neurons.\n" "# Each row contains: " "Blocker/Collector tag (b/c) -- Population ID -- Neuron ID -- Time -- Membrane Potential\n" "### DATA START ###\n") for pop_id, pop_v in enumerate(voltages["blockers_v"]): for v in pop_v: fv.write("b " + str(int(pop_id)) + " " + str(int(v[0])) + " " + str(v[1]) + " " + str(v[2]) + "\n") for pop_id, pop_v in enumerate(voltages["collector_v"]): for v in pop_v: fv.write("c " + str(int(pop_id)) + " " + str(int(v[0])) + " " + str(v[1]) + " " + str(v[2]) + "\n") fv.write("### DATA END ###") fv.close() return voltages def _write_preamble(self, opened_file_descriptor): if opened_file_descriptor is not None: f = opened_file_descriptor f.write("### PREAMBLE START ###\n") f.write("# Experiment name: \n\t{0}\n".format( self.experiment_name)) f.write( "# Network parameters " "(size in ensembles, x-dimension, y-dimension, minimum disparity, maximum disparity, " "radius of excitation, radius of inhibition): " "\n\t{0} {1} {2} {3} {4} {5} {6}\n".format( self.size, self.dim_x, self.dim_y, self.min_disparity, self.max_disparity, self.cell_params['topological']['radius_e'], self.cell_params['topological']['radius_i'])) f.write( "# Neural parameters " "(tau_excitation, tau_inhibition, tau_membrane, v_reset_blocker, v_reset_collector): " "\n\t{0} {1} {2} {3} {4}\n".format( self.cell_params['neural']['tau_E'], self.cell_params['neural']['tau_I'], self.cell_params['neural']['tau_mem'], self.cell_params['neural']['v_reset_blocker'], self.cell_params['neural']['v_reset_collector'])) f.write( '# Synaptic parameters ' '(wBC, dBC, wSC, dSC, wSaB, dSaB, wSzB, dSzB, wCCi, dCCi, wCCe, dCCe): ' '\n\t{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}\n'. format(self.cell_params['synaptic']['wBC'], self.cell_params['synaptic']['dBC'], self.cell_params['synaptic']['wSC'], self.cell_params['synaptic']['dSC'], self.cell_params['synaptic']['wSaB'], self.cell_params['synaptic']['dSaB'], self.cell_params['synaptic']['wSzB'], self.cell_params['synaptic']['dSzB'], self.cell_params['synaptic']['wCCi'], self.cell_params['synaptic']['dCCi'], self.cell_params['synaptic']['wCCe'], self.cell_params['synaptic']['dCCe'])) f.write( '# Comments: Caution: The synaptic parameters may vary according with ' 'different simulation time steps. To understand the abbreviations for the ' 'synaptic parameters, see the code documentation.\n') f.write("### PREAMBLE END ###\n")
# in a safe way afterwards, and verify the behavior pop_forward.record() # Activate the sending of live spikes ExternalDevices.activate_live_output_for( pop_forward, database_notify_host="localhost", database_notify_port_num=19996) # Create a sender of packets for the forward population def send_input_forward(label, sender): print "Sending forward spike for neuron 0" sender.send_spike(label, 0) # Create a receiver of live spikes def receive_spikes(label, time, neuron_ids): for neuron_id in neuron_ids: print "Received spike at time", time, "from", label, "-", neuron_id # Set up the live connection for sending spikes live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=None, local_port=19999, send_labels=["spike_injector_forward"]) # Set up callbacks to occur at the start of simulation live_spikes_connection.add_start_callback("spike_injector_forward", send_input_forward) # if not using the c visualiser, then a new spynnaker live spikes connection # is created to define that there are python code which receives the # outputted spikes. live_spikes_connection = SpynnakerLiveSpikesConnection( receive_labels=["pop_forward"], local_port=19996, send_labels=None) # Set up callbacks to occur when spikes are received live_spikes_connection.add_receive_callback("pop_forward", receive_spikes) # Run the simulation on spiNNaker Frontend.run(run_time) # Retrieve spikes from the synfire chain population spikes_forward = pop_forward.getSpikes() # If there are spikes, plot using matplotlib if len(spikes_forward) != 0:
for pop in range(0, populationCount): collector.append(Frontend.Population(neuronCount, Frontend.IF_curr_exp, cell_params_col, label='{0}'.format(pop))) source.append(Frontend.Population(neuronCount, Frontend.SpikeSourceArray, {'spike_times': spikeTimes} , label='s{0}'.format(pop))) Frontend.Projection(source[pop], collector[pop], Frontend.OneToOneConnector(weights=22, delays=0.2), target='excitatory') collector[pop].record() counter_received_spikes.append(0) collector_labels.append('{0}'.format(pop)) def receive_spike_cell(label, time, neuron_ids): if time < 5050 : counter_received_spikes[int(label)] += len(neuron_ids) for col in collector: ExternalDevices.activate_live_output_for(col, database_notify_host="localhost",database_notify_port_num=19996) live_spikes_connection_receiver = SpynnakerLiveSpikesConnection(receive_labels=collector_labels, local_port=19996, send_labels=None) for label in collector_labels: live_spikes_connection_receiver.add_receive_callback(label, receive_spike_cell) Frontend.run(run_time) total_spikes_count = 0 for col in collector: total_spikes_count += len(col.getSpikes()) print "Spikes count collector:", total_spikes_count print "Spikes count received:", sum(counter_received_spikes) Frontend.end()
class _ROS_Spinnaker_Interface(object): """ Transform incoming ROS Messages into spikes and inject them into the Spinnaker Board and the other way round. a Args: b n_neurons_source (int): The number of neurons of the Spike Source. transfer_function_send (function handle): A handle to the transfer function used to convert the ROS input data into spikes. transfer_function_recv (function handle): A handle to the transfer function used to convert the live spikes to a ROS value. output_population (pynn.Population): The pyNN.Population you want to get the live spikes from. Defaults to None, so the live output is disabled. ros_topic_send (str): The ROS Topic used for sending into spinnaker. Defaults to "to_spinnaker". ros_topic_recv (str): The ROS Topic used for sending into ROS. Defaults to "from_spinnaker". clk_rate (int): The frequency the ROS Node is running with in Hz. Defaults to 1000 Hz. ros_output_rate (int): The frequency with which ros messages are sent out. Defaults to 10 Hz. benchmark (bool): Receive a timing output at the end of the simulation. Defaults to False. Attributes: InjectorPopulation: The ExternalDevices.SpikeInjector instance which is used internally. Functions: is_roscore_running(): True if the ros core is runnig else False. activate_live_output_for(pynn.Population): Set the pynn population you want to get the live spikes from. add_simulation_start_callback(function): Register the function as callback at simulation start. Examples: Have a look at the ros_spinnaker_interface_example.py or other example scripts. Notes: This interface uses the Spinnaker LiveSpikesConnection internally with the local ports 19999 and 17895 and the spinnaker port 12345. These ports are widely used for live spikes and therefore should'nt cause any problems, however you can also simply change them in the constructor if needed. For each parallel interface used, these port numbers are increased by one, so the second interface will use the local ports 20000 and 17896 and 12346 on spinnaker, etc. If you want to change or extend this interface, consider that there is a sub process started by the interface itself, as well as a thread controlled by spinnaker. Make sure they terminate and communicate properly. Currently only the std_msgs.msg.Int64 type is supported for ROS Messages. If you want to use your own ros message types it is possible, but you need to change some code yourself: - in the _incoming_ros_package_callback unpack the ros message fields and decide what to do with it. - in run_ros_node adjust the Publisher and Subscriber message types and (if needed) the publisher callback. """ _instance_counter = count(0) def __init__(self, n_neurons_source=None, Spike_Source_Class=None, Spike_Sink_Class=None, output_population=None, ros_topic_send='to_spinnaker', ros_topic_recv='from_spinnaker', clk_rate=1000, ros_output_rate=10, benchmark=False): # Members self.n_neurons = n_neurons_source if n_neurons_source is not None else 1 self._Spike_Source_Class = Spike_Source_Class self._Spike_Sink_Class = Spike_Sink_Class self.interface_id = self._instance_counter.next() self._output_population = output_population self.send_topic = ros_topic_send self.recv_topic = ros_topic_recv self._clk_rate = clk_rate # in Hz self._ros_output_rate = ros_output_rate # Hz self._benchmark = benchmark self._injector_label = 'injector{}'.format(self.interface_id) spike_injector_port = 12345 + self.interface_id local_port = 19999 + self.interface_id local_recv_port = 17895 self._database_notify_port = local_port self._queue_ros_spinnaker = Queue() self._queue_spinnaker_ros = Queue() # My own "population" data structures to send and receive spikes, initialized later. self._spike_source = None self._spike_sink = None send_labels = [self._injector_label] rcv_labels = None self.sender_active = n_neurons_source is not None and self._Spike_Source_Class is not None self.receiver_active = self._output_population is not None and self._Spike_Sink_Class is not None if self.receiver_active: rcv_labels = [self._output_population.label] self._spike_injector_population = pynn.Population(size=self.n_neurons, cellclass=ExternalDevices.SpikeInjector, cellparams={'port': spike_injector_port, 'database_notify_port_num':local_port}, label=self._injector_label) self._spinnaker_connection = LiveSpikesConnection(receive_labels=rcv_labels, local_port=local_port, send_labels=send_labels) self._spinnaker_connection.add_start_callback(self._injector_label, self._init_ros_node) # spinnaker thread! if self.receiver_active: self._spinnaker_connection.add_receive_callback(self._output_population.label, self._incoming_spike_callback) ExternalDevices.activate_live_output_for(self._output_population, port=local_recv_port+self.interface_id, database_notify_port_num=self._database_notify_port) def _init_ros_node(self, label, sender): """ Initialize the spike source and start the ros node. This is started as thread from the spinnaker LiveSpikesConnection at the beginning of the simulation. """ timestep = 1.0 / self._clk_rate * 1000 #if the readout population consists of more than one neuron -> set the readout_pop flag if self._output_population.size > 1: self._readout_pop_flag = True print('**********readout_flag_activated*************'.format(self.interface_id)) if self.sender_active: self._spike_source = self._Spike_Source_Class(self.n_neurons, label, sender, self._queue_ros_spinnaker, timestep) if self.receiver_active: self._spike_sink = self._Spike_Sink_Class(len(self._output_population), # get number of neurons self._queue_spinnaker_ros, timestep) if not self.is_roscore_running(): sys.exit(0) p = Process(target=self.run_ros_node) p.daemon = True print("Interface {} started".format(self.interface_id)) p.start() def run_ros_node(self): """ Initialize a ROS Node and subscribe and publish to the given ROS Topics. ROS requires this function to run in its own child process. The tick generator makes sure that it runs once per timestep. """ rospy.init_node('spinnaker_ros_interface{}'.format(self.interface_id), anonymous=True) if self._readout_pop_flag: if self.receiver_active: publisher = rospy.Publisher(self.recv_topic, Pop_List, queue_size=10) if self.sender_active: rospy.Subscriber(self.send_topic, Int64, self._incoming_ros_package_callback) else: if self.receiver_active: publisher = rospy.Publisher(self.recv_topic, Int64, queue_size=10) if self.sender_active: rospy.Subscriber(self.send_topic, Int64, self._incoming_ros_package_callback) rospy.on_shutdown(self.on_ros_node_shutdown) def ros_publisher_callback(event): if not self.receiver_active: return try: publisher.publish(self._spike_sink._get_ros_value()) except rospy.ROSException: return rospy.Timer(rospy.Duration(1.0 / self._ros_output_rate), ros_publisher_callback) # 10 Hz default ros_timer = rospy.Rate(self._clk_rate) self.interface_start_time = time.time() if self._benchmark: last = time.clock() self._num_timer_warnings = 0 self._num_ticks = 0 self._mainloop_execution_times = [] while not rospy.is_shutdown(): if self.sender_active: self._spike_source._update() if self.receiver_active: self._spike_sink._update() # Count if the mainloop execution takes too long if self._benchmark: self._num_ticks += 1 now = time.clock() self._mainloop_execution_times.append(now - last) if (now - last) > (1.0 / self._clk_rate): self._num_timer_warnings += 1 last = now ros_timer.sleep() def _incoming_ros_package_callback(self, ros_msg): """ Callback for the incoming data. Forwards the data via UDP to the Spinnaker Board. """ self._queue_ros_spinnaker.put(ros_msg.data) # data is the name of the ros std_msgs data field. def _incoming_spike_callback(self, label, time, neuron_ids): """ Call this callback to process incoming live spikes. """ for neuron_id in neuron_ids: spike = (label, time, neuron_id) self._queue_spinnaker_ros.put(spike) def is_roscore_running(self): """ Returns True if the ROS Core is running and False otherwise. """ return True # TODO try: _, _, ros_master_pid = rospy.get_master().getPid() return True except socket.error: print('\n\n[!] Cannot communicate with ROS Master. Please check if ROS Core is running.\n\n') return False @property def InjectorPopulation(self): """ The handle to the ExternalDevices.SpikeInjector which is used internally. Can be used for pynn.Connectors """ return self._spike_injector_population if self.sender_active else None def __str__(self): return 'ROS-Spinnaker-Interface' def __repr__(self): return self._spike_injector_population def on_ros_node_shutdown(self): # These do nothing on default. The plot functions need to be redefined in the SpikeSink/Source used to # actually do something. if self._benchmark: lock.acquire() print("Interface {} Benchmark".format(self.interface_id)) # print("startet running on time {}".format(self.interface_start_time)) # print("stopped runnning on time {}".format(time.time())) print("Number of times the mainloop took too long: {}".format(self._num_timer_warnings)) print("Number of Mainloop Calls: {}".format(self._num_ticks)) import numpy as np mean_execution_time = np.mean(self._mainloop_execution_times) print("Mean Mainloop Execution Time: {} ms, (max {} ms)".format(mean_execution_time, 1.0 / self._clk_rate)) print("Highest possible interface clock rate: {} Hz\n".format(1.0 / mean_execution_time)) lock.release() if self.sender_active: self._spike_source.plot() if self.receiver_active: self._spike_sink.plot() def add_simulation_start_callback(self, function): if self.sender_active: self._spinnaker_connection.add_start_callback(self._injector_label, function)
#~ cv2.imshow("new window", out) #~ cv2.waitKey(1) sim.setup(timestep=1.0, min_delay=1.0, max_delay=10.0) # echo population ---------------------------------------------------------- target = sim.Population(num_neurons, model, cell_params, label="echo") target.record() ExternalDevices.activate_live_output_for(target, database_notify_host="localhost", database_notify_port_num=live_out_port) live_spikes_receive = SpynnakerLiveSpikesConnection(receive_labels=["echo",], local_port=receive_port, send_labels=None) live_spikes_receive.add_receive_callback("echo", receive_spikes) # END: echo population ---------------------------------------------------------- # stim population ---------------------------------------------------------- stimulation = sim.Population(num_neurons, ImageDvsEmulatorDevice, cam_params, label="Webcam population") # END: stim population ---------------------------------------------------------- # connections ----------------------------------------------------------
class ExternalImageDvsEmulatorDevice(ReverseIpTagMultiCastSource, AbstractProvidesOutgoingConstraints, ): MODE_128 = "128" MODE_64 = "64" MODE_32 = "32" MODE_16 = "16" UP_POLARITY = "UP" DOWN_POLARITY = "DOWN" MERGED_POLARITY = "MERGED" POLARITY_DICT = {UP_POLARITY: uint8(0), DOWN_POLARITY: uint8(1), MERGED_POLARITY: uint8(2), 0: UP_POLARITY, 1: DOWN_POLARITY, 2: MERGED_POLARITY} OUTPUT_RATE = "RATE" OUTPUT_TIME = "TIME" OUTPUT_TIME_BIN = "TIME_BIN" OUTPUT_TIME_BIN_THR = "TIME_BIN_THR" BEHAVE_MICROSACCADE = "SACCADE" BEHAVE_ATTENTION = "ATTENTION" BEHAVE_TRAVERSE = "TRAVERSE" BEHAVE_FADE = "FADE" IMAGE_TYPES = ["png", 'jpeg', 'jpg'] MAX_LOADED_IMAGES = 100 def __init__(self, n_neurons, machine_time_step, timescale_factor, label, images=None, port=12345, virtual_key=None, spikes_per_second=0, ring_buffer_sigma=None, database_socket=None, behaviour="SACCADE", max_saccade_distance=1, frames_per_microsaccade = 1, frames_per_saccade = 29, #~30 total_on_time_ms = 1000, inter_off_time_ms = 100, background_gray = 0, fps=90, mode="128", scale_img=True, polarity="MERGED", inhibition = False, inh_area_width = 2, threshold=12, adaptive_threshold = False, min_threshold=6, max_threshold=168, threshold_delta_down = 2, threshold_delta_up = 12, output_type="TIME", num_bits_per_spike=5, history_weight=0.99, save_spikes=None, local_port=19876): """ :param device_id: int for webcam modes, or string for video file :param mode: The retina "mode" :param retina_key: The value of the top 16-bits of the key :param polarity: The "polarity" of the retina data :param machine_time_step: The time step of the simulation :param timescale_factor: The timescale factor of the simulation :param label: The label for the population :param n_neurons: The number of neurons in the population """ self._loaded_idx = 0 self._total_images = 0 self._image_list = self.get_images_paths(images) fixed_n_neurons = n_neurons if mode == ExternalImageDvsEmulatorDevice.MODE_128 or \ mode == ExternalImageDvsEmulatorDevice.MODE_64 or \ mode == ExternalImageDvsEmulatorDevice.MODE_32 or \ mode == ExternalImageDvsEmulatorDevice.MODE_16: self._out_res = int(mode) else: raise exceptions.SpynnakerException("the model does not " "recongise this mode") if (polarity == ExternalImageDvsEmulatorDevice.UP_POLARITY or polarity == ExternalImageDvsEmulatorDevice.DOWN_POLARITY): fixed_n_neurons = self._out_res**2 else: fixed_n_neurons = 2*(self._out_res**2) if fixed_n_neurons != n_neurons and n_neurons is not None: logger.warn("The specified number of neurons for the DVS emulator" " device has been ignored {} will be used instead" .format(fixed_n_neurons)) self._center_x = 0 self._center_y = 0 self._max_saccade_distance = max_saccade_distance self._frames_per_microsaccade = frames_per_microsaccade self._frames_per_saccade = frames_per_saccade self._traverse_speed = (self._out_res*2.)/((total_on_time_ms/1000.)*fps) self._behaviour = behaviour self._total_on_time_ms = total_on_time_ms self._inter_off_time_ms = inter_off_time_ms self._background_gray = background_gray self._polarity = polarity self._polarity_n = ExternalImageDvsEmulatorDevice.POLARITY_DICT[polarity] self._global_max = int16(0) self._output_type = output_type self._raw_frame = None self._gray_frame = None self._tmp_frame = None self._ref_frame = 128*numpy.ones((self._out_res, self._out_res), dtype=int16) self._curr_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._moved_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._silence_frame = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._spikes_frame = numpy.zeros((self._out_res, self._out_res, 3), dtype=uint8) self._diff = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._abs_diff = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._spikes = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._adaptive_threshold = adaptive_threshold self._thresh_matrix = None if adaptive_threshold: self._thresh_matrix = numpy.zeros((self._out_res, self._out_res), dtype=int16) self._threshold_delta_down = int16(threshold_delta_down) self._threshold_delta_up = int16(threshold_delta_up) self._max_threshold = int16(max_threshold) self._min_threshold = int16(min_threshold) self._up_spikes = None self._down_spikes = None self._spikes_lists = None self._threshold = int16(threshold) self._data_shift = uint8(numpy.log2(self._out_res)) self._up_down_shift = uint8(2*self._data_shift) self._data_mask = uint8(self._out_res - 1) if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN: self._num_bins = 8 #8-bit images don't need more elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._num_bins = 6 #should be enough? else: self._num_bins = int(1000./fps) self._num_bits_per_spike = min(num_bits_per_spike, self._num_bins) if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN or \ self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: self._log2_table = generate_log2_table(self._num_bits_per_spike, self._num_bins) else: self._log2_table = generate_log2_table(self._num_bits_per_spike, 8) #stupid hack, compatibility issues self._scale_img = scale_img self._img_height = 0 self._img_height_crop_u = 0 self._img_height_crop_b = 0 self._img_width = 0 self._img_width_crop_l = 0 self._img_width_crop_r = 0 self._img_ratio = 0. self._img_scaled_width = 0 self._scaled_width = 0 self._fps = fps self._half_frame = fps/2 self._max_time_ms = int16((1./fps)*1000) self._time_per_spike_pack_ms = self.calculate_time_per_pack() self._get_sizes = True self._scale_changed = False self._running = True self._label = label self._n_neurons = fixed_n_neurons self._local_port = local_port self._inh_area_width = inh_area_width self._inhibition = inhibition self._history_weight = history_weight ################################################################ if spinn_version == "2015.005": ReverseIpTagMultiCastSource.__init__(self, n_neurons=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, port=self._local_port, label=self._label, virtual_key=virtual_key) else: ReverseIpTagMultiCastSource.__init__(self, n_keys=self._n_neurons, machine_time_step=machine_time_step, timescale_factor=timescale_factor, label=self._label, receive_port=self._local_port, virtual_key=virtual_key) AbstractProvidesOutgoingConstraints.__init__(self) print "number of neurons for webcam = %d"%self._n_neurons self._live_conn = SpynnakerLiveSpikesConnection(send_labels = [self._label, ], local_port = self._local_port) def init(label, n_neurons, run_time_ms, machine_timestep_ms): print("Sending %d neuron sources from %s"%(n_neurons, label)) self._live_conn.add_init_callback(self._label, init) self._live_conn.add_start_callback(self._label, self.run) self._sender = None self._save_spikes = save_spikes self._spike_list = [] def get_outgoing_edge_constraints(self, partitioned_edge, graph_mapper): constraints = ReverseIpTagMultiCastSource\ .get_outgoing_edge_constraints( self, partitioned_edge, graph_mapper) constraints.append(KeyAllocatorContiguousRangeContraint()) return constraints def get_number_of_mallocs_used_by_dsg(self, vertex_slice, in_edges): mallocs = \ ReverseIpTagMultiCastSource.get_number_of_mallocs_used_by_dsg( self, vertex_slice, in_edges) if config.getboolean("SpecExecution", "specExecOnHost"): return 1 else: return mallocs def __del__(self): self._running = False def stop(self): self.__del__() def run(self, label, sender): self._label = label self._sender = sender #spike_list = self._spike_list max_run_time_s = self.no_machine_time_steps/float(self.machine_time_step) + 0.1 time_per_frame_s = 1./self._fps time_per_image_s = self._total_on_time_ms/1000. time_off_s = self._inter_off_time_ms/1000. bg_gray = self._background_gray spike_queue = Queue() spike_emmision_proc = Process(target=self.send_spikes, args=(spike_queue,)) spike_emmision_proc.start() img_queue = Queue() #~ spike_gen_proc = Process(target=self.process_frame, args=(img_queue,)) spike_gen_proc = Process(target=self.process_frame, args=(img_queue, spike_queue)) spike_gen_proc.start() grab_times = [] start_time = 0. app_start_time = time.time() app_curr_time = time.time() frame_start = 0. time_diff = 0. processed_images = 0 buffer_idx = 0 image_start_time = time.time() first_run = True silence_on = False frame_count = 1 first_frame_time = True while self._running: frame_start = time.time() if first_run or ( silence_on and \ (frame_start - image_start_time) >= time_off_s ): # done waiting in silence, grab frame self.grab_frame(processed_images) self._moved_frame[:] = self._curr_frame silence_on = False first_run = False image_start_time = frame_start processed_images += 1 silence_on = False frame_count = 1 self._center_x = 0 self._center_y = 0 elif not silence_on and \ (frame_start - image_start_time) >= time_per_image_s: # done showing current image, go to silence image_start_time = frame_start silence_on = True frame_count = 1 #reset count of images, run through them again if processed_images >= self._total_images: processed_images = 0 # send the minimum difference value once to synchronize time-based # decoding on the receiver end if self._output_type != ExternalImageDvsEmulatorDevice.OUTPUT_RATE and \ first_frame_time == True: first_frame_time = False self._silence_frame[:] = bg_gray + self._threshold + 1 img_queue.put(self._silence_frame) else: if silence_on: self._moved_frame[:] = bg_gray else: self._moved_frame[:] = self.move_image(frame_count) #"send" image to processing thread img_queue.put(self._moved_frame) # emulate frames per second time_diff = time.time() - frame_start if time_diff < time_per_frame_s: time.sleep(time_per_frame_s - time_diff*0.9) frame_count += 1 # is application runtime done? app_curr_time = time.time() if app_curr_time - app_start_time > max_run_time_s: self._running = False print "imager runtime ", app_curr_time - app_start_time img_queue.put(None) spike_gen_proc.join() spike_queue.put(None) spike_emmision_proc.join() cv2.destroyAllWindows() def process_frame(self, img_queue, spike_queue): label = self._label sender = self._sender spikes_frame = self._spikes_frame spike_list = [] move_times = [] gen_times = [] compose_times = [] transform_times = [] ref_up_times = [] start_time = 0. end_time = 0. lists = None while True: image = img_queue.get() if image is None or not self._running: break start_time = time.time() self.generate_spikes(image) gen_times.append(time.time()-start_time) start_time = time.time() self.update_reference() ref_up_times.append(time.time()-start_time) start_time = time.time() lists = self.transform_spikes() transform_times.append(time.time() - start_time) spike_queue.put(lists) if self._save_spikes is not None: spike_list.append(lists) start_time = time.time() self.compose_output_frame() compose_times.append(time.time()-start_time) #show detected spikes cv2.imshow (label, spikes_frame) if cv2.waitKey(1) & 0xFF == ord('q'):#\ #or not sender.isAlive(): self._running = False break #pipe_end.send(spike_list) print("gen times") print(numpy.array(gen_times).mean()) print("update ref times") print(numpy.array(ref_up_times).mean()) print("transform times") print(numpy.array(transform_times).mean()) print("compose times") print(numpy.array(compose_times).mean()) spike_queue.put(None) cv2.destroyAllWindows() if self._save_spikes is not None: #print spike_list print "attempting to save spike_list" pickle.dump( spike_list, open(self._save_spikes, "wb") ) def send_spikes(self, spike_queue): sender = self._sender while True: spikes = spike_queue.get() if spikes is None or not self._running: break self.emit_spikes(sender, spikes) cv2.destroyAllWindows() def move_image(self, frame_number): img = self._moved_frame fps = self._fps orig = self._curr_frame ref = self._ref_frame behaviour = self._behaviour half_frame = self._half_frame max_dist = self._max_saccade_distance speed = self._traverse_speed fp_uscd = self._frames_per_microsaccade fp_scd = self._frames_per_saccade bg_gray = self._background_gray cx = self._center_x cy = self._center_y if behaviour == ExternalImageDvsEmulatorDevice.BEHAVE_TRAVERSE: img[:] = traverse_image(orig, frame_number, speed, bg_gray) elif behaviour == ExternalImageDvsEmulatorDevice.BEHAVE_FADE: img[:] = fade_image(orig, frame_number, half_frame, bg_gray) elif behaviour == ExternalImageDvsEmulatorDevice.BEHAVE_MICROSACCADE: img[:], cx, cy = usaccade_image(orig, frame_number, fp_uscd, max_dist, cx, cy, bg_gray) else: img[:], cx, cy = attention_image(orig, img, ref, frame_number, fp_uscd, fp_scd, max_dist, cx, cy, bg_gray) self._center_x = cx self._center_y = cy return img def grab_frame(self, idx): self._gray_frame = cv2.imread(self._image_list[idx], CV_LOAD_IMAGE_GRAYSCALE) if self._gray_frame is None: print "could not read image %s"%self._image_list[idx] self._curr_frame[:] = 0 return True #~ start_time = time.time() if self._get_sizes or self._scale_changed: self._get_sizes = False self._scale_changed = False self._img_height, self._img_width = self._gray_frame.shape if self._img_width <= self._out_res and self._img_height <= self._out_res: diff = self._out_res - self._img_width self._img_width_crop_l = diff//2 self._img_width_crop_r = self._img_width_crop_l + self._img_width diff = self._out_res - self._img_height self._img_height_crop_u = diff//2 self._img_height_crop_b = self._img_height_crop_u + self._img_height row_from = self._img_height_crop_u row_to = self._img_height_crop_b col_from = self._img_width_crop_l col_to = self._img_width_crop_r self._curr_frame[row_from:row_to, col_from:col_to] = self._gray_frame return True else: self._img_ratio = float(self._img_width)/float(self._img_height) self._img_scaled_width = int(float(self._out_res)*self._img_ratio) if self._scale_img: diff = self._img_scaled_width - self._out_res self._img_width_crop_l = diff//2 self._img_width_crop_r = self._img_width_crop_l + self._out_res else: diff = self._img_width - self._out_res self._img_width_crop_l = diff//2 self._img_width_crop_r = self._img_width_crop_l + self._out_res diff = self._img_height - self._out_res self._img_height_crop_u = diff//2 self._img_height_crop_b = self._img_height_crop_u + self._out_res self._tmp_frame = numpy.zeros((self._out_res, self._img_scaled_width)) #~ end_time = time.time() #~ print("Time to calculate sizes = ", end_time - start_time) #~ start_time = time.time() if self._img_width <= self._out_res and self._img_height <= self._out_res: row_from = self._img_height_crop_u row_to = self._img_height_crop_b col_from = self._img_width_crop_l col_to = self._img_width_crop_r self._curr_frame[row_from:row_to, col_from:col_to] = self._gray_frame elif self._scale_img: self._tmp_frame[:] = cv2.resize(self._gray_frame, (self._img_scaled_width, self._out_res), interpolation=CV_INTER_NN) self._curr_frame[:] = self._tmp_frame[:, self._img_width_crop_l: self._img_width_crop_r] else: self._curr_frame[:] = self._gray_frame[self._img_height_crop_u: self._img_height_crop_b, self._img_width_crop_l: self._img_width_crop_r] #~ end_time = time.time() #~ print("Time to scale frame = ", end_time - start_time) return True def emit_spikes(self, sender, lists): up_spks = self._up_spikes dn_spks = self._down_spikes lbl = self._label max_time_s = self._time_per_spike_pack_ms/1000. #~ lists = self._spikes_lists send_spikes = sender.send_spikes keys = [] #from generate_spikes.pyx (cython) if lists is not None: for spike_pack in lists: start_time = time.time() send_spikes(lbl, spike_pack, send_full_keys=False) elapsed_time = time.time() - start_time if elapsed_time < max_time_s: time.sleep(max_time_s - elapsed_time) def generate_spikes(self, image): self._curr_frame = image curr_frame = self._curr_frame #~ curr_frame = image ref_frame = self._ref_frame diff = self._diff abs_diff = self._abs_diff spikes = self._spikes img_w = self._out_res inh_w = self._inh_area_width polarity = self._polarity_n inhibition = self._inhibition max_thresh = self._max_threshold min_thresh = self._min_threshold threshold = self._threshold if self._adaptive_threshold: thresh_mat = self._thresh_matrix thresh_delta_up = self._threshold_delta_down thresh_delta_down = self._threshold_delta_up #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = thresholded_difference_adpt(curr_frame, ref_frame, thresh_mat) else: #all from generate_spikes.pyx (cython) diff[:], abs_diff[:], spikes[:] = thresholded_difference(curr_frame, ref_frame, threshold) if inhibition: spikes[:] = local_inhibition(spikes, abs_diff, img_w, img_w, inh_w) def update_reference(self): abs_diff = self._abs_diff spikes = self._spikes ref_frame = self._ref_frame min_thresh = self._min_threshold max_thresh = self._max_threshold threshold = self._threshold max_time_ms = self._max_time_ms history_weight = self._history_weight num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits-1] #no values for 0-bit encoding if self._adaptive_threshold: thresh_mat = self._thresh_matrix thresh_delta_down = self._threshold_delta_down thresh_delta_up = self._threshold_delta_up ref_frame[:], thresh_mat[:] = update_reference_rate_adpt(abs_diff, spikes, ref_frame, thresh_mat, min_thresh, max_thresh, thresh_delta_down, thresh_delta_up, max_time_ms, history_weight) else: if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_RATE: ref_frame[:] = update_reference_rate(abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME: ref_frame[:] = update_reference_time_thresh(abs_diff, spikes, ref_frame, threshold, max_time_ms, history_weight) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN: ref_frame[:] = update_reference_time_binary_raw(abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: ref_frame[:] = update_reference_time_binary_thresh(abs_diff, spikes, ref_frame, threshold, max_time_ms, num_bits, history_weight, log2_table) def transform_spikes(self): up_spks = self._up_spikes dn_spks = self._down_spikes g_max = self._global_max data_shift = self._data_shift up_down_shift = self._up_down_shift data_mask = self._data_mask polarity = self._polarity_n spikes = self._spikes max_thresh = self._max_threshold min_thresh = self._min_threshold #~ lists = self._spikes_lists max_time_ms = self._max_time_ms abs_diff = self._abs_diff num_bins = self._num_bins num_bits = self._num_bits_per_spike log2_table = self._log2_table[num_bits - 1] dn_spks, up_spks, g_max = split_spikes(spikes, abs_diff, polarity) lists = None #from generate_spikes.pyx (cython) if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_RATE: lists = make_spike_lists_rate(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME: lists = make_spike_lists_time(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, num_bins, max_time_ms, min_thresh, max_thresh) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN: lists = make_spike_lists_time_bin(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, min_thresh, max_thresh, num_bins, log2_table) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN_THR: lists = make_spike_lists_time_bin_thr(up_spks, dn_spks, g_max, up_down_shift, data_shift, data_mask, max_time_ms, min_thresh, max_thresh, num_bins, log2_table) return lists def compose_output_frame(self): curr_frame = self._curr_frame spikes_frame = self._spikes_frame spikes = self._spikes width = self._out_res height = self._out_res polarity = self._polarity_n #from generate_spikes.pyx (cython) spikes_frame[:] = render_frame(spikes=spikes, curr_frame=curr_frame, width=width, height=height, polarity=polarity) def calculate_time_per_pack(self): time_per_pack = 0 if self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_RATE: time_per_pack = 1 elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME: time_per_pack = (self._max_time_ms)/ \ (min(self._max_time_ms, self._max_threshold/self._min_threshold + 1)) elif self._output_type == ExternalImageDvsEmulatorDevice.OUTPUT_TIME_BIN: time_per_pack = (self._max_time_ms)/(8) #raw difference value could be 8-bit else: time_per_pack = (self._max_time_ms)/(self._num_bits_per_spike + 1) return time_per_pack def get_images_paths(self, images): imgs = [] self._total_images = 0 if type(images) == type(list()): #if we've got a list of image paths for img in images: if os.path.isfile(img): #check if the image file exists imgs.append(img) self._total_images += 1 elif type(images) == type(str()): # if we get a string if os.path.isfile(images): # is it a file? imgs.append(images) self._total_images += 1 elif os.path.isdir(images): # or a directory? for extension in ExternalImageDvsEmulatorDevice.IMAGE_TYPES: for img in glob.glob(os.path.join(images, "*.%s"%extension)): if os.path.isfile(img): imgs.append(img) self._total_images += 1 if len(imgs) == 0: raise exceptions.SpynnakerException("No images loaded! ") return imgs
weight_to_spike = 2. rate_weight = 1.5 delay = 1 rate_delay = 16 pool_size = 1 # Create breakout population and activate live output for it breakout_pop = p.Population(1, spinn_breakout.Breakout, {}, label="breakout") ex.activate_live_output_for(breakout_pop, host="0.0.0.0", port=UDP_PORT) # Create spike injector to inject keyboard input into simulation key_input = p.Population(2, ex.SpikeInjector, {"port": 12367}, label="key_input") key_input_connection = SpynnakerLiveSpikesConnection(send_labels=["key_input"]) # Connect key spike injector to breakout population p.Projection(key_input, breakout_pop, p.OneToOneConnector(weights=2)) # Create visualiser visualiser = spinn_breakout.Visualiser(UDP_PORT, key_input_connection, x_res=X_RESOLUTION, y_res=Y_RESOLUTION, x_bits=X_BITS, y_bits=Y_BITS) direction_population = p.Population(3, p.IF_curr_exp, cell_params_lif) p.Projection( direction_population, breakout_pop,