function structureSet = getStructureSetAssociatedScan(scanSet, planC)
% DK
% LM: APA, 10/22/08: Fixed to output correct associated structure index
%
% copyright (c) 2001-2008, Washington University in St. Louis.
%
% Permission is granted to use or modify only for non-commercial,
% non-treatment-decision applications, and further only if this header is
% not removed from any file. No warranty is expressed or implied for any
% use whatever: use at your own risk.  Users can request use of CERR for
% institutional review board-approved protocols.  Commercial users can
% request a license.  Contact Joe Deasy for more information
% (radonc.wustl.edu@jdeasy, reversed).

if ~exist('planC','var')
    global planC
end
indexS = planC{end};

structureSet = [];
structureSet = sparse(structureSet);

[assocScanUID{1:length(planC{indexS.structureArray})}] = deal(planC{indexS.structureArray}.assocScanUID);

if isempty(assocScanUID)
    structureSet = [];
    return
end

for i = 1:length(scanSet)

    scanUID = planC{indexS.scan}(scanSet(i)).scanUID;
    try
        structureSet(i) = find(strcmpi(scanUID,assocScanUID));
    end
end


classdef PTKMaximumFissurePoints < PTKPlugin
    % PTKMaximumFissurePoints. Plugin which is part of the lobar segmentation.
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %     PTKMaximumFissurePoints is an intermediate stage in segmenting the
    %     lobes.
    %
    %     For more information, see
    %     [Doel et al., Pulmonary lobe segmentation from CT images using
    %     fissureness, airways, vessels and multilevel B-splines, 2012]
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Fissureness <br>Maxima'
        ToolTip = ''
        Category = 'Fissures'

        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = true
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true
        Visibility = 'Developer'
    end

    methods (Static)
        function results = RunPlugin(application, reporting)
            fissure_approximation = application.GetResult('PTKFissureApproximation');

            left_and_right_lungs = application.GetResult('PTKLeftAndRightLungs');

            results_left = PTKMaximumFissurePoints.GetLeftLungResults(application, fissure_approximation);
            results_right = PTKMaximumFissurePoints.GetRightLungResults(application, fissure_approximation);

            results = PTKCombineLeftAndRightImages(application.GetTemplateImage(PTKContext.LungROI), results_left, results_right, left_and_right_lungs);
            results.ImageType = PTKImageType.Colormap;
        end

        function results = GenerateImageFromResults(results, ~, ~)
        end
    end

    methods (Static, Access = private)
        function left_results = GetLeftLungResults(application, fissure_approximation)
            fissureness_roi = application.GetResult('PTKFissurenessROI');

            lung_mask = application.GetResult('PTKLeftAndRightLungs');
            lung_mask.ChangeRawImage(uint8(lung_mask.RawImage == 2));

            left_lung_roi = application.GetResult('PTKGetLeftLungROI');
            fissure_approximation = fissure_approximation.Copy;
            fissure_approximation.ResizeToMatch(left_lung_roi);
            lung_mask.ResizeToMatch(left_lung_roi);

            [high_fissure_indices, ref_image] = PTKGetMaxFissurePoints(fissure_approximation.RawImage == 6, lung_mask, fissureness_roi.LeftMainFissure, left_lung_roi, left_lung_roi.ImageSize);

            left_results = left_lung_roi.BlankCopy;
            left_results.ChangeRawImage(ref_image);
        end

        function right_results = GetRightLungResults(application, fissure_approximation)
            fissureness_roi = application.GetResult('PTKFissurenessROI');

            lung_mask = application.GetResult('PTKLeftAndRightLungs');
            lung_mask.ChangeRawImage(uint8(lung_mask.RawImage == 1));

            right_lung_roi = application.GetResult('PTKGetRightLungROI');
            fissure_approximation = fissure_approximation.Copy;
            fissure_approximation.ResizeToMatch(right_lung_roi);
            lung_mask.ResizeToMatch(right_lung_roi);

            [high_fissure_indices, ref_image_o] = PTKGetMaxFissurePoints(fissure_approximation.RawImage == 2, lung_mask, fissureness_roi.RightMainFissure, right_lung_roi, right_lung_roi.ImageSize);

            [high_fissure_indices_m, ref_image_m] = PTKGetMaxFissurePoints(fissure_approximation.RawImage == 3, lung_mask, fissureness_roi.RightMidFissure, right_lung_roi, right_lung_roi.ImageSize);

            ref_image = ref_image_m;
            ref_image(ref_image_o == 1) = 1;
            ref_image(ref_image_m == 1) = 8;

            right_results = right_lung_roi.BlankCopy;
            right_results.ChangeRawImage(ref_image);
        end
    end
end


function [validBeacon, mpdu, validPacket] = nonHTBeaconRxMPDUDecode(payload)
% nonHTBeaconRxMPDUDecode Checks if the payload input is from a beacon
% packet and returns its MPDU information. This is a helper function for
% the non-HT beacon receiver example.
%
%   [VALIDBEACON, MPDU] = nonHTBeaconRxMPDUDecode(PAYLOAD) checks the
%   PAYLOAD binary input and sets VALIDBEACON to be true if PAYLOAD is from
%   a beacon packet. The MPDU information is also returned, but it is
%   meaningful only when VALIDBEACON is true.

% Copyright 2015-2016 The MathWorks, Inc.

%#codegen

coder.extrinsic('warning')

persistent crcDetector defaultMPDU

% Frame check sequence (FCS)
if isempty(crcDetector)
    crcDetector = comm.CRCDetector( ...
        [32 26 23 22 16 12 11 10 8 7 5 4 2 1 0], ...
        'InitialConditions', 1, ...
        'DirectMethod',      true, ...
        'FinalXOR',          1);
    defaultMPDU.Header = parseMPDUHeader(zeros(64,1), 1);
    defaultMPDU.FrameBody = unknownMPDU();
end

% Predefine output
validBeacon = false;
mpdu = defaultMPDU;
validPacket = false;

% If the CRC for the header decodes correctly (i.e. CRC flag is 0) and the
% received MPDU payload length is greater than or equal to the expected
% length, then turn on the MPDU decoder
if (length(payload) >= 32+16)
    % Compute CRC based on IEEE Std 802.11(TM)-2007 section 7.1.3.7.
    [frame, mpduCRCd] = crcDetector(double(payload));
    mpduCRC = mpduCRCd > 0; % Convert to logical

    % Extract header information
    [mpdu.Header, mpduHeaderLen] = parseMPDUHeader(frame, mpduCRC);

    validPacket = mpduCRC == 0;

    % Evaluate frame body
    if (mpduCRC == 1) || ((mpdu.Header.FrameCtrl.Type ~= 0) ...
            || (mpdu.Header.FrameCtrl.Subtype ~= 8))
        mpdu.FrameBody = unknownMPDU();
    else
        validBeacon = true;
        mpdu.FrameBody = parseBeaconMPDU(frame(mpduHeaderLen+1:end, 1), mpduCRC);
    end
end

end

function [mpduHeader, len] = parseMPDUHeader(frame, mpduCRC)
% Based on IEEE Std 802.11-2007 chapter 7.

mpduHeader.FrameCtrl       = parseFrameControl(frame(1:16,1), mpduCRC);
mpduHeader.DurationID      = zeros(1,2,'uint8');
mpduHeader.Address1        = zeros(1,6,'uint8');
mpduHeader.Address2        = zeros(1,6,'uint8');
mpduHeader.Address3        = zeros(1,6,'uint8');
mpduHeader.SequenceControl = zeros(1,2,'uint8');
mpduHeader.Address4        = zeros(1,6,'uint8');
len = (2+6+6+6+2+6)*8 + 16;

if (mpduCRC == 0)
    p = 1;
    mpduHeader.FrameCtrl  = parseFrameControl(frame(p:p+15,1), mpduCRC);
    p = p+16;
    mpduHeader.DurationID = bit2Octet(frame(p:p+15,1),2);
    p = p+16;
    mpduHeader.Address1   = bit2Octet(frame(p:p+47,1),6);
    p = p+48;

    isManagementFrame = (mpduHeader.FrameCtrl.Type == 0);
    isControlFrame = (mpduHeader.FrameCtrl.Type == 1);
    isDataFrame = (mpduHeader.FrameCtrl.Type == 2);
    isCTSFrame = isControlFrame && (mpduHeader.FrameCtrl.Subtype == 12);
    isACKFrame = isControlFrame && (mpduHeader.FrameCtrl.Subtype == 13);

    if ~(isCTSFrame || isACKFrame)
        mpduHeader.Address2 = bit2Octet(frame(p:p+47,1),6);
        p = p+48;
    end
    if isManagementFrame
        mpduHeader.Address3 = bit2Octet(frame(p:p+47,1),6);
        p = p+48;
    end
    if ~isControlFrame
        mpduHeader.SequenceControl = bit2Octet(frame(p:p+15,1),2);
        p = p+16;
    end
    if isDataFrame
        mpduHeader.Address4 = bit2Octet(frame(p:p+47,1),6);
        p = p+48;
    end
    len = p-1;
end
end

function frameCtrl = parseFrameControl(fcBits, mpduCRC)
if (mpduCRC == 0)
    frameCtrl.ProtocolVersion = uint8(bi2de(fcBits(1:2,1)'));
    frameCtrl.Type            = uint8(bi2de(fcBits(3:4,1)'));
    frameCtrl.Subtype         = uint8(bi2de(fcBits(5:8,1)'));
    frameCtrl.ToDS            = uint8(bi2de(fcBits(9,1)'));
    frameCtrl.FromDS          = uint8(bi2de(fcBits(10,1)'));
    frameCtrl.MoreFragments   = uint8(bi2de(fcBits(11,1)'));
    frameCtrl.Retry           = uint8(bi2de(fcBits(12,1)'));
    frameCtrl.PowerManagement = uint8(bi2de(fcBits(13,1)'));
    frameCtrl.MoreData        = uint8(bi2de(fcBits(14,1)'));
    frameCtrl.ProtectedFrame  = uint8(bi2de(fcBits(15,1)'));
    frameCtrl.Order           = uint8(bi2de(fcBits(16,1)'));
else
    frameCtrl.ProtocolVersion = uint8(0);
    frameCtrl.Type            = uint8(0);
    frameCtrl.Subtype         = uint8(0);
    frameCtrl.ToDS            = uint8(0);
    frameCtrl.FromDS          = uint8(0);
    frameCtrl.MoreFragments   = uint8(0);
    frameCtrl.Retry           = uint8(0);
    frameCtrl.PowerManagement = uint8(0);
    frameCtrl.MoreData        = uint8(0);
    frameCtrl.ProtectedFrame  = uint8(0);
    frameCtrl.Order           = uint8(0);
end
end

function frameBody = parseBeaconMPDU(frame, mpduCRC)
if (mpduCRC == 0)
    bitCount = uint32(1);
    frameBody.TimeStamp      = bit2Octet(frame(bitCount:bitCount+63,1),8);
    bitCount = bitCount + 64;
    frameBody.BeaconInterval = bit2Octet(frame(bitCount:bitCount+15,1),2);
    bitCount = bitCount + 16;
    frameBody.Capability     = parseCapabilities(frame(81:96), mpduCRC);
    bitCount = bitCount + 16;
else
    frameBody.TimeStamp      = zeros(1,8,'uint8');
    frameBody.BeaconInterval = zeros(1,2,'uint8');
    frameBody.Capability     = parseCapabilities(frame(81:96), mpduCRC);
    bitCount = uint32(97);
end

frameLength = length(frame);

frameBody.NumInfoElements = uint8(0);
macElementStruct = struct('ID', uint8(255), ...
    'Length', uint8(0), ...
    'Value', zeros(1,257,'uint8'));
frameBody.InfoElements = repmat(macElementStruct, 1, 60);

if (mpduCRC == 0)
    while bitCount < frameLength
        frameBody.NumInfoElements = frameBody.NumInfoElements + 1;
        frameBody.InfoElements(frameBody.NumInfoElements).ID = ...
            bit2Octet(frame(bitCount:bitCount+7,1), 1);
        bitCount = bitCount + 8;
        elemLength = bit2Octet(frame(bitCount:bitCount+7,1), 1);
        frameBody.InfoElements(frameBody.NumInfoElements).Length = elemLength;
        bitCount = bitCount + 8;
        for p=1:elemLength
            frameBody.InfoElements(frameBody.NumInfoElements).Value(p) = ...
                bit2Octet(frame(bitCount:bitCount+7),1);
            bitCount = bitCount+8;
        end
    end
end
end

function capability = parseCapabilities(frame, mpduCRC)
if (mpduCRC == 0)
    capability.ESS                = frame(1,1);
    capability.IBSS               = frame(2,1);
    capability.CFPollable         = frame(3,1);
    capability.CFPollRequest      = frame(4,1);
    capability.Privacy            = frame(5,1);
    capability.ShortPreamble      = frame(6,1);
    capability.PBCC               = frame(7,1);
    capability.ChannelAgility     = frame(8,1);
    capability.SpectrumManagement = frame(9,1);
    capability.QoS                = frame(10,1);
    capability.ShortSlotTime      = frame(11,1);
    capability.APSD               = frame(12,1);
    capability.Reserved           = frame(13,1);
    capability.DSSOFDM            = frame(14,1);
    capability.DelayedBlockAck    = frame(15,1);
    capability.ImmediateBlockAck  = frame(16,1);
else
    capability.ESS                = double(false);
    capability.IBSS               = double(false);
    capability.CFPollable         = double(false);
    capability.CFPollRequest      = double(false);
    capability.Privacy            = double(false);
    capability.ShortPreamble      = double(false);
    capability.PBCC               = double(false);
    capability.ChannelAgility     = double(false);
    capability.SpectrumManagement = double(false);
    capability.QoS                = double(false);
    capability.ShortSlotTime      = double(false);
    capability.APSD               = double(false);
    capability.Reserved           = double(false);
    capability.DSSOFDM            = double(false);
    capability.DelayedBlockAck    = double(false);
    capability.ImmediateBlockAck  = double(false);
end
end

function frameBody = unknownMPDU()
frameBody.TimeStamp      = zeros(1,8,'uint8');
frameBody.BeaconInterval = zeros(1,2,'uint8');
frameBody.Capability     = parseCapabilities(zeros(16,1), 1);

frameBody.NumInfoElements = uint8(0);
macElementStruct = struct('ID', uint8(255), ...
    'Length', uint8(0), ...
    'Value', zeros(1,257,'uint8'));
frameBody.InfoElements = repmat(macElementStruct, 1, 60);
end

function octets = bit2Octet(bits,numOctets)
octets = zeros(1, numOctets, 'uint8');
for p=1:numOctets
    octets(1,p) = (bits((p-1)*8+1:p*8)')*2.^(0:7)';
end
end


% connect to Arduino
try
    a = arduino;
    disp(a)
catch
    warning('Unable to connect, user input required')
    disp('For Windows:')
    disp('  Open device manager, select "Ports (COM & LPT)"')
    disp('  Look for COM port of Arduino such as COM4')
    disp('For MacOS:')
    disp('  Open terminal and type: ls /dev/*.')
    disp('  Search for /dev/tty.usbmodem* or /dev/tty.usbserial*. The port number is *.')
    disp('For Linux')
    disp('  Open terminal and type: ls /dev/tty*')
    disp('  Search for /dev/ttyUSB* or /dev/ttyACM*. The port number is *.')
    disp('')
    com_port = input('Specify port (e.g. COM4 for Windows or /dev/ttyUSB0 for Linux): ','s');
    a = arduino(com_port,'Uno');
    disp(a)
end

% voltage read functions
v1 = @() readVoltage(a, 'A0');
v2 = @() readVoltage(a, 'A2');

% temperature calculations as a function of voltage for TMP36
TC = @(V) (V - 0.5)*100.0;          % Celsius
TK = @(V) TC(V) + 273.15;           % Kelvin
TF = @(V) TK(V) * 9.0/5.0 - 459.67; % Fahrenhiet

% temperature read functions
T1C = @() TC(v1());
T2C = @() TC(v2());

% LED function (0 <= level <= 1)
led = @(level) writePWMDutyCycle(a,'D9',max(0,min(1,level)));  % ON

% heater output (0 <= heater <= 100)
% limit to 0-0.9 (0-100%)
h1 = @(level) writePWMDutyCycle(a,'D3',max(0,min(100,level))*0.9/100);
% limit to 0-0.5 (0-100%)
h2 = @(level) writePWMDutyCycle(a,'D5',max(0,min(100,level))*0.5/100);


function varargout = getPrmDflt( prm, dfs, checkExtra )
% Helper to set default values (if not already set) of parameter struct.
%
% Takes input parameters and a list of 'name'/default pairs, and for each
% 'name' for which prm has no value (prm.(name) is not a field or 'name'
% does not appear in prm list), getPrmDflt assigns the given default
% value. If default value for variable 'name' is 'REQ', and value for
% 'name' is not given, an error is thrown. See below for usage details.
%
% USAGE (nargout==1)
%  prm = getPrmDflt( prm, dfs, [checkExtra] )
%
% USAGE (nargout>1)
%  [ param1 ... paramN ] = getPrmDflt( prm, dfs, [checkExtra] )
%
% INPUTS
%  prm          - param struct or cell of form {'name1' v1 'name2' v2 ...}
%  dfs          - cell of form {'name1' def1 'name2' def2 ...}
%  checkExtra   - [0] if 1 throw error if prm contains params not in dfs
%                 if -1 if prm contains params not in dfs adds them
%
% OUTPUTS (nargout==1)
%  prm    - parameter struct with fields 'name1' through 'nameN' assigned
%
% OUTPUTS (nargout>1)
%  param1 - value assigned to parameter with 'name1'
%   ...
%  paramN - value assigned to parameter with 'nameN'
%
% EXAMPLE
%  dfs = { 'x','REQ', 'y',0, 'z',[], 'eps',1e-3 };
%  prm = getPrmDflt( struct('x',1,'y',1), dfs )
%  [ x y z eps ] = getPrmDflt( {'x',2,'y',1}, dfs )
%
% See also INPUTPARSER
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.60
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

if( mod(length(dfs),2) ), error('odd number of default parameters'); end
if nargin<=2, checkExtra = 0; end

% get the input parameters as two cell arrays: prmVal and prmField
if iscell(prm) && length(prm)==1, prm=prm{1}; end
if iscell(prm)
  if(mod(length(prm),2)), error('odd number of parameters in prm'); end
  prmField = prm(1:2:end); prmVal = prm(2:2:end);
else
  if(~isstruct(prm)), error('prm must be a struct or a cell'); end
  prmVal = struct2cell(prm); prmField = fieldnames(prm);
end

% get and update default values using quick for loop
dfsField = dfs(1:2:end); dfsVal = dfs(2:2:end);
if checkExtra>0
  for i=1:length(prmField)
    j = find(strcmp(prmField{i},dfsField));
    if isempty(j), error('parameter %s is not valid', prmField{i}); end
    dfsVal(j) = prmVal(i);
  end
elseif checkExtra<0
  for i=1:length(prmField)
    j = find(strcmp(prmField{i},dfsField));
    if isempty(j), j=length(dfsVal)+1; dfsField{j}=prmField{i}; end
    dfsVal(j) = prmVal(i);
  end
else
  for i=1:length(prmField)
    dfsVal(strcmp(prmField{i},dfsField)) = prmVal(i);
  end
end

% check for missing values
if any(strcmp('REQ',dfsVal))
  cmpArray = find(strcmp('REQ',dfsVal));
  error(['Required field ''' dfsField{cmpArray(1)} ''' not specified.'] );
end

% set output
if nargout==1
  varargout{1} = cell2struct( dfsVal, dfsField, 2 );
else
  varargout = dfsVal;
end


function varargout = sv_gridMc(varargin)
% SV_GRIDMc Application M-file for sv_gridMv.fig
%    FIG = SV_GRID launch sv_grid GUI.
%    SV_GRIDMc('callback_name', ...) invoke the named callback.

% Last Modified by GUIDE v2.0 22-Aug-2002 10:30:09

if nargin == 1  % LAUNCH GUI

	fig = openfig(mfilename,'reuse');

	% Use system color scheme for figure:
	set(fig,'Color',get(groot,'defaultUicontrolBackgroundColor'));

	% Generate a structure of handles to pass to callbacks, and store it.
	handles = guihandles(fig);
	guidata(fig, handles);

if varargin{1} == 1
    set(handles.lblSpacingDepth, 'String', 'Latitude spacing [deg]:');
    set(handles.txtSpacingDepth, 'String', '0.1');
    set(handles.lblSpacingHorizontal, 'String', 'Longitude spacing [deg]:');
    set(handles.txtSpacingHorizontal, 'String', '0.1');
else
    set(handles.lblSpacingDepth, 'String', 'Depth spacing [km]:');
    set(handles.txtSpacingDepth, 'String', '1');
    set(handles.lblSpacingHorizontal, 'String', 'Horizontal spacing [km]:');
    set(handles.txtSpacingHorizontal, 'String', '1');
end
if get(handles.radNumber, 'Value') == 1
    set(handles.txtNumber, 'Enable', 'on');
    set(handles.radRadius, 'Value', [0]);
    set(handles.txtRadius, 'Enable', 'off');
else
    set(handles.txtNumber, 'Enable', 'off');
    set(handles.radRadius, 'Value', [1]);
    set(handles.txtRadius, 'Enable', 'on');
end

% if get(handles.radSplitTime, 'Value') == 1
%     set(handles.txtSplitTime, 'Enable', 'on');
%     set(handles.txtTimePeriod, 'Enable', 'on');
% else
%     set(handles.radSplitTime, 'Value', [1]);
%     set(handles.txtSplitTime, 'Enable', 'on');
%     set(handles.txtTimePeriod, 'Enable', 'on');
% end
	% Wait for callbacks to run and window to be dismissed:
	uiwait(fig);

	if nargout > 0
		varargout{1} = fig;
	end

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

	try
		if (nargout)
			[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
		else
			feval(varargin{:}); % FEVAL switchyard
		end
	catch
		disp(lasterr);
	end

end

%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and
%| sets objects' callback properties to call them through the FEVAL
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback.  You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks.  Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.

% --------------------------------------------------------------------
% Radiobutton: Number of events
function varargout = radNumber_Callback(h, eventdata, handles, varargin)

if get(handles.radNumber, 'Value') == 1
  set(handles.txtNumber, 'Enable', 'on');
  set(handles.txtMaxRadius, 'Enable', 'on');
  set(handles.radRadius, 'Value', [0]);
  set(handles.txtRadius, 'Enable', 'off');
  set(handles.radRectangle, 'Value', [0]);
  set(handles.txtSizeRectHorizontal, 'Enable', 'off');
  set(handles.txtSizeRectDepth, 'Enable', 'off');
else
  set(handles.txtNumber, 'Enable', 'off');
  set(handles.txtMaxRadius, 'Enable', 'off');
  set(handles.radRadius, 'Value', [1]);
  set(handles.txtRadius, 'Enable', 'on');
  set(handles.radRectangle, 'Value', [0]);
  set(handles.txtSizeRectHorizontal, 'Enable', 'off');
  set(handles.txtSizeRectDepth, 'Enable', 'off');
end

% --------------------------------------------------------------------
% Radiobutton: Constant radius
function varargout = radRadius_Callback(h, eventdata, handles, varargin)

if get(handles.radRadius, 'Value') == 1
  set(handles.txtRadius, 'Enable', 'on');
  set(handles.radNumber, 'Value', [0]);
  set(handles.txtMaxRadius, 'Enable', 'off');
  set(handles.txtNumber, 'Enable', 'off');
  set(handles.radRectangle, 'Value', [0]);
  set(handles.txtSizeRectHorizontal, 'Enable', 'off');
  set(handles.txtSizeRectDepth, 'Enable', 'off');
else
  set(handles.txtRadius, 'Enable', 'off');
  set(handles.txtMaxRadius, 'Enable', 'on');
  set(handles.radNumber, 'Value', [1]);
  set(handles.txtNumber, 'Enable', 'on');
  set(handles.radRectangle, 'Value', [0]);
  set(handles.txtSizeRectHorizontal, 'Enable', 'off');
  set(handles.txtSizeRectDepth, 'Enable', 'off');
end

% --------------------------------------------------------------------
% Radiobutton: Rectangle size
function varargout = radRectangle_Callback(h, eventdata, handles, varargin)

if get(handles.radRectangle, 'Value') == 1
  set(handles.txtSizeRectHorizontal, 'Enable', 'on');
  set(handles.txtSizeRectDepth, 'Enable', 'on');
  set(handles.radRadius, 'Value', [0]);
  set(handles.txtRadius, 'Enable', 'off');
  set(handles.radNumber, 'Value', [0]);
  set(handles.txtNumber, 'Enable', 'off');
  set(handles.txtMaxRadius, 'Enable', 'off');
else
  set(handles.radRadius, 'Value', [0]);
  set(handles.txtRadius, 'Enable', 'off');
  set(handles.radNumber, 'Value', [1]);
  set(handles.txtNumber, 'Enable', 'on');
  set(handles.txtMaxRadius, 'Enable', 'on');
end

% --------------------------------------------------------------------
% Radiobutton: Split Time
function varargout = radSplitTime_Callback(h, eventdata, handles, varargin)

if get(handles.radSplitTime, 'Value') == 1
   set(handles.txtSplitTime, 'Enable', 'on');
   set(handles.txtTimePeriod, 'Enable', 'on');
else
  set(handles.txtTimePeriod, 'Enable', 'on');
  set(handles.txtSplitTime, 'Enable', 'off');
end

% --------------------------------------------------------------------
function varargout = chkTimePeriod_Callback(h, eventdata, handles, varargin)

if get(handles.chkTimeperiod, 'Value') == 1
  set(handles.txtTimeperiod, 'Enable', 'on');
else
  set(handles.txtTimeperiod, 'Enable', 'off');
end

% --------------------------------------------------------------------
function varargout = chkSaveParameter_Callback(h, eventdata, handles, varargin)

if get(handles.chkSaveParameter, 'Value') == 1
  set(handles.btnSaveParameter, 'Enable', 'on');
else
  set(handles.btnSaveParameter, 'Enable', 'off');
end

% --------------------------------------------------------------------
function varargout = btnSaveParameter_Callback(h, eventdata, handles, varargin)

[newfile, newpath] = uiputfile('*.mat','Choose parameter file');
% Cancel pressed?
if isequal(newfile, 0)  ||  isequal(newpath, 0)
  return;
end
% Everything ok?
newfile = [newpath newfile];
if length(newfile) > 1
  set(handles.lblSaveParameter, 'String', newfile);
end

% --------------------------------------------------------------------
function varargout = btnOK_Callback(h, eventdata, handles, varargin)

handles.answer = 1;
guidata(h, handles);
uiresume(handles.figGrid);

% --------------------------------------------------------------------
function varargout = btnCancel_Callback(h, eventdata, handles, varargin)

handles.answer = 0;
guidata(h, handles);
uiresume(handles.figGrid);


%kkimportasc 'Import ASCII Data File to Data Segment'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros kimportasc.pane file
%
% Parameters:
% InputFile: i1 'ASCII Input File', required: 'ASCII input data file containing new data segment'
% InputFile: i2 'Data Object Input', optional: 'data object input to insert the new segment into'
% Integer: so 'Start Offset ', default: 0: 'starting point in ASCII input file to start importing at'
% Integer: sf 'Skip Factor ', default: 0: 'number of points in ASCII file to skip between reads'
% Integer: nr 'Number of Reads ', default: 1: 'number of points in ASCII file to read between skips'
% Integer: dim 'Segment Dimension ', default: 5: 'dimension of the segment'
% OutputFile: o 'Output Object', required: 'output data object'
% Integer: wsize 'WIDTH ', default: 1: 'size of width dimension in index specified'
% Integer: hsize 'HEIGHT ', default: 1: 'size of height dimension in index specified'
% Integer: dsize 'DEPTH ', default: 1: 'size of depth dimension in index specified'
% Integer: tsize 'TIME ', default: 1: 'size of time dimension in index specified'
% Integer: esize 'ELEMENTS ', default: 1: 'size of elements dimension in index specified'
%
% Example: o = kkimportasc({i1, i2}, {'i1','';'i2','';'so',0;'sf',0;'nr',1;'dim',5;'o','';'wsize',1;'hsize',1;'dsize',1;'tsize',1;'esize',1})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% kimportasc - Import ASCII Data File to Data Segment
%
%  DESCRIPTION
% This routine will import an ASCII data file and insert it into a
% specified data object.  The new segment will be inserted into this
% data object.  If a source object was specified, then all of its data
% segments and the global object attributes will be copied to the
% destination.  If no source object was specified, then the resulting
% output object will contain only the imported segment.
% There are four attributes of the new segment that can be specified:
% dimension, index order, size and data type.  The number of indices
% and sizes specified must be equal to the dimension.
% The parameter dimension must be greater than 0 and and less than or
% equal to 5.
% The segment size is an optional argument specified by five different
% size variables: 'wsize', 'hsize', 'dsize', 'tsize', and 'esize'.  Each size
% variable must be >= to 1.  Note that although the size variables are
% optional, if no size variables are specified, the output will be of
% size 1.
% The index order is also specified by five different variables:
% 'windex', 'hindex', 'dindex', 'tindex', and 'eindex'.  The value for each
% index variable must be unique and range from 1 to 5.  Note that the index
% order dictates how data is stored and retrieved.  For example if the
% index order is specified as windex 1, hindex 2, dindex 3, tindex 4,
% eindex 5 then data will be accessed along width first, followed by height,
% depth, time, and elements.  If, however the index order is specified as
% eindex 1, windex 2, hindex 3, dindex 4, tindex 5 then data will be accessed
% along elements first, followed by width, height, depth, and time.
% The start offset specifies the point in the ASCII data from which to
% start importing in the data into the specified segment.  All points before
% the start offset are ignored.
% The skip factor specifies the number of points to skip in the ASCII data
% between reads.
% The number of reads specifies the number of points to read before skipping.
% For example, if the number of reads is 2 and the skip factor is 3, two
% values will be read, three will be skipped, followed by two more reads,
% three skips, etc. until all the data has been read.
% If the segment_name is one of the Polymorphic segments, the correct
% dimensionality must be provided :
%
%          Segment Name               Dimension
%        ---------------------------------------------------
%              KDA_SEGMENT_VALUE         5
%              KDA_SEGMENT_MAP           5
%              KDA_SEGMENT_MASK          5
%              KDA_SEGMENT_LOCATION      4
%              KDA_SEGMENT_TIME          1
%
% When importing ASCII data to either the value, map, or mask segment, all
% five size variables (wsize, hsize, dsize, tsize, and esize) may be specified
% since these segments are five dimensional.  Likewise, a five dimensional
% index order may be provided.
% When importing ASCII data to the locations segment, only four size variables
% (wsize, hsize, dsize, and esize) may be specified since the location segment
% is four dimensional.  Likewise only a four dimensional index order (windex,
% hindex, dindex, eindex) may be provided.
% When importing ASCII data to the time segment, only one size variable
% (tsize) may be specified since the location segment is one dimensional.
% Likewise only a one dimensional index order (tindex) may be provided.
% Complex values in ASCII are represented by number pairs, surrounded
% by parenthesis and separated by a comma.  These numbered pairs correspond
% to the real and imaginary values respectively.  For example, (8, 3) represents
% the complex number 8+3i.
%
%
%
%  EXAMPLES
% Consider a simple ASCII input file which looks as follows:
%
% 	file:  "ascii_data"
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
%
% This data can be imported into the 'value' segment in any number of ways which
% is illustrated in the following four examples.
% .I
% Value Segment Example 1
% % kimportasc -i1 ascii_data -o output -wsize 2 -hsize 5 -dsize 1 -tsize 1 -esize 1 -so 0 -sf 1 -nr 1 -windex 1 -hindex 2 -dindex 3 -tindex 4 -eindex 5 -segment value -type 6
% This will import the above ASCII data into the value segment of a polymorphic
% data object such that the size is "2x5x1x1x1", index order is "w,h,d,t,e",
% and data type is integer.  The output from kimportasc would conceptually
% look as follows:
%
% 	1 3
% 	1 3
% 	1 3
% 	1 3
% 	1 3
%
% .I
% Value Segment Example 2
% % kimportasc -i1 ascii_data -o output -wsize 1 -hsize 5 -dsize 1 -tsize 1 -esize 1 -so 1 -sf 3 -nr 1 -windex 1 -hindex 2 -dindex 3 -tindex 4 -eindex 5 -segment value -type 4
% This will import the above ASCII data into the value segment of a polymorphic
% data object such that the size is "1x5x1x1x1", index order is "w,h,d,t,e",
% and data type is short.  The output from kimportasc would conceptually
% look as follows:
%
% 	2
% 	2
% 	2
% 	2
% 	2
%
% .I
% Value Segment Example 3
% % kimportasc -i1 ascii_data -o output -wsize 3 -hsize 5 -dsize 1 -tsize 1 -esize 1 -so 1 -sf 1 -nr 3 -windex 1 -hindex 2 -dindex 3 -tindex 4 -eindex 5 -segment value -type 10
% This will import the above ASCII data into the value segment of a polymorphic
% data object such that the size is "3x5x1x1x1", index order is "w,h,d,t,e",
% and data type is float.  The output from kimportasc would conceptually
% look as follows:
%
% 	2 3 4
% 	2 3 4
% 	2 3 4
% 	2 3 4
% 	2 3 4
%
% .I
% Value Segment Example 4
% % kimportasc -i1 ascii_data -o output -wsize 5 -hsize 4 -dsize 1 -tsize 1 -esize
%  1 -so 0 -sf 0 -nr 20 -segment value -type 8
% This will import the above ASCII data into the value segment of a polymorphic
% data object such that the size is "4x5x1x1x1", index order is "w,h,d,t,e",
% and data type is long.  The output from kimportasc would conceptually look
% as follows:
%
% 	1 2 3 4 1
% 	2 3 4 1 2
% 	3 4 1 2 3
% 	4 1 2 3 4
%
% The same input data can be imported into the 'map' segment which is
% illustrated in the following example.
% .I
% Map Segment Example
% % kimportasc -i1 ascii_data -i2 data_without_map -o output -wsize 4 -hsize 5 -dsize 1 -tsize 1 -esize 1 -so 0 -sf 0 -nr 1 -windex 1 -hindex 2 -dindex 3 -tindex 4 -eindex 5 -segment map -type 6
% This will import the above ASCII data into the map segment of the polymorphic
% data object specified by the input file "data_without_map" such that the size
% of the map is "4x5x1x1x1", index order is "mw,mh,md,mt,me", and data type is
% integer, where "mw,mh,md,mt,me" coorespond to map width, map height, map depth,
% map time, and map elements respectively.  The map segment output from
% kimportasc would conceptually look like the input ASCII data.
%
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
% 	1 2 3 4
%
% .I
% Mask Segment Example
% The following input data can be imported into the 'mask' segment which is
% illustrated in the following example.
%
% 	file:  "map_ascii_data"
% 	1 0 0 1
% 	0 0 1 0
% 	1 1 0 0
% 	1 1 1 1
% 	1 0 1 0
%
% % kimportasc -i1 map_ascii_data -i2 data_without_mask -o output -wsize 4 -hsize 5 -dsize 1 -tsize 1 -esize 1 -so 0 -sf 0 -nr 1 -windex 1 -hindex 2 -dindex 3 -tindex 4 -eindex 5 -segment mask -type 6
% This will import the above ASCII data into the mask segment of the polymorphic
% data object specified by the input file "data_without_mask" such that the size
% of the mask is "4x5x1x1x1", index order is "w,h,d,t,e" and data type is
% integer.  The mask segment output from kimportasc would conceptually look
% like the ASCII input.
% .I
% Time Segment Example
% The following input data can be imported into the 'time' segment which is
% illustrated in the following example.
%
% 	file: "time_ascii_data"
% 	1 5 10 15 19 36 40 52
%
% % kimportasc -i1 time_ascii_data -i2 data_with_time_series -o output -tsize 8 -so 0 -sf 0 -nr 1 -tindex 1 -segment time -type 6 -dim 1
% This will import the above ASCII data into the time segment of the polymorphic
% data object specified by the input file "data_with_time_series" such that the
% size of the explicit time segment is "8", index order is "t", and data type is
% integer.  The time segment output from kimportasc would conceptually look
% like the ASCII input.
% .I
% Location Segment Example
% The following input data can be imported into the 'location'segment which
% is illustrated in the following example.
%
% 	file:  "location_ascii_data"
% 	1  3  5  7
% 	9  11 13 15
% 	17 19 21 23
% 	25 27 29 31
% 	33 35 37 39
%
% % kimportasc -i1 location_ascii_data -i2 data_without_locations -o output -wsize 4 -hsize 5 -dsize 1 -esize 1 -so 0 -sf 0 -nr 1 -windex 1 -hindex 2 -dindex 3 -eindex 4 -segment location -type 6 -dim 4
% This will import the above ASCII data into the location segment of the
% polymorphic data object specified by the input file "data_without_locations"
% such that the size of the explicit location segment is "4x5x1x1", index
% order is "w,h,d,e", and data type is integer.  The location segment output
% from kimportasc would conceptually look like the ASCII input.
%
%  "SEE ALSO"
% kasc2val, kasc2mask, kasc2loc, kasc2time, kasc2map
%
%  RESTRICTIONS
% If no size variables are specified (wsize, hsize, dsize, tsize, or esize),
% the output data object will be of size 1.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kkimportasc(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kkimportasc(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i1', '__input';'i2', '__input';'so', 0;'sf', 0;'nr', 1;'dim', 5;'o', '__output';'wsize', 1;'hsize', 1;'dsize', 1;'tsize', 1;'esize', 1};
maxval={0,1,1,1,2,2,0,2,2,2,2,2};
minval={0,1,1,1,2,2,0,2,2,2,2,2};
istoggle=[0,1,1,1,1,1,0,1,1,1,1,1];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','Integer','Integer','Integer','Integer','OutputFile','Integer','Integer','Integer','Integer','Integer'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'kimportasc"  '],Inputs,narglist);


classdef Plot < handle
%Plot OlyDat Browser Plot
%   A Plot object represents a plot/analysis in the OlyDat Browser. A plot
%   has various responsibilities (all except for the actual plotting are
%   "as appropriate"):
%
%   * Custom data preprocessing
%   * The actual plotting
%   * Interactivity: sending and responding to experiment-selection signals
%   * Math/statistical analysis
%
%   See also OlyDat.Plot/preprocessData, OlyDat.Plot/doPlot,
%   OlyDat.Browser, OlyDat.BrowserStat, OlyDat.ExperimentCoordinator.

    properties (Abstract)
        Name;
        AllowsMultiStats; % (logical) If true, this plot handles multiple statistics
        UsesAuxVar; % Either true, false, or 'custom'.
                    % If true: this plot uses the auxiliary pulldown, as configured at Browser startup.
                    % If false: this plot does not use the aux pulldown. (It will be inactivated.)
                    % If 'custom': This plot configures the auxiliary pulldown itself (using groupVarChanged()).
		    %	           pltCfg.auxVar will be empty when doPlot() is called. This class can use
		    % 		   auxVarChanged() to cache the current auxvar setting.
		    %		   TODO Requiring this class to cache the the current auxvar is unnecessary.

        UsesGroupVar2; % Either true or false
        GroupVarLabel; % Text label for Group Var 1
        GroupVar2Label;

        AutoReplotAfterStatChange; % (logical) If true, stat selection causes replot
        AutoReplotAfterGroupChange;
    end

    methods

        function data = preprocessData(obj,data,plotCfg) %#ok<INUSD,MANU>
            %data = preprocessData(obj,data,plotCfg)
            %   Plots should override this method if they need custom data
            %   manipulation/flattening for their plot. Typical uses
            %   include flattening statistics in the .Scores field to the
            %   top level, averaging scores over tubes, normalizing stats,
            %   etc.
            %
            %   plotCfg is a struct with fields .stat, .grp, .grpVals,
            %   .aux.

            % default implementation: no-op
        end

        function groupChanged(obj,grpStat,allData,hCtrls) %#ok<INUSD,MANU>
            % Called when user selects a new grouping variable. (When the
            % plot is first selected, the current grouping variable is
            % considered to be selected.)
            %
            % grpStat: OlyDat.BrowserStat for new grouping var.
            % allData: struct array, all data loaded in browser.
            % hCtrls: scalar struct:
            %         * hCtrls.pumAuxVar is the auxiliary var pulldown.

            % This method is used when a plot needs to eg customize what
            % auxiliary vars are available, depending on the grouping var.
            % Default implementation: no-op
        end

        function auxVarChanged(obj,auxVar,allData,hCtrls) %#ok<MANU,INUSD>
            % Called when a user selects a new auxiliary variable. (When
            % the plot is first selected, the current aux variable is
            % considered to be selected.)
            %
            % auxVar: OlyDat.BrowserStat for new aux var. if
            % UsesAuxVar=='custom', auxVar will be [].
            % allData: struct array, all data loaded in browser.
            % hCtrls: scalar struct:
            %           * hCtrls.pumAuxVar is the auxiliary var pulldown.

            % Default impl: no-op
        end

    end

    methods (Abstract)
        %detailStr = doPlot(obj,ax,data,stat,grp,plotCfg,expCoordinator)
        %   * ax: axes object
        %   * data: preprocessed data struct for current dataset
        %   * stat: Nrows x Nstats numeric matrix. As a convenience the
        %   Browser puts the statistic(s) of interest into a numeric array
        %   for plotting. Nrows is the number of elements in the
        %   preprocessed data struct.
        %   * grp: Nrows x 1 column vector, either numeric or cellstr. As a
        %   convenience the Browser puts the value of the grouping variable
        %   (if any) in a column vector for plotting.
        %   * plotCfg: The plot configuration specified by the user within
        %   the Browser. This is a struct with fields .stat, .grp,
        %   .grpVals, and .aux.
        %   * expCoordinator: ExperimentCoordinator object used by Browser.
        %   Plots that want to participate in plot interactivity should
        %   register appropriately with the coordinator.
        %   * detailStr: Plots should return a string/cellstr that will be
        %   displayed in the Browser. Typical uses include a description of
        %   the plot, or math details of any statistics performed, etc.
        %
        % OlyDat calls this method when drawing a plot in an axis. This can
        % occur either in the main Browser window, or in standalone figures
        % (eg in the case of 'Compare plots'). If doPlot() performs any
        % actions that require cleanup, that cleanup should be put in ax's
        % DeleteFcn. The Browser will ensure this method is called when a
        % plot is going away. Unregistering from the expCoordinator is an
        % example of such a cleanup action.
        %
        % TODO: unregistering from the expCoordinator is a common action,
        % we should make this easier for users.
        str = doPlot(obj,ax,data,bstat,grp,pltCfg,expCoordinator)
    end

    %% Utilities

    methods (Static)

      function messageAxisCenter(ax,txt)
        % Put a message in the center of axis ax.

        axes(ax);
        xl = xlim(ax);
        yl = ylim(ax);
        hTxt = text(mean(xl),mean(yl),txt);
        set(hTxt,'horizontalalignment','center','interpreter','none');
      end

    end

end


function rx = rxShowStats(rx,flag);
%
% rx = rxShowStats([rx],flag);
%
% mrRx:
% Show or Hide the text controls
% for the statistics of comparing
% the volume and reference images/vols.
%
% fig: figure to add/remove fields from.
%
% flag: if 1, add fields; if 0, remove.
%
%
% 03/05 ras.
if ieNotDefined('rx')
    cfig = findobj('Tag','rxControlFig');
    rx = get(cfig,'UserData');
end

if flag==1
    % move the axes over to make room
    set(rx.ui.compareAxes,'Position',[0.05 .25 .9 .7]);

    % show/create fields
    if isfield(rx.ui,'compareStats') & ishandle(rx.ui.compareStats.corrcoefVal)

        % show
        fields = fieldnames(rx.ui.compareStats);
        for i = 1:length(fields)
            set(rx.ui.compareStats.(fields{i}),'Visible','on');
        end
    else
        %%%%% create %%%%%

        % create text for corr coefficient (R)
        h = uicontrol('Style','text',...
                      'Units','Normalized',...
                      'Position',[0 .16 .25 .05],...
                      'String','Correlation [R]:',...
                      'FontWeight','bold',...
                      'FontAngle','italic',...
                      'HorizontalAlignment','left',...
                      'BackgroundColor',get(gcf,'Color'),...
                      'ForegroundColor',[0 .4 0]);
        rx.ui.compareStats.corrcoefLabel = h;
        h = uicontrol('Style','text',...
                      'Units','Normalized',...
                      'Position',[.25 .16 .2 .05],...
                      'String','(N/A)',...
                      'HorizontalAlignment','left',...
                      'BackgroundColor',get(gcf,'Color'),...
                      'ForegroundColor',[0 0 0]);
        rx.ui.compareStats.corrcoefVal = h;

        % create text for root mean square error
        h = uicontrol('Style','text',...
                      'Units','Normalized',...
                      'Position',[0 .1 .25 .05],...
                      'String','R.M.S. Error:',...
                      'FontWeight','bold',...
                      'FontAngle','italic',...
                      'HorizontalAlignment','left',...
                      'BackgroundColor',get(gcf,'Color'),...
                      'ForegroundColor',[.5 0 0]);
        rx.ui.compareStats.rmseLabel = h;
        h = uicontrol('Style','text',...
                      'Units','Normalized',...
                      'Position',[.25 .1 .2 .05],...
                      'String','(N/A)',...
                      'HorizontalAlignment','left',...
                      'BackgroundColor',get(gcf,'Color'),...
                      'ForegroundColor',[0 0 0]);
        rx.ui.compareStats.rmseVal = h;
    end
else
    % hide 'em
    fields = fieldnames(rx.ui.compareStats);
    for i = 1:length(fields)
        set(rx.ui.compareStats.(fields{i}),'Visible','off');
    end

    % restore axes to full size
	set(rx.ui.compareAxes,'Position',[0.05 .1 .9 .85]);
end

if ishandle(rx.ui.controlFig)
    set(rx.ui.controlFig,'UserData',rx);
end

rxRefresh(rx);

return


function y=str2strs(s)

% this function takes s (a string deliminated by tabs, commas, etc.)
%  and breaks it up into sub strings stored in y (a cell array of strings)
%
% spaces are eliminated by the function strcat so these are replaced in the
%  beginning by an underscore. space delimination can be handled, though s
%  should be checked for any pre-existing underscrores.
%
% recovery of the individual elements is by using the char command
%
% e.g., applying it to a tab deliminated string...
%   fields = str2strs('abc	d%*	34_EF	5	s p a c e s')     returns
%   'abc'    'd%*'    '34_EF'    '5'    's_p_a_c_e_s'
% and then
%   char(fields(3))     returns
%   34_EF
%
% David Malicky  malicky@umich.edu

% replace each space w/ a character that strcat won't miss
s=strrep(s,' ','_');
delim='	'; % that long space is a tab, though any character may be used

lens=length(s);
tabs=findstr(s,delim);
numtabs=length(tabs);	% this is 1 less than the number of sub-strings

i=0;
for j=1:numtabs+1
	y(j)=cellstr('');
	while ( (i<lens) & (s(i+1)~=delim)  )  % another tab
		y(j)=strcat(y(j),s(i+1));
		i=i+1;
	end;
	i=i+1;
end;

y;


%{
 * Copyright (C) 2020-2030, The Regents of The University of Michigan.
 * All rights reserved.
 * This software was developed in the Biped Lab (https://www.biped.solutions/)
 * under the direction of Jessy Grizzle, grizzle@umich.edu. This software may
 * be available under alternative licensing terms; contact the address above.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Regents of The University of Michigan.
 *
 * AUTHOR: Bruce JK Huang (bjhuang[at]umich.edu)
 * WEBSITE: https://www.brucerobot.com/
%}

function [x,y,z] = genSquarePoints(app)
    method = app.DistributionDropDown.Value;
    switch method
        case 'Uniform'
            [x, y, z] = genUniformPoints(app);
        case 'Grid'
            [x, y, z] = genGriddedPoints(app);
    end
end


function s = lp_e(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,...
             i17,i18,i19,i20)
%
%  Auxiliary routine for the execution of strings with MATLAB
%  expressions, which depend on numerical values.
%
%  Input:
%
%    i1,...,i20 strings or numerical values.
%
%  Output:
%
%    s          string.
%
%
%  LYAPACK 1.0 (Thilo Penzl, November 1999)

ni = nargin;

if ni>=1, if ischar(i1), s = i1; else, s = num2str(i1); end, end
if ni>=2, if ischar(i2), s = [s,i2]; else, s = [s,num2str(i2)]; end, end
if ni>=3, if ischar(i3), s = [s,i3]; else, s = [s,num2str(i3)]; end, end
if ni>=4, if ischar(i4), s = [s,i4]; else, s = [s,num2str(i4)]; end, end
if ni>=5, if ischar(i5), s = [s,i5]; else, s = [s,num2str(i5)]; end, end
if ni>=6, if ischar(i6), s = [s,i6]; else, s = [s,num2str(i6)]; end, end
if ni>=7, if ischar(i7), s = [s,i7]; else, s = [s,num2str(i7)]; end, end
if ni>=8, if ischar(i8), s = [s,i8]; else, s = [s,num2str(i8)]; end, end
if ni>=9, if ischar(i9), s = [s,i9]; else, s = [s,num2str(i9)]; end, end
if ni>=10, if ischar(i10), s = [s,i10]; else, s = [s,num2str(i10)]; end, end
if ni>=11, if ischar(i11), s = [s,i11]; else, s = [s,num2str(i11)]; end, end
if ni>=12, if ischar(i12), s = [s,i12]; else, s = [s,num2str(i12)]; end, end
if ni>=13, if ischar(i13), s = [s,i13]; else, s = [s,num2str(i13)]; end, end
if ni>=14, if ischar(i14), s = [s,i14]; else, s = [s,num2str(i14)]; end, end
if ni>=15, if ischar(i15), s = [s,i15]; else, s = [s,num2str(i15)]; end, end
if ni>=16, if ischar(i16), s = [s,i16]; else, s = [s,num2str(i16)]; end, end
if ni>=17, if ischar(i17), s = [s,i17]; else, s = [s,num2str(i17)]; end, end
if ni>=18, if ischar(i18), s = [s,i18]; else, s = [s,num2str(i18)]; end, end
if ni>=19, if ischar(i19), s = [s,i19]; else, s = [s,num2str(i19)]; end, end
if ni>=20, if ischar(i20), s = [s,i20]; else, s = [s,num2str(i20)]; end, end
if ni>=21, error('Too many input arguments.'); end


function b = includes(s1, s2)

% Sep 4, 2020: Removed verLessThan because it's slowing down Homer3 startup

% if verLessThan('matlab','9.1')
%     b = ~isempty(strfind(s1,s2));
% else
%     b = contains(s1,s2);
% end

if iscell(s1)
    b = ~isempty(find(strcmp(s1, s2)));
else
    b = ~isempty(strfind(s1,s2)); %#ok<STREMP>
    % b = contains(s1,s2);
end


% read_erplabheader() - import ERPLAB dataset files
%
% Usage:
%   >> header = read_erplabheader(filename);
%
% Inputs:
%   filename - [string] file name
%
% Outputs:
%   header   - FILEIO toolbox type structure
%
% Modified from read_eeglabheader

%123456789012345678901234567890123456789012345678901234567890123456789012

% Copyright (C) 2008 Arnaud Delorme, SCCN, INC, UCSD, arno@salk.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function header = read_erplabheader(filename)

if nargin < 1
  help read_erplabheader;
  return;
end;

if ~isstruct(filename)
  load('-mat', filename);
else
  ERP = filename;
end;

header.Fs          = ERP.srate;
header.nChans      = ERP.nchan;
header.nSamples    = ERP.pnts;
header.nSamplesPre = -ERP.xmin*ERP.srate;
header.nTrials     = ERP.nbin;
try
  header.label       = { ERP.chanlocs.labels }';
catch
  ft_warning('creating default channel names');
  for i=1:header.nChans
    header.label{i} = sprintf('chan%03d', i);
  end
end
ind = 1;
for i = 1:length( ERP.chanlocs )
    if isfield(ERP.chanlocs(i), 'X') && ~isempty(ERP.chanlocs(i).X)
        header.elec.label{ind, 1} = ERP.chanlocs(i).labels;
        % this channel has a position
        header.elec.pnt(ind,1) = ERP.chanlocs(i).X;
        header.elec.pnt(ind,2) = ERP.chanlocs(i).Y;
        header.elec.pnt(ind,3) = ERP.chanlocs(i).Z;
        ind = ind+1;
    end;
end;

header.orig = ERP;


%
%   FILE NAME: getMetsFromBiGG.m
%
%   PURPOSE: Generate data structure for BiGG metabolites
%

% Move to the target folder
cd('/Users/haowa/Box Sync/HMR3/BiGG');

% Load the text format BiGG reactions, after fixing errors with M01870
T=readtable('bigg_models_metabolites_20180424.txt','ReadVariableNames',1);
BiGGMets=table2struct(T,'ToScalar',true);

% Rename the fields according to RAVEN specification
BiGGMets.mets=BiGGMets.bigg_id;
BiGGMets.metNames=BiGGMets.name;
BiGGMets.universalID=BiGGMets.universal_bigg_id;

% Add oldids field as cell array based on info from old_bigg_ids
num=numel(BiGGMets.bigg_id);
BiGGMets.oldids=cell(num,1);
BiGGMets.oldids(:)={''};
% Add MNX field
metMNXID=regexp(BiGGMets.database_links,'MNXM\d+','match');
BiGGMets.metMNXID=cell(num,1);
BiGGMets.metMNXID(:)={''};
count=0;
for i=1:num
		if ~isempty(BiGGMets.old_bigg_ids{i})
				% Remove existing BiGG ids and universal ids from oldids
				BiGGMets.oldids{i}=setdiff(transpose(strsplit(BiGGMets.old_bigg_ids{i},'; ')),BiGGMets.mets{i});
				BiGGMets.oldids{i}=setdiff(BiGGMets.oldids{i},BiGGMets.universalID{i});
		end
		if ~isempty(metMNXID{i})
				if numel(metMNXID{i})==1
						BiGGMets.metMNXID{i}=metMNXID{i}{1};
				else
						BiGGMets.metMNXID{i}=metMNXID{i};
						count=count+1;
				end
		end
end
%count=0
numel(find(~cellfun(@isempty,BiGGMets.metMNXID)))  %ans = 9915

% Remove some fields
BiGGMets=rmfield(BiGGMets,{'bigg_id','name','universal_bigg_id','old_bigg_ids'});

save('BiGGMets.mat','BiGGMets');


function [mri, hdr, cpersist] = read_ctf_mri4(filename);

% READ_CTF_MRI reads header and imnage data from CTF format MRI file
%
% [mri, hdr] = read_ctf_mri(filename)
%
% See also READ_CTF_MEG4, READ_CTF_RES4

% Copyright (C) 2008 Ivar Clemens
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: read_ctf_mri4.m 1443 2010-07-22 07:03:17Z jansch $

fid = fopen(filename,'rb', 'ieee-be');

if fid<=0
  error(sprintf('could not open MRI file: %s\n', filename));
end

[cpersist] = read_cpersist(fid);

% turn warnings off
ws = warning('off');

% general header information
hdr.identifierString        = get_value(cpersist, '_CTFMRI_VERSION');      % CTF_MRI_FORMAT VER 4.1
hdr.imageSize               = get_value(cpersist, '_CTFMRI_SIZE');         % 256
hdr.dataSize                = get_value(cpersist, '_CTFMRI_DATASIZE');     % 1 or 2(bytes)
hdr.orthogonalFlag          = get_value(cpersist, '_CTFMRI_ORTHOGONALFLAG');   % if set then image is orthogonal
hdr.interpolatedFlag        = get_value(cpersist, '_CTFMRI_INTERPOLATEDFLAG'); % if set than image was interpolated
hdr.comment                 = get_value(cpersist, '_CTFMRI_COMMENT');

hdr.Image.modality          = get_value(cpersist, '_SERIES_MODALITY');
hdr.Image.manufacturerName  = get_value(cpersist, '_EQUIP_MANUFACTURER');
hdr.Image.instituteName     = get_value(cpersist, '_EQUIP_INSTITUTION');
hdr.Image.imagedNucleus     = get_value(cpersist, '_MRIMAGE_IMAGEDNUCLEUS');
hdr.Image.FieldStrength     = get_value(cpersist, '_MRIMAGE_FIELDSTRENGTH');
hdr.Image.EchoTime          = get_value(cpersist, '_MRIMAGE_ECHOTIME');
hdr.Image.RepetitionTime    = get_value(cpersist, '_MRIMAGE_REPETITIONTIME');
hdr.Image.InversionTime     = get_value(cpersist, '_MRIMAGE_INVERSIONTIME');
hdr.Image.FlipAngle         = get_value(cpersist, '_MRIMAGE_FLIPANGLE');

% euler angles to align MR to head coordinate system(angles in degrees !)
rotation = split_nvalue(get_value(cpersist, '_CTFMRI_ROTATE'));
hdr.rotate_coronal  = rotation(1);
hdr.rotate_sagittal = rotation(2);
hdr.rotate_axial    = rotation(3);

hdr.transformMatrix = split_nvalue(get_value(cpersist, '_CTFMRI_TRANSFORMMATRIX'));
hdr.transformMatrix = reshape(hdr.transformMatrix, 4, 4)';

mmPerPixel = split_nvalue(get_value(cpersist, '_CTFMRI_MMPERPIXEL'));
hdr.mmPerPixel_sagittal = mmPerPixel(1);
hdr.mmPerPixel_coronal  = mmPerPixel(2);
hdr.mmPerPixel_axial    = mmPerPixel(3);

% HeadModel_Info specific header items
hmNasion = split_nvalue(get_value(cpersist, '_HDM_NASION'));
hdr.HeadModel.Nasion_Sag = hmNasion(1);
hdr.HeadModel.Nasion_Cor = hmNasion(2);
hdr.HeadModel.Nasion_Axi = hmNasion(3);

hmLeftEar = split_nvalue(get_value(cpersist, '_HDM_LEFTEAR'));
hdr.HeadModel.LeftEar_Sag = hmLeftEar(1);
hdr.HeadModel.LeftEar_Cor = hmLeftEar(2);
hdr.HeadModel.LeftEar_Axi = hmLeftEar(3);

hmRightEar = split_nvalue(get_value(cpersist, '_HDM_RIGHTEAR'));
hdr.HeadModel.RightEar_Sag = hmRightEar(1);
hdr.HeadModel.RightEar_Cor = hmRightEar(2);
hdr.HeadModel.RightEar_Axi = hmRightEar(3);

hmSphere = split_nvalue(get_value(cpersist, '_HDM_DEFAULTSPHERE'));
hdr.HeadModel.defaultSphereX = hmSphere(1);
hdr.HeadModel.defaultSphereY = hmSphere(2);
hdr.HeadModel.defaultSphereZ = hmSphere(3);
hdr.HeadModel.defaultSphereRadius = hmSphere(4);

hmOrigin = split_nvalue(get_value(cpersist, '_HDM_HEADORIGIN'));
hdr.headOrigin_sagittal = hmOrigin(1);
hdr.headOrigin_coronal = hmOrigin(2);
hdr.headOrigin_axial = hmOrigin(3);

%fread(fid,204,'char'); % unused, padding to 1028 bytes

% revert to previous warning state
warning(ws);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% READ THE IMAGE DATA
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

mri = zeros(256, 256, 256);

for slice = 1:256
  name = sprintf('_CTFMRI_SLICE_DATA#%.5d', slice);
  offset = get_value(cpersist, name);

  fseek(fid, offset, 'bof');

  if(hdr.dataSize == 1)
    slicedata = uint8(fread(fid, [256 256], 'uint8'));
  elseif(hdr.dataSize == 2)
    slicedata = uint16(fread(fid, [256 256], 'uint16'));
  else
    error('Unknown datasize in CTF MRI file');
  end;

  mri(:, :, slice) = slicedata;
end;

%mri = reshape(mri, [256 256 256]);
fclose(fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% DO POST-PROCESSING
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Data is stored in PIR order (i.e. fastest changing direction goes from
% anterior to Posterior, then from superior to Inferior, finally from left
% to Right) assuming subject position was not too oblique and proper
% conversion to .mri format.  (Does this depend on hdr.imageOrientation?)
% On the other hand, the transformation matrix and fiducials are in RPI
% order so we must reorient the image data to match them.
mri = permute(mri, [3 1 2]);

transformMatrix = hdr.transformMatrix;

% Construct minimal transformation matrix if fiducials were not defined.
% Bring data into same orientation (head coordinates are ALS) at least.
if all(transformMatrix == 0)
  transformMatrix(1, 2) = -1;
  transformMatrix(2, 1) = -1;
  transformMatrix(3, 3) = -1;
  transformMatrix(4, 4) = 1;
end

% determine location of fiducials in MRI voxel coordinates
% flip the fiducials in voxel coordinates to correspond to the previous flip along left-right
hdr.fiducial.mri.nas = [hdr.HeadModel.Nasion_Sag hdr.HeadModel.Nasion_Cor hdr.HeadModel.Nasion_Axi];
hdr.fiducial.mri.lpa = [hdr.HeadModel.LeftEar_Sag hdr.HeadModel.LeftEar_Cor hdr.HeadModel.LeftEar_Axi];
hdr.fiducial.mri.rpa = [hdr.HeadModel.RightEar_Sag hdr.HeadModel.RightEar_Cor hdr.HeadModel.RightEar_Axi];

% Reorient the image data, the transformation matrix and the fiducials
% along the left-right direction.
% This may have been done only for visualization?  It can probably be
% "turned off" without problem.
if false
  mri = flipdim(mri, 1);
  flip = [-1 0 0 hdr.imageSize+1
           0 1 0 0
           0 0 1 0
           0 0 0 1    ];
  transformMatrix = flip*transformMatrix;
  hdr.fiducial.mri.nas = [hdr.fiducial.mri.nas, 1] * flip(1:3, :)';
  hdr.fiducial.mri.lpa = [hdr.fiducial.mri.lpa, 1] * flip(1:3, :)';
  hdr.fiducial.mri.rpa = [hdr.fiducial.mri.rpa, 1] * flip(1:3, :)';
end

% re-compute the homogeneous transformation matrices (apply voxel scaling)
scale = eye(4);
scale(1,1) = hdr.mmPerPixel_sagittal;
scale(2,2) = hdr.mmPerPixel_coronal;
scale(3,3) = hdr.mmPerPixel_axial;
hdr.transformHead2MRI = transformMatrix*inv(scale);
hdr.transformMRI2Head = scale*inv(transformMatrix);

% compute location of fiducials in MRI and HEAD coordinates
hdr.fiducial.head.nas = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.nas, 'homogenous');
hdr.fiducial.head.lpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.lpa, 'homogenous');
hdr.fiducial.head.rpa = warp_apply(hdr.transformMRI2Head, hdr.fiducial.mri.rpa, 'homogenous');

%
% Reads a series of delimited numbers from a string
%
% @param input string Delimited string to process
% @param delim string The delimiter (default: \\)
%
% @return values matrix Array containing the numbers found
%
  function [values] = split_nvalue(input, delim)
    if(nargin < 2), delim = '\\'; end;

    remain = input;
    values = [];

    while(numel(remain > 0))
      [value, remain] = strtok(remain, delim);
      values(end + 1) = str2num(value);
    end;
  end

%
% Reads a value from the CPersist structure
%
% @param cpersist struct-array The CPersist structure
% @param key string The name of the parameter
%
% @return value mixed The value of the named parameter
%
  function [value] = get_value(cpersist, key)
    idx = find(strcmp({cpersist.key}, key));

    if(numel(idx) < 1), error('Specified key does not exist.'); end;
    if(numel(idx) > 1), error('Specified key is not unique.'); end;

    value = cpersist(idx).value;
  end

%
% Processes the CTF CPersist structure into a struct-array
%
% @param fid numeric File handle from which to read the CPersist structure
% @return cpersist struct-array
%
  function [cpersist] = read_cpersist(fid)
    magic = char(fread(fid, 4, 'char'))';

    if(~strcmp(magic, 'WS1_')), error('Invalid CPersist header'); end;

    cpersist = struct('key', {}, 'value', {});

    while(~feof(fid))
      % Read label
      lsize = fread(fid, 1, 'int32');
      ltext = char(fread(fid, lsize, 'char'))';

      % Last label in file is always EndOfParameters
      if(strcmp(ltext, 'EndOfParameters')), return; end;

      % Read value
      vtype = fread(fid, 1, 'int32');
      value = read_cpersist_value(fid, vtype);

      cpersist(end + 1).key = ltext;
      cpersist(end).value = value;
    end
  end

%
% Reads a single value of type (vtype) from fid
%
% @param fid numeric  The file to read the value from
% @param vtype numeric The type of value to read
%
% @return value mixed The read value
%
  function [value] = read_cpersist_value(fid, vtype)
    switch vtype
      case 3
        vsize = fread(fid, 1, 'int32');
        value = ftell(fid);
        fseek(fid, vsize, 'cof');
      case 4
        value = fread(fid, 1, 'double');
      case 5
        value = fread(fid, 1, 'int32');
      case 6
        value = fread(fid, 1, 'int16');
      case 10
        vsize = fread(fid, 1, 'int32');
        value = char(fread(fid, vsize, 'char'))';
      otherwise
        error(['Unsupported valuetype (' num2str(vtype) ') found in CPersist object']);
        return
    end
  end

end


classdef GraphicalAnalysisIndepVarEnum < matlab.mixin.SetGet
    %GraphicalAnalysisIndepVarEnum Summary of this class goes here
    %   Detailed explanation goes here

    enumeration
        Time('Time')
        MissionElapsedTime('Mission Elapsed Time');
        TrueAnomaly('True Anomaly');
        Longitude('Longitude')
        Altitude('Altitude')
    end

    properties
        name(1,:) char
    end

    methods
        function obj = GraphicalAnalysisIndepVarEnum(name)
            obj.name = name;
        end
    end

    methods(Static)
        function [listBoxStr, m] = getListboxStr()
            m = enumeration('GraphicalAnalysisIndepVarEnum');
            listBoxStr = {m.name};
        end
    end
end


function params = mrInitGUI_analParams(params);
% Assign analysis parameters for a new mrVista session (mrInit2).
%
% params = mrInitGUI_analParams(params);
%
% This GUI allows the user to assign GLM ("event-related") and
% coherence ("block") analysis parameters to scans, assign parfiles
% to scans, and group scans. It returns params for mrInit2 which include
% the updated parameters.
%
%
% ras, 07/2007.
if notDefined('params'),    params = mrInitDefaultParams;       end

%% GUI update function switch
% the callbacks will call this function with special calls to sub-functions
% in lieu of a params struct. Parse this:
if ischar(params)
	switch lower(params)
		case 'assignglmparams', mrInitGUI_assignGlmParams;
		case 'assigncoparams', mrInitGUI_assignCoParams;
		case 'assignparfiles', mrInitGUI_assignParfiles;
		case 'assignparfilepattern', mrInitGUI_assignParfilePattern;
		case 'groupscans', mrInitGUI_groupScans;
		otherwise, error(sprintf('Invalid argument for %s', mfilename));
	end
	return
end

% --- the code below makes the GUI --- %
%%%%% params
fsz = 10;  % fontsize for controls
bgColor = [.9 .9 .9];  % background color for figure

%%%%% Create the main GUI figure
hFig = figure('Units', 'norm', 'Position', [.15 .3 .7 .35], ...
	'UserData', params, ...
	'Name', 'Assign Analysis Parameters', 'NumberTitle', 'off', ...
	'Color', bgColor, 'CloseRequestFcn', 'OK = 0; uiresume;');

%%%%% listboxes
%% scans listbox
annotations = {};
for i = 1:length(params.annotations)
	annotations{i} = sprintf('%i: %s', i, params.annotations{i});
end
hScans = uicontrol('Style', 'listbox', 'String', annotations, ...
	'Min', 0, 'Max', 2, 'Tag', 'ScanList', ... % multiple selection
	'Units', 'norm', 'Position', [.05 .2 .25 .7], ...
	'BackgroundColor', 'w', 'ForegroundColor', 'k', 'FontSize', fsz);

% text label
uicontrol('Style', 'text', 'String', 'Scans', 'FontSize', fsz+2, ...
	'Units', 'norm', 'Position', [.05 .93 .25 .05], ...
	'HorizontalAlignment', 'center', 'BackgroundColor', bgColor);

%% parfiles listbox
for i = 1:length(annotations)  % nScans
	if (length(params.parfile) >= i) & (~isempty(params.parfile{i}))
		parfiles{i} = sprintf('%i: %s', i, params.parfile{i});
	else
		parfiles{i} = sprintf('%i: (none)', i);
	end
end
hParfiles = uicontrol('Style', 'listbox', 'String', parfiles, ...
	'Min', 0, 'Max', 2, 'Tag', 'ParfilesList', ... % multiple selection
	'Units', 'norm', 'Position', [.35 .2 .15 .7], 'Value', [], ...
	'BackgroundColor', bgColor, 'ForegroundColor', 'k', 'FontSize', fsz);

% text label
uicontrol('Style', 'text', 'String', 'Parfiles', 'FontSize', fsz+2, ...
	'Units', 'norm', 'Position', [.35 .93 .15 .05],  ...
	'HorizontalAlignment', 'center', 'BackgroundColor', bgColor);

%% scan groups listbox
for i = 1:length(annotations)  % nScans
	scanGroups{i} = sprintf('%i: (none)', i);
end

for i = 1:length(params.scanGroups)
	for j = params.scanGroups{i}
		scanGroups{j} = sprintf('%i: %s', i, num2str(params.scanGroups{i}));
	end
end

hScanGroups = uicontrol('Style', 'listbox', 'String', scanGroups, ...
	'Min', 0, 'Max', 2, 'Tag', 'ScanGroupsList', ... % multiple selection
	'Units', 'norm', 'Position', [.55 .2 .15 .7], 'Value', [], ...
	'BackgroundColor', bgColor, 'ForegroundColor', 'k', 'FontSize', fsz);

% text label
uicontrol('Style', 'text', 'String', 'Scan Groups', 'FontSize', fsz+2, ...
	'Units', 'norm', 'Position', [.55 .93 .12 .05], ...
	'HorizontalAlignment', 'center', 'BackgroundColor', bgColor);

%%%%% buttons
%% assign co params button
uicontrol('Style', 'pushbutton', 'String', 'Assign Coherence Params', ...
	'Units', 'norm', 'Position', [.75 .8 .2 .12], ...
	'BackgroundColor', [.8 .8 .9], 'ForegroundColor', 'k', 'FontSize', fsz, ...
	'Callback', 'mrInitGUI_analParams(''assignCoParams''); ');

%% assign GLM params button
uicontrol('Style', 'pushbutton', 'String', 'Assign GLM Params', ...
	'Units', 'norm', 'Position', [.75 .65 .2 .12], ...
	'BackgroundColor', [.8 .8 .9], 'ForegroundColor', 'k', 'FontSize', fsz, ...
	'Callback', 'mrInitGUI_analParams(''assignGlmParams''); ');

%% assign parfiles button
uicontrol('Style', 'pushbutton', 'String', 'Assign Parfiles', ...
	'Units', 'norm', 'Position', [.75 .5 .2 .12], ...
	'UserData', hParfiles, ...
	'BackgroundColor', [.8 .8 .9], 'ForegroundColor', 'k', 'FontSize', fsz, ...
	'Callback', 'mrInitGUI_analParams(''assignParfiles''); ');

%% assign parfiles pattern button
uicontrol('Style', 'pushbutton', 'String', 'Assign Parfile Pattern', ...
	'Units', 'norm', 'Position', [.75 .35 .2 .12], ...
	'UserData', hParfiles, ...
	'BackgroundColor', [.8 .8 .9], 'ForegroundColor', 'k', 'FontSize', fsz, ...
	'Callback', 'mrInitGUI_analParams(''assignParfilePattern''); ');

%% group scans button
uicontrol('Style', 'pushbutton', 'String', 'Group Scans', ...
	'Units', 'norm', 'Position', [.75 .2 .2 .12], ...
	'UserData', hScanGroups, ...
	'BackgroundColor', [.8 .8 .9], 'ForegroundColor', 'k', 'FontSize', fsz, ...
	'Callback', 'mrInitGUI_analParams(''groupScans''); ');

%%%%%  GO / Cancel Buttons
uicontrol('Style', 'pushbutton', 'Units', 'norm', 'Position', [.1 .02 .2 .08], ...
		  'BackgroundColor', [.9 .8 .8], 'String', 'Cancel', ...
		  'Callback', 'OK = 0; uiresume;');

uicontrol('Style', 'pushbutton', 'Units', 'norm', 'Position', [.5 .02 .2 .08], ...
		  'BackgroundColor', [.4 .8 .5], 'String', 'OK', ...
		  'Callback', 'OK = 1; uiresume;');

%%%%% get the params: do a uiwait/uiresume
% (uiresume is in the callbacks for this GUI)
uiwait;

%% we uiresumed: get the updated values from the figure
OK = evalin('base', 'OK');
evalin('base', 'clear OK'); % clear from base workspace
if OK==1
	% get modified params
	params = get(gcf, 'UserData');
end

delete(hFig);

return
% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function mrInitGUI_assignCoParams;
% put up a dialog to set the coherence params for the selected scans,
% then modify the stored coParams field to match the edited params.
params = get(gcf, 'UserData');

hScans = findobj('Parent', gcf, 'Tag', 'ScanList');
selScans = get(hScans, 'Value');

% get initial values: take from the first selected scan
% if it's assigned in params, use that; else use defaults
s = selScans(1);
if (length(params.coParams) >= s)  &  (~isempty(params.coParams{s}))
	coParams = params.coParams{s};
else
	coParams = coParamsDefault;
end

% have user edit the values
[coParams ok] = coParamsEdit(coParams);
if ~ok, return; end

% update the params field
for s = selScans
	params.coParams{s} = coParams;
end

set(gcf, 'UserData', params);
return
% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function mrInitGUI_assignGlmParams;
% put up a dialog to set the GLM analysis params for the selected scans,
% then modify the stored glmParams field to match the edited params.
params = get(gcf, 'UserData');

hScans = findobj('Parent', gcf, 'Tag', 'ScanList');
selScans = get(hScans, 'Value');

% get initial values: take from the first selected scan
% if it's assigned in params, use that; else use defaults
s = selScans(1);
if (length(params.coParams) >= s)  &  (~isempty(params.coParams{s}))
	glmParams = params.glmParams{s};
else
	glmParams = er_defaultParams;
end

% have user edit the values
[glmParams ok] = er_editParams(glmParams);
if ~ok, return; end

% update the params field
for s = selScans
	params.glmParams{s} = glmParams;
end

set(gcf, 'UserData', params);
return
% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function mrInitGUI_assignParfiles;
% prompt the user to select parfiles to assign to the selected scans,
% and update the params and GUI accordingly.
params = get(gcf, 'UserData');

hScans = findobj('Parent', gcf, 'Tag', 'ScanList');
selScans = get(hScans, 'Value');

% first, we need to make sure we have a parfiles directory:
% this is either stim/parfiles or Stimuli/parfiles in the session dir:
parDir = fullfile(params.sessionDir, 'Stimuli', 'parfiles');
if ~exist(parDir, 'dir')
	if exist( fullfile(params.sessionDir, 'stim', 'parfiles'), 'dir' )
		parDir = fullfile(params.sessionDir, 'stim', 'parfiles');
	end
end

if ~exist(parDir, 'dir')
	myWarnDlg(['You don''t have a Stimuli/parfiles directory ' ...
			   'in your session directory. Parfiles should be kept there.']);
   return
end

parList = dir( fullfile(parDir, '*.par') );
parList = {parList.name};

% also add an option to remove the assignment of a parfile:
parList = [{'(none)'} parList];

% put up the dialog
ttl = sprintf('Select parfiles to assign to scans: %s', num2str(selScans));

[sel, ok] = listdlg('PromptString', ttl, 'ListSize', [400 600], ...
					'ListString', parList, 'InitialValue', 1, ...
					'OKString', 'OK');
if ~ok  return;  end

% ensure the selected parfiles match the number of selected scans.
% The strategy here is simple: if sel is shorter than selScans,
% all scans in between get assigned the last selected parfile.
% This way, you can assign one parfile to many scans easily.
if length(sel) < length(selScans)
	nExtra = length(selScans) - length(sel);
	sel = [sel repmat(sel(end), [1 nExtra])];
end

% update the parfiles listbox
hParfiles = findobj('Parent', gcf, 'Tag', 'ParfilesList');
str = get(hParfiles, 'String');
for s = 1:length(selScans)
	str{selScans(s)} = sprintf('%i: %s', s, parList{sel(s)});
end
set(hParfiles, 'String', str);

% update the params field
for s = 1:length(selScans)
	if sel(s)==1	% selected 'none', no parfile to this scan
		params.parfile{selScans(s)} = '';
	else
		params.parfile{selScans(s)} = parList{sel(s)};
	end
end
set(gcf, 'UserData', params);

return
% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function mrInitGUI_assignParfilePattern;
% a separate dialog providing a more flexible way to assign parfiles
% to scans: if the parfiles for several scans have a common pattern
% in their names -- e.g., 'run1.par' through 'run5.par' -- this dialog
% lets the user specify the pattern, and the sequence of numbers which
% correspond to the selected scans.
%
% Note that the sequence of numbers need not run from 1 to N, nor
% be linear increasing. For instance, suppose I ran my scripts in a
% counterbalanced order, going forwards (1-10) in one session, and
% backwards (10-1) in another session. And suppose a scanning glitch
% caused run 1 to precede run 2. I might assign it thusly:
%
% pattern: run%i.par
% runs:  [10:-1:3 1 2]
%
% Since this code uses sprintf formatting, the user needs to put the
% symbol '%i' where the number should go.
%
% The code then updates the params and the GUI with the new parfiles.
params = get(gcf, 'UserData');

hScans = findobj('Parent', gcf, 'Tag', 'ScanList');
selScans = get(hScans, 'Value');

% build the dialog
dlg(1).fieldName = 'pattern';
dlg(1).style	 = 'edit';
dlg(1).string	 = ['Parfile pattern: insert a %i where the run number ' ...
					'should go. (E.g. ''run%i.par'') '];
dlg(1).value	 = '%i.par';

dlg(2).fieldName = 'runVals';
dlg(2).style	 = 'edit';
dlg(2).string	 = ['Run values (will be pasted in %i position); ' ...
					'E.g. ''1:8'', ''8:-1:1'', ''[1 3 5:9]'' '];
dlg(2).value	 = '';

% put up the dialog and get a response
resp = generalDialog(dlg, 'Assign Parfile Pattern', 'center');

% generate the new parfile list
runVals = str2num( resp.runVals );
for s = runVals
	parList{s} = sprintf( resp.pattern, s );
end

% update the parfiles listbox
hParfiles = findobj('Parent', gcf, 'Tag', 'ParfilesList');
str = get(hParfiles, 'String');
for s = selScans
	str{s} = sprintf('%i: %s', s, parList{s});
end
set(hParfiles, 'String', str);

% update the params field
for s = 1:length(selScans)
	params.parfile{selScans(s)} = parList{s};
end
set(gcf, 'UserData', params);

return
% /------------------------------------------------------------------/ %

% /------------------------------------------------------------------/ %
function mrInitGUI_groupScans;
% group the selected scans in the scans list. This modified the
% params.scanGroupField, and updates the scan group listbox to
% reflect that change.
params = get(gcf, 'UserData');

hScans = findobj('Parent', gcf, 'Tag', 'ScanList');
selScans = get(hScans, 'Value');

params.scanGroups{end+1} = selScans;

% update the scan groups listbox
hScanGroup = findobj('Parent', gcf, 'Tag', 'ScanGroupsList');
str = get(hScanGroup, 'String');
for s = selScans
	str{s} = sprintf('%i: [%s]', s, num2str(selScans));
end
set(hScanGroup, 'String', str);

% set updated params
set(gcf, 'UserData', params);
return


function pth = mrtInstallSampleData(sourceFolder, projectName, ...
    dFolder, forceOverwrite, varargin)
%MRTINSTALLSAMPLEDATA Install sample data set on local path.
%
% Syntax:
%   pth = MRTINSTALLSAMPLEDATA(sourceFolder, projectName, ...
%      [dFolder], [forceOverwrite], varargin)
%
% Description:
%   A data set is stored on the OSF website (https://osf.io/t8pb2/). If
%   found locally in fullfile(vistaRootPath, 'local'), the local version is
%   used. If not, it is downloaded from the OSF page.
%
%
% Inputs
%     sourceFolder:     Name of folder where project is stored
%                         Examples: 'functional' | 'anatomy' | 'diffusion'
%     projectName:      Name of project
%                         Examples: 'mrBOLD_01' | 'prfInplane'
%     dFolder:          Destination folder
%                         [default = fullfile(vistaRootPath, 'local')]
%     forceOverwrite:   If true, unzip the project even if project folder
%                           is found. If false, do not unzip if project
%                           folder is found.
%                          [default = true]
%     varargin:         Pairs of parameters, values
%                           'filetype', {'zip' 'dat' 'mat' etc}
% Outputs
%      pth:             Full path to installed project folder or file
%
% Example:
%    pth = mrtInstallSampleData('functional', 'mrBOLD_01');
%
% See also:
%   MRVTEST

% Examples:
%{
  srcFolder = 'anatomy';
  project = 'anatomyNIFTI';
  dFolder = fullfile(vistaRootPath,'local');
  mrtInstallSampleData('anatomy','anatomyNIFTI',dFolder);

%}

% Check inputs
if notDefined('forceOverwrite'), forceOverwrite = true; end
if notDefined('dFolder'), dFolder = fullfile(vistaRootPath, 'local'); end
if exist('varargin', 'var')
    for ii = 1:2:length(varargin)
        switch varargin{ii}
            case 'filetype', filetype = varargin{ii+1};
            otherwise, error('%s parameter unrecognized.', varargin{ii});
        end
    end
end

% Check whether test data is installed locally
pth = fullfile(vistaRootPath, 'local', 'testData');
if isfolder(pth) % go on, local copy found
else
    fprintf('Test data not found. Downloading from OSF. This may take several minutes.');
    testdata = websave(fullfile(vistaRootPath, 'local', 'testData.zip'), ...
        'https://osf.io/t8pb2/download');
    unzip(testdata, fullfile(vistaRootPath, 'local'));
end

% By default, assume we are loading a zip file
if notDefined('filetype'), filetype = 'zip'; end

% Find the zip file
pth = fullfile(vistaRootPath, 'local', 'testData', sourceFolder);
d = dir (fullfile(pth, sprintf('%s*.%s', projectName, filetype)));

% Return the directory containing the unzipped data
pth = fullfile(dFolder, projectName);

% If the filetype was not a zip file, we are done. Otherwise unzip.
if ~strcmpi(filetype, 'zip')
    pth = fullfile(d.folder, d.name);
    return;
end

% Unzip
if exist(pth, 'dir') && ~forceOverwrite
    % If the project directory already exists and user has requested NOT to
    % force overwrite, then we do not unzip
    fprintf('Data directory %s already exists. Skipping unzip.\n', pth);
else
    zipfile = fullfile(d.folder, d.name);
    unzip(zipfile, dFolder);
end

if ~exist(pth, 'dir')
    warning('Cannot locate unzipped data directory %s', pth)
end

return


function metabolites = formula2mets(formula)
% Takes a rxn formula and produces a list of metabolites
%
% USAGE:
%
%    metabolites = formula2mets(formula)
%
% INPUT:
%    formula:       rxn formula
%
% OUTPUT:
%    metabolites:   list of metabolites
%
% NOTE:
%    uses `parseRxnFormula.m` (Cobra Toolbox)
%
% .. Author: - Stefan G. Thorleifsson 2011
%
% .. rBioNet is published under GNU GENERAL PUBLIC LICENSE 3.0+
% .. Thorleifsson, S. G., Thiele, I., rBioNet: A COBRA toolbox extension for
% .. reconstructing high-quality biochemical networks, Bioinformatics, Accepted.
% .. rbionet@systemsbiology.is
mets = parseRxnFormula(formula);
metabolites = regexprep(mets, '\[.+\]', '');


function EEG = highPassAndICA(EEG, varargin)
% Perform a high-pass filter and ICA on data that has been Prepped
%
% Parameters
%    EEG   EEGLAB EEG structure
%    varargin    name value pairs
%         detrendChannels
%         detrendCutoff
%         icatype
%         extended
try
    %% Convert name-value pair parameters to structure
    params = vargin2struct(varargin);

    if isfield(EEG.etc, 'noiseDetection') && ...
            isfield(EEG.etc.noiseDetection, 'detrend') && ...
            ~isfield(params, 'detrendChannels')
        params.detrendChannels = EEG.etc.noiseDetection.detrend.detrendChannels;
    end
    [EEG, detrend]  = removeTrend(EEG, params);
    EEG.etc.highPassAndICA.detrend = detrend;

    %% Perform ICA on the data
    icatype = 'runica';
    if isfield(params, 'icatype')
        icatype = params.icatype;
    end
    extended = 1;
    if isfield(params, 'extended')
        extended = params.extended;
    end
    if isfield(EEG.etc, 'noiseDetection') && ...
            isfield(EEG.etc.noiseDetection, 'reference')
        referenceChannels = ...
            EEG.etc.noiseDetection.reference.referenceChannels;
        interpolatedChannels = ...
            EEG.etc.noiseDetection.reference.interpolatedChannels.all;
        channelsLeft = setdiff(referenceChannels, interpolatedChannels);
        pcaDim = length(channelsLeft) - 1;
        fprintf('%s: pcaDim = %d\n', EEG.setname, pcaDim);
        EEG = pop_runica(EEG, 'icatype', icatype, 'extended', extended, ...
            'chanind', referenceChannels, 'pca', pcaDim);
        EEG.etc.highPassAndICA.ICA = ...
            ['extended infomax with pca Dim ' num2str(pcaDim)];
        EEG.etc.noiseDetection.reference = ...
                   cleanupReference(EEG.etc.noiseDetection.reference);
    else
        EEG = pop_runica(EEG, 'icatype', icatype, 'extended', extended);
        EEG.etc.highPassAndICA.ICA = [icatype '_extended_' extended];
    end

catch mex
    errorMessages.highPassAndICA = ['failed highPassAndICA: ' getReport(mex)];
    errorMessages.status = 'unprocessed';
    EEG.etc.highPassAndICA.errors = errorMessages;
    fprintf(2, '%s\n', errorMessages.highPassAndICA);
end