GithubHelp home page GithubHelp logo

symphony-das / symphony-matlab Goto Github PK

View Code? Open in Web Editor NEW
19.0 7.0 5.0 6.05 MB

Symphony Data Acquisition System

Home Page: http://symphony-das.github.io

License: MIT License

MATLAB 98.31% M 0.28% Java 1.31% HTML 0.07% CSS 0.03%
matlab data-acquisition electrophysiology daq scientific

symphony-matlab's Introduction

Symphony

Symphony is a MATLAB based data acquisition system for electrophysiologists. It provides a framework for writing acquisition routines and a user interface to conduct experiments.

Clone

git clone https://github.com/Symphony-DAS/symphony-matlab.git --recursive

Note: You must use the --recursive option to recursively clone all submodules.

Build

Matlab functions in the root directory are used to build the project. The scripts are named according to the build phase they execute. The phases include:

  • test: run tests using the Matlab unit test framework
  • package: package the project into a .mlappinstall file
  • install: install the packaged product into Matlab

Similar to the Maven Build Lifecycle, each phase will execute all phases before it (i.e. running install will execute test, package, install). In addition there is a site script to generate the project's documentation from the wiki.

Directory Structure

The project directory structure generally follows the Maven Standard Directory Layout.

License

Licensed under the MIT License, which is an open source license.

symphony-matlab's People

Contributors

cafarm avatar samcooler avatar zfj1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

symphony-matlab's Issues

Work on UI performance

Things feel a bit slow in the UI, especially on first load. This is partly unavoidable because MATLAB is slow but there might be some areas where things could be improved. In areas where they can't, showing spinners is helpful to communicate that things are working after the user clicks something (the Initialize Rig window really needs a spinner because it can take some time after the user clicks "Initialize" before anything happens).

protocol preset queue

We'd like our actions during the course of the experiment to be less tied to the durations of procol epoch sets, always waiting on the rig to pick the next protocol's parameters. Typically, I know the first several things I'm going to do to a cell, once I'm attached well. Some cells have 30 minutes of pre-determined protocol sets, and I don't need to watch all the results as they come in.

So I propose a new feature, which is an experiment session queue, in which protocols, with params encapsulated as presets, chosen from the list, are added and ordered and executed one after the other, in a visual queue GUI. The queue can be reordered and modified (drag and drop?).
The play/pause/stop controls are then moved to this queue window. The protocol browser, as it is now, is used to create and modify the presets. That is, its behavior is not connected to the run state. The buttons at the bottom of this are then "add as preset" "add to queue" "add to queue and as preset". The preset browser has buttons "add as next" "add as last", and context menus to "add as preset".

-sam

Documentation has some visual bugs in R2016b

MathWorks changed some stuff about the Documentation viewer in R2016b and now the Symphony documentation has some visual bugs:

  • There is a second set of scroll bars around the documentation itself
  • There is a second line above the TOCs in the "Contents" side bar

Sort sources by creation date

Sources should be shown in the data manager by creation date. This isn't a problem when you initially make the sources because they naturally add in that order but the order becomes random when you reopen an existing file.

Change properties that use cellArrayFromEnumerable from properties to methods

Some classes that derive from CoreObject have properties that call cellArrayFromEnumerable. For example, EpochGroup:

function b = get.epochBlocks(obj)
    b = obj.cellArrayFromEnumerable(obj.cobj.EpochBlocks, @symphonyui.core.persistent.EpochBlock);
end

These properties should probably be changed to methods because they're potentially long running. The only exception might be when the enumerable list is guaranteed to be short.

For the example above, the method would look like:

function b = getEpochBlocks(obj)
    b = obj.cellArrayFromEnumerable(obj.cobj.EpochBlocks, @symphonyui.core.persistent.EpochBlock);
end

Descriptor value getter methods can be more efficient

Descriptor value getters like:

  • Device.getConfigurationSetting()
  • Device.hasConfigurationSetting()
  • Entity.getProperty()

Can be more efficient by not retrieving all the descriptors and using findByName() and instead getting the value from the core map directly.

For example:

Current:

function v = getConfigurationSetting(obj, name)
    % Gets the value of an existing configuration setting
    
    descriptors = obj.getConfigurationSettingDescriptors();
    d = descriptors.findByName(name);
    if isempty(d)
        error([name ' does not exist']);
    end
    v = d.value;
end

More efficient:

function v = getConfigurationSetting(obj, name)
    % Gets the value of an existing configuration setting
    
    v = obj.tryCoreWithReturn(@()obj.cobj.Configuration.Item(name));
    v = obj.valueFromPropertyValue(convert(v));
end

Add a new DAQController for HEKA's new drivers

HEKA releases new ITC drivers a while ago. It looks like they're more stable, more capable, and actually being maintained by HEKA. We should create a new DAQController for these drivers.

Help regarding integrating of rig switches

Hi Mark,
Thanks for integrating Heka device support. I am trying to integrate rig toggle switches to control the state (start, stop and pause) of acquisition software.

Can you please review below approach and advise on it ?

  • Extending UnitConvertingDevice with following events and
classdef RigSwitches < symphonyui.builtin.devices.UnitConvertingDevice

events
    RunProtocol
    DontSave
    UpdateFigures
    StopProtocol
end

methods

    function obj = RigSwitches(name)
        [email protected](name, symphonyui.core.Measurement.UNITLESS);
    end

    function checkStatus(obj, response, index)
        n = length(response);
        state = response(n);

        switch(index)
            case 1
                notify(obj, 'RunProtocol', symphonyui.app.AppEventData(state))
        end
    end
end
end
  • Creating Rig description
classdef HekaITC18Multiclamp < symphonyui.core.descriptions.RigDescription
....
  methods

        function obj = HekaITC18Multiclamp()
            import symphonyui.builtin.daqs.*;
            import symphonyui.builtin.devices.*;
            import fi.helsinki.biosci.ala-alaurila.devices.*;
            ....
            rigSwitch1 = RighSwitch('rigSwitch1').bindStream(daq.getStream('DIGITAL_IN.1'))
            daq.getStream('DIGITAL_IN.1').setBitPosition(rigSwitch1, 1)
            ...
            obj.devices = {amp1, amp2, green, blue, trigger1, trigger2, rigSwitch1};
  • Check for toogle switch status before every prepare epoch
classdef Pulse < symphonyui.core.Protocol
    ....
        function prepareEpoch(obj, epoch)
           .....
           ..... 
            d = obj.rig.getDevice('rigSwitch1');
            r = epoch.response(d)
            d.checkStatus(r, 1)
But am not sure where to bind Rig Switch event listeners, Is it ok to bind on acquisition service constructor ?

If am doing some thing wrong, kindly correct me

Thanks,
Sathish

Allow users to update existing protocol presets

Some users would like to be able to update existing protocol presets after they've been created (rather than delete and recreate them). I'm not sure how this would work from a UI perspective without over-complicating things.

ITC1600 board integration on HekaDaqController

Current HekaDaqController.m can create only one kind of daq.

cobj = Heka.HekaDAQController(double(Heka.NativeInterop.ITCMM.USB18_ID), 0);

But I need to create cobj based on board (ITC1600_ID or USB18_ID). Is it advisable to modify HekaDaqController constructor to take an argument and create cobj based on it ?

classdef HekaDaqController < symphonyui.core.DaqController
    enumeration
        ITC1600, ITC18
     ...
function obj = HekaDaqController(board)
           ....
            if(board == HekaDaqController.ITC18)
                cobj = Heka.HekaDAQController(double(Heka.NativeInterop.ITCMM.USB18_ID), 0);
            elseif(board == HekaDaqController.ITC1600)
                cobj = Heka.HekaDAQController(double(Heka.NativeInterop.ITCMM.ITC1600_ID), 0);
            else
                error(['board should either be ITC1600 or ITC18']);
            end

Kindly clarify

Filter protocol presets by protocol

The preset window can become clogged with many presets for each of many protocols. A method to filter these would be useful. At a minimum, having an option to show only those for the currently active protocol would be good.

Use similar stream names for HEKA and NI DAQControllers

We currently use "ANALOG_IN.0" and "DIGITAL_IN.0" style stream names for HekaDaqController, and "ai0" and "diport0" style stream names for NiDaqController. It would be nice to settle on a common standard here.

The NI style is used in National Instruments documentation/software. The HEKA style was developed specifically for Symphony. HEKA does not have a standard stream name approach AFAIK. Therefore it probably makes sense just to use the NI style across both DaqControllers.

Add ability to search protocol list

JIDE offers a pretty cool searchable JComboBox that would make finding a protocol in a long list of protocols easier. You just click on the ComboBox and start typing:

search

Here's some sample code:

import com.jidesoft.combobox.*;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.swing.*;

JComboBox comboBox = new JComboBox(names);
comboBox.setEditable(false); // combobox searchable only works when combobox is not editable.
SearchableUtils.installSearchable(comboBox);

Warnings/mechanisms to avoid losing data

At the Schwartz lab, we sometimes make mistakes. One of those mistakes looks like pressing the wrong button, viewing (rather than recording) a bunch of epochs, then realizing they were not recorded at all. In Symphony 1, a large red text indicator made it clear when epochs were not being recorded. In Symphony 2, this is much more subtle, with the only sign being "viewing" rather than "recording" at the bottom.

To ameliorate this issue, it would be good to have some warning, or perhaps a fail-safe mechanism. Something like the red text, displayed when a data file is open but not being written to, would be a good place to start. Or, perhaps, a confirmation step required for viewing-only when a file is open. Alternatively, all epochs (from both view and record mode) could be saved automatically, then those marked as "view mode" would be not stored with the saved recording h5, unless they were mode-switched beforehand.

Add a clearDataCache method to Response

Some users may want to view Response data while it's being recorded. Currently, the getData method caches the data on first use and always returns the cached data. The user should be able to get around this by adding a clearDataCache method to Response which they can call before calling getData.

Add Visual C++ 2010 runtime dlls to release package

The HEKA stuff requires Visual C++ 2010 runtime. Instead of requiring thats users install it on there own, see if we can include it in the release package (if it's not too large).

Probably located in: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\x64\Microsoft.VC100.CRT

No exception traceback info for exceptions that occur in onCompletedEpoch

Symphony shows a really unhelpful traceback when an exception occurs in Controller.onCompletedEpoch (usually when an exception occurs in a FigureHandler or Protocol.completeEpoch).

Per Sam Cooler:

I'm doing work that involves a lot of debugging. But my errors keep coming up with file/line reference to the Controller.m, with traceback info lost:

Warning: DEBUG: Struct contents reference
from a non-struct array object.
Error using
symphonyui.core.Controller/process (line 284)
Struct contents reference from a non-struct
array object.

Error in symphonyui.core.Controller/run (line
249)
obj.process();

UI shows wrong state when running from presets and recording a large number of epochs

Jacob reports that if he runs a preset and records a large number of epochs, he is able to run the next preset while the main window shows that Symphony is "stopped". We tried to reproduce this briefly but were unable to make it happen. I suspect it occurs when you record a large number of epochs and the data manager takes a while to populate the epoch list. During this time, it may be able to run the next preset but have the state change event swallowed by the data manager or something else in the system.

Add the ability to split and merge epoch groups

Some users forget to create a new epoch group or accidentally close an epoch group too soon, causing their data not to be organized in the way they want. The ability to split and merge epoch groups would go a long way toward alleviating this issue.

Add symphony-core to the symphony-matlab repo as a submodule

When a release of Symphony is made, the symphony-matlab repo is tagged but the symphony-core repo is not. Because of this, there's not a great way to go back and look at the state of the core source code at particular release versions.

If we add the core repo as a submodule to the matlab module, the matlab repo tag will allow us to preserve the revision of the core repo used to make that release. It will also make it easier to automate more of the release process, perhaps with a "release.m" or "deploy.m" script.

Saving stopped epochs

When a protocol is run, and stopped during an epoch, sometimes the epoch stage display runs through completion. However, the data is dumped and not recorded as an epoch. This means that it is sometimes necessary to wait for an entire extra epoch to run to ensure that the last desired epoch is saved, which is time consuming if epochs are long. Could the stop button be altered to have a "stop after this epoch is completed" functionality?

Fix dateTimeOffsetFromDatetime for 'Europe/London' timezone

The symphonyui.core.CoreObject.dateTimeOffsetFromDatetime method is currently broken when your timezone is 'Europe/London'. The below code includes the fix.

function dto = dateTimeOffsetFromDatetime(obj, t) %#ok<INUSL>
    if isempty(t.TimeZone)
        error('Datetime ''TimeZone'' must be set');
    end
    t.Format = 'ZZZZZ';
    tz = char(t);
    if tz(1) == '+'
        tz(1) = [];
    elseif strcmp(tz, 'Z')
        tz = '00:00';
    end
    offset = System.TimeSpan.Parse(tz);
    dto = System.DateTimeOffset(t.Year, t.Month, t.Day, t.Hour, t.Minute, floor(t.Second), round(1000*rem(t.Second, 1)), offset);
end

Quick switching of the source will label the wrong source

To reproduce:

  1. Add a source with a nested source
  2. Select the nested source
  3. Press up on the keyboard to change the selection to the parent source and quickly press the add source button
  4. The GUI will think the nest source is still selected when adding a new source
  5. Add the new source to the nested source and try to modify its label
  6. The parent sources label will be change instead of the nested sources

Store sweeps across instances of the built in figure handlers

When you change a protocol property, the figure handlers close (by design). This causes the stored sweep in the builtin handlers to disappear. It would be nice if the stored sweeps stuck around until they were explicitly cleared.

Here is the pattern to store info across figure handlers:

classdef Figure < symphonyui.core.FigureHandler

    methods

        function obj = Figure()
            % Get stored info.
            averages = obj.storedAverages();
        end

        function store(obj)
            % Store some data.
            obj.storedAverages([1 2 3]);
        end

    end

    methods (Static)

        function averages = storedAverages(averages)
            % This method stores means across figure handlers.

            persistent stored;
            if nargin > 0
                stored = averages;
            end
            averages = stored;
        end

    end

end

Add HEKA digital port information to docs

Per Sam Cooler:

I spent a while dealing with an issue today, getting digital output to work from the ITC-18. Turns out, the ITC front panel is doport1, not doport0, and that the bit position is what is equivalent to Symphony 1's DIGITAL_OUT.x label.

Though I've got it figured out now, I think a mapping from physical ports to port name strings (and bit position) would be helpful for others, for the future.

Ah, I meant a text information mapping. I'm just saying to add to the symphony documentation, or example rig configs, or somewhere, the words "The ITC-18 front panel digital lines are doport1, and are accessed individually using the bit positions"

More informative data manager tree UI strings

There is a lot more information that could be shown in the data manager in order to make browsing the data tree more efficient and simple. Currently, the epoch's time is displayed, for instance, but, for protocols with changing variables over epochs, that value could be displayed. For a direction selectivity measurement, for example, it should display the movement direction angle for each epoch: "angle: 60". This is already pulled out and displayed within the epoch's data area on the right, but it's not currently available for browsing the tree quickly.

Add support for class (@) folders

Per Khris:

I've found myself desiring a specific enhancement where Symphony would support class folders.
If anyone else wants it, here is the change I've made on our local machines. It doesn't require recompiling Symphony-core so I've just modified our Symphony installer (.mlappinstall) rather than repackaging it. Obviously, this will revert if an update comes out.

The original line (74) is:
elseif ~isempty(name) && name(1) == '+'

And I've changed it to:
elseif ~isempty(name) && (name(1) == '+' || name(1) == '@')

Allow figure handlers to decide if they want to handle interval epochs

There are cases where a FigureHandler may want to handle interval epochs. Right now, only "true" epochs are passed to the handleEpoch method of handlers. It might make sense to pass all epochs to handlers and let the handler decide if it wants to deal with "interval" epochs.

Adding an isInterval method to Epoch would also be helpful for this.

Add a cleanup file

It would be nice to have something like the "startup file", a script that runs when Symphony starts, for cleanup. A "cleanup file" sounds right.

Allow users to hide individual protocols from their protocol list

As users write more protocols, the dropdown list for selecting the current protocol can become frustrating to navigate. It would be nice if users could hide protocols they're not interested in seeing. A new page under Configure > Options would probably be the best place for this.

Add a convenience package name

Importing Symphony stuff from packages is quite a bit of typing. It would be nice if there was a convenience package with a short name like sym so the a user could write something like sym.Protocol instead of symphonyui.core.Protocol and sym.ResponseFigure instead of symphonyui.builtin.figures.ResponseFigure.

Reading data from Serial port?

Hi,
Can I acquire data from serial port?
I have a PCB board that uses the Intan RHD 2132 chip. The board has 32 channels and a sampling rate of 1000 samples per a second, so it returns 32 data points every millisecond. The board interfaces with the computer with USB SPI. Can I acquire the data from my custom PCB in with Symphony?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.