diffusivityUnitStr = '(\mum^2/msec)';

if(~exist('dataDir','var'))
    dataDir = 'dti';
end

if(ispc)
    baseDir = '//171.64.204.10/biac2-wandell2/data/reading_longitude';
else
    baseDir = '/biac2/wandell2/data/reading_longitude';
end

subDir = fullfile(baseDir,dataDir,'*0*');
outFileName = ['mniRoiAnalysis_' dataDir];
outDir = fullfile(baseDir,'roiAnalyses');
if(~exist(outDir,'dir')) mkdir(outDir); end
dataSumFile = fullfile(outDir,[outFileName '_sum.mat']);
logFileName = fullfile(outDir,[outFileName '_log_' datestr(now,'yymmdd_HHMM') '.txt']);

if(~exist(dataSumFile,'file'))
    % Klingberg:
    % "The VOI had a volume of 960 mm^3, and was located within x = -36 to -26,
    % y = -50 to -10, and z = 0 to 32 mm relative the to anterior commissure."
    % (These are presumably MNI coordinates; peak at [-28 -20 28])
    %kCoordsMni = [-31 -20 26];
    % Beaulieu: -28 -14 24
    % Klingberg: -28 -20 28 (reported in Tal: -28 -22 29)
    % Deutsch: -28 -28 24 (reported in Tal: -28 -26 23)
    % Nagy: -27 -29 5 (reported in Tal: -27 -28 6)
    % Niogy: hard to tell. The slice shown has a coord above it, probably Tal, -28 -11 26, which is in MNI: -28 -12 28.
    clear c mniRois;
    c(1).name = 'Klingberg'; c(1).coords = [-28 -20 28];
    c(2).name = 'Deutsch'; c(2).coords = [-28 -28 24];
    c(3).name = 'Nagy'; c(3).coords = [-27 -29 5];
    c(4).name = 'Niogi'; c(4).coords = [-28 -12 28];
    for(ii=1:length(c))
        mniRois(ii,1) = dtiNewRoi([c(ii).name '03']); mniRois(ii,1).coords = dtiBuildSphereCoords(c(ii).coords, 3);
        mniRois(ii,2) = dtiNewRoi([c(ii).name '05']); mniRois(ii,2).coords = dtiBuildSphereCoords(c(ii).coords, 5);
    end
    mniRois = mniRois(:);

    excludeSubs = {'dh040607','an041018','hy040602','lg041019','mh040630','tk040817'};
    [f,sc] = findSubjects(subDir,'*_dt6_noMask',excludeSubs);
    N = length(f);

    goodSubs = ones(1,N);
    clear data;
    s=license('inuse'); userName = s(1).user;
    analysisDate = datestr(now,31);
    analyzedBy = userName;
    logFile = fopen(logFileName,'wt');
    fprintf(logFile, '* * * Analysis run by %s on %s * * *\n', userName, analysisDate);
    nSubs = 0;
    for(ii=1:N)
        tic;
        fname = f{ii};
        disp(['Processing ' fname '...']);
        fprintf(logFile, ['Processing ' fname ': ']);
        roiPath = fullfile(fileparts(fname), 'ROIs');
        fiberPath = fullfile(fileparts(fname), 'fibers');

        dt = load(f{ii});
        % We need to invert the spatial normalization
        def = dt.t1NormParams(1);
        if(isfield(def,'name')&&~strcmp(def.name,'MNI'))
            error(['Problem with MNI sn for ' fname '.']);
        end
        [def.deformX, def.deformY, def.deformZ] = mrAnatInvertSn(def.sn);
        def.inMat = inv(def.sn.VF.mat); % xform from acpc space to deformation field space

        data(ii).sc = sc{ii};
        % WARP MNI ROIS TO THIS BRAIN & GET THE TENSORS
        for(jj=1:length(mniRois))
            roi = mniRois(jj);
            roi.coords = mrAnatXformCoords(dt.t1NormParams.sn, roi.coords);
            roi.coords = unique(round(roi.coords),'rows');
            roi = dtiRoiClean(roi, 3, {'fillHoles', 'removeSat'});
            %dtiWriteRoi(roi, fullfile(roiPath, roi.name), 1, 'acpc');
            data(ii).rois(jj) = roi;
            % get the tensors for this ROI
            data(ii).dt6{jj} = dtiGetValFromTensors(dt.dt6, roi.coords, inv(dt.xformToAcPc), 'dt6', 'nearest');
        end
        fprintf('(%0.1f seconds) ',toc);
    end
    fclose(logFile);
    save(dataSumFile, 'data', 'f', 'mniRois', 'analysisDate', 'analyzedBy');
else
    disp(['Loading ' dataSumFile '...']);
    load(fullfile(outDir,[outFileName '_sum.mat']));
end

behavDataFile = fullfile(baseDir,'read_behav_measures.csv');
[bd,bdColNames] = dtiGetBehavioralData({data(:).sc},behavDataFile);
ageInd = strmatch('Age',bdColNames);
paInd = strmatch('Phonological Awareness',bdColNames);
widInd = strmatch('Word ID ss',bdColNames);
readerTypeInd = strmatch('Type of Reader',bdColNames);
goodReaders = bd(:,readerTypeInd)'>=0;

%goodSubs=[1:43,45:length(f)];
goodSubs=[1:length(f)];

clear fa md rd ad pdd;
for(ii=1:length(data))
  for(jj=1:length(data(ii).dt6))
    [vec,val] = dtiEig(data(ii).dt6{jj});
    val = val./1000;
    fa(ii,jj) = mean(dtiComputeFA(val));
    md(ii,jj) = mean(val(:));
    rd(ii,jj) = mean((val(:,2)+val(:,3))./2);
    ad(ii,jj) = mean(val(:,1));
    pdd(ii,jj,:) = mean(squeeze(vec(:,:,1)));
  end
end

logFile = fopen(logFileName,'wt');
fprintf(logFile, '\nSTATS:\n');
roiNames = {mniRois.name};
bdInds = [1:3,5,7:20];
roiInds = [1:8];
valNames = {'fa','md','rd'};
for(valNum=1:length(valNames))
    eval(['val=' valNames{valNum} ';']);
    fprintf('\n\n%s:\n',upper(valNames{valNum}));
    fprintf(logFile,'\n\n%s:\n',upper(valNames{valNum}));
    for(ii=bdInds)
        [r,p] = corrcoef([bd(goodSubs,ii),val(goodSubs,:)]);
        r = r(2:end,1); p = p(2:end,1);
        fprintf('%031s:',bdColNames{ii});
        fprintf(logFile,'%031s:',bdColNames{ii});
        for(jj=roiInds)
            if(p(jj)<0.01) sig='***'; elseif(p(jj)<0.05) sig='** '; elseif(p(jj)<0.1) sig='*  '; else sig='   '; end
            fprintf('\t%s r=%+0.2f %s',roiNames{jj},r(jj),sig);
            fprintf(logFile,'\t%s r=%+0.2f %s',roiNames{jj},r(jj),sig);
        end
        fprintf('\n'); fprintf(logFile,'\n');
    end
end
fclose(logFile);

bdInds = [3,5,7,8,9,10];
for(jj=bdInds)
    figure; set(gcf,'name',bdColNames{jj});
    for(ii=1:4)
        subplot(2,2,ii);
        x = bd(goodSubs,jj);
        y = fa(goodSubs,ii);
        plot(x,y,'k.');
        xlabel(bdColNames{jj});
        ylabel(['FA (' roiNames{ii} ')']);
        [r,p] = corr(x,y);
        title(sprintf('r=%0.2f (p=%0.4f)',r,p));
    end
end

for(jj=bdInds)
    for(ii=1:4)
        x = bd(goodSubs,jj);
        y = fa(goodSubs,ii);
        xlabel(bdColNames{jj});
        ylabel(['FA (' roiNames{ii} ')']);
        [r,p] = corr(x,y);
        title(sprintf('r=%0.2f (p=%0.4f)',r,p));
    end
end

meanPdd = dtiDirMean(permute(pdd,[2 3 1]));
error('stop here');

%% Whole-brain analysis

diffusivityUnitStr = '(\mum^2/msec)';
dataDir = 'dti';
baseDir = '/biac2/wandell2/data/reading_longitude';
subDir = fullfile(baseDir,dataDir,'*0*');
outFileName = ['mniRoiAnalysis_' dataDir];
outDir = fullfile(baseDir,'roiAnalyses');
if(~exist(outDir,'dir')) mkdir(outDir); end
dataSumFile = fullfile(outDir,[outFileName '_sum.mat']);
logFileName = fullfile(outDir,[outFileName '_log_' datestr(now,'yymmdd_HHMM') '.txt']);
excludeSubs = {'dh040607','an041018','hy040602','lg041019','mh040630','tk040817'};
[f,sc] = findSubjects(subDir,'*_dt6_noMask',excludeSubs);
N = length(f);

addpath /home/bob/matlab/stats/

behavDataFile = fullfile(baseDir,'read_behav_measures.csv');
[bd,bdColNames] = dtiGetBehavioralData(sc,behavDataFile);
ageInd = strmatch('Age',bdColNames);
paInd = strmatch('Phonological Awareness',bdColNames);
widInd = strmatch('Word ID ss',bdColNames);
readerTypeInd = strmatch('Type of Reader',bdColNames);
goodReaders = bd(:,readerTypeInd)'>=0;
goodSubs=[1:length(f)];

ni = niftiRead(fullfile('/silver/scr1/mniWarpAnalysis/data/',[sc{1} '_FA_sn.nii.gz']));
xform = ni.qto_xyz;
fa = zeros([size(ni.data),N]);
fa(:,:,:,1) = ni.data;
for(ii=2:N)
   ni = niftiRead(fullfile('/silver/scr1/mniWarpAnalysis/data/',[sc{ii} '_FA_sn.nii.gz']));
   fa(:,:,:,ii) = ni.data;
end

mnFa = mean(fa,4);
%mask = mnFa>=0.25;
mask = dtiCleanImageMask(all(fa>=0.15,4));
maskInds = find(mask);
showMontage(mask);
faInd = zeros(N,length(maskInds));
for(ii=1:N)
   tmp = fa(:,:,:,ii);
   faInd(ii,:) = tmp(maskInds);
end

bdInd = paInd;
valName = 'FA';
%[p,s] = myStatTest(bd(:,bdInd),faInd,'r');
[p,s] = myStatTest(bd(:,bdInd),faInd,'k');

imP=zeros(size(mask)); imP(maskInds)=p;

slAc=[10:2:40];
slIm = inv(xform)*[ones(2,length(slAc));slAc;ones(1,length(slAc))];
slIm = round(slIm(3,:));

% Remove 26-connected regions samller than clustThresh voxels
clustThresh = 10;
pThresh = 0.05;

imR=zeros(size(mask)); imR(maskInds)=s;
threshIm = imP<pThresh & imR<0; threshIm(~mask) = 0;
threshIm = bwareaopen(threshIm,clustThresh,26);
imR(~threshIm) = 0;
mrAnatOverlayMontage(-imR, xform, mnFa, xform, autumn(256), [0.1 1], slAc, fullfile(outDir,'FA_PA_negCorr'), 3, 1, true, 1);
set(gcf,'name','negative correlations');

imR=zeros(size(mask)); imR(maskInds)=s;
threshIm = imP<pThresh & imR>0; threshIm(~mask) = 0;
threshIm = bwareaopen(threshIm,clustThresh,26);
imR(~threshIm) = 0;
%showMontage(imR);
mrAnatOverlayMontage(imR, xform, mnFa, xform, autumn(256), [0.1 1], slAc, fullfile(outDir,'FA_PA'), 3, 1, true, 1);
set(gcf,'name','positive correlations');

% Show stats for each cluster
[clustLabel,clustN] = bwlabeln(threshIm, 26);
fprintf('%s vs. %s: %d clusters passed the size threshold of %d.\n',bdColNames{bdInd},valName,clustN,clustThresh);
plotBest = false;
for(jj=1:clustN)
    % Get the original data for each cluster and summarize it.
    curClust = clustLabel==jj;
    nvox = sum(curClust(:));
    clustInds = find(curClust(:));
    [inMask,maskLoc] = ismember(clustInds,maskInds);
    [x,y,z] = ind2sub(size(mask),clustInds);
    bestVox = find(p(maskLoc)==min(p(maskLoc)));
    mniCoords = mrAnatXformCoords(xform, [x,y,z]);
    mnMni = mean(mniCoords);
    bestMni = mniCoords(bestVox,:);
    if(mean(s(maskLoc))<0) sSum = min(s(maskLoc));
    else sSum = max(s(maskLoc)); end
    fprintf('   Cluster %d: size = %d voxels; tau = %0.2f; p = %0.5f; mean MNI: [%d %d %d]\n',...
        jj, nvox, sSum, min(p(maskLoc)), round(mnMni));
    % Plot the mean or best data within the cluster vs. behavior
    if(plotBest)
        mnDataVal = faInd(:,maskLoc(bestVox(1)));
    else
        mnDataVal = mean(faInd(:,maskLoc),2);
    end
    bdSum = bd(:,bdInd);
    notNan = ~isnan(bdSum);
    [curP,curR,curDf] = myStatTest(mnDataVal(notNan),bdSum(notNan),'r');
    [curKP,curKR] = myStatTest(mnDataVal(notNan),bdSum(notNan),'k');
    figure;
    set(gcf,'Name',sprintf('%d: %s vs. %s Scatter',jj,valName,bdColNames{bdInd}));
    plot(mnDataVal(notNan),bdSum(notNan),'ko');
    axis square;
    %fprintf('[%d %d %d]: r=%0.2f (p=%0.1e), tau=%0.2f (p=%0.1e), n=%d\n',round(mnMni),curR,curP,curKR,curKP,nvox);
    xlabel(valName);
    ylabel(bdColNames{bdInd});
end

[sigN,sigInd] = fdr(p,0.2,'original','mean');


function [hAx, prim, varargin] = parseDrawInput(prim, valFun, type, defOpts, varargin)
%PARSEDRAWINPUT Parse input arguments for drawing functions: draw*.
%
%   INPUT:
%       PRIM: The primitive object: line, plane, ...
%       VALFUN: An anonymous Function to validate PRIM
%       TYPE: The drawing type of PRIM: 'line', 'patch', ...
%       DEFOPTS: The default drawing options for PRIM as struct
%
%   OUTPUT:
%       HAX: The current or specified axes for drawing
%       PRIM: validated PRIM

% ------
% Author: oqilipo
% E-mail: N/A
% Created: 2017-10-13, using R2017b
% Copyright 2017-2022

% Check if first input argument is an axes handle
if isAxisHandle(prim)
    hAx = prim;
    prim = varargin{1};
    varargin(1) = [];
else
    hAx = gca;
end

% Check if the primitive is valid
p=inputParser;
addRequired(p,'prim',valFun)
parse(p,prim)

% parse input arguments if there are any
if ~isempty(varargin)
    if length(varargin) == 1
        if isstruct(varargin{1})
            % if options are specified as struct, need to convert to
            % parameter name-value pairs
            varargin = [fieldnames(varargin{1}) struct2cell(varargin{1})]';
            varargin = varargin(:)';
        else
            % if option is a single argument, assume it is the color
            switch type
                case 'line'
                    varargin = {'Color', varargin{1}};
                case 'patch'
                    varargin = {'FaceColor', varargin{1}};
            end
        end
    end
else
    % If no arguments are given, use the default options
    varargin = [fieldnames(defOpts) struct2cell(defOpts)]';
    varargin = varargin(:)';
end

end


function test_pull2111

% WALLTIME 00:10:00
% MEM 1gb
% DEPENDENCY ft_read_data, ft_read_header

filename = dccnpath('/home/common/matlab/fieldtrip/data/test/pull2110/data_test_pull2111.mat');

hdr = ft_read_header(filename, 'headerformat', 'neuroomega_mat', 'chantype', 'ecog');
data = ft_read_data(filename, 'header', hdr, 'dataformat', 'neuroomega_mat', 'headerformat', 'neuroomega_mat');


function fieldnames = listAllFieldNames(planC)
% List all fieldnames in the plan.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

indexS = planC{end};
cellNames = fields(indexS);
for i=1:length(cellNames)
    cellVals(i) = indexS.(cellNames{i});
end

fieldnames = [];
%Call listFields on each cell in planC.  Manually generate the index alias.
for i=1:length(cellNames)
    fieldnames = [fieldnames;listFields(planC{cellVals(i)}, ['planC{indexS.' cellNames{i} '}'])];
end
fieldnames = unique(fieldnames);

function fieldnames = listFields(structure, myName)
% list fields in struct given the name of the structure above.
fieldnames = {myName};
dataType = class(structure);
switch dataType
    case 'struct'
        for i=1:length(structure(:))
            fieldNames = fields(structure);
            for j=1:length(fieldNames)
                childName = [myName '.' fieldNames{j}];
                childFields = listFields(structure(i).(fieldNames{j}), childName);
                fieldnames = [fieldnames;childFields];
            end
        end
end


classdef PTKAirwayForContext < PTKPlugin
    % PTKAirwayForContext. Plugin for returning the main bronchi serving the lung regions for a given context
    %
    %     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.
    %
    %     PTKAirwayForContext returns a set of bronchi which correspond to the
    %     specified context
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Bronchus for<br>context'
        ToolTip = 'Plugin for returning the main bronchi serving the lung regions for a given context'
        Category = 'Analysis'

        Context = PTKContextSet.Any
        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        PluginType = 'DoNothing'
        HidePluginInDisplay = true
        FlattenPreviewImage = false
        PTKVersion = '2'
        ButtonWidth = 6
        ButtonHeight = 1
        GeneratePreview = false
        Visibility = 'Developer'
    end

    methods (Static)
        function results = RunPlugin(dataset, context, reporting)
            bronchi = [];
            switch context
                case {PTKContext.Lungs, PTKContext.LungROI, PTKContext.OriginalImage}
                    airways = dataset.GetResult('PTKAirwayCentreline');
                    bronchi =  airways.AirwayCentrelineTree;
                case {PTKContext.LeftLung}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.Left;
                case {PTKContext.RightLung}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.Right;
                case {PTKContext.LeftUpperLobe}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.LeftUpper;
                case {PTKContext.LeftLowerLobe}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.LeftLower;
                case {PTKContext.RightUpperLobe}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.RightUpper;
                case {PTKContext.RightLowerLobe}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.RightLower;
                case {PTKContext.RightMiddleLobe}
                    airways = dataset.GetResult('PTKAirwaysLabelledByLobe');
                    bronchi = airways.StartBranches.RightMid;
                case {PTKContext.R_AP, PTKContext.R_P, PTKContext.R_AN, PTKContext.R_L, ...
                        PTKContext.R_M, PTKContext.R_S, PTKContext.R_MB, PTKContext.R_AB, PTKContext.R_LB, ...
                        PTKContext.R_PB, PTKContext.L_APP, PTKContext.L_APP2, PTKContext.L_AN, PTKContext.L_SL, ...
                        PTKContext.L_IL, PTKContext.L_S, PTKContext.L_AMB, PTKContext.L_LB, PTKContext.L_PB}
                    airways = dataset.GetResult('PTKSegmentsByNearestBronchus');
                    bronchi = PTKAirwayForContext.FindSegmentalBronchus(airways.AirwaysBySegment.Trachea, context);
            end
            for branch = bronchi
                branch.GenerateBranchParameters;
            end

            results = [];
            results.AirwayForContext = bronchi;
        end

        function bronchus = FindSegmentalBronchus(airways, context)
            segment_label = uint8(PTKPulmonarySegmentLabels.(char(context)));
            airways_to_do = CoreStack(airways);
            while ~airways_to_do.IsEmpty
                next_airways = airways_to_do.Pop;
                if next_airways.SegmentIndex == segment_label
                    bronchus = next_airways;
                    return;
                end
                airways_to_do.Push(next_airways.Children);
            end

            bronchus = [];
        end
    end
end


function output = TestCopySynthRegressionR(n_test)
output = false;
original_speech_dir = '/Users/kawahara/Music/VCTK_CORPUS/VCTK-Corpus/wav48/';
if isOctave
  target_analysis_dir = '/Users/kawahara/m-file/STRAIGHTV40_007e/analysisDataO/';
  target_wave_dir = '/Users/kawahara/m-file/STRAIGHTV40_007e/waveDataO/';
else
  target_analysis_dir = '/Users/kawahara/m-file/STRAIGHTV40_007e/analysisDataR/';
  target_wave_dir = '/Users/kawahara/m-file/STRAIGHTV40_007e/waveDataR/';
end;
target_files = dir([target_wave_dir '*.wav']);
n_files = length(target_files);
selected_id = randi(n_files, n_test);
command1 = 'rand("seed", 12345);';
command2 = 'randn("seed", 12345);';
for ii = 1:n_test
  tmp_name = target_files(selected_id(ii)).name;
  [x, fs] = audioread([original_speech_dir tmp_name(1:4) '/' tmp_name]);
  disp([num2str(ii) ': ' tmp_name ' ' datestr(now)]);
  if isOctave
    eval(command1);
    eval(command2);
  else
    rng(12345); % initialize frozen random number
  end;
  f0raw = MulticueF0v14(x, fs);
  ap = exstraightAPind(x, fs, f0raw);
  n3sgram=exstraightspec(x, f0raw, fs);
  tmp_name_root = tmp_name(1:end - 4);
  if ~CheckAnalysisData(f0raw, ap, n3sgram, target_analysis_dir, tmp_name_root)
    disp(['Failed: ' tmp_name ' data is not similar.']);
  end;
  wave_pathname = [target_wave_dir tmp_name];
  [sy, fs] = audioread(wave_pathname);
  if isOctave
    eval(command1);
    eval(command2);
  else
    rng(12345); % initialize frozen random number
  end;
  y = exstraightsynth(f0raw,n3sgram,ap,fs);
  disp(['Relative error SD: ' num2str(100 * std(sy - y / max(abs(y)) * 0.9) / std(sy)) ' %']);
  if std(sy - y / max(abs(y)) * 0.9) / std(sy) > 10 ^ (-3)
    disp(['Failed! ' tmp_name ' copy synthesis test.']);
    keyboard
    return;
  end;
end;
disp(['Success! ' num2str(n_test) ' files are passed copy-synth regression.']);
output = true;
end


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

    enumeration
        PointTarget('Point Target');
        LatLongRectGrid('Lat/Long Rectangular Grid')
        LatLongCircGrid('Lat/Long Circular Grid');
    end

    properties
        name(1,:) char
    end

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

    methods(Static)
        function listBoxStr = getListBoxStr()
            m = enumeration('SensorTargetEnum');
            [~,I] = sort({m.name});
            listBoxStr = {m(I).name};
        end

        function [ind, enum] = getIndForName(name)
            m = enumeration('SensorTargetEnum');
            [~,I] = sort({m.name});
            m = m(I);
            ind = find(ismember({m.name},name),1,'first');
            enum = m(ind);
        end

        function [enum, ind] = getEnumForListboxStr(nameStr)
            m = enumeration('SensorTargetEnum');
            ind = find(ismember({m.name},nameStr),1,'first');
            enum = m(ind);
        end
    end
end


function test_suite = test_regression_hier

%   Run specific demo, save values and compare the results to the expected.
%   Works for both xUnit Test Framework package by Steve Eddins and for
%   the built-in Unit Testing Framework (as of Matlab version 2013b).
%
%   See also
%     TEST_ALL, DEMO_REGRESSION_HIER
%
% Copyright (c) 2011-2012 Ville Tolvanen
% Copyright (c) 2014 Tuomas Sivula

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  % Check which package to use
  if exist('initTestSuite', 'file')
    initTestSuite_path = which('initTestSuite');
  else
    initTestSuite_path = '';
  end
  if ~isempty(initTestSuite_path) && ...
     exist([initTestSuite_path(1:end-15) 'runtests'], 'file')
    % xUnit package
    initTestSuite;
  else
    % Built-in package
    % Use all functions except the @setup
    tests = localfunctions;
    tests = tests(~cellfun(@(x)strcmp(func2str(x),'setup'),tests));
    test_suite = functiontests(tests);
  end
end

% -------------
%     Tests
% -------------

function testRunDemo(testCase)
  % Run the correspondin demo and save the values. Note this test has to
  % be run at lest once before the other test may succeed.
  rundemo(getName())
end

function testPredictionMissingData(testCase)
  verifyVarsEqual(testCase, getName(), {'Eff'}, {@mean}, ...
    'RelTolElement', 0.01, 'RelTolRange', 0.005)
end

% ------------------------
%     Helper functions
% ------------------------

function testCase = setup
  % Helper function to suply empty array into variable testCase as an
  % argument for each test function, if using xUnit package. Not to be
  % used with built-in test framework.
  testCase = [];
end

function name = getName
  % Helperfunction that returns the name of the demo, e.g. 'binomial1'.
  name = mfilename;
  name = name(6:end);
end


% LFDefaultField - Convenience function to set up structs with default field values
%
% Usage:
%
%   ParentStruct = LFDefaultField( ParentStruct, FieldName, DefaultVal )
%
% This provides an elegant way to establish default field values in a struct. See LFDefaultValue for
% setting up non-struct variables with default values.
%
% Inputs:
%
%   ParentStruct: string giving the name of the struct; the struct need not already exist
%   FieldName: string giving the name of the field
%   DefaultVal: default value for the field
%
% Outputs:
%
%   ParentStruct: if the named struct and field already existed, the output matches the struct's
%                 original value; otherwise the output is a struct with an additional field taking
%                 on the specified default value
%
% Example:
%
%   clearvars
%   ExistingStruct.ExistingField = 42;
%   ExistingStruct = LFDefaultField( 'ExistingStruct', 'ExistingField', 3 )
%   ExistingStruct = LFDefaultField( 'ExistingStruct', 'NewField', 36 )
%   OtherStruct = LFDefaultField( 'OtherStruct', 'Cheese', 'Indeed' )
%
%
%   Results in :
%       ExistingStruct =
%           ExistingField: 42
%                NewField: 36
%       OtherStruct =
%                  Cheese: 'Indeed'
%
% Usage for setting up default function arguments is demonstrated in most of the LF Toolbox
% functions.
%
% User guide: LFToolbox.pdf
% See also: LFDefaultVal

% Copyright (c) 2013-2020 Donald G. Dansereau

function ParentStruct = LFDefaultField( ParentStruct, FieldName, DefaultVal )

%---First make sure the struct exists---
CheckIfExists = sprintf('exist(''%s'', ''var'') && ~isempty(%s)', ParentStruct, ParentStruct);
VarExists = evalin( 'caller', CheckIfExists );
if( ~VarExists )
    ParentStruct = [];
else
    ParentStruct = evalin( 'caller', ParentStruct );
end

%---Now make sure the field exists---
if( ~isfield( ParentStruct, FieldName ) )
    ParentStruct.(FieldName) = DefaultVal;
end

end


%% imrician
% Below is a demonstration of the features of the |imrician| function

%%
clear; close all; clc;

%% Syntax
% |M_rice=imrician(M,s);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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 3 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, see <http://www.gnu.org/licenses/>.


function [ret,algo] = training(algo,dat)

  ret=feval(algo.type,algo,dat);


function loadlayerprofile(varargin)
%*************************************************
%DATE: 10/8/2007 (created); 	10/8/2007 (modified)
%FUNCTION: 	load layer profiles
%INPUTS: 	NULL
%OUTPUTS:	NULL
%muwn.gu@gmail.com
%*************************************************
global Layerprofile
Layerprofile.color.silicon =  	[53, 53, 53]/255;
Layerprofile.color.sidioxi=  	[85, 85, 85]/255;
Layerprofile.color.metal =  	[146, 146, 146]/255;
Layerprofile.color.sini=  		[190, 190, 190]/255;
Layerprofile.color.posi=  		[220, 220, 200]/255;
Layerprofile.color.phore =  	[0.1, 0.1, 0.4];

Layerprofile.origin.x = 20;
Layerprofile.origin.y = 10;

Layerprofile.stepSpace = 6;

Layerprofile.currentY = Layerprofile.origin.y;

Layerprofile.diameter = 54;

Layerprofile.lineWidth = 0.3;

global layerMatrix;
global layerColor;


function [cache_exists,cache_name] = find_cache()
  % FIND_CACHE Called at the beginning of a very expensive caller function,
  % this function writes the input parameters (whatever's currently in scope)
  % to a temporary file and gets that files md5 checksum as a "cachename". If a
  % file with path built from that cache name and caller name exists and is
  % younger than the caller file name or any of its dependencies, then this
  % returns true and the cache name.
  %
  % [cache_exists,cache_name] = find_cache()
  %
  % Outputs:
  %   cache_exists  true if the cache_name file exists
  %   cache_name  path to cache file for this caller function on these inputs.
  %
  % See also: create_cache

  %if ~ismac
  if ~isunix
    cache_exists = false;
    cache_name = '';
  end

  S = dbstack(1);
  caller_name = S.name;
  % get a list of current variables in this scope, this is the input "state"
  variables = evalin('caller','who');
  % get a temporary file's name
  tmpf = [tempname('.') '.mat'];

  variable_names = sprintf('^%s$|',variables{:});
  save_cmd = sprintf('save(''%s'',''-regexp'',''%s'');',tmpf,variable_names);
  % save the "state" of the caller to file, so we can get a md5 checksum
  evalin('caller',save_cmd);

  % get md5 checksum on input "state", we append .cache.mat to the check sum
  % because we'll use the checksum as the cache file name
  if ismac
    md5_cmd = 'md5 -r';
  elseif isunix
    md5_cmd = 'md5sum';
  else
    assert(false,'What OS is this?')
  end
  [s,md5_res] = system(sprintf('tail -c +117 %s | %s',tmpf,md5_cmd));
  if s~=0
    cache_exists = false;
    cache_name = '';
    return;
  end
  md5_res = sscanf(md5_res,'%s',1);
  cache_name = sprintf('.%s.cache.%s.mat',caller_name,md5_res);

  % clean up
  delete(tmpf);
  clear s tmpf variables;
  cache_exists = exist(cache_name,'file')~=0;
  % If cache exists, check that it's older than the caller file.
  if cache_exists
    cache_file = dir(cache_name);
    cache_date = datenum(cache_file.date);
    caller_dependencies = depends(caller_name);
    for si = 1:numel(caller_dependencies)
      caller_dep_name = caller_dependencies{si};
      caller_dep_file = dir(which(caller_dep_name));
      caller_dep_date = datenum(caller_dep_file.date);
      if cache_date < caller_dep_date
        cache_exists = false;
      end
    end
  end
end


function F = flipud(F)
%FLIPUD   Flip the rows of a chebmatrix.

%  Copyright 2017 by The University of Oxford and The Chebfun Developers.
%  See http://www.chebfun.org/ for Chebfun information.

F.blocks = flipud(F.blocks);

end


% MAKEELEC - subroutine to make electrode file in EEGPLOT
%
% Usage:   >> makeelec(chans)
%          >> [channames] = makeelec(chans)
%
% Inputs:
%   chans - number of channels
%
% Author: Colin Humprhies, CNL / Salk Institute, 1996
%
% See also: EEGPLOT

% Copyright (C) Colin Humphries, CNL / Salk Institute, Aug, 1996
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% 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 HOLDER 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.

% 01-25-02 reformated help & license, added links -ad

function channames = makeelec(chans);

global is_done_pressed
is_done_pressed = 0;

lines = ceil(chans/2);

fh = 180 + chans*12;
fl = 400;

figure('Units','Pixels','Position',[400 200 fl fh])

fighandle = gcf;

axes('Units','Pixels','Position',[0 0 fl fh],'Visible','off','Xlim',[0 fl],'Ylim',[0 fh]);

text(fl/2,fh-20,'Make Electrode-File','HorizontalAlignment','Center','Fontsize',14)

titleb = uicontrol('Units','Pixels','Style','Edit','Position',...
                     [fl/2 fh-60 .4*fl 20],'UserData',0,'HorizontalAlignment','left');
text(fl/2-20,fh-50,'Filename:','HorizontalAlignment','Right')

text(fl/2,fh-75,'Electrodes','HorizontalAlignment','center')
%line([fl*.2 fl*.8],[fh-85 fh-85],'color','w')

for i = 1:chans

   k = 2*ceil(i/2);

   if (i==k)
      ede(i,:) = uicontrol('Units','Pixels','Style','Edit',...
'Position',[fl*.65 fh-90-k*12 fl*.15 20],'UserData',i,'HorizontalAlignment','left');
      text(fl*.65-15,fh-90-k*12+10,num2str(i),'HorizontalAlignment','right')
   else
      ede(i,:) = uicontrol('Units','Pixels','Style','Edit',...
'Position',[fl*.2 fh-90-k*12 fl*.15 20],'UserData',i,'HorizontalAlignment','left');
      text(fl*.2-15,fh-90-k*12+10,num2str(i),'HorizontalAlignment','right')
   end

end

TIMESTRING = ['chans1973 = get(gco,''UserData'');','OH1973 = findobj(''Style'',''edit'',''UserData'',0);','FILENAME1973 = get(OH1973,''string'');','if isempty(FILENAME1973);','fprintf(''Filename Missing'');','else;','channames1973 = zeros(chans1973,6);','for i1973 = 1:chans1973;','Aa1973 = findobj(''Style'',''edit'',''UserData'',i1973);','elabel1973 = get(Aa1973,''string'');','channames1973(i1973,6-length(elabel1973)+1:6) = elabel1973;','end;','for i1973 = 1:length(channames1973(:));','if channames1973(i1973) == 0;','channames1973(i1973) = ''.'';','end;','end;','FID1973 = fopen(FILENAME1973,''w'');','fprintf(FID1973,''%s'',channames1973'');','fclose(FID1973);','fprintf(''Saving file'');','end;','clear chans1973 OH1973 FILENAME1973  Aa1973 elabel1973 ii1973 FID1973 channames1973 i1973;'];
saveb = uicontrol('Units','Pixels','Style','PushButton','Position',[fl/10 20 fl*.15 25],'String','Save','UserData',chans,'Callback',TIMESTRING);

TIMESTRING = ['global is_done_pressed;','is_done_pressed = 1;','clear is_done_pressed'];
closeb = uicontrol('Units','Pixels','Style','PushButton','Position',...
               [fl*.45 20 fl*.15 25],'String','Done','Callback',TIMESTRING);

TIMESTRING = ['global is_done_pressed;','is_done_pressed = 2;','clear is_done_pressed'];
cancelb = uicontrol('Units','Pixels','Style','PushButton','Position',...
               [fl*.75 20 fl*.15 25],'String','Cancel','Callback',TIMESTRING);

while(is_done_pressed == 0)
   drawnow;
end

if is_done_pressed == 1
   channames = [];
   for i = 1:chans
      a = findobj('Style','edit','UserData',i);
      elabel = get(a,'string');
      channames = str2mat(channames,elabel);
   end
   channames = str2mat(channames,' ');
else

   channames = [];
end

delete(fighandle)
clear is_done_pressed


function c = appendevent(a, b)

% APPENDEVENT

% Copyright (C) 2008, Robert Oostenveld
%
% 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: appendevent.m 2885 2011-02-16 09:41:58Z roboos $

if isempty(a)
  c = b(:);
elseif isempty(b)
  c = a(:);
else
  c = a(:);
  for i=1:numel(b)
    c(end+1).type     = b(i).type;
    c(end  ).value    = b(i).value;
    c(end  ).sample   = b(i).sample;
    if isfield(b, 'timestamp')
      c(end  ).timestamp = b(i).timestamp; % optional
    end
    if isfield(b, 'offset')
      c(end  ).offset    = b(i).offset;    % optional
    end
    if isfield(b, 'duration')
      c(end  ).duration  = b(i).duration;  % optional
    end
  end
end


function I=processvarargin(I,D)
%function I2=processvarargin(I,D)
%
%PURPOSE
%
%Subfunction of various functions in Icasso.
%
%INPUT
%
% I (cell array) input {'id1' value1 'id2' value2 ...}
% D (cell array) defaults {'id1 value1 'id2' value2 'id3' value3 ...}
%
%OUTPUT
%
% I2 (cell array) combination of inputs I and defaults D.
%
%DETAILS
%
%Checks that the format of input I is correct:
%Error if the input array I is not of form
% {string whatever string whatever ...}.
%That is, there are 2N elements in the array and elements with odd
%index are strings (identifiers).
%
%Adds defaults, i.e., adds those id, value pairs in
%cell array D whose id do _not_ appear in input I.

%COPYRIGHT NOTICE
%This function is a part of Icasso software library
%Copyright (C) 2003-2005 Johan Himberg
%
%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 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.

% ver 1.2 johan 100105

I=I(:);
D=D(:);
Ninput=length(I);

%%% Check number of pairs
if fix(Ninput/2)~=Ninput/2,
  error('Optional ''identifier'',value pairs mismatch!');
end

%%% Take default ids and values from the cell array

for i=1:2:Ninput,
  if ~ischar(I{i})
    error('Optional ''identifier'',value pairs mismatch!');
  end
  %% Check if some default is redefined, and drop the default away

  index2default=find(strcmp(lower(D(1:2:end)),lower(I{i})));
  if any(index2default);
    index2default=index2default(:)*2-1;
    index2default=[index2default;index2default+1];
    D(index2default)=[];
  end
end

I=[I;D]';


function Handle = GCO_Create(NumSites,NumLabels)
% GCO_Create    Create a GCoptimization object.
%    Handle = GCO_Create(NumSites,NumLabels) creates a new GCoptimization
%    object and returns a 'handle' to uniquely identify it.
%    Call GCO_Delete(Handle) to delete the object and free its memory.
%    Call GCO_Delete(GCO_ListHandles) to delete all GCO objects.

GCO_LoadLib();
if (nargin < 2), error('Expected 2 arguments'); end
Handle = gco_matlab('gco_create_general',int32(NumSites),int32(NumLabels));
end


function planC = flipAlongX(scanNum,planC)
% function planC = flipAlongX(scanNum,planC)
%
% Flip scan, structures and doses along Y direction
%
% USAGE:
% global planC
% scanNum = 1;
% planC = flipAlongY(scanNum)
%
% APA, 05/17/2010
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

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

[xVals, yVals, zVals] = getScanXYZVals(planC{indexS.scan}(scanNum));

xMin = min(xVals);
xMax = max(xVals);

[assocScansV, relStructNumV] = getStructureAssociatedScan(1:length(planC{indexS.structures}),planC);

strV = find(assocScansV == scanNum);

%% Flip structures
for strNum = 1:length(strV)
    for slcNum = 1:length(planC{indexS.structures}(strV(strNum)).contour)
        for segNum = 1:length(planC{indexS.structures}(strV(strNum)).contour(slcNum).segments)
            pointsM = planC{indexS.structures}(strV(strNum)).contour(slcNum).segments(segNum).points;
            if ~isempty(pointsM)
                pointsM(:,1) = xMin + xMax - pointsM(:,1);
                planC{indexS.structures}(strV(strNum)).contour(slcNum).segments(segNum).points = pointsM;
            end
        end
    end
end

%% Flip Scan
planC{indexS.scan}(scanNum).scanArray = flipdim(planC{indexS.scan}(scanNum).scanArray,2);

%% Flip Dose
for doseNum = 1:length(planC{indexS.dose})
    assocScanNum = getAssociatedScan(planC{indexS.dose}(doseNum).assocScanUID,planC);
    if scanNum == assocScanNum
        planC{indexS.dose}(doseNum).doseArray = flipdim(planC{indexS.dose}(doseNum).doseArray,2);
        xV = getDoseXYZVals(planC{indexS.dose}(doseNum));
        planC{indexS.dose}(doseNum).coord1OFFirstPoint = ...
           2*planC{indexS.scan}(scanNum).scanInfo(1).xOffset - xV(end);
    end
end

%ReRaster and ReUniformize
planC = reRasterAndUniformize(planC,scanNum);

if isfield(stateS,'handle') && isfield(stateS.handle,'CERRSliceViewer') && ...
        ishandle(stateS.handle.CERRSliceViewer) && ...
        isfield(stateS,'planLoaded') && stateS.planLoaded
    CERRRefresh
end


function hdr = empty_hdr
% Create an empty NIFTI-1 header
% FORMAT hdr = empty_hdr
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id: empty_hdr.m 1143 2008-02-07 19:33:33Z spm $

org = niftistruc;
for i=1:length(org),
    hdr.(org(i).label) = org(i).def;
end;