From cb9aeba4a86e15b939a0cd76938a066c52f1643b Mon Sep 17 00:00:00 2001 From: Xulu Sun Date: Mon, 23 Mar 2026 18:04:37 -0700 Subject: [PATCH] all Trodes version compatible FSGUI --- 20251031-180550_fsgui_log.h5 | Bin 0 -> 800 bytes 20251106-191542_fsgui_log.h5 | Bin 0 -> 800 bytes config.yaml | 37 ++ fsgui/__main__.py | 7 +- fsgui/filter/lfp/ripple_new.py | 4 +- fsgui/network.py | 4 +- fsgui/spikegadgets/action/__init__.py | 178 ++++--- fsgui/spikegadgets/action/__init__original.py | 355 +++++++++++++ .../action/__init__without_train_in_sc.py | 335 ++++++++++++ .../action/__init__without_train_new.py | 335 ++++++++++++ fsgui/spikegadgets/action/pulse.py | 116 +++- fsgui/spikegadgets/action/shortcut.py | 23 +- fsgui/spikegadgets/action/test.ipynb | 496 ++++++++++++++++++ fsgui/spikegadgets/source/binned_camera.py | 9 +- fsgui/spikegadgets/source/camera.py | 9 +- fsgui/spikegadgets/source/lfp.py | 7 +- fsgui/spikegadgets/source/spikes.py | 9 +- fsgui/spikegadgets/source/timestamp.py | 7 +- 18 files changed, 1803 insertions(+), 128 deletions(-) create mode 100644 20251031-180550_fsgui_log.h5 create mode 100644 20251106-191542_fsgui_log.h5 create mode 100644 config.yaml create mode 100644 fsgui/spikegadgets/action/__init__original.py create mode 100644 fsgui/spikegadgets/action/__init__without_train_in_sc.py create mode 100644 fsgui/spikegadgets/action/__init__without_train_new.py create mode 100644 fsgui/spikegadgets/action/test.ipynb diff --git a/20251031-180550_fsgui_log.h5 b/20251031-180550_fsgui_log.h5 new file mode 100644 index 0000000000000000000000000000000000000000..82daee09f5d9bab4d4ef6cf1c24d6067e7457f8a GIT binary patch literal 800 zcmeD5aB<`1lHy_j0S*oZ76t(@6Gr@p0tIG>2#gPtPk=HQp>zk7Ucm%mFfxE31A_!q zTo7tLy1I}cS67e{nE5aos%?}S;UVDR>KFhDf(U3ha6su3&~ygng3}s^4OR>jq<{th Dq@*Z_ literal 0 HcmV?d00001 diff --git a/20251106-191542_fsgui_log.h5 b/20251106-191542_fsgui_log.h5 new file mode 100644 index 0000000000000000000000000000000000000000..82daee09f5d9bab4d4ef6cf1c24d6067e7457f8a GIT binary patch literal 800 zcmeD5aB<`1lHy_j0S*oZ76t(@6Gr@p0tIG>2#gPtPk=HQp>zk7Ucm%mFfxE31A_!q zTo7tLy1I}cS67e{nE5aos%?}S;UVDR>KFhDf(U3ha6su3&~ygng3}s^4OR>jq<{th Dq@*Z_ literal 0 HcmV?d00001 diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..8125c02 --- /dev/null +++ b/config.yaml @@ -0,0 +1,37 @@ +nodes: +- type_id: trodes-camera-data-type + instance_id: cb37189e-bc24-11f0-91ca-a0369f6f691e + nickname: Trodes Camera +- type_id: geometry-filter-type + instance_id: d21a00a4-bc24-11f0-91ca-a0369f6f691e + nickname: Geometry filter + source_id: null + trackgeometry: + filename: /home/xulu/Xulu/Behavior/Geometry/for_sleepbox_recording.trackgeometry + zone_id: 2 + cameraWidth: 1000 + cameraHeight: 995 +- type_id: trodes-digital-pulse-action-type + instance_id: d896866e-bc24-11f0-91ca-a0369f6f691e + nickname: Digital Pulsetrain + trigger_id: + id: d5b04c5a-bc24-11f0-91ca-a0369f6f691e + data: + label: Geometry filter + type: filter + value: d21a00a4-bc24-11f0-91ca-a0369f6f691e + children: [] + condition_id: null + pulseLength: 1 + nPulses: 1 + preDelay: 0 + sequencePeriod: 100 + nOutputTrains: 1 + trainInterval: 1000 + primaryBit: 1 + lockout_time: 0 + functNum: 0 + action_enabled: true + off_when_false: false + delay_enabled: true + reward_based_trigger_enabled: false diff --git a/fsgui/__main__.py b/fsgui/__main__.py index a8d0933..05e3808 100644 --- a/fsgui/__main__.py +++ b/fsgui/__main__.py @@ -6,20 +6,21 @@ import fsgui.config import fsgui.filter import fsgui.simulation +import fsgui.spikegadgets.trodes as trodes import fsgui.spikegadgets import qtapp import qtgui if __name__ == "__main__": try: - args = fsgui.spikegadgets.trodes.TrodesSpawnArgParser().parse_args(sys.argv) - network = fsgui.spikegadgets.trodes.TrodesNetworkLocation( + args = trodes.TrodesSpawnArgParser().parse_args(sys.argv) + network = trodes.TrodesNetworkLocation( args['serverAddress'], args['serverPort'] ) except Exception as e: logging.warning('command line arguments were not found, using default network location') - network = fsgui.spikegadgets.trodes.TrodesNetworkLocation("tcp://127.0.0.1", 49152) + network = trodes.TrodesNetworkLocation("tcp://127.0.0.1", 49152) qtgui.run_qt_app(functools.partial( qtapp.window.FSGuiWindow, diff --git a/fsgui/filter/lfp/ripple_new.py b/fsgui/filter/lfp/ripple_new.py index 3a436c7..3311828 100644 --- a/fsgui/filter/lfp/ripple_new.py +++ b/fsgui/filter/lfp/ripple_new.py @@ -153,7 +153,7 @@ def write_template(self, config = None): 'upper': 200, 'units': 'power', 'decimals': 2, - 'default': 0, + 'default': config['means_magic_input'], 'tooltip': 'Hard coded ripple LFP mean, used for mean + threshold * sd', 'live_editable': True, }, @@ -165,7 +165,7 @@ def write_template(self, config = None): 'upper': 200, 'units': 'power', 'decimals': 2, - 'default': 0, + 'default': config['sigmas_magic_input'], 'tooltip': 'Hard coded ripple LFP sd, used for mean + threshold * sd', 'live_editable': True, }, diff --git a/fsgui/network.py b/fsgui/network.py index 8739efc..5ab6e6f 100644 --- a/fsgui/network.py +++ b/fsgui/network.py @@ -9,7 +9,7 @@ def __init__(self, location=None): self._sock.bind(location) self._location = location else: - self._sock.bind_to_random_port('tcp://0.0.0.0') + self._sock.bind_to_random_port('tcp://127.0.0.1') self._location = self._sock.get_string(zmq.LAST_ENDPOINT) def send(self, data): @@ -41,4 +41,4 @@ def recv(self, timeout=None): assert mask == 1 return sock.recv_json() else: - return None \ No newline at end of file + return None diff --git a/fsgui/spikegadgets/action/__init__.py b/fsgui/spikegadgets/action/__init__.py index 12595e0..c0d36d4 100644 --- a/fsgui/spikegadgets/action/__init__.py +++ b/fsgui/spikegadgets/action/__init__.py @@ -1,58 +1,15 @@ import fsgui.process import fsgui.network import functools -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork import operator import time + def generate_statescript(function_num, pre_delay, n_pulses, n_trains, - train_interval, sequence_period, primary_stim_pin, pulse_length): - """ - This script was copied and translated from StimConfigureWidget::generateStateScript. The original logic is - from 2015. - - This may need to be edited in order to include biphasic stimulation. In the case that we want to generate more - complex code. - - Example output: - ``` - int f11go - int f11PulseCounter = 1 - int f11TrainCounter = 1; - int f11LockOut = 0; - function 11 - if (f11LockOut == 0) do - f11LockOut = 1 - f11go = 1 - f11PulseCounter = 1 - f11TrainCounter = 1 - if f11go == 1 do in 3 - while f11go == 1 && f11TrainCounter <= 7 do every 13 - while f11go == 1 && f11PulseCounter <= 5 do every 17 - portout[19]=1 - do in 23 - portout[19]=0 - end - f11PulseCounter = f11PulseCounter + 1 - then do - f11PulseCounter = 1 - f11TrainCounter = f11TrainCounter + 1 - end - then do - f11PulseCounter = 1 - f11TrainCounter = 1 - end - end - f11LockOut = 0 - end - end; - - function 12 - f11go = 0 - end; - ``` - """ + train_interval, sequence_period, primary_stim_pin, pulse_length, + delay_enabled, reward_based_trigger_enabled): stop_function_num = function_num+1 go_var = f'f{function_num}go' pulse_counter_var = f'f{function_num}PulseCounter' @@ -60,7 +17,24 @@ def generate_statescript(function_num, pre_delay, lockout_var = f'f{function_num}LockOut' go_check = f'{go_var} == 1' - + #here is the first code we need to edit, as we want to seperate based on whether reward is given + #or whether delay of laser is perscribed + if reward_based_trigger_enabled: + sc_check = 'ifStim == 1' + else: + sc_check = f'{go_var} == 1' + #here we set up the delay condition, the delay enabled variable is controling whether we want to delay the laser + #stimulation when the animal gets a reward it will only delay if the reward is delayed, therefore we check if delay enabled + if delay_enabled: + sc_delay_check = 'ifDelay == 1' + pre_delay_tmp = pre_delay + #here if delay is not enabled we set the delay check to always true, whether the reward is delayed or not = + else: + sc_delay_check=f'{go_var} == 1' + pre_delay_tmp=0 + sc_no_delay = 'ifDelay == 0' + # sc_delay_check = 'ifDelay == 1' + no_delay=0 # declare spaces s2 = ' ' s4 = s2*2 @@ -68,6 +42,7 @@ def generate_statescript(function_num, pre_delay, s8 = s2*4 s10 = s2*5 s12 = s2*6 + s14 = s2*7 endl = '\n' script = "" @@ -76,62 +51,85 @@ def generate_statescript(function_num, pre_delay, # declare and init pulse & train counters and lockout # not sure why there is no semicolon on the first one script += f'int {pulse_counter_var} = 1' + endl - script += f'int {train_counter_var} = 1;' + endl + script += f'int {train_counter_var} = 1' + endl script += f'int {lockout_var} = 0;' + endl script += f'function {function_num}' + endl - #script += s2 + f'portout[25]=1' + endl - #script += s2 + f'portout[25]=0' + endl script += s2 + f'if ({lockout_var} == 0) do' + endl script += s4 + f'{lockout_var} = 1' + endl script += s4 + f'{go_var} = 1' + endl script += s4 + f'{pulse_counter_var} = 1' + endl script += s4 + f'{train_counter_var} = 1' + endl - if pre_delay == 0: - script += s4 + f'if {go_check} do' + endl - else: - script += s4 + f'if {go_check} do in {pre_delay}' + endl - # set the number of trains if we're not doing continuous pulses + # script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay_tmp}' + endl + script += s4 + f'if {go_check} && {sc_check} do' + endl + script += s6 + f'if {sc_delay_check} do in {pre_delay}' + endl + if n_pulses != 0: if n_trains == 1: # No extra scheduling pass - elif n_trains != 0: - script += s6 +f'while {go_check} && {train_counter_var} <= {n_trains} do every {train_interval}' + endl else: - # otherwise we want continuous pulse trains, so we use 1 as the check value and skip incrementing the counter below - # we only do this if we're not doing continuous pulses - script += s6 + f'while {go_check} && {train_counter_var} <= {1} do every {train_interval}' + endl - script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl - else: - script += s8 + f'while {go_check}&& {pulse_counter_var} <= {1} do every {sequence_period}' + endl + script += s8 +f'while {go_check} && {train_counter_var} <= {n_trains} do every {train_interval}' + endl - script += s10 + f'portout[{primary_stim_pin}]=1' + endl + # we're currently only doing one train (multiple pulses) for the delayed stim. + script += s10 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl - script += s10 + f'do in {pulse_length}' + endl; - script += s12 + f'portout[{primary_stim_pin}]=0' + endl - script += s10 + 'end' + endl + script += s12 + f'portout[{primary_stim_pin}]=1' + endl + script += s12 + f'do in {pulse_length}' + endl + script += s14 + f'portout[{primary_stim_pin}]=0' + endl + script += s12 + 'end' + endl + + if n_pulses != 0: + script += s12 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + script += s10 + 'then do' + endl + script += s12 + f'{pulse_counter_var} = 1' + endl # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains > 1: + script += s12 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s10 + 'end' + endl + + if n_trains == 1: # No extra scheduling + pass + else: + script += s8 + f'then do' + endl + script += s8 + f'end' + endl + script += s6 + f'else do' + endl + + + if n_pulses != 0: + if n_trains == 1: # No extra scheduling + pass + else: + script += s8 +f'while {go_check} && {train_counter_var} <= {n_trains} do every {train_interval}' + endl + + script += s10 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + + script += s12 + f'portout[{primary_stim_pin}]=1' + endl + + script += s12 + f'do in {pulse_length}' + endl + script += s14 + f'portout[{primary_stim_pin}]=0' + endl + script += s12 + 'end' + endl if n_pulses != 0: - script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + script += s12 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl - script += s8 + 'then do' + endl - script += s10 + f'{pulse_counter_var} = 1' + endl + + script += s10 + 'then do' + endl + script += s12 + f'{pulse_counter_var} = 1' + endl # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses - if n_pulses != 0 and n_trains != 0: - script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl - script += s8 + 'end' + endl - - # we need to end the TrainCounter while loop - if n_trains != 1: - #if n_pulses != 0: - script += s6 + 'then do' + endl - script += s8 + f'{pulse_counter_var} = 1' + endl - script += s8 + f'{train_counter_var} = 1' + endl - script += s6 + 'end' + endl + if n_pulses != 0 and n_trains > 1: + + script += s12 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s10 + 'end' + endl + if n_trains == 1: # No extra scheduling + pass + else: + script += s8 + f'then do' + endl + script += s8 + f'end' + endl + script += s6 + 'end' + endl # end the second if script += s4 + 'end' + endl @@ -140,17 +138,18 @@ def generate_statescript(function_num, pre_delay, # end the first if script += s2 + 'end' + endl + # end the action triggering function script += 'end;' + endl # declare the stop function script += endl script += f'function {stop_function_num}' + endl - #script += s2 + f'portout[26]=1' + endl - #script += s2 + f'portout[26]=0' + endl script += s2 + f'{go_var} = 0' + endl script += s2 + f'portout[{primary_stim_pin}]=0' + endl script += 'end;' + endl + + return script def build_shortcut_command( @@ -158,13 +157,17 @@ def build_shortcut_command( filter_tree, network_location, lockout_time, + n_trains, on_funct_num, action_enabled, off_when_false, + delay_enabled, + reward_based_trigger_enabled, condition_tree=None, off_funct_num=None, ): + def setup(reporter, data): # setup each value data['sub_values'] = { @@ -244,6 +247,8 @@ def evaluate_node(node, data): evaluation = evaluation and condition + + if data['action_enabled']: if evaluation: currentTime = time.time() @@ -265,7 +270,8 @@ def evaluate_node(node, data): 'OUTPUT_timestamp': data['last_triggered'] }) else: - triggered = 0 + #triggered = 0 + pass else: if triggered == 1: #if condition is suddenly not true, sent suppress if off_funct_num is not None: @@ -349,4 +355,4 @@ def evaluate_node(node, data): data['last_triggered'] = None ''' - return fsgui.process.build_process_object(setup, workload) \ No newline at end of file + return fsgui.process.build_process_object(setup, workload) diff --git a/fsgui/spikegadgets/action/__init__original.py b/fsgui/spikegadgets/action/__init__original.py new file mode 100644 index 0000000..db80991 --- /dev/null +++ b/fsgui/spikegadgets/action/__init__original.py @@ -0,0 +1,355 @@ +import fsgui.process +import fsgui.network +import functools +import trodesnetwork +import operator +import time + +def generate_statescript(function_num, pre_delay, + n_pulses, n_trains, + train_interval, sequence_period, primary_stim_pin, pulse_length, + delay_enabled, reward_based_trigger_enabled): + """ + This script was copied and translated from StimConfigureWidget::generateStateScript. The original logic is + from 2015. + + This may need to be edited in order to include biphasic stimulation. In the case that we want to generate more + complex code. + + Example output: + ``` + int f11go + int f11PulseCounter = 1 + int f11TrainCounter = 1; + int f11LockOut = 0; + function 11 + if (f11LockOut == 0) do + f11LockOut = 1 + f11go = 1 + f11PulseCounter = 1 + f11TrainCounter = 1 + if f11go == 1 do in 3 + while f11go == 1 && f11TrainCounter <= 7 do every 13 + while f11go == 1 && f11PulseCounter <= 5 do every 17 + portout[19]=1 + do in 23 + portout[19]=0 + end + f11PulseCounter = f11PulseCounter + 1 + then do + f11PulseCounter = 1 + f11TrainCounter = f11TrainCounter + 1 + end + then do + f11PulseCounter = 1 + f11TrainCounter = 1 + end + end + f11LockOut = 0 + end + end; + + function 12 + f11go = 0 + end; + ``` + """ + stop_function_num = function_num+1 + go_var = f'f{function_num}go' + pulse_counter_var = f'f{function_num}PulseCounter' + train_counter_var = f'f{function_num}TrainCounter' + lockout_var = f'f{function_num}LockOut' + + go_check = f'{go_var} == 1' + + # declare spaces + s2 = ' ' + s4 = s2*2 + s6 = s2*3 + s8 = s2*4 + s10 = s2*5 + s12 = s2*6 + endl = '\n' + + script = "" + script += f'int {go_var}' + endl + + # declare and init pulse & train counters and lockout + # not sure why there is no semicolon on the first one + script += f'int {pulse_counter_var} = 1' + endl + script += f'int {train_counter_var} = 1;' + endl + script += f'int {lockout_var} = 0;' + endl + + script += f'function {function_num}' + endl + #script += s2 + f'portout[25]=1' + endl + #script += s2 + f'portout[25]=0' + endl + script += s2 + f'if ({lockout_var} == 0) do' + endl + script += s4 + f'{lockout_var} = 1' + endl + script += s4 + f'{go_var} = 1' + endl + script += s4 + f'{pulse_counter_var} = 1' + endl + script += s4 + f'{train_counter_var} = 1' + endl + + if pre_delay == 0: + script += s4 + f'if {go_check} do' + endl + else: + script += s4 + f'if {go_check} do in {pre_delay}' + endl + + # set the number of trains if we're not doing continuous pulses + if n_pulses != 0: + if n_trains == 1: # No extra scheduling + pass + elif n_trains != 0: + script += s6 +f'while {go_check} && {train_counter_var} <= {n_trains} do every {train_interval}' + endl + else: + # otherwise we want continuous pulse trains, so we use 1 as the check value and skip incrementing the counter below + # we only do this if we're not doing continuous pulses + script += s6 + f'while {go_check} && {train_counter_var} <= {1} do every {train_interval}' + endl + script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + else: + script += s8 + f'while {go_check}&& {pulse_counter_var} <= {1} do every {sequence_period}' + endl + + script += s10 + f'portout[{primary_stim_pin}]=1' + endl + + script += s10 + f'do in {pulse_length}' + endl; + script += s12 + f'portout[{primary_stim_pin}]=0' + endl + script += s10 + 'end' + endl + + # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0: + script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + script += s8 + 'then do' + endl + script += s10 + f'{pulse_counter_var} = 1' + endl + + # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains != 0: + script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s8 + 'end' + endl + + # we need to end the TrainCounter while loop + if n_trains != 1: + #if n_pulses != 0: + script += s6 + 'then do' + endl + script += s8 + f'{pulse_counter_var} = 1' + endl + script += s8 + f'{train_counter_var} = 1' + endl + script += s6 + 'end' + endl + + # end the second if + script += s4 + 'end' + endl + # reset the lock out + script += s4 + f'{lockout_var} = 0' + endl + # end the first if + script += s2 + 'end' + endl + + script += 'end;' + endl + + # declare the stop function + script += endl + script += f'function {stop_function_num}' + endl + #script += s2 + f'portout[26]=1' + endl + #script += s2 + f'portout[26]=0' + endl + script += s2 + f'{go_var} = 0' + endl + script += s2 + f'portout[{primary_stim_pin}]=0' + endl + script += 'end;' + endl + + return script + +def build_shortcut_command( + pipe_map, + filter_tree, + network_location, + lockout_time, + on_funct_num, + action_enabled, + off_when_false, + delay_enabled, + reward_based_trigger_enabled, + condition_tree=None, + off_funct_num=None, + ): + + def setup(reporter, data): + # setup each value + data['sub_values'] = { + sub_name: False + for sub_name in pipe_map.keys() + } + + data['trodes_sender'] = trodesnetwork.ServiceConsumer('trodes.hardware', server_address = f'{network_location.address}:{network_location.port}') + + # live updated variables + data['action_enabled'] = action_enabled + data['off_when_false'] = off_when_false + + # runtime variables + data['last_triggered'] = 0 + data['currently_triggered'] = False + + if data['off_when_false']: + assert off_funct_num is not None + + def workload(connection, publisher, reporter, data): + triggered = 0 + + # update live variables + if connection.pipe_poll(timeout = 0): + msg_tag, msg_data = connection.pipe_recv() + if msg_tag == 'update': + msg_varname, msg_value = msg_data + # update the variable + data[msg_varname] = msg_value + + if data['off_when_false']: + assert off_funct_num is not None + + ''' + # for reporter/visualization + testT = time.time() + if (testT % 0.01 <= 1e-3): #update rate is 100Hz, will plot 1000 samples in each hit + if triggered == 1: + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + reporter.send({ + 'OUTPUT_trigger': 0, + 'OUTPUT_timestamp': time.time() + }) + ''' + + + # loop updates all of the sub_values from pipe + for sub_name, source_pipe in pipe_map.items(): + if source_pipe.poll(timeout=0): + value = source_pipe.recv() + data['sub_values'][sub_name] = value + + def evaluate_node(node, data): + if 'gate' == node['data']['type']: + if 'gate-and' == node['data']['value']: + return functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-or' == node['data']['value']: + return functools.reduce(operator.or_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-nand' == node['data']['value']: + return not functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'filter' == node['data']['type']: + value = data['sub_values'][node['data']['value']] + return value + else: + raise ValueError('evaluate error: {}'.format(node)) + + evaluation = evaluate_node(filter_tree, data) if filter_tree is not None else False + + # by default the condition is True + condition = evaluate_node(condition_tree, data) if condition_tree is not None else True + + evaluation = evaluation and condition + + + if data['action_enabled']: + if evaluation: + currentTime = time.time() + if currentTime > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + #print('trigger time delta') + data['last_triggered'] = time.time() + #print(time.time() - currentTime) + + triggered = 1 + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + triggered = 0 + else: + if triggered == 1: #if condition is suddenly not true, sent suppress + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num}]) + else: + currentTime = time.time() + triggered = 0 + elif not data['action_enabled']: + if triggered == 1: + currentTime = time.time() + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + triggered = 0 + + + + ''' + if data['action_enabled']: + if evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + else: + # we're in lockout, so we must wait + pass + elif not data['currently_triggered']: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + elif not evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + + if not condition or data['off_when_false'] and off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + + elif not data['action_enabled']: + # we're disabled, so we want to check + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + else: + # we shut off when the action is disabled + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + ''' + + return fsgui.process.build_process_object(setup, workload) diff --git a/fsgui/spikegadgets/action/__init__without_train_in_sc.py b/fsgui/spikegadgets/action/__init__without_train_in_sc.py new file mode 100644 index 0000000..8b43e88 --- /dev/null +++ b/fsgui/spikegadgets/action/__init__without_train_in_sc.py @@ -0,0 +1,335 @@ +import fsgui.process +import fsgui.network +import functools +import trodesnetwork +import operator +import time + + +def generate_statescript(function_num, pre_delay, + n_pulses, n_trains, + train_interval, sequence_period, primary_stim_pin, pulse_length, + delay_enabled, reward_based_trigger_enabled): + stop_function_num = function_num+1 + go_var = f'f{function_num}go' + pulse_counter_var = f'f{function_num}PulseCounter' + train_counter_var = f'f{function_num}TrainCounter' + lockout_var = f'f{function_num}LockOut' + + go_check = f'{go_var} == 1' + #here is the first code we need to edit, as we want to seperate based on whether reward is given + #or whether delay of laser is perscribed + if reward_based_trigger_enabled: + sc_check = 'ifStim == 1' + else: + sc_check = f'{go_var} == 1' + #here we set up the delay condition, the delay enabled variable is controling whether we want to delay the laser + #stimulation when the animal gets a reward it will only delay if the reward is delayed, therefore we check if delay enabled + if delay_enabled: + sc_delay_check = 'ifDelay == 1' + pre_delay_tmp = pre_delay + #here if delay is not enabled we set the delay check to always true, whether the reward is delayed or not = + else: + sc_delay_check=f'{go_var} == 1' + pre_delay_tmp=0 + sc_no_delay = 'ifDelay == 0' + # sc_delay_check = 'ifDelay == 1' + no_delay=0 + # declare spaces + s2 = ' ' + s4 = s2*2 + s6 = s2*3 + s8 = s2*4 + s10 = s2*5 + s12 = s2*6 + s14 = s2*7 + endl = '\n' + + script = "" + script += f'int {go_var}' + endl + + # declare and init pulse & train counters and lockout + # not sure why there is no semicolon on the first one + script += f'int {pulse_counter_var} = 1' + endl + script += f'int {train_counter_var} = 1' + endl + script += f'int {lockout_var} = 0;' + endl + + script += f'function {function_num}' + endl + script += s2 + f'if ({lockout_var} == 0) do' + endl + script += s4 + f'{lockout_var} = 1' + endl + script += s4 + f'{go_var} = 1' + endl + script += s4 + f'{pulse_counter_var} = 1' + endl + script += s4 + f'{train_counter_var} = 1' + endl + + + # script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay_tmp}' + endl + script += s4 + f'if {go_check} && {sc_check} do' + endl + script += s6 + f'if {sc_delay_check} do in {pre_delay}' + endl + + # we're currently only doing one train (multiple pulses) for the delayed stim. + script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + + script += s10 + f'portout[{primary_stim_pin}]=1' + endl + + script += s10 + f'do in {pulse_length}' + endl + script += s12 + f'portout[{primary_stim_pin}]=0' + endl + script += s10 + 'end' + endl + + if n_pulses != 0: + script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + script += s8 + 'then do' + endl + script += s10 + f'{pulse_counter_var} = 1' + endl + # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains != 0: + script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s8 + 'end' + endl + script += s6 + f'else do' + endl + + + script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + + script += s10 + f'portout[{primary_stim_pin}]=1' + endl + + script += s10 + f'do in {pulse_length}' + endl + script += s12 + f'portout[{primary_stim_pin}]=0' + endl + script += s10 + 'end' + endl + if n_pulses != 0: + script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + + script += s8 + 'then do' + endl + script += s10 + f'{pulse_counter_var} = 1' + endl + + # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains != 0: + script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s8 + 'end' + endl + script += s6 + 'end' + endl + + # end the second if + script += s4 + 'end' + endl + # reset the lock out + script += s4 + f'{lockout_var} = 0' + endl + # end the first if + script += s2 + 'end' + endl + + # end the action triggering function + script += 'end;' + endl + + # declare the stop function + script += endl + script += f'function {stop_function_num}' + endl + script += s2 + f'{go_var} = 0' + endl + script += s2 + f'portout[{primary_stim_pin}]=0' + endl + script += 'end;' + endl + + + + return script + + + +def build_shortcut_command( + pipe_map, + filter_tree, + network_location, + lockout_time, + on_funct_num, + action_enabled, + off_when_false, + delay_enabled, + reward_based_trigger_enabled, + condition_tree=None, + off_funct_num=None, + ): + + def setup(reporter, data): + # setup each value + data['sub_values'] = { + sub_name: False + for sub_name in pipe_map.keys() + } + + data['trodes_sender'] = trodesnetwork.ServiceConsumer('trodes.hardware', server_address = f'{network_location.address}:{network_location.port}') + + # live updated variables + data['action_enabled'] = action_enabled + data['off_when_false'] = off_when_false + + # runtime variables + data['last_triggered'] = 0 + data['currently_triggered'] = False + + if data['off_when_false']: + assert off_funct_num is not None + + def workload(connection, publisher, reporter, data): + triggered = 0 + + # update live variables + if connection.pipe_poll(timeout = 0): + msg_tag, msg_data = connection.pipe_recv() + if msg_tag == 'update': + msg_varname, msg_value = msg_data + # update the variable + data[msg_varname] = msg_value + + if data['off_when_false']: + assert off_funct_num is not None + + ''' + # for reporter/visualization + testT = time.time() + if (testT % 0.01 <= 1e-3): #update rate is 100Hz, will plot 1000 samples in each hit + if triggered == 1: + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + reporter.send({ + 'OUTPUT_trigger': 0, + 'OUTPUT_timestamp': time.time() + }) + ''' + + + # loop updates all of the sub_values from pipe + for sub_name, source_pipe in pipe_map.items(): + if source_pipe.poll(timeout=0): + value = source_pipe.recv() + data['sub_values'][sub_name] = value + + def evaluate_node(node, data): + if 'gate' == node['data']['type']: + if 'gate-and' == node['data']['value']: + return functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-or' == node['data']['value']: + return functools.reduce(operator.or_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-nand' == node['data']['value']: + return not functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'filter' == node['data']['type']: + value = data['sub_values'][node['data']['value']] + return value + else: + raise ValueError('evaluate error: {}'.format(node)) + + evaluation = evaluate_node(filter_tree, data) if filter_tree is not None else False + + # by default the condition is True + condition = evaluate_node(condition_tree, data) if condition_tree is not None else True + + evaluation = evaluation and condition + + + + + if data['action_enabled']: + if evaluation: + currentTime = time.time() + if currentTime > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + #print('trigger time delta') + data['last_triggered'] = time.time() + #print(time.time() - currentTime) + + triggered = 1 + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + triggered = 0 + #pass + else: + if triggered == 1: #if condition is suddenly not true, sent suppress + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num}]) + else: + currentTime = time.time() + triggered = 0 + elif not data['action_enabled']: + if triggered == 1: + currentTime = time.time() + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + triggered = 0 + + + + ''' + if data['action_enabled']: + if evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + else: + # we're in lockout, so we must wait + pass + elif not data['currently_triggered']: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + elif not evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + + if not condition or data['off_when_false'] and off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + + elif not data['action_enabled']: + # we're disabled, so we want to check + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + else: + # we shut off when the action is disabled + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + ''' + + return fsgui.process.build_process_object(setup, workload) +generate_statescript diff --git a/fsgui/spikegadgets/action/__init__without_train_new.py b/fsgui/spikegadgets/action/__init__without_train_new.py new file mode 100644 index 0000000..c5ff354 --- /dev/null +++ b/fsgui/spikegadgets/action/__init__without_train_new.py @@ -0,0 +1,335 @@ +import fsgui.process +import fsgui.network +import functools +import trodesnetwork +import operator +import time + + +def generate_statescript(function_num, pre_delay, + n_pulses, n_trains, + train_interval, sequence_period, primary_stim_pin, pulse_length, + delay_enabled, reward_based_trigger_enabled): + stop_function_num = function_num+1 + go_var = f'f{function_num}go' + pulse_counter_var = f'f{function_num}PulseCounter' + train_counter_var = f'f{function_num}TrainCounter' + lockout_var = f'f{function_num}LockOut' + + go_check = f'{go_var} == 1' + #here is the first code we need to edit, as we want to seperate based on whether reward is given + #or whether delay of laser is perscribed + if reward_based_trigger_enabled: + sc_check = 'ifStim == 1' + else: + sc_check = f'{go_var} == 1' + #here we set up the delay condition, the delay enabled variable is controling whether we want to delay the laser + #stimulation when the animal gets a reward it will only delay if the reward is delayed, therefore we check if delay enabled + if delay_enabled: + sc_delay_check = 'ifDelay == 1' + pre_delay_tmp = pre_delay + #here if delay is not enabled we set the delay check to always true, whether the reward is delayed or not = + else: + sc_delay_check=f'{go_var} == 1' + pre_delay_tmp=0 + sc_no_delay = 'ifDelay == 0' + # sc_delay_check = 'ifDelay == 1' + no_delay=0 + # declare spaces + s2 = ' ' + s4 = s2*2 + s6 = s2*3 + s8 = s2*4 + s10 = s2*5 + s12 = s2*6 + s14 = s2*7 + endl = '\n' + + script = "" + script += f'int {go_var}' + endl + + # declare and init pulse & train counters and lockout + # not sure why there is no semicolon on the first one + script += f'int {pulse_counter_var} = 1' + endl + script += f'int {train_counter_var} = 1' + endl + script += f'int {lockout_var} = 0;' + endl + + script += f'function {function_num}' + endl + script += s2 + f'if ({lockout_var} == 0) do' + endl + script += s4 + f'{lockout_var} = 1' + endl + script += s4 + f'{go_var} = 1' + endl + script += s4 + f'{pulse_counter_var} = 1' + endl + script += s4 + f'{train_counter_var} = 1' + endl + + + # script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay_tmp}' + endl + script += s4 + f'if {go_check} && {sc_check} do' + endl + script += s6 + f'if {sc_delay_check} do in {pre_delay}' + endl + + # we're currently only doing one train (multiple pulses) for the delayed stim. + script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + + script += s10 + f'portout[{primary_stim_pin}]=1' + endl + + script += s10 + f'do in {pulse_length}' + endl + script += s12 + f'portout[{primary_stim_pin}]=0' + endl + script += s10 + 'end' + endl + + if n_pulses != 0: + script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + script += s8 + 'then do' + endl + script += s10 + f'{pulse_counter_var} = 1' + endl + # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains != 0: + script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s8 + 'end' + endl + script += s6 + f'else do' + endl + + + script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl + + script += s10 + f'portout[{primary_stim_pin}]=1' + endl + + script += s10 + f'do in {pulse_length}' + endl + script += s12 + f'portout[{primary_stim_pin}]=0' + endl + script += s10 + 'end' + endl + if n_pulses != 0: + script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl + + + script += s8 + 'then do' + endl + script += s10 + f'{pulse_counter_var} = 1' + endl + + # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses + if n_pulses != 0 and n_trains != 0: + script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl + script += s8 + 'end' + endl + script += s6 + 'end' + endl + + # end the second if + script += s4 + 'end' + endl + # reset the lock out + script += s4 + f'{lockout_var} = 0' + endl + # end the first if + script += s2 + 'end' + endl + + # end the action triggering function + script += 'end;' + endl + + # declare the stop function + script += endl + script += f'function {stop_function_num}' + endl + script += s2 + f'{go_var} = 0' + endl + script += s2 + f'portout[{primary_stim_pin}]=0' + endl + script += 'end;' + endl + + + + return script + + + +def build_shortcut_command( + pipe_map, + filter_tree, + network_location, + lockout_time, + on_funct_num, + action_enabled, + off_when_false, + delay_enabled, + reward_based_trigger_enabled, + condition_tree=None, + off_funct_num=None, + ): + + def setup(reporter, data): + # setup each value + data['sub_values'] = { + sub_name: False + for sub_name in pipe_map.keys() + } + + data['trodes_sender'] = trodesnetwork.ServiceConsumer('trodes.hardware', server_address = f'{network_location.address}:{network_location.port}') + + # live updated variables + data['action_enabled'] = action_enabled + data['off_when_false'] = off_when_false + + # runtime variables + data['last_triggered'] = 0 + data['currently_triggered'] = False + + if data['off_when_false']: + assert off_funct_num is not None + + def workload(connection, publisher, reporter, data): + triggered = 0 + + # update live variables + if connection.pipe_poll(timeout = 0): + msg_tag, msg_data = connection.pipe_recv() + if msg_tag == 'update': + msg_varname, msg_value = msg_data + # update the variable + data[msg_varname] = msg_value + + if data['off_when_false']: + assert off_funct_num is not None + + ''' + # for reporter/visualization + testT = time.time() + if (testT % 0.01 <= 1e-3): #update rate is 100Hz, will plot 1000 samples in each hit + if triggered == 1: + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + reporter.send({ + 'OUTPUT_trigger': 0, + 'OUTPUT_timestamp': time.time() + }) + ''' + + + # loop updates all of the sub_values from pipe + for sub_name, source_pipe in pipe_map.items(): + if source_pipe.poll(timeout=0): + value = source_pipe.recv() + data['sub_values'][sub_name] = value + + def evaluate_node(node, data): + if 'gate' == node['data']['type']: + if 'gate-and' == node['data']['value']: + return functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-or' == node['data']['value']: + return functools.reduce(operator.or_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'gate-nand' == node['data']['value']: + return not functools.reduce(operator.and_, map(lambda n: evaluate_node(n, data), node['children'])) + elif 'filter' == node['data']['type']: + value = data['sub_values'][node['data']['value']] + return value + else: + raise ValueError('evaluate error: {}'.format(node)) + + evaluation = evaluate_node(filter_tree, data) if filter_tree is not None else False + + # by default the condition is True + condition = evaluate_node(condition_tree, data) if condition_tree is not None else True + + evaluation = evaluation and condition + + + + + if data['action_enabled']: + if evaluation: + currentTime = time.time() + if currentTime > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + #print('trigger time delta') + data['last_triggered'] = time.time() + #print(time.time() - currentTime) + + triggered = 1 + reporter.send({ + 'OUTPUT_trigger': 1, + 'OUTPUT_timestamp': data['last_triggered'] + }) + else: + #triggered = 0 + pass + else: + if triggered == 1: #if condition is suddenly not true, sent suppress + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num}]) + else: + currentTime = time.time() + triggered = 0 + elif not data['action_enabled']: + if triggered == 1: + currentTime = time.time() + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + triggered = 0 + + + + ''' + if data['action_enabled']: + if evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + else: + # we're in lockout, so we must wait + pass + elif not data['currently_triggered']: + # we passed lockout time + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': on_funct_num} + ]) + data['last_triggered'] = time.time() + data['currently_triggered'] = True + elif not evaluation: + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + + if not condition or data['off_when_false'] and off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + + elif not data['action_enabled']: + # we're disabled, so we want to check + if data['currently_triggered']: + if time.time() > data['last_triggered'] + lockout_time / 1000.0: + # action already ended, no need to shut off + data['currently_triggered'] = False + data['last_triggered'] = None + else: + # we shut off when the action is disabled + if off_funct_num is not None: + data['trodes_sender'].request([ + 'tag', + 'HRSCTrig', + {'fn': off_funct_num} + ]) + data['currently_triggered'] = False + data['last_triggered'] = None + ''' + + return fsgui.process.build_process_object(setup, workload) +generate_statescript diff --git a/fsgui/spikegadgets/action/pulse.py b/fsgui/spikegadgets/action/pulse.py index 589ef41..2580940 100644 --- a/fsgui/spikegadgets/action/pulse.py +++ b/fsgui/spikegadgets/action/pulse.py @@ -1,12 +1,15 @@ import multiprocessing as mp import fsgui.process import fsgui.node -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import fsgui.spikegadgets.action.shortcut import functools import operator import time - +import threading class DigitalPulseWaveActionType(fsgui.node.NodeTypeObject): def __init__(self, type_id, network_location): super().__init__( @@ -35,11 +38,44 @@ def __init__(self, type_id, network_location): 'functNum': 0, 'action_enabled': False, 'off_when_false': False, + 'delay_enabled': False, + 'reward_based_trigger_enabled': False, } ) self.network_location = network_location + def get_gui_config(self): + return [ + { + 'type': 'checkbox', + 'name': 'action_enabled', + 'label': 'enabled', + 'checked': 'start', + 'unchecked': 'stop', + }, + { + 'type': 'checkbox', + 'name': 'delay_enabled', + 'label': 'delay', + 'checked': True, + 'unchecked': False, + }, + { + 'type': 'checkbox', + 'name': 'reward_based_trigger_enabled', + 'label': 'reward_based_trigger', + 'checked': True, + 'unchecked': False, + }, + { + 'type': 'checkbox', + 'name': 'off_when_false', + 'label': 'Turn off when false', + 'checked': True, + 'unchecked': False, + }, + ] def write_template(self, config = None): if config is None: config = self.default() @@ -179,32 +215,80 @@ def write_template(self, config = None): 'live_editable': True, 'tooltip': 'Whether or not the stimulation is shut off when false.', }, + { + 'label': 'delay', + 'name':'delay_enabled', + 'type':'boolean', + 'live_editable':True, + 'default':config['delay_enabled'], + 'tooltip':'check for whether need delay after cetain event', + + }, + { + 'label': 'reward_based_trigger', + 'name':'reward_based_trigger_enabled', + 'type':'boolean', + 'live_editable':True, + 'default':config['reward_based_trigger_enabled'], + 'tooltip':'if set true, laser will be triggered only when agent is rewarded', + }, ] def build(self, config, address_map): - # send the script - consumer = trodesnetwork.ServiceConsumer('statescript.service', server_address = f'{self.network_location.address}:{self.network_location.port}') - consumer.request({ - 'command': fsgui.spikegadgets.action.generate_statescript( - function_num=config['functNum'], - pre_delay=config['preDelay'], - n_pulses=config['nPulses'], - n_trains=config['nOutputTrains'], - train_interval=config['trainInterval'], - sequence_period=config['sequencePeriod'], - primary_stim_pin=config['primaryBit'], - pulse_length=config['pulseLength'] - ), - }) + # send the script + # consumer = trodesnetwork.ServiceConsumer('statescript.service', server_address=f'{self.network_location.address}:{self.network_location.port}') + # consumer.request({...}) + + sscClient = trodesnetwork.StateScriptClient( + server_address=f'{self.network_location.address}:{self.network_location.port}' + ) + + # Start the thread that monitors incoming messages. You only need to do this if you want to monitor the messages. + # Commands will work without it + # sscClient.open() + + # Send a statescript command + sscClient.send(fsgui.spikegadgets.action.generate_statescript( + function_num=config['functNum'], + pre_delay=config['preDelay'], + n_pulses=config['nPulses'], + n_trains=config['nOutputTrains'], + train_interval=config['trainInterval'], + sequence_period=config['sequencePeriod'], + primary_stim_pin=config['primaryBit'], + pulse_length=config['pulseLength'], + delay_enabled=config['delay_enabled'], + reward_based_trigger_enabled=config['reward_based_trigger_enabled'] + )) return fsgui.spikegadgets.action.build_shortcut_command( pipe_map=address_map, filter_tree=config['trigger_id'], network_location=self.network_location, lockout_time=config['lockout_time'], + n_trains=config['nOutputTrains'], on_funct_num=config['functNum'], action_enabled=config['action_enabled'], off_when_false=config['off_when_false'], off_funct_num=config['functNum'] + 1, condition_tree=config['condition_id'], + delay_enabled=config['delay_enabled'], + reward_based_trigger_enabled=config['reward_based_trigger_enabled'] ) + + # send the script +# consumer = trodesnetwork.ServiceConsumer('statescript.service', server_address = #f'{self.network_location.address}:{self.network_location.port}') +# consumer.request({ +# 'command': fsgui.spikegadgets.action.generate_statescript( +# function_num=config['functNum'], +# pre_delay=config['preDelay'], +# n_pulses=config['nPulses'], +# n_trains=config['nOutputTrains'], +# train_interval=config['trainInterval'], +# sequence_period=config['sequencePeriod'], +# primary_stim_pin=config['primaryBit'], +# pulse_length=config['pulseLength'], +# delay_enabled=config['delay_enabled'], +# reward_based_trigger_enabled=config['reward_based_trigger_enabled'] +# ), +# }) diff --git a/fsgui/spikegadgets/action/shortcut.py b/fsgui/spikegadgets/action/shortcut.py index 8795ea9..49894a0 100644 --- a/fsgui/spikegadgets/action/shortcut.py +++ b/fsgui/spikegadgets/action/shortcut.py @@ -1,7 +1,9 @@ import multiprocessing as mp import fsgui.process import fsgui.node -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import functools import operator import time @@ -24,6 +26,8 @@ def __init__(self, type_id, network_location): 'lockout_time': 0, 'functNum': 0, 'action_enabled': False, + 'delay_enabled': False, + 'reward_based_trigger_enabled': False, } ) @@ -93,6 +97,23 @@ def write_template(self, config = None): 'live_editable': True, 'tooltip': 'Whether or not the action is enabled.', }, + { + 'label': 'delay', + 'name':'delay_enabled', + 'type':'boolean', + 'live_editable':True, + 'default':config['delay_enabled'], + 'tooltip':'check for whether need delay after cetain event', + + }, + { + 'label': 'reward_based_trigger', + 'name':'reward_based_trigger_enabled', + 'type':'boolean', + 'live_editable':True, + 'default':config['reward_based_trigger_enabled'], + 'tooltip':'if set true, laser will be triggered only when agent is rewarded', + } ] def build(self, config, address_map): diff --git a/fsgui/spikegadgets/action/test.ipynb b/fsgui/spikegadgets/action/test.ipynb new file mode 100644 index 0000000..62d2ef0 --- /dev/null +++ b/fsgui/spikegadgets/action/test.ipynb @@ -0,0 +1,496 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "12e39e5d", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def generate_statescript(function_num, pre_delay,\n", + " n_pulses, n_trains,\n", + " train_interval, sequence_period, primary_stim_pin, pulse_length,\n", + " delay_enabled, reward_based_trigger_enabled):\n", + " \"\"\"\n", + " This script was copied and translated from StimConfigureWidget::generateStateScript. The original logic is\n", + " from 2015.\n", + "\n", + " This may need to be edited in order to include biphasic stimulation. In the case that we want to generate more\n", + " complex code.\n", + "\n", + " Example output:\n", + " ```\n", + " int f11go\n", + " int f11PulseCounter = 1\n", + " int f11TrainCounter = 1;\n", + " int f11LockOut = 0;\n", + " function 11\n", + " if (f11LockOut == 0) do\n", + " f11LockOut = 1\n", + " f11go = 1\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = 1\n", + " if f11go == 1 do in 3\n", + " while f11go == 1 && f11TrainCounter <= 7 do every 13\n", + " while f11go == 1 && f11PulseCounter <= 5 do every 17\n", + " portout[19]=1\n", + " do in 23\n", + " portout[19]=0\n", + " end\n", + " f11PulseCounter = f11PulseCounter + 1\n", + " then do\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = f11TrainCounter + 1\n", + " end\n", + " then do\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = 1\n", + " end\n", + " end\n", + " f11LockOut = 0\n", + " end\n", + " end;\n", + "\n", + " function 12\n", + " f11go = 0\n", + " end;\n", + " ```\n", + " \"\"\"\n", + " stop_function_num = function_num+1\n", + " go_var = f'f{function_num}go'\n", + " pulse_counter_var = f'f{function_num}PulseCounter'\n", + " train_counter_var = f'f{function_num}TrainCounter'\n", + " lockout_var = f'f{function_num}LockOut'\n", + "\n", + " go_check = f'{go_var} == 1'\n", + " #here is the first code we need to edit, as we want to seperate based on whether reward is given\n", + " #or whether delay of laser is perscribed\n", + " if reward_based_trigger_enabled:\n", + " sc_check = 'ifStim == 1'\n", + " else:\n", + " sc_check = '1'\n", + " #here we set up the delay condition, the delay enabled variable is controling whether we want to delay the laser\n", + " #stimulation when the animal gets a reward it will only delay if the reward is delayed, therefore we check if delay enabled\n", + " if delay_enabled:\n", + " sc_delay_check = 'ifDelay == 1'\n", + " pre_delay_tmp = pre_delay\n", + " #here if delay is not enabled we set the delay check to always true, whether the reward is delayed or not =\n", + " else:\n", + " sc_delay_check='1'\n", + " pre_delay_tmp=0\n", + " sc_no_delay = 'ifDelay == 0'\n", + " # sc_delay_check = 'ifDelay == 1'\n", + " no_delay=0\n", + " # declare spaces\n", + " s2 = ' '\n", + " s4 = s2*2\n", + " s6 = s2*3\n", + " s8 = s2*4\n", + " s10 = s2*5\n", + " s12 = s2*6\n", + " s14 = s2*7\n", + " endl = '\\n'\n", + "\n", + " script = \"\"\n", + " script += f'int {go_var}' + endl\n", + "\n", + " # declare and init pulse & train counters and lockout\n", + " # not sure why there is no semicolon on the first one\n", + " script += f'int {pulse_counter_var} = 1' + endl\n", + " script += f'int {train_counter_var} = 1' + endl\n", + " script += f'int {lockout_var} = 0;' + endl\n", + "\n", + " script += f'function {function_num}' + endl\n", + " script += s2 + f'if ({lockout_var} == 0) do' + endl\n", + " script += s4 + f'{lockout_var} = 1' + endl\n", + " script += s4 + f'{go_var} = 1' + endl\n", + " script += s4 + f'{pulse_counter_var} = 1' + endl\n", + " script += s4 + f'{train_counter_var} = 1' + endl\n", + "\n", + "\n", + " # script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay_tmp}' + endl\n", + " script += s4 + f'if {go_check} && {sc_check} do' + endl\n", + " script += s6 + f'if {sc_delay_check} do in {pre_delay}' + endl\n", + "\n", + " # we're currently only doing one train (multiple pulses) for the delayed stim.\n", + " script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl\n", + "\n", + " script += s10 + f'portout[{primary_stim_pin}]=1' + endl\n", + "\n", + " script += s10 + f'do in {pulse_length}' + endl\n", + " script += s12 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += s10 + 'end' + endl\n", + "\n", + " # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0:\n", + " script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl\n", + " # script += s8 + 'end' + endl\n", + "\n", + " script += s6 + f'else do' + endl\n", + "\n", + "\n", + " script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl\n", + "\n", + " script += s10 + f'portout[{primary_stim_pin}]=1' + endl\n", + "\n", + " script += s10 + f'do in {pulse_length}' + endl\n", + " script += s12 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += s10 + 'end' + endl\n", + "\n", + " # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0:\n", + " script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl\n", + " script += s6 + 'end' + endl\n", + "\n", + " script += s8 + 'then do' + endl\n", + " script += s10 + f'{pulse_counter_var} = 1' + endl\n", + " pre_delay_tmp = pre_delay\n", + "\n", + " # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0 and n_trains != 0:\n", + " script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl\n", + " script += s8 + 'end' + endl\n", + "\n", + " # end the second if\n", + " script += s4 + 'end' + endl\n", + " # reset the lock out\n", + " script += s4 + f'{lockout_var} = 0' + endl\n", + " # end the first if\n", + " script += s2 + 'end' + endl\n", + "\n", + " # end the action triggering function\n", + " script += 'end;' + endl\n", + "\n", + " # declare the stop function\n", + " script += endl\n", + " script += f'function {stop_function_num}' + endl\n", + " script += s2 + f'{go_var} = 0' + endl\n", + " script += s2 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += 'end;' + endl\n", + "\n", + " # script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay_tmp}' + endl\n", + "\n", + " # # we're currently only doing one train (multiple pulses) for the delayed stim.\n", + " # script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl\n", + "\n", + " # script += s10 + f'portout[{primary_stim_pin}]=1' + endl\n", + "\n", + " # script += s10 + f'do in {pulse_length}' + endl\n", + " # script += s12 + f'portout[{primary_stim_pin}]=0' + endl\n", + " # script += s10 + 'end' + endl\n", + "\n", + " # # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " # if n_pulses != 0:\n", + " # script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl\n", + "\n", + " # script += s8 + 'then do' + endl\n", + " # script += s10 + f'{pulse_counter_var} = 1' + endl\n", + " # pre_delay_tmp = pre_delay\n", + "\n", + " # # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " # if n_pulses != 0 and n_trains != 0:\n", + " # script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl\n", + " # script += s8 + 'end' + endl\n", + "\n", + " # # end the second if\n", + " # script += s4 + 'end' + endl\n", + " # # reset the lock out\n", + " # script += s4 + f'{lockout_var} = 0' + endl\n", + " # # end the first if\n", + " # script += s2 + 'end' + endl\n", + "\n", + " # # end the action triggering function\n", + " # script += 'end;' + endl\n", + "\n", + " # # declare the stop function\n", + " # script += endl\n", + " # script += f'function {stop_function_num}' + endl\n", + " # script += s2 + f'{go_var} = 0' + endl\n", + " # script += s2 + f'portout[{primary_stim_pin}]=0' + endl\n", + " # script += 'end;' + endl\n", + "\n", + " return script\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "f2d23868", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_statescript(function_num, pre_delay,\n", + " n_pulses, n_trains,\n", + " train_interval, sequence_period, primary_stim_pin, pulse_length,\n", + " delay_enabled, reward_based_trigger_enabled):\n", + " \"\"\"\n", + " This script was copied and translated from StimConfigureWidget::generateStateScript. The original logic is\n", + " from 2015.\n", + "\n", + " This may need to be edited in order to include biphasic stimulation. In the case that we want to generate more\n", + " complex code.\n", + "\n", + " Example output:\n", + " ```\n", + " int f11go\n", + " int f11PulseCounter = 1\n", + " int f11TrainCounter = 1;\n", + " int f11LockOut = 0;\n", + " function 11\n", + " if (f11LockOut == 0) do\n", + " f11LockOut = 1\n", + " f11go = 1\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = 1\n", + " if f11go == 1 do in 3\n", + " while f11go == 1 && f11TrainCounter <= 7 do every 13\n", + " while f11go == 1 && f11PulseCounter <= 5 do every 17\n", + " portout[19]=1\n", + " do in 23\n", + " portout[19]=0\n", + " end\n", + " f11PulseCounter = f11PulseCounter + 1\n", + " then do\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = f11TrainCounter + 1\n", + " end\n", + " then do\n", + " f11PulseCounter = 1\n", + " f11TrainCounter = 1\n", + " end\n", + " end\n", + " f11LockOut = 0\n", + " end\n", + " end;\n", + "\n", + " function 12\n", + " f11go = 0\n", + " end;\n", + " ```\n", + " \"\"\"\n", + " stop_function_num = function_num+1\n", + " go_var = f'f{function_num}go'\n", + " pulse_counter_var = f'f{function_num}PulseCounter'\n", + " train_counter_var = f'f{function_num}TrainCounter'\n", + " lockout_var = f'f{function_num}LockOut'\n", + "\n", + " go_check = f'{go_var} == 1'\n", + " sc_check = 'ifStim == 1'\n", + " sc_no_delay = 'ifDelay == 0'\n", + " sc_delay_check = 'ifDelay == 1'\n", + "\n", + " # declare spaces\n", + " s2 = ' '\n", + " s4 = s2*2\n", + " s6 = s2*3\n", + " s8 = s2*4\n", + " s10 = s2*5\n", + " s12 = s2*6\n", + " s14 = s2*7\n", + " endl = '\\n'\n", + "\n", + " script = \"\"\n", + " script += f'int {go_var}' + endl\n", + "\n", + " # declare and init pulse & train counters and lockout\n", + " # not sure why there is no semicolon on the first one\n", + " script += f'int {pulse_counter_var} = 1' + endl\n", + " script += f'int {train_counter_var} = 1' + endl\n", + " script += f'int {lockout_var} = 0;' + endl\n", + "\n", + " script += f'function {function_num}' + endl\n", + " script += s2 + f'if ({lockout_var} == 0) do' + endl\n", + " script += s4 + f'{lockout_var} = 1' + endl\n", + " script += s4 + f'{go_var} = 1' + endl\n", + " script += s4 + f'{pulse_counter_var} = 1' + endl\n", + " script += s4 + f'{train_counter_var} = 1' + endl\n", + "\n", + " # if delay_enabled:\n", + "\n", + " script += s4 + f'if {go_check} && {sc_check} && {sc_no_delay} do' + endl\n", + "\n", + " # set the number of trains if we're not doing continuous pulses\n", + " if n_pulses != 0:\n", + " if n_trains == 1: # No extra scheduling\n", + " pass\n", + " elif n_trains != 0:\n", + " script += s6 +f'while {go_check} && {train_counter_var} <= {n_trains} do every {train_interval}' + endl\n", + " else:\n", + " # otherwise we want continuous pulse trains, so we use 1 as the check value and skip incrementing the counter below\n", + " # we only do this if we're not doing continuous pulses\n", + " script += s6 + f'while {go_check} && {train_counter_var} <= {1} do every {train_interval}' + endl\n", + " script += s8 + f'while in {pre_delay}e {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl\n", + " else:\n", + " script += s8 + f'while {go_check} && {pulse_counter_var} <= {1} do every {sequence_period}' + endl\n", + "\n", + " script += s10 + f'portout[{primary_stim_pin}]=1' + endl\n", + "\n", + " script += s10 + f'do in {pulse_length}' + endl\n", + " script += s12 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += s10 + 'end' + endl\n", + "\n", + " # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0:\n", + " script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl\n", + "\n", + " script += s8 + 'then do' + endl\n", + " script += s10 + f'{pulse_counter_var} = 1' + endl\n", + "\n", + " # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0 and n_trains != 0:\n", + " script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl\n", + " script += s8 + 'end' + endl\n", + "\n", + " # we need to end the TrainCounter while loop\n", + " if n_trains != 1:\n", + " #if n_pulses != 0:\n", + " script += s6 + 'then do' + endl\n", + " script += s8 + f'{pulse_counter_var} = 1' + endl\n", + " script += s8 + f'{train_counter_var} = 1' + endl\n", + " script += s6 + 'end' + endl\n", + "\n", + " # end the second if\n", + " script += s4 + 'end' + endl\n", + " # reset the lock out\n", + " # script += s4 + f'{lockout_var} = 0' + endl\n", + " # end the first if\n", + " # script += s2 + 'end' + endl\n", + "# else:\n", + "###### add a parallel logic statement for doing predelay ######\n", + " script += s4 + f'if {go_check} && {sc_check} && {sc_delay_check} do in {pre_delay}' + endl\n", + "\n", + " # we're currently only doing one train (multiple pulses) for the delayed stim.\n", + " script += s8 + f'while {go_check} && {pulse_counter_var} <= {n_pulses} do every {sequence_period}' + endl\n", + "\n", + " script += s10 + f'portout[{primary_stim_pin}]=1' + endl\n", + "\n", + " script += s10 + f'do in {pulse_length}' + endl\n", + " script += s12 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += s10 + 'end' + endl\n", + "\n", + " # increment the counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0:\n", + " script += s10 + f'{pulse_counter_var} = {pulse_counter_var} + 1' + endl\n", + "\n", + " script += s8 + 'then do' + endl\n", + " script += s10 + f'{pulse_counter_var} = 1' + endl\n", + "\n", + " # increment the train counter unless the value is 0, which corresponds to continuous (infinite) pulses\n", + " if n_pulses != 0 and n_trains != 0:\n", + " script += s10 + f'{train_counter_var} = {train_counter_var} + 1' + endl\n", + " script += s8 + 'end' + endl\n", + "\n", + " # end the second if\n", + " script += s4 + 'end' + endl\n", + " # reset the lock out\n", + " script += s4 + f'{lockout_var} = 0' + endl\n", + " # end the first if\n", + " script += s2 + 'end' + endl\n", + "\n", + " # end the action triggering function\n", + " script += 'end;' + endl\n", + "\n", + " # declare the stop function\n", + " script += endl\n", + " script += f'function {stop_function_num}' + endl\n", + " script += s2 + f'{go_var} = 0' + endl\n", + " script += s2 + f'portout[{primary_stim_pin}]=0' + endl\n", + " script += 'end;' + endl\n", + "\n", + " return script" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "a111550b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "int f0go\n", + "int f0PulseCounter = 1\n", + "int f0TrainCounter = 1\n", + "int f0LockOut = 0;\n", + "function 0\n", + " if (f0LockOut == 0) do\n", + " f0LockOut = 1\n", + " f0go = 1\n", + " f0PulseCounter = 1\n", + " f0TrainCounter = 1\n", + " if f0go == 1 && 1 do\n", + " if ifDelay == 1 do in 333\n", + " while f0go == 1 && f0PulseCounter <= 5 do every 100\n", + " portout[1]=1\n", + " do in 1\n", + " portout[1]=0\n", + " end\n", + " f0PulseCounter = f0PulseCounter + 1\n", + " else do\n", + " while f0go == 1 && f0PulseCounter <= 5 do every 100\n", + " portout[1]=1\n", + " do in 1\n", + " portout[1]=0\n", + " end\n", + " f0PulseCounter = f0PulseCounter + 1\n", + " end\n", + " then do\n", + " f0PulseCounter = 1\n", + " f0TrainCounter = f0TrainCounter + 1\n", + " end\n", + " end\n", + " f0LockOut = 0\n", + " end\n", + "end;\n", + "\n", + "function 1\n", + " f0go = 0\n", + " portout[1]=0\n", + "end;\n", + "\n" + ] + } + ], + "source": [ + "# generate_statescript(function_num, pre_delay,\n", + "# n_pulses, n_trains,\n", + "# train_interval, sequence_period, primary_stim_pin, pulse_length,\n", + "# delay_enabled, reward_based_trigger_enabled):\n", + "print(generate_statescript(0,333,5,1,1000,100,1,1,True,False))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f99c197", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "fsgui", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/fsgui/spikegadgets/source/binned_camera.py b/fsgui/spikegadgets/source/binned_camera.py index 9464c60..99cbaa4 100644 --- a/fsgui/spikegadgets/source/binned_camera.py +++ b/fsgui/spikegadgets/source/binned_camera.py @@ -1,9 +1,10 @@ import multiprocessing as mp import fsgui.process import fsgui.node -import fsgui.spikegadgets.trodes import logging -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import fsgui.network import time import numpy as np @@ -72,7 +73,7 @@ def setup(logging, data): data['receive_none_counter'] = 0 def workload(connection, publisher, reporter, data): - camera_data = data['camera_sub'].receive(timeout=50) + camera_data = data['camera_sub'].receive() if camera_data is None: data['receive_none_counter'] += 1 if data['receive_none_counter'] > 40 and data['receive_none_counter'] % 40 == 0: @@ -100,4 +101,4 @@ def workload(connection, publisher, reporter, data): }) return fsgui.process.build_process_object(setup, workload) - \ No newline at end of file + diff --git a/fsgui/spikegadgets/source/camera.py b/fsgui/spikegadgets/source/camera.py index 5b80837..e59770e 100644 --- a/fsgui/spikegadgets/source/camera.py +++ b/fsgui/spikegadgets/source/camera.py @@ -1,9 +1,10 @@ import multiprocessing as mp import fsgui.process import fsgui.node -import fsgui.spikegadgets.trodes import logging -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import fsgui.network import time @@ -58,7 +59,7 @@ def setup(logging, data): data['receive_none_counter'] = 0 def workload(connection, publisher, reporter, data): - camera_data = data['camera_sub'].receive(timeout=50) + camera_data = data['camera_sub'].receive() if camera_data is None: data['receive_none_counter'] += 1 if data['receive_none_counter'] > 40 and data['receive_none_counter'] % 40 == 0: @@ -68,4 +69,4 @@ def workload(connection, publisher, reporter, data): publisher.send(camera_data) return fsgui.process.build_process_object(setup, workload) - \ No newline at end of file + diff --git a/fsgui/spikegadgets/source/lfp.py b/fsgui/spikegadgets/source/lfp.py index 4c2668e..73db347 100644 --- a/fsgui/spikegadgets/source/lfp.py +++ b/fsgui/spikegadgets/source/lfp.py @@ -2,8 +2,9 @@ import fsgui.process import fsgui.node import fsgui.network -import fsgui.spikegadgets.trodes -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import json import time @@ -59,7 +60,7 @@ def setup(logging, data): data['receive_none_counter'] = 0 def workload(connection, publisher, reporter, data): - lfp_data = data['lfp_sub'].receive(timeout=50) + lfp_data = data['lfp_sub'].receive() if lfp_data is None: data['receive_none_counter'] += 1 if data['receive_none_counter'] > 40 and data['receive_none_counter'] % 40 == 0: diff --git a/fsgui/spikegadgets/source/spikes.py b/fsgui/spikegadgets/source/spikes.py index 3c16020..d1696dd 100644 --- a/fsgui/spikegadgets/source/spikes.py +++ b/fsgui/spikegadgets/source/spikes.py @@ -2,8 +2,9 @@ import fsgui.process import fsgui.node import fsgui.network -import fsgui.spikegadgets.trodes -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket import logging import json import numpy as np @@ -77,9 +78,9 @@ def workload(connection, publisher, reporter, data): msg_varname, msg_value = msg_data config[msg_varname] = msg_value - spikes_data = data['spikes_sub'].receive(timeout=50) + spikes_data = data['spikes_sub'].receive() if spikes_data is not None: spikes_data['samples'] = (np.array(spikes_data['samples']) * config['voltage_scaling_factor']).tolist() publisher.send(spikes_data) - return fsgui.process.build_process_object(setup, workload) \ No newline at end of file + return fsgui.process.build_process_object(setup, workload) diff --git a/fsgui/spikegadgets/source/timestamp.py b/fsgui/spikegadgets/source/timestamp.py index b1e4e53..0c4729d 100644 --- a/fsgui/spikegadgets/source/timestamp.py +++ b/fsgui/spikegadgets/source/timestamp.py @@ -1,12 +1,13 @@ import multiprocessing as mp import fsgui.process import fsgui.node -import fsgui.spikegadgets.trodes import logging import json import time import fsgui.network -import fsgui.spikegadgets.trodesnetwork as trodesnetwork +import trodesnetwork +from trodesnetwork import trodes +from trodesnetwork import socket class TimestampDataType(fsgui.node.NodeTypeObject): def __init__(self, type_id, network_location): @@ -59,7 +60,7 @@ def setup(reporter, data): data['sub'] = trodesnetwork.SourceSubscriber('source.lfp', server_address = f'{self.network_location.address}:{self.network_location.port}') def workload(connection, publisher, reporter, data): - timestamp_data = data['sub'].receive(timeout=50) + timestamp_data = data['sub'].receive() if timestamp_data is not None: hardware_ts = timestamp_data['localTimestamp'] publisher.send(hardware_ts)