You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<h2>Creating & loading a Python Module<aclass="headerlink" href="#creating-loading-a-python-module" title="Permalink to this heading">#</a></h2>
563
563
<p>Once the plugin is loaded into the signal chain, a Python module (script) needs to be loaded into the GUI. This module should take the same form as the <aclass="reference external" href="https://github.com/open-ephys-plugins/python-processor/blob/main/Modules/template/processor_template.py">processor template</a> provided in the plugin’s GitHub repository. The <codeclass="code docutils literal notranslate"><spanclass="pre">PyProcessor</span></code> class is designed to expose the following functions to the Python module to allow interaction with the incoming data:</p>
564
-
<dlclass="py function">
564
+
<dlclass="py method">
565
565
<dtclass="sig sig-object py" id="init__">
566
-
<spanclass="sig-name descname"><spanclass="pre">__init__</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">num_channels</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">sample_rate</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#init__" title="Permalink to this definition">#</a></dt>
566
+
<spanclass="sig-name descname"><spanclass="pre">__init__</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">processor</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">num_channels</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">sample_rate</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#init__" title="Permalink to this definition">#</a></dt>
567
567
<dd><p>A new processor is initialized when the module is imported/reloaded, or the plugin’s settings are updated (i.e., the number of input channels changes, or a new stream is selected).</p>
<li><p><strong>num_channels</strong> – number of input channels from the selected stream</p></li>
572
-
<li><p><strong>sample_rate</strong> – the selected stream’s sample rate</p></li>
571
+
<li><p><strong>processor</strong> (<em>object</em>) – Python Processor class object used for adding events from python.</p></li>
572
+
<li><p><strong>num_channels</strong> (<em>int</em>) – number of input channels from the selected stream</p></li>
573
+
<li><p><strong>sample_rate</strong> (<em>float</em>) – the selected stream’s sample rate</p></li>
573
574
</ul>
574
575
</dd>
575
576
</dl>
576
577
</dd></dl>
577
578
578
-
<dlclass="py function">
579
+
<dlclass="py method">
579
580
<dtclass="sig sig-object py" id="process">
580
-
<spanclass="sig-name descname"><spanclass="pre">process</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">data</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#process" title="Permalink to this definition">#</a></dt>
581
+
<spanclass="sig-name descname"><spanclass="pre">process</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">data</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#process" title="Permalink to this definition">#</a></dt>
581
582
<dd><p>Process each incoming data buffer. Any modifications to the <codeclass="code docutils literal notranslate"><spanclass="pre">data</span></code> variable will be passed to downstream processors.</p>
<spanclass="sig-name descname"><spanclass="pre">start_acquisition</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#start_acquisition" title="Permalink to this definition">#</a></dt>
592
+
<spanclass="sig-name descname"><spanclass="pre">start_acquisition</span></span><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="headerlink" href="#start_acquisition" title="Permalink to this definition">#</a></dt>
592
593
<dd><p>Called before starting acquisition. Allows the script to do some setup/initialization before acquisition starts.</p>
<spanclass="sig-name descname"><spanclass="pre">stop_acquisition</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#stop_acquisition" title="Permalink to this definition">#</a></dt>
598
+
<spanclass="sig-name descname"><spanclass="pre">stop_acquisition</span></span><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="headerlink" href="#stop_acquisition" title="Permalink to this definition">#</a></dt>
598
599
<dd><p>Called after stopping acquisition. Allows the script to do some finalization after acquisition stops.</p>
<spanclass="sig-name descname"><spanclass="pre">start_recording</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">recording_dir</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#start_recording" title="Permalink to this definition">#</a></dt>
604
+
<spanclass="sig-name descname"><spanclass="pre">start_recording</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">recording_dir</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#start_recording" title="Permalink to this definition">#</a></dt>
604
605
<dd><p>Called before starting recording. Informs the plugin that the GUI is now recording data, in case it needs to save any information of its own.</p>
<ddclass="field-odd"><p><strong>recording_dir</strong> – directory where recording related files are supposed to be stored</p>
608
+
<ddclass="field-odd"><p><strong>recording_dir</strong>(<em>str</em>) – directory where recording related files are supposed to be stored</p>
608
609
</dd>
609
610
</dl>
610
611
</dd></dl>
611
612
612
-
<dlclass="py function">
613
+
<dlclass="py method">
613
614
<dtclass="sig sig-object py" id="stop_recording">
614
-
<spanclass="sig-name descname"><spanclass="pre">stop_recording</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">self</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#stop_recording" title="Permalink to this definition">#</a></dt>
615
+
<spanclass="sig-name descname"><spanclass="pre">stop_recording</span></span><spanclass="sig-paren">(</span><spanclass="sig-paren">)</span><aclass="headerlink" href="#stop_recording" title="Permalink to this definition">#</a></dt>
615
616
<dd><p>Called before stopping recording. Informs the plugin that the GUI is no longer recording data.</p>
<li><p><strong>source_node</strong> – id of the processor this spike was generated from</p></li>
643
-
<li><p><strong>electrode_name</strong> – name of the electrode</p></li>
644
-
<li><p><strong>num_channels</strong> – number of channels associated with the electrode type</p></li>
645
-
<li><p><strong>num_samples</strong> – total number of samples in the spike waveform</p></li>
646
-
<li><p><strong>sample_number</strong> – sample number of the spike</p></li>
647
-
<li><p><strong>sorted_id</strong> – the sorted ID for this spike</p></li>
648
-
<li><p><strong>spike_data</strong> – waveform as N x M numpy array, where N = num_channels & M = num_samples (read-only).</p></li>
643
+
<li><p><strong>source_node</strong>(<em>int</em>) – id of the processor this spike was generated from</p></li>
644
+
<li><p><strong>electrode_name</strong>(<em>str</em>) – name of the electrode</p></li>
645
+
<li><p><strong>num_channels</strong>(<em>int</em>) – number of channels associated with the electrode type</p></li>
646
+
<li><p><strong>num_samples</strong>(<em>int</em>) – total number of samples in the spike waveform</p></li>
647
+
<li><p><strong>sample_number</strong>(<em>int</em>) – sample number of the spike</p></li>
648
+
<li><p><strong>sorted_id</strong>(<em>int</em>) – the sorted ID for this spike</p></li>
649
+
<li><p><strong>spike_data</strong>(<em>ndarrary</em>) – waveform as N x M numpy array, where N = num_channels & M = num_samples (read-only).</p></li>
649
650
</ul>
650
651
</dd>
651
652
</dl>
@@ -656,21 +657,22 @@ <h2>Creating & loading a Python Module<a class="headerlink" href="#creating-
656
657
<pclass="admonition-title">Note</p>
657
658
<p>Pay careful attention to the latency introduced by processing data in Python, especially with high-channel-count data.</p>
658
659
</div>
659
-
<p>There is also a way to send TTL events back from Python to C++. These events will be added to the event buffer for the downstream processors to handle. It is possible using a C++ function exposed to the Python module via an embedded module called <codeclass="code docutils literal notranslate"><spanclass="pre">oe_pyprocessor</span></code>. To use this function, the <codeclass="code docutils literal notranslate"><spanclass="pre">oe_pyprocessor</span></code> module needs to be imported inside the script and then the C++ function can be invoked like this: <codeclass="code docutils literal notranslate"><spanclass="pre">oe_pyprocessor.add_python_event(line,</span><spanclass="pre">state)</span></code></p>
660
-
<dlclass="py function">
660
+
<p>There is also a way to send TTL events back from Python to C++. These events will be added to the event buffer for the downstream processors to handle. It is possible using a C++ function exposed to the Python module via an embedded module called <codeclass="code docutils literal notranslate"><spanclass="pre">oe_pyprocessor</span></code>.</p>
<spanclass="sig-name descname"><spanclass="pre">add_python_event</span></span><spanclass="sig-paren">(</span><emclass="sig-param"><spanclass="n"><spanclass="pre">line</span></span></em>, <emclass="sig-param"><spanclass="n"><spanclass="pre">state</span></span></em><spanclass="sig-paren">)</span><aclass="headerlink" href="#add_python_event" title="Permalink to this definition">#</a></dt>
<li><p><strong>line</strong>– (int) event line number [0-255]</p></li>
668
-
<li><p><strong>electrode_name</strong>– (bool) event state True (ON) or False (OFF)</p></li>
668
+
<li><p><strong>line</strong>(<em>int</em>) – event line number [0-255]</p></li>
669
+
<li><p><strong>state</strong>(<em>bool</em>) – event state True (ON) or False (OFF)</p></li>
669
670
</ul>
670
671
</dd>
671
672
</dl>
672
673
</dd></dl>
673
674
675
+
<p>To use this function, the <codeclass="code docutils literal notranslate"><spanclass="pre">oe_pyprocessor</span></code> module needs to be imported inside the script and then the C++ function can be invoked by using the processor object provided in the <aclass="reference internal" href="#init__" title="__init__"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">__init__()</span></code></a> method, like this: <codeclass="code docutils literal notranslate"><spanclass="pre">self.processor.add_python_event(line,</span><spanclass="pre">state)</span></code></p>
674
676
<p>An example script is provided in the plugin’s GitHub repository in the form of a <aclass="reference external" href="https://github.com/open-ephys-plugins/python-processor/blob/main/Modules/examples/bandpass_filter.py">Butterworth Bandpass filter</a>. This filter is the same as the one used in the GUI’s built-in Filter Node plugin.</p>
0 commit comments