Skip to content

Commit

Permalink
Added digital option for stimmers
Browse files Browse the repository at this point in the history
  • Loading branch information
theonlydvr committed Jun 21, 2024
1 parent ee61e3e commit a84f541
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 22 deletions.
9 changes: 9 additions & 0 deletions pybehave/Components/DigitalWaveformStim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from pybehave.Components.Component import Component
from pybehave.Components.WaveformStim import WaveformStim


class DigitalWaveformStim(WaveformStim):

@staticmethod
def get_type() -> Component.Type:
return Component.Type.DIGITAL_OUTPUT
2 changes: 1 addition & 1 deletion pybehave/Events/OENetworkLogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def receive(self) -> None:
def log_events(self, events: collections.deque[LoggerEvent]) -> None:
for event in events:
self.event_count += 1
if isinstance(event.event, self.OEEvent):
if isinstance(event.event, OEEvent):
if event.event.event_type == 'startAcquisition':
self.send_string("startAcquisition")
elif event.event.event_type == 'stopAcquisition':
Expand Down
34 changes: 19 additions & 15 deletions pybehave/Events/OEWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def __init__(self, name: str, address: str, port: str):
oe_text_layout = QHBoxLayout(self.oe_group)
oe_control_layout = QVBoxLayout(self.oe_group)

icons_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Workstation/icons'))

# Widget corresponding to the path for the output folder for OpenEphys
rec_dir_box = QGroupBox('RecDir')
rec_dir_layout = QHBoxLayout(self.oe_group)
Expand All @@ -54,7 +56,7 @@ def __init__(self, name: str, address: str, port: str):
self.rec_dir.setReadOnly(True)
rec_dir_layout.addWidget(self.rec_dir)
self.rec_dir_browse = QPushButton()
self.rec_dir_browse.setIcon(QIcon('Workstation/icons/folder.svg'))
self.rec_dir_browse.setIcon(QIcon(os.path.join(icons_dir, 'folder.svg')))
self.rec_dir_browse.setFixedWidth(30)
self.rec_dir_browse.clicked.connect(lambda: self.get_file_path())
rec_dir_layout.addWidget(self.rec_dir_browse)
Expand All @@ -76,11 +78,11 @@ def __init__(self, name: str, address: str, port: str):
oe_rec_layout.addLayout(oe_text_layout)
oe_group_layout.addLayout(oe_rec_layout)

self.acq_button = IconButton('Workstation/icons/play.svg', 'Workstation/icons/play_hover.svg')
self.acq_button = IconButton(os.path.join(icons_dir, 'play.svg'), os.path.join(icons_dir, 'play_hover.svg'))
self.acq_button.setFixedWidth(30)
self.acq_button.clicked.connect(self.acquisition)
oe_control_layout.addWidget(self.acq_button)
self.rec_button = IconButton('Workstation/icons/record.svg', 'Workstation/icons/record_hover.svg')
self.rec_button = IconButton(os.path.join(icons_dir, 'record.svg'), os.path.join(icons_dir, 'record_hover.svg'))
self.rec_button.setFixedWidth(30)
self.rec_button.clicked.connect(self.record)
oe_control_layout.addWidget(self.rec_button)
Expand Down Expand Up @@ -114,33 +116,35 @@ def set_chamber(self, cw: ChamberWidget) -> None:
"%m-%d-%Y")))

def acquisition(self) -> None:
icons_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Workstation/icons'))
if not self.acq:
self.acq_button.icon = 'Workstation/icons/stop_play.svg'
self.acq_button.hover_icon = 'Workstation/icons/stop_play_hover.svg'
self.acq_button.icon = os.path.join(icons_dir, 'stop_play.svg')
self.acq_button.hover_icon = os.path.join(icons_dir, 'stop_play_hover.svg')
self.acq_button.setIcon(QIcon(self.acq_button.icon))
self.send_string("startAcquisition")
# self.queue.put_nowait(PybEvents.OEEvent(self.cw.task, "startAcquisition").format())
self.acq = True
elif self.acq:
self.acq_button.icon = 'Workstation/icons/play.svg'
self.acq_button.hover_icon = 'Workstation/icons/play_hover.svg'
self.acq_button.icon = os.path.join(icons_dir, 'play.svg')
self.acq_button.hover_icon = os.path.join(icons_dir, 'play_hover.svg')
self.acq_button.setIcon(QIcon(self.acq_button.icon))
if self.rec:
self.rec_button.icon = 'Workstation/icons/record.svg'
self.rec_button.hover_icon = 'Workstation/icons/record_hover.svg'
self.rec_button.icon = os.path.join(icons_dir, 'record.svg')
self.rec_button.hover_icon = os.path.join(icons_dir, 'record_hover.svg')
self.rec_button.setIcon(QIcon(self.rec_button.icon))
self.rec = False
self.send_string("stopAcquisition")
# self.queue.put_nowait(PybEvents.OEEvent(self.cw.task, "stopAcquisition").format())
self.acq = False

def record(self) -> None:
icons_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Workstation/icons'))
if not self.rec:
self.acq_button.icon = 'Workstation/icons/stop_play.svg'
self.acq_button.hover_icon = 'Workstation/icons/stop_play_hover.svg'
self.acq_button.icon = os.path.join(icons_dir, 'stop_play.svg')
self.acq_button.hover_icon = os.path.join(icons_dir, 'stop_play_hover.svg')
self.acq_button.setIcon(QIcon(self.acq_button.icon))
self.rec_button.icon = 'Workstation/icons/stop_record.svg'
self.rec_button.hover_icon = 'Workstation/icons/stop_record_hover.svg'
self.rec_button.icon = os.path.join(icons_dir, 'stop_record.svg')
self.rec_button.hover_icon = os.path.join(icons_dir, 'stop_record_hover.svg')
self.rec_button.setIcon(QIcon(self.rec_button.icon))
self.send_string("startRecord RecDir={} prependText={} appendText={}".format(self.rec_dir.text(),
self.pre.text(),
Expand All @@ -149,8 +153,8 @@ def record(self) -> None:
self.acq = True
self.rec = True
elif self.rec:
self.rec_button.icon = 'Workstation/icons/record.svg'
self.rec_button.hover_icon = 'Workstation/icons/record_hover.svg'
self.rec_button.icon = os.path.join(icons_dir, 'record.svg')
self.rec_button.hover_icon = os.path.join(icons_dir, 'record_hover.svg')
self.rec_button.setIcon(QIcon(self.rec_button.icon))
self.send_string("stopRecord")
# self.queue.put_nowait(PybEvents.OEEvent(self.cw.task, "stopRecord").format())
Expand Down
43 changes: 37 additions & 6 deletions pybehave/Sources/NIDAQSource.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,30 @@ def __init__(self, dev):
self.streams = {}
self.ao_task = None
self.ao_stream = None
self.do_task = None
self.do_stream = None
self.ao_inds = {}
self.do_inds = {}

def initialize(self):
dev_obj = system.Device(self.dev)
dev_obj.reset_device()

def register_component(self, component, metadata):
if component.get_type() == Component.Type.DIGITAL_OUTPUT:
task = nidaqmx.Task()
task.do_channels.add_do_chan(self.dev + component.address,
line_grouping=LineGrouping.CHAN_FOR_ALL_LINES)
task.start()
self.tasks[component.id] = task
if component.sr is None:
task = nidaqmx.Task()
task.do_channels.add_do_chan(self.dev + component.address,
line_grouping=LineGrouping.CHAN_FOR_ALL_LINES)
task.start()
self.tasks[component.id] = task
else:
if self.do_task is None:
self.do_task = nidaqmx.Task()
self.do_task.auto_start = True
self.do_task.do_channels.add_do_chan(self.dev + component.address)
self.do_stream = stream_writers.DigitalMultiChannelWriter(self.do_task.out_stream, auto_start=True)
self.do_inds[component.id] = len(self.do_inds)
elif component.get_type() == Component.Type.ANALOG_OUTPUT:
if self.ao_task is None:
self.ao_task = nidaqmx.Task()
Expand All @@ -76,6 +87,10 @@ def close_source(self):
self.ao_task.close()
self.ao_task = None
self.ao_stream = None
if self.do_task is not None:
self.do_task.close()
self.do_task = None
self.do_stream = None
for task in self.tasks:
task.close()
self.tasks = {}
Expand All @@ -88,12 +103,26 @@ def close_component(self, component_id):
self.ao_task = None
self.ao_stream = None
else:
if self.components[component_id].sr is not None:
if self.do_task is not None:
self.do_task.stop()
self.do_task.close()
self.do_task = None
self.do_stream = None
self.tasks[component_id].stop()
self.tasks[component_id].close()

def write_component(self, component_id, msg):
if self.components[component_id].get_type() == Component.Type.DIGITAL_OUTPUT:
self.tasks[component_id].write(msg)
if self.components[component_id].sr is not None:
output = np.zeros((len(self.do_inds), msg.shape[1]))
output[self.do_inds[component_id], :] = np.squeeze(msg)
# self.do_task.timing.cfg_samp_clk_timing(self.components[component_id].sr,
# sample_mode=nidaqmx.constants.AcquisitionType.FINITE,
# samps_per_chan=msg.shape[1])
self.do_stream.write_many_sample_port_uint32(np.uint32(output))
else:
self.tasks[component_id].write(msg)
elif self.components[component_id].get_type() == Component.Type.ANALOG_OUTPUT:
output = np.zeros((len(self.ao_inds), msg.shape[1]))
output[self.ao_inds[component_id], :] = np.squeeze(msg)
Expand All @@ -109,5 +138,7 @@ def write_component(self, component_id, msg):
def metadata_defaults(comp_type: Component.Type = None) -> Dict:
if comp_type == Component.Type.ANALOG_OUTPUT:
return {"sr": 30000}
elif comp_type == Component.Type.DIGITAL_OUTPUT:
return {"sr": None}
else:
return {}

0 comments on commit a84f541

Please sign in to comment.