Skip to content

medengineer/MatlabInterface

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Matlab Interface

The Matlab plugin for the Open Ephys GUI allows users to stream live data from the Open Ephys GUI to a live Matlab session. A Matlab API is included which allows seamless processing of the incoming data in real-time. This is an early release of the plugin that currently supports streaming a single channel to Matlab in real time. If you are interested in additional functionality, please open an issue describing your intended use case and we can prioritize development based on demand.

Installation:

Option 1: Download pre-compiled binaries

If you are using the pre-compiled version of the Open Ephys GUI, you should download the pre-compiled Matlab plugin for your particular platform in the table below. Once downloaded, extract the .zip file contents into the plugins directory of your Open Ephys folder.

Platform Link
Windows matlab-plugin-for-windows
Linux matlab-plugin-for-linux
Mac matlab-plugin-for-mac

Option 2: Build from source

If you have compiled the Open Ephys GUI from source already, you can compile the Matlab plugin from source as well. As with all outside plugins, the root folder should be stored inside a directory at the same level as the plugin-GUI. For example:

plugin-GUI
└───Source
└───Build

OEPlugins
└───MatlabEngine
    └───Source
    └───Build
    └───MatlabAPI

Using the above directory format, installing from source (on Linux) would look like this:

cd OEPlugins
git clone https://github.com/open-ephys-plugins/matlab-plugin.git
cd Build
cmake -G "Unix Makefiles" ..
make install

Usage:

Once installed, the plugin will appear as 'MatlabEngine' in the 'Filters' section of the 'Processor List' of the Open Ephys GUI. The Matlab plugin can be placed after any source or filter in the signal chain and will stream the data generated by the preceding processor into your Matlab session.

When you are ready to acquire data, you will need to press the 'Connect' button in the 'MatlabEngine' editor to initiate a connection between Open Ephys and your Matlab session. The plugin will open a socket using the IP and Port address listed in the MatlabEngine editor.

To initialize the connection on the Matlab side, you will need to call your generated script from Matlab following the instructions below. Once the connection has been initiated on both sides, pressing the Play button in the Open Ephys GUI will automatically stream the incoming data to Matlab.

Matlab API

In order to process the incoming data in Matlab, you will need to leverage the included Matlab API. The API was designed specifically to introduce/reinforce object oriented programming and to encourage Matlab evangelists to consider developing plugins in C++.

The Matlab API is centered around a GenericProcessor class that encapsulates an Open Ephys data processor. The idea is to write your own class that inherits and extends a Generic Processor. A starting template is included below:

classdef MyClass < GenericProcessor

    properties
        %define any variables you want to keep track of here (see examples)
    end

    methods 

        function self = Plotter(host, port)
            
            self = self@GenericProcessor(host, port);

            %Initialize any variables here (see examples)

            self.process();

        end

    end

    methods (Access = protected)

        function process(self)
            
            while (true) 

                process@GenericProcessor(self); 

                numSamples = self.dataIn.numSamplesFetched;
                
                data = self.dataIn.continuous(1:end);

                %Do whatever you want with the data here (see examples)

            end

        end

    end

end

Here's an example of a simple peak detection algorithm:

classdef PeakDetector < GenericProcessor

    properties
        peaks;
    end
    
    methods 

        function self = PeakDetector(host, port)
            
            self = self@GenericProcessor(host, port);
            self.process();

        end

    end

    methods (Access = protected)

        function process(self)
            
            while (true)
                process@GenericProcessor(self); 
                
                yd = diff(self.dataIn.continuous)./diff(1:self.dataIn.numSamplesFetched);
                self.peaks = find(~yd);
                
            end

        end

    end

end

And a simple threshold detector...

classdef ThresholdDetector < GenericProcessor

    properties
        thresholdValue;
    end

    methods 

        function self = ThresholdDetector(host, port)
            
            self = self@GenericProcessor(host, port);
            
            self.thresholdValue = 3.2; %V
            
            self.process();

        end

    end

    methods (Access = protected)

        function process(self)
            
            while (true)
                
                process@GenericProcessor(self); 
                k = find(self.dataIn.continuous > self.thresholdValue);

            end

        end

    end

end

And here's an example of a Plotter that plots the incoming data to a figure in real-time.

classdef Plotter < GenericProcessor

    properties
        hPlot;
    end
    
    properties
        xAxisRange;
        yAxisRange;
    end

    methods 

        function self = Plotter(host, port)
            
            self = self@GenericProcessor(host, port);
            
            self.xAxisRange = [0,80000];
            self.yAxisRange = [-1000 1000];
            
            plotTitle = 'Open Ephys Data Stream';
            xLabel = 'Sample Count';
            yLabel = 'Voltage [uV]';

            clf; cla; 
            self.hPlot = plot(0,0); drawnow; hold on;
            title(plotTitle);
            xlabel(xLabel); ylabel(yLabel);
            xlim(self.xAxisRange); ylim(self.yAxisRange);
            
            self.process();

        end

    end

    methods (Access = protected)

        function process(self)
            
            lastSample = 0;
            xAxisSize = self.xAxisRange(2);
            
            while ishandle(self.hPlot) 

                process@GenericProcessor(self); 

                numSamples = self.dataIn.numSamplesFetched;

                if lastSample + numSamples > xAxisSize
                    xData = (lastSample+1):xAxisSize;
                    yData = self.dataIn.continuous(1:(xAxisSize-lastSample));
                else
                    xData = (lastSample+1):(lastSample+numSamples);
                    yData = self.dataIn.continuous;
                end

                self.hPlot = plot(xData,yData); drawnow;
                set(self.hPlot, 'XData', xData, 'YData', yData); 

                %TODO: Currently ignores (doesn't plot) samples that overshoot x-axis range
                lastSample = lastSample + numSamples;
                if lastSample > xAxisSize
                    lastSample = 0;
                    cla; self.hPlot = plot(0,0); drawnow; 
                end

            end

        end

    end

end

Once you have designed your class, you can call it from the Matlab command window using MyClass(host,port), where host and port need to match the entries specified in the MatlabEngine editor in the OpenEphys GUI.

Questions and Troubleshooting

If you have any questions and/or issues regarding this plugin, please reach out to me directly at [email protected].

I will keep track of FAQs here as they come in.

About

Open Ephys plugin for streaming data to Matlab.

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •