Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R7 development #2

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
124 changes: 124 additions & 0 deletions Figure Handlers/PowerSpectrumFigureHandler.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
% Copyright (c) 2012 Howard Hughes Medical Institute.
% All rights reserved.
% Use is subject to Janelia Farm Research Campus Software Copyright 1.1 license terms.
% http://license.janelia.org/license/jfrc_copyright_1_1.html

classdef PowerSpectrumFigureHandler < FigureHandler

properties (Constant)
figureType = 'Power Spectrum'
end

properties
meanPlots % array of structures to store the properties of each class of epoch.
meanParamNames
end

methods

function obj = PowerSpectrumFigureHandler(protocolPlugin, varargin)
obj = obj@FigureHandler(protocolPlugin);

xlabel(obj.axesHandle(), 'sec');
set(obj.axesHandle(), 'XTickMode', 'auto');

obj.resetPlots();

ip = inputParser;
ip.addParamValue('GroupByParams', {}, @(x)iscell(x) || ischar(x));
ip.parse(varargin{:});

if iscell(ip.Results.GroupByParams)
obj.meanParamNames = ip.Results.GroupByParams;
else
obj.meanParamNames = {ip.Results.GroupByParams};
end
end


function handleCurrentEpoch(obj)
[responseData, sampleRate, units] = obj.protocolPlugin.response();
responseData = fft(responseData);
responseData = responseData.*conj(responseData);

% Get the parameters for this "class" of epoch.
% An epoch class is defined by a set of parameter values.
if isempty(obj.meanParamNames)
% Automatically detect the set of parameters.
epochParams = obj.protocolPlugin.epochSpecificParameters();
else
% The protocol has specified which parameters to use.
for i = 1:length(obj.meanParamNames)
epochParams.(obj.meanParamNames{i}) = obj.protocolPlugin.epoch.ProtocolParameters.Item(obj.meanParamNames{i});
end
end

% Check if we have existing data for this class of epoch.
meanPlot = struct([]);
for i = 1:numel(obj.meanPlots)
if isequal(obj.meanPlots(i).params, epochParams)
meanPlot = obj.meanPlots(i);
break;
end
end

if isempty(meanPlot)
% This is the first epoch of this class to be plotted.
meanPlot = {};
meanPlot.params = epochParams;
meanPlot.data = responseData;
meanPlot.sampleRate = sampleRate;
meanPlot.units = [units,'^2'];
meanPlot.count = 1;
hold(obj.axesHandle(), 'on');
meanPlot.plotHandle = loglog(obj.axesHandle(), (1:length(meanPlot.data)/2) * sampleRate, meanPlot.data(1:length(meanPlot.data)/2));
obj.meanPlots(end + 1) = meanPlot;
else
% This class of epoch has been seen before, add the current response to the mean.
% TODO: Adjust response data to the same sample rate and unit as previous epochs if needed.
% TODO: if the length of data is varying then the mean will not be correct beyond the min length.
meanPlot.data = (meanPlot.data * meanPlot.count + responseData) / (meanPlot.count + 1);
meanPlot.count = meanPlot.count + 1;
set(meanPlot.plotHandle, 'XData', (1:length(meanPlot.data)/2) * sampleRate, ...
'YData', meanPlot.data);
obj.meanPlots(i) = meanPlot;
end

% Update the y axis with the units of the response.
ylabel(obj.axesHandle(), [units,'^2']);

if isempty(epochParams)
titleString = 'All epochs grouped together.';
else
paramNames = fieldnames(epochParams);
titleString = ['Grouped by ' humanReadableParameterName(paramNames{1})];
for i = 2:length(paramNames) - 1
titleString = [titleString ', ' humanReadableParameterName(paramNames{i})];
end
if length(paramNames) > 1
titleString = [titleString ' and ' humanReadableParameterName(paramNames{end})];
end
end
title(obj.axesHandle(), titleString);
end


function clearFigure(obj)
obj.resetPlots();

clearFigure@FigureHandler(obj);
end


function resetPlots(obj)
obj.meanPlots = struct('params', {}, ... % The params that define this class of epochs.
'data', {}, ... % The mean of all responses of this class.
'sampleRate', {}, ... % The sampling rate of the mean response.
'units', {}, ... % The units of the mean response.
'count', {}, ... % The number of responses used to calculate the mean reponse.
'plotHandle', {}); % The handle of the plot for the mean response of this class.
end

end

end
37 changes: 0 additions & 37 deletions Protocols/Grid/allcombs.m

This file was deleted.

37 changes: 0 additions & 37 deletions Protocols/HotspotsDS/allcombs.m

This file was deleted.

134 changes: 134 additions & 0 deletions Protocols/LEDFlash/LEDFlash.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
% Creates a single stimulus composed of mean + flash.
% Implements SymphonyProtocol
%
% Copyright (c) 2012 Howard Hughes Medical Institute.
% All rights reserved.
% Use is subject to Janelia Farm Research Campus Software Copyright 1.1 license terms.
% http://license.janelia.org/license/jfrc_copyright_1_1.html
%
% Modified by TA 9.8.12 from LED Family to create a single LED pulse protocol

classdef LEDFlash < SymphonyProtocol

properties (Constant)
identifier = 'helsinki.yliopisto.pal'
version = 1
displayName = 'LED Flash'
end

properties
stimPoints = uint16(100);
prePoints = uint16(1000);
tailPoints = uint16(4000);
stimAmplitude = 0.5;
lightMean = 0.0;
preSynapticHold = -60;
numberOfAverages = uint8(5);
interpulseInterval = 0.6;
continuousRun = false;
end

properties (Dependent = true, SetAccess = private) % these properties are inherited - i.e., not modifiable
% ampOfLastStep;
end

methods

function [stimulus, lightAmplitude] = stimulusForEpoch(obj, ~) % epoch Num is usually required
% Calculate the light amplitude for this epoch.
% phase = single(mod(epochNum - 1, obj.stepsInFamily)); % Frank's clever way to determine which flash in a family to deliver
lightAmplitude = obj.stimAmplitude; % * obj.ampStepScale ^ phase; % Frank's clever way to determine the amplitude of the flash family to deliver

% Create the stimulus
stimulus = ones(1, obj.prePoints + obj.stimPoints + obj.tailPoints) * obj.lightMean;
stimulus(obj.prePoints + 1:obj.prePoints + obj.stimPoints) = lightAmplitude;
end


function stimulus = sampleStimuli(obj) % Return a cell array
% you can only create one stimulus with this protocol TA
stimulus{1} = obj.stimulusForEpoch();
end


function prepareRig(obj)
% Call the base class method to set the DAQ sample rate.
prepareRig@SymphonyProtocol(obj);

%obj.setDeviceBackground('LED', obj.lightMean, 'V');

% if strcmp(obj.rigConfig.multiClampMode('Amplifier_Ch1'), 'IClamp')
% obj.setDeviceBackground('Amplifier_Ch1', double(obj.preSynapticHold) * 1e-12, 'A');
% else
% obj.setDeviceBackground('Amplifier_Ch1', double(obj.preSynapticHold) * 1e-3, 'V');
% end
end


function prepareRun(obj)
% Call the base class method which clears all figures.
prepareRun@SymphonyProtocol(obj);

obj.openFigure('Response');
obj.openFigure('Mean Response', 'GroupByParams', {'lightAmplitude'});
obj.openFigure('Response Statistics', 'StatsCallback', @responseStatistics);
end


function prepareEpoch(obj)
% Call the base class method which sets up default backgrounds and records responses.
prepareEpoch@SymphonyProtocol(obj);

[stimulus, lightAmplitude] = obj.stimulusForEpoch(obj.epochNum);
obj.addParameter('lightAmplitude', lightAmplitude);
%obj.addStimulus('LED', 'test-stimulus', stimulus, 'V'); %
obj.setDeviceBackground('LED', obj.lightMean, 'V');
if strcmp(obj.multiClampMode, 'VClamp')
obj.setDeviceBackground('Amplifier_Ch1', double(obj.preSynapticHold) * 1e-3, 'V');
else
obj.setDeviceBackground('Amplifier_Ch1', double(obj.preSynapticHold) * 1e-12, 'A');
end
obj.addStimulus('LED', 'LED stimulus', stimulus, 'V'); %
end


function stats = responseStatistics(obj)
r = obj.response();

% baseline mean and var
if ~isempty(r)
stats.mean = mean(r(1:obj.prePoints));
stats.var = var(r(1:obj.prePoints));
else
stats.mean = 0;
stats.var = 0;
end
end


function completeEpoch(obj)
% Call the base class method which updates the figures.
completeEpoch@SymphonyProtocol(obj);

% Pause for the inter-pulse interval.
pause on
pause(obj.interpulseInterval);
end


function keepGoing = continueRun(obj)
% First check the base class method to make sure the user hasn't paused or stopped the protocol.
keepGoing = continueRun@SymphonyProtocol(obj);

if keepGoing
keepGoing = obj.epochNum < obj.numberOfAverages;
end
end


% function amp = get.ampOfLastStep(obj) % The product of the number of steps in family, the first step amplitude, and the 'scale factor'
% amp = obj.baseLightAmplitude * obj.ampStepScale ^ (obj.stepsInFamily - 1);
% end

end
end
Loading