function dataset = ilsvrc15(dataset, usage, use_flip, root_path)

if  exist([root_path '/' usage '.mat'])
  tic; load([root_path '/' usage '.mat']); toc; return;
end

switch usage
    case {'val15'}
        dataset.imdb_test     = imdb_from_ilsvrc15(root_path, 'val', false);
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', roidb_name_suffix, 'rootDir', root_path);
          % clear images without any object
          valid = ~cellfun(@isempty, {dataset.roidb_test.rois.gt});
            dataset.roidb_test.rois = dataset.roidb_test.rois(valid);
            dataset.imdb_test.is_blacklisted = dataset.imdb_test.is_blacklisted(valid);
            dataset.imdb_test.sizes = dataset.imdb_test.sizes(valid,:);
            dataset.imdb_test.image_ids = dataset.imdb_test.image_ids(valid);
            dataset.imdb_test.image_at = @(i) ...
            fullfile(dataset.imdb_test.image_dir, [dataset.imdb_test.image_ids{i} '.' dataset.imdb_test.extension]);

    case {'train15'}
        dataset.imdb_train     = {imdb_from_ilsvrc15(root_path, 'train', use_flip)};
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);

          % clear images without any object
        valid = ~cellfun(@isempty, {dataset.roidb_train{1, 1}.rois.gt});
          dataset.roidb_train{1, 1}.rois = dataset.roidb_train{1, 1}.rois(valid);
          dataset.imdb_train{1, 1}.is_blacklisted = dataset.imdb_train{1, 1}.is_blacklisted(valid);
          dataset.imdb_train{1, 1}.sizes = dataset.imdb_train{1, 1}.sizes(valid,:);
          if use_flip, dataset.imdb_train{1, 1}.flip_from = dataset.imdb_train{1, 1}.flip_from(valid); end
          dataset.imdb_train{1, 1}.image_ids = dataset.imdb_train{1, 1}.image_ids(valid);
            dataset.imdb_train{1, 1}.image_at = @(i) ...
            fullfile(dataset.imdb_train{1, 1}.image_dir, [dataset.imdb_train{1, 1}.image_ids{i} '.' dataset.imdb_train{1, 1}.extension]);
    case {'VIDval16'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false);
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', '', 'rootDir', root_path);
    case {'VIDtrain16'}
        dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip)};
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);
    case {'VID+DETtrain16'}
        dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip) } ;
       dataset.imdb_train{2} =   imdb_from_ilsvrc15(root_path, 'train', use_flip );
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);
       % remove classes in DET that do not match vid
       [dataset.imdb_train{2},dataset.roidb_train{2}] = ...
         imdb_remove_cls(dataset.imdb_train{2},dataset.roidb_train{2}, dataset.imdb_train{1}) ;
    case {'VID+DETtrain16sample'}

       dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip) } ;
       dataset.imdb_train{2} =   imdb_from_ilsvrc15(root_path, 'train', use_flip );
       dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
       dataset.imdb_train, 'UniformOutput', false);

       % remove classes in DET that do not match vid
       [dataset.imdb_train{2},dataset.roidb_train{2}] = ...
         imdb_remove_cls(dataset.imdb_train{2},dataset.roidb_train{2}, dataset.imdb_train{1}) ;

       % sample 2k classes
       [dataset.imdb_train{2},dataset.roidb_train{2}] = ...
         imdb_sample_cls(dataset.imdb_train{2},dataset.roidb_train{2}, 2000) ;

       [dataset.imdb_train{1},dataset.roidb_train{1}] = ...
         imdb_sample_frames(dataset.imdb_train{1},dataset.roidb_train{1}, 30) ;

    case {'DETtrain16sample5k'}
        dataset.imdb_train{2} =   imdb_from_ilsvrc15(root_path, 'train', use_flip );
        dataset.roidb_train(2) = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
            dataset.imdb_train(2), 'UniformOutput', false);

       % remove classes in DET that do not match vid
       [dataset.imdb_train{2},dataset.roidb_train{2}] = ...
         imdb_remove_cls(dataset.imdb_train{2},dataset.roidb_train{2}, dataset.imdb_train{1}) ;

       % sample 5k classes with replacement
       [dataset.imdb_train{2},dataset.roidb_train{2}] = ...
         imdb_sample_cls(dataset.imdb_train{2},dataset.roidb_train{2}, 5000, true) ;

    case {'VIDval16lite'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 5e4 );
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'lite50k', 'rootDir', root_path);
    case {'VIDval16lite5k'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 5e3 );
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'lite5k', 'rootDir', root_path);
    case {'VIDval16lite30frames'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 30 );
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'lite30frames', 'rootDir', root_path);
  case {'VIDval16lite3frames'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 3 );
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'lite3frames', 'rootDir', root_path);
  case {'VIDval16liteStride10'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 10, 'uniform');
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'liteStride10', 'rootDir', root_path);
  case {'VIDval16liteStride5'}
        dataset.imdb_test     = imdb_from_ilsvrc15vid(root_path, 'vid_val', false, 5, 'uniform');
        dataset.roidb_test    = dataset.imdb_test.roidb_func(dataset.imdb_test, ...
            'roidb_name_suffix', 'liteStride5', 'rootDir', root_path);
    case {'VIDtrain16lite3frames'}
        dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip, 3)};
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', 'lite3frames', 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);
    case {'VIDtrain16sample'}
        dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip) } ;
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);
          frame_offset = 3;
       [dataset.imdb_train{1},dataset.roidb_train{1}] = ...
         imdb_sample_frames(dataset.imdb_train{1},dataset.roidb_train{1}, 30, frame_offset) ;
    case {'VIDtrain16sample5frames'}
        dataset.imdb_train     = {imdb_from_ilsvrc15vid(root_path, 'vid_train', use_flip) } ;
        dataset.roidb_train = cellfun(@(x) x.roidb_func(x, 'roidb_name_suffix', '', 'rootDir', root_path), ...
            dataset.imdb_train, 'UniformOutput', false);
          frame_offset = 3;
       [dataset.imdb_train{1},dataset.roidb_train{1}] = ...
         imdb_sample_frames(dataset.imdb_train{1},dataset.roidb_train{1}, 5, frame_offset) ;

  otherwise
        error('usage = ''train14'' or ''test''');
end

if  0 %strfind(usage, 'VID') &&  strfind(usage, 'train')
  if isfield(dataset, 'imdb_train')
    f='_train';
    imdb = dataset.(['imdb' f]){1};
    roidb = dataset.(['roidb' f]){1};
  else f='_test';
    imdb = dataset.(['imdb' f]);
    roidb = dataset.(['roidb' f]);
  end
  video_label_freq = zeros(numel(imdb.video_ids),imdb.num_classes);
  labelCount = zeros(numel(imdb.video_ids),1);
  for i = 1:numel(imdb.image_ids)
    labels = (unique(roidb.rois(i).overlap==1,'rows'));
    [r, c] = find(labels) ;

%     fprintf('%s-', imdb.classes{c});
    if isfield(imdb,'image_id_sel')
      vid_idx = imdb.vid_id(imdb.image_id_sel(i));
    else
      vid_idx = imdb.vid_id(i);
    end
    video_label_freq(vid_idx,c) = video_label_freq(vid_idx,c) + 1;
    labelCount(vid_idx) = labelCount(vid_idx) + ~isempty(labels);
  end

  video_label_freq(labelCount~=0,:) = bsxfun(@rdivide, video_label_freq(labelCount~=0,:), labelCount(labelCount~=0));

  if isfield(dataset, 'imdb_train')
    dataset.imdb_train{1}.video_label_freq = video_label_freq;
  else
   dataset.imdb_test.video_label_freq = video_label_freq;
  end
end
if  ~isempty(strfind(usage, 'train')) && ~isempty(strfind(usage, 'sample'))
  save([root_path '/' usage], 'dataset', '-v7.3');
end


function varargout = ma_OtherSpacecraftGUI(varargin)
% MA_OTHERSPACECRAFTGUI MATLAB code for ma_OtherSpacecraftGUI.fig
%      MA_OTHERSPACECRAFTGUI, by itself, creates a new MA_OTHERSPACECRAFTGUI or raises the existing
%      singleton*.
%
%      H = MA_OTHERSPACECRAFTGUI returns the handle to a new MA_OTHERSPACECRAFTGUI or the handle to
%      the existing singleton*.
%
%      MA_OTHERSPACECRAFTGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in MA_OTHERSPACECRAFTGUI.M with the given input arguments.
%
%      MA_OTHERSPACECRAFTGUI('Property','Value',...) creates a new MA_OTHERSPACECRAFTGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before ma_OtherSpacecraftGUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to ma_OtherSpacecraftGUI_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help ma_OtherSpacecraftGUI

% Last Modified by GUIDE v2.5 29-Mar-2019 17:03:34

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @ma_OtherSpacecraftGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @ma_OtherSpacecraftGUI_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before ma_OtherSpacecraftGUI is made visible.
function ma_OtherSpacecraftGUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to ma_OtherSpacecraftGUI (see VARARGIN)

% Choose default command line output for ma_OtherSpacecraftGUI
handles.output = hObject;
handles.ma_MainGUI = varargin{1};
handles.ksptotMainGUI = varargin{2};

populateBodiesCombo(getappdata(handles.ma_MainGUI,'celBodyData'), handles.centralBodyCombo);
bodyComboValue = findValueFromComboBox('Kerbin', handles.centralBodyCombo);
if(isempty(bodyComboValue))
    bodyComboValue = 1;
end
set(handles.centralBodyCombo,'Value',bodyComboValue);

setupGUI(handles);

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes ma_OtherSpacecraftGUI wait for user response (see UIRESUME)
uiwait(handles.ma_OtherSpacecraftGUI);

function setupGUI(handles)
    maData = getappdata(handles.ma_MainGUI,'ma_data');

    if(~isfield(maData.spacecraft,'otherSC'))
        maData.spacecraft.otherSC = cell(0,1);
        setappdata(handles.ma_MainGUI,'ma_data',maData);
    end

    if(isempty(maData.spacecraft.otherSC))
        set(handles.otherSCListbox,'String','');
        updateOSCListbox(handles);
    else
        oSCValue = get(handles.otherSCListbox,'Value');
        oSC = maData.spacecraft.otherSC{oSCValue};

        populateSpacecraft(handles,oSC);
        updateOSCListbox(handles);
        otherSCListbox_Callback(handles.otherSCListbox, [], handles);
    end

function populateSpacecraft(handles,oSC)
    set(handles.scNameText,'String',oSC.name);

    set(handles.epochText,'String',num2str(oSC.epoch));
    set(handles.smaText,'String',num2str(oSC.sma));
    set(handles.eccText,'String',num2str(oSC.ecc));
    set(handles.incText,'String',num2str(oSC.inc));
    set(handles.raanText,'String',num2str((oSC.raan)));
    set(handles.argText,'String',num2str(oSC.arg));
    set(handles.truText,'String',num2str(rad2deg(computeTrueAnomFromMean(deg2rad(oSC.mean), oSC.ecc))));
    set(handles.maxCommRangeText,'String',num2str(oSC.maxCommRange));

    bodyComboValue = findValueFromComboBox(oSC.parent, handles.centralBodyCombo);
    if(isempty(bodyComboValue))
        bodyComboValue = 1;
    end
    set(handles.centralBodyCombo,'Value',bodyComboValue);

    colorComboStr = getStringFromLineSpecColor(oSC.color);
	value = findValueFromComboBox(colorComboStr, handles.otherSCColor);
    set(handles.otherSCColor,'Value',value);

    if(isfield(oSC,'linestyle'))
        lineStyle = getLineStyleFromString(oSC.linestyle);

        value = findValueFromComboBox(lineStyle, handles.otherSCLineStyle);
        set(handles.otherSCLineStyle,'Value',value);
    else
        set(handles.otherSCLineStyle,'Value',2);
    end

    if(isfield(oSC,'lineWidth'))
        lineWidth = oSC.lineWidth;

        contents = handles.lineWidthCombo.String;
        contentsDouble = str2double(contents);
        ind = find(contentsDouble == lineWidth);
        set(handles.lineWidthCombo,'Value',ind);
    else
        set(handles.lineWidthCombo,'Value',2);
    end

% --- Outputs from this function are returned to the command line.
function varargout = ma_OtherSpacecraftGUI_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
    varargout{1} = [];

% --- Executes on selection change in otherSCListbox.
function otherSCListbox_Callback(hObject, eventdata, handles)
% hObject    handle to otherSCListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns otherSCListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from otherSCListbox
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    otherSC = maData.spacecraft.otherSC;
    oSCValue = get(handles.otherSCListbox,'Value');

    if(~isempty(otherSC) && ~isempty(oSCValue))
        oSC = otherSC{oSCValue};
        populateSpacecraft(handles,oSC);

        if(strcmpi(get(handles.ma_OtherSpacecraftGUI,'SelectionType'),'open'))
            celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
            bodyInfo = getBodyInfoByNumber(oSC.parentID, celBodyData);
            tru = computeTrueAnomFromMean(deg2rad(oSC.mean), oSC.ecc);
            [rVect,vVect]=getStatefromKepler(oSC.sma, oSC.ecc, deg2rad(oSC.inc), deg2rad(oSC.raan), deg2rad(oSC.arg), tru, bodyInfo.gm);

            UT = oSC.epoch;

            rX = rVect(1);
            rY = rVect(2);
            rZ = rVect(3);

            vX = vVect(1);
            vY = vVect(2);
            vZ = vVect(3);

            state = [UT, rX, rY, rZ, vX, vY, vZ, oSC.parentID, 0 0 0 0 1];
            viewSpacecraftStatePopupGUI(maData.spacecraft.propellant.names, state, 1, celBodyData);
        end
    end

% --- Executes during object creation, after setting all properties.
function otherSCListbox_CreateFcn(hObject, eventdata, handles)
% hObject    handle to otherSCListbox (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in updateSCButton.
function updateSCButton_Callback(hObject, eventdata, handles)
% hObject    handle to updateSCButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    errMsg = validateInputs(handles);
    if(~isempty(errMsg))
        msgbox(errMsg,'Errors were found while updating a spacecraft.','error');
        return;
    end

    maData = getappdata(handles.ma_MainGUI,'ma_data');
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');

    if(isempty(get(handles.otherSCListbox,'String')))
        return;
    end
    oscLBValue = get(handles.otherSCListbox,'Value');

    oldOtherSC = maData.spacecraft.otherSC{oscLBValue};
    oldID = oldOtherSC.id;

    ecc = str2double(get(handles.eccText,'String'));
    tru = deg2rad(str2double(get(handles.truText,'String')));
    mean = rad2deg(computeMeanFromTrueAnom(tru, ecc));

    contents = cellstr(get(handles.otherSCColor,'String'));
    oSCColorStr = contents{get(handles.otherSCColor,'Value')};
    oscColor = getLineSpecColorFromString(oSCColorStr);

    contents = cellstr(get(handles.otherSCLineStyle,'String'));
	oscLineStyle = contents{get(handles.otherSCLineStyle,'Value')};
    lineStyle = getLineStyleStrFromText(oscLineStyle);

    contents = cellstr(get(handles.lineWidthCombo,'String'));
	oscLineWidth = str2double(contents{get(handles.lineWidthCombo,'Value')});

    otherSC = struct();

    otherSC.name = get(handles.scNameText,'String');

    otherSC.epoch = str2double(get(handles.epochText,'String'));
    otherSC.sma = str2double(get(handles.smaText,'String'));
    otherSC.ecc = ecc;
    otherSC.inc = str2double(get(handles.incText,'String'));
    otherSC.raan = str2double(get(handles.raanText,'String'));
    otherSC.arg = str2double(get(handles.argText,'String'));
    otherSC.mean = mean;
    otherSC.maxCommRange = str2double(get(handles.maxCommRangeText,'String'));

    contents = cellstr(get(handles.centralBodyCombo,'String'));
    cbName = strtrim(contents{get(handles.centralBodyCombo,'Value')});
    bodyInfo = celBodyData.(strtrim(lower(cbName)));
    otherSC.parent = cbName;
    otherSC.parentID = bodyInfo.id;

    otherSC.id = oldID;
    otherSC.color = oscColor;
    otherSC.linestyle = lineStyle;
    otherSC.lineWidth = oscLineWidth;

    maData.spacecraft.otherSC{oscLBValue} = otherSC;
    setappdata(handles.ma_MainGUI,'ma_data',maData);

    updateOSCListbox(handles);

% --- Executes on button press in addSCButton.
function addSCButton_Callback(hObject, eventdata, handles)
% hObject    handle to addSCButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');

    oscColor = 'r';
    lineStyle = '-';

    otherSC = struct();

    otherSC.name = 'New Spacecraft';

    otherSC.epoch = 0.0;
    otherSC.sma = 7000;
    otherSC.ecc = 0.0;
    otherSC.inc = 0.0;
    otherSC.raan = 0.0;
    otherSC.arg = 0.0;
    otherSC.mean = 0.0;
    otherSC.maxCommRange = Inf;

    contents = cellstr(get(handles.centralBodyCombo,'String'));
    cbName = contents{1};
    bodyInfo = celBodyData.(strtrim(lower(cbName)));
    otherSC.parent = cbName;
    otherSC.parentID = bodyInfo.id;

    otherSC.id = rand();
    otherSC.color = oscColor;
    otherSC.linestyle = lineStyle;
    otherSC.lineWidth = 0.5;

    maData.spacecraft.otherSC{end+1} = otherSC;
    setappdata(handles.ma_MainGUI,'ma_data',maData);

    updateOSCListbox(handles);
    set(handles.otherSCListbox,'Value',length(maData.spacecraft.otherSC));
    otherSCListbox_Callback(handles.otherSCListbox, [], handles);

function updateOSCListbox(handles)
	maData = getappdata(handles.ma_MainGUI,'ma_data');

    if(isempty(maData.spacecraft.otherSC))
        enableUI('off', maData, handles);
    else
        enableUI('on', maData, handles);
    end

    otherSC = maData.spacecraft.otherSC;
    otherSCStr = cell(0,1);
    for(i=1:length(otherSC)) %#ok<*NO4LP>
        otherSCStr{end+1} = otherSC{i}.name; %#ok<AGROW>
    end

    if(isempty(otherSC))
        enableUI('off', maData, handles)
    else
        enableUI('on', maData, handles)
    end

	if(isempty(get(handles.otherSCListbox,'Value')))
        set(handles.otherSCListbox,'Value',1);
    elseif(get(handles.otherSCListbox,'Value') > length(otherSC))
        set(handles.otherSCListbox,'Value',length(otherSC));
    elseif(get(handles.otherSCListbox,'Value') == 0 && ~isempty(otherSC))
        set(handles.otherSCListbox,'Value',1);
	end

    set(handles.otherSCListbox,'String',otherSCStr);

% --- Executes on button press in removeSCButton.
function removeSCButton_Callback(hObject, eventdata, handles)
% hObject    handle to removeSCButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    oSCValue = get(handles.otherSCListbox,'Value');

    otherSC = maData.spacecraft.otherSC;

    script = maData.script;
    for(i=1:length(script))
        event = script{i};

        if(strcmpi(event.type,'Docking'))
            if(event.oScId == otherSC{oSCValue}.id)
                warnstr = sprintf('Cannot delete other spacecraft "%s".  This spacecraft is in use by event %u "%s".', otherSC{oSCValue}.name, i, event.name);
                warndlg(warnstr,'Cannot Delete Spacecraft', 'modal');

                return;
            end
        end
    end

    otherSC(oSCValue) = [];
    maData.spacecraft.otherSC = otherSC;
    setappdata(handles.ma_MainGUI,'ma_data',maData);

    updateOSCListbox(handles);
    otherSCListbox_Callback(handles.otherSCListbox, [], handles);

function enableUI(enable, maData, handles)
    set(handles.otherSCListbox,'Enable',enable)
    set(handles.scNameText,'Enable',enable)
    set(handles.otherSCColor,'Enable',enable)
    set(handles.otherSCLineStyle,'Enable',enable)
    set(handles.centralBodyCombo,'Enable',enable)
    set(handles.epochText,'Enable',enable)
    set(handles.smaText,'Enable',enable)
    set(handles.eccText,'Enable',enable)
    set(handles.incText,'Enable',enable)
    set(handles.raanText,'Enable',enable)
    set(handles.scNameText,'Enable',enable)
    set(handles.argText,'Enable',enable)
    set(handles.truText,'Enable',enable)
    set(handles.maxCommRangeText,'Enable',enable)

	if(isempty(maData.spacecraft.otherSC))
        set(handles.removeSCButton,'Enable','off')
    else
        set(handles.removeSCButton,'Enable','on')
	end

function scNameText_Callback(hObject, eventdata, handles)
% hObject    handle to scNameText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of scNameText as text
%        str2double(get(hObject,'String')) returns contents of scNameText as a double
    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function scNameText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to scNameText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in centralBodyCombo.
function centralBodyCombo_Callback(hObject, eventdata, handles)
% hObject    handle to centralBodyCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns centralBodyCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from centralBodyCombo
    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function centralBodyCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to centralBodyCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function epochText_Callback(hObject, eventdata, handles)
% hObject    handle to epochText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of epochText as text
%        str2double(get(hObject,'String')) returns contents of epochText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function epochText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to epochText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function smaText_Callback(hObject, eventdata, handles)
% hObject    handle to smaText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of smaText as text
%        str2double(get(hObject,'String')) returns contents of smaText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function smaText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to smaText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function eccText_Callback(hObject, eventdata, handles)
% hObject    handle to eccText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of eccText as text
%        str2double(get(hObject,'String')) returns contents of eccText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function eccText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to eccText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function incText_Callback(hObject, eventdata, handles)
% hObject    handle to incText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of incText as text
%        str2double(get(hObject,'String')) returns contents of incText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function incText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to incText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function raanText_Callback(hObject, eventdata, handles)
% hObject    handle to raanText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of raanText as text
%        str2double(get(hObject,'String')) returns contents of raanText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function raanText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to raanText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function argText_Callback(hObject, eventdata, handles)
% hObject    handle to argText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of argText as text
%        str2double(get(hObject,'String')) returns contents of argText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function argText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to argText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function truText_Callback(hObject, eventdata, handles)
% hObject    handle to truText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of truText as text
%        str2double(get(hObject,'String')) returns contents of truText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function truText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to truText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function errMsg = validateInputs(handles)
    errMsg = {};

    eEcc = str2double(get(handles.eccText,'String'));
    enteredStr = get(handles.eccText,'String');
    numberName = 'Orbit Eccentricity';
    lb = 0;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(eEcc, numberName, lb, ub, isInt, errMsg, enteredStr);

    if(not(isempty(errMsg)))
        msgbox(errMsg,'Errors were found while creating the spacecraft orbit.','error');
        return;
    end

    epoch = str2double(get(handles.epochText,'String'));
    enteredStr = get(handles.epochText,'String');
    numberName = 'Orbit Epoch';
    lb = 0;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(epoch, numberName, lb, ub, isInt, errMsg, enteredStr);

    eSMA = str2double(get(handles.smaText,'String'));
    enteredStr = get(handles.smaText,'String');
    if(eEcc < 1.0)
        lb = 1;
        ub = Inf;
        numberName = 'Eccentric Orbit Semi-Major Axis';
    else
        lb = -Inf;
        ub = -1;
        numberName = 'Hyperbolic Orbit Semi-Major Axis';
    end
    isInt = false;
    errMsg = validateNumber(eSMA, numberName, lb, ub, isInt, errMsg, enteredStr);

    eInc = str2double(get(handles.incText,'String'));
    enteredStr = get(handles.incText,'String');
    numberName = 'Orbit Inclination';
    lb = 0;
    ub = 180;
    isInt = false;
    errMsg = validateNumber(eInc, numberName, lb, ub, isInt, errMsg, enteredStr);

    eRAAN = str2double(get(handles.raanText,'String'));
    enteredStr = get(handles.raanText,'String');
    numberName = 'Orbit RAAN';
    lb = 0;
    ub = 360;
    isInt = false;
    errMsg = validateNumber(eRAAN, numberName, lb, ub, isInt, errMsg, enteredStr);

    eArg = str2double(get(handles.argText,'String'));
    enteredStr = get(handles.argText,'String');
    numberName = 'Orbit Argument of Periapse';
    lb = 0;
    ub = 360;
    isInt = false;
    errMsg = validateNumber(eArg, numberName, lb, ub, isInt, errMsg, enteredStr);

    eTru = str2double(get(handles.truText,'String'));
    enteredStr = get(handles.truText,'String');
    numberName = 'Orbit True Anomaly';
    lb = -180;
    ub = 360;
    isInt = false;
    errMsg = validateNumber(eTru, numberName, lb, ub, isInt, errMsg, enteredStr);

    maxCommRange = str2double(get(handles.maxCommRangeText,'String'));
    enteredStr = get(handles.maxCommRangeText,'String');
    numberName = 'Max Comm. Range';
    lb = 0;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(maxCommRange, numberName, lb, ub, isInt, errMsg, enteredStr);

% --------------------------------------------------------------------
function getOrbitFromSFSFileContextMenu_Callback(hObject, eventdata, handles)
% hObject    handle to getOrbitFromSFSFileContextMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    [refBodyID, scName] = orbitPanelGetOrbitFromSFSContextCallBack(handles.ksptotMainGUI, handles.smaText, handles.eccText, handles.incText, handles.raanText, handles.argText, handles.truText, handles.epochText);
    tru = computeTrueAnomFromMean(deg2rad(str2double(get(handles.truText,'String'))), str2double(get(handles.eccText,'String')));
    set(handles.truText,'String',num2str(rad2deg(tru)));

    if(~isempty(refBodyID) && isnumeric(refBodyID))
        celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
        bodyInfo = getBodyInfoByNumber(refBodyID, celBodyData);
        value = findValueFromComboBox(bodyInfo.name, handles.centralBodyCombo);
        set(handles.centralBodyCombo,'Value',value);
    end

    if(~isempty(scName))
        if(strcmpi(handles.scNameText.String,'New Spacecraft'))
            set(handles.scNameText,'String',scName);
        else
            qstring = sprintf('Do you wish overwrite the name of the spacecraft with the name of the imported spacecraft (%s)?', scName);
            title = 'Update S/C Name?';
            button = questdlg(qstring,title,'Yes','No','No');

            if(strcmpi(button,'Yes'))
                set(handles.scNameText,'String',scName);
            end
        end
    end

    updateSCButton_Callback([], [], handles);

% --------------------------------------------------------------------
function getOrbitFromKSPTOTConnectContextMenu_Callback(hObject, eventdata, handles)
% hObject    handle to getOrbitFromKSPTOTConnectContextMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    [refBodyID, scName] = orbitPanelGetOrbitFromKSPTOTConnectCallBack(handles.smaText, handles.eccText, handles.incText, handles.raanText, handles.argText, handles.truText, handles.epochText);
    tru = computeTrueAnomFromMean(deg2rad(str2double(get(handles.truText,'String'))), str2double(get(handles.eccText,'String')));
    set(handles.truText,'String',num2str(rad2deg(tru)));

    if(~isempty(refBodyID) && isnumeric(refBodyID))
        celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
        bodyInfo = getBodyInfoByNumber(refBodyID, celBodyData);
        value = findValueFromComboBox(bodyInfo.name, handles.centralBodyCombo);
        set(handles.centralBodyCombo,'Value',value);
    end

    if(~isempty(scName))
        if(strcmpi(handles.scNameText.String,'New Spacecraft'))
            set(handles.scNameText,'String',scName);
        else
            qstring = sprintf('Do you wish overwrite the name of the spacecraft with the name of the imported spacecraft (%s)?', scName);
            title = 'Update S/C Name?';
            button = questdlg(qstring,title,'Yes','No','No');

            if(strcmpi(button,'Yes'))
                set(handles.scNameText,'String',scName);
            end
        end
    end

    updateSCButton_Callback([], [], handles);

% --- Executes on selection change in otherSCColor.
function otherSCColor_Callback(hObject, eventdata, handles)
% hObject    handle to otherSCColor (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns otherSCColor contents as cell array
%        contents{get(hObject,'Value')} returns selected item from otherSCColor
    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function otherSCColor_CreateFcn(hObject, eventdata, handles)
% hObject    handle to otherSCColor (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --------------------------------------------------------------------
function copyOrbitToClipboardMenu_Callback(hObject, eventdata, handles)
% hObject    handle to copyOrbitToClipboardMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    maData = getappdata(handles.ma_MainGUI,'ma_data');
    oscLBValue = get(handles.otherSCListbox,'Value');
    oldOtherSC = maData.spacecraft.otherSC{oscLBValue};

    copyOrbitToClipboardFromText(handles.epochText, handles.smaText, handles.eccText, ...
                                 handles.incText, handles.raanText, handles.argText, ...
                                 handles.truText, true, oldOtherSC.parentID);

% --------------------------------------------------------------------
function pasteOrbitFromClipboardMenu_Callback(hObject, eventdata, handles)
% hObject    handle to pasteOrbitFromClipboardMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
    pasteOrbitFromClipboard(handles.epochText, handles.smaText, handles.eccText, ...
                                 handles.incText, handles.raanText, handles.argText, ...
                                 handles.truText, true, handles.centralBodyCombo, celBodyData);

    updateSCButton_Callback([], [], handles);

% --- Executes on key press with focus on ma_OtherSpacecraftGUI or any of its controls.
function ma_OtherSpacecraftGUI_WindowKeyPressFcn(hObject, eventdata, handles)
% hObject    handle to ma_OtherSpacecraftGUI (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
    switch(eventdata.Key)
        case 'escape'
            close(handles.ma_OtherSpacecraftGUI);
    end

% --- Executes on selection change in otherSCLineStyle.
function otherSCLineStyle_Callback(hObject, eventdata, handles)
% hObject    handle to otherSCLineStyle (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns otherSCLineStyle contents as cell array
%        contents{get(hObject,'Value')} returns selected item from otherSCLineStyle
    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function otherSCLineStyle_CreateFcn(hObject, eventdata, handles)
% hObject    handle to otherSCLineStyle (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --------------------------------------------------------------------
function getOrbitFromKSPActiveVesselMenu_Callback(hObject, eventdata, handles)
% hObject    handle to getOrbitFromKSPActiveVesselMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    [refBodyID, scName] = orbitPanelGetOrbitFromKSPTOTConnectActiveVesselCallBack(handles.smaText, handles.eccText, handles.incText, handles.raanText, handles.argText, handles.truText, handles.epochText);
    tru = computeTrueAnomFromMean(deg2rad(str2double(get(handles.truText,'String'))), str2double(get(handles.eccText,'String')));
    set(handles.truText,'String',fullAccNum2Str(rad2deg(tru)));

    if(~isempty(refBodyID) && isnumeric(refBodyID))
        celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
        bodyInfo = getBodyInfoByNumber(refBodyID, celBodyData);
        value = findValueFromComboBox(bodyInfo.name, handles.centralBodyCombo);
        set(handles.centralBodyCombo,'Value',value);
    end

    if(~isempty(scName))
        if(strcmpi(handles.scNameText.String,'New Spacecraft'))
            set(handles.scNameText,'String',scName);
        else
            qstring = sprintf('Do you wish overwrite the name of the spacecraft with the name of the imported spacecraft (%s)?', scName);
            title = 'Update S/C Name?';
            button = questdlg(qstring,title,'Yes','No','No');

            if(strcmpi(button,'Yes'))
                set(handles.scNameText,'String',scName);
            end
        end
    end

    updateSCButton_Callback([], [], handles);

function maxCommRangeText_Callback(hObject, eventdata, handles)
% hObject    handle to maxCommRangeText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of maxCommRangeText as text
%        str2double(get(hObject,'String')) returns contents of maxCommRangeText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function maxCommRangeText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to maxCommRangeText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on selection change in lineWidthCombo.
function lineWidthCombo_Callback(hObject, eventdata, handles)
% hObject    handle to lineWidthCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns lineWidthCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from lineWidthCombo
    updateSCButton_Callback([], [], handles);

% --- Executes during object creation, after setting all properties.
function lineWidthCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to lineWidthCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


function EditrunGui
% Modifiable runGUI file
clc;
clear all;
fileName = 'zoom_strips_plot.mat';    %USER - ENTER FILENAME
fileData=load(fileName);
temp=fileData(1).temp;

f = figure('Visible','on',...
'Units','normalized',...
'Position',[0,0,1,1],...
'MenuBar','none',...
'NumberTitle','off');

%SENSE COMPUTER AND SET FILE DELIMITER
switch(computer)
    case 'MACI64',		char= '/';
    case 'GLNX86',  char='/';
    case 'PCWIN',	char= '\';
    case 'PCWIN64', char='\';
    case 'GLNXA64', char='/';
end

% start_path='c:\data\matlab_gui\speech_files';

% find speech files directory by going up one level and down one level
% on the directory chain; as follows:
    dir_cur=pwd; % this is the current Matlab exercise directory path
    s=regexp(dir_cur,'\'); % find the last '\' for the current directory
    s1=s(length(s)); % find last '\' character; this marks upper level directory
    dir_fin=strcat(dir_cur(1:s1),'speech_files'); % create new directory
    start_path=dir_fin; % save new directory for speech files location

Callbacks_zoom_strips_plot_GUI25(f,temp,start_path);    %USER - ENTER PROPER CALLBACK FILE
%panelAndButtonEdit(f, temp);       % Easy access to Edit Mode

% Note comment PanelandBUttonCallbacks(f,temp) if panelAndButtonEdit is to
% be uncommented and used
end

% 2 Panels -- one for speech processing parameters, one for graphics
% 1 Graphics Panel -- strips waveform plot
% 1 Text Box
% 8 Buttons
%   #1 - pushbutton - Get Speech Directory (speech_files)
%   #2 - popupmenu - array of speech files from directory speech_files
%   #3 - editable button - starting sample of strips waveform plot
%   #4 - editable button - number of samples per line
%   #5 - popupmenu - samples or seconds for horizontal axis
%   #6 - pushbutton - Play Speech File
%   #7 - pushbutton - Plot Speech File
%   #8 - pushbutton - Close GUI


function X = arg_setdirect(X,value)
% Recursively set the arg_direct flag in a data structure to the given value.
% [Result] = arg_setdirect(Data,Value)
%
% This function treats occurrences of the string arg_direct in cell arrays as a part of a
% name-value pair to update, and fields named arg_direct in structs or struct arrays as
% fields to update. This function does not append the flag if none is currently present.
%
% In:
%	Data : the data structure to update
%
%	Value : value of the arg_direct flag (true or false)
%
% Out:
%	Result : data structure with arg_direct flag updated;
%
% Notes:
%	This function is not yet particularly fast for large data structures.
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2012-02-20

% Copyright (C) Christian Kothe, SCCN, 2012, christian@sccn.ucsd.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

if nargin < 2
    error('please supply a value.'); end

if isempty(X), return; end

if iscell(X)
    for k=1:numel(X)
         X{k} = arg_setdirect(X{k},value);
        if ischar(X{k}) && strcmpi(X{k},'arg_direct')
            X{k+1} = value; end
    end
elseif isstruct(X)
    if length(X) > 1
        for k=1:numel(X)
            X(k) = arg_setdirect(X(k),value); end
    else
        for fn=fieldnames(X)'
            X.(fn{1}) = arg_setdirect(X.(fn{1}),value);
            if strcmp(fn{1},'arg_direct')
                X.(fn{1}) = value; end
        end
    end
end


function Tc = slcompresstext(T, varargin)
%SLCOMPRESSTEXT Compresses a cell array of text
%
% $ Syntax $
%   - Tc = slcompresstext(T, ...)
%
% $ Arguments $
%   - T:        the source text to be compressed
%   - Tc:       the compressed text
%
% $ Description $
%   - Tc = slcompresstext(T, ...) compresses the text T, represented in
%     cell array of lines. You can specify the properties to control the
%     process of compression.
%     \*
%     \t    Table 1. Properties of Text Compression
%     \h    name        &    description
%          'rmempty'    &  whether to remove empty line (default = true)
%          'proc'       &  the method of processing each line
%                          (default='trim')
%                          - 'off': do not process
%                          - 'trim': trim the leading and trailing spaces
%                          - 'deblank': trim only the trailing spaces
%
% $ History $
%   - Created by Dahua Lin, on Aug 9th, 2006
%

%% parse and verify input arguments

if ~iscell(T)
    error('sltoolbox:invalidarg', ...
        'T should be a cell array of strings');
end

opts.rmempty = true;
opts.proc = 'trim';
opts = slparseprops(opts, varargin{:});

switch opts.proc
    case 'off'
        procfunc = [];
    case 'trim'
        procfunc = 'strtrim';
    case 'deblank'
        procfunc = 'deblank';
    otherwise
        error('sltoolbox:invalidarg', ...
            'Invalid string processing method %s', opts.proc);
end

%% Process

if ~isempty(procfunc)
    Tc = slfiltertext(T, procfunc);
else
    Tc = T;
end

%% Select

if opts.rmempty
    nlines = length(Tc);
    is_effline = true(nlines, 1);
    has_deleted = false;
    for i = 1 : nlines
        if isempty(Tc{i})
            is_effline(i) = false;
            has_deleted = true;
        end
    end

    if has_deleted
        Tc = Tc(is_effline);
    end
end


 function h = titlef(varargin)
%function h = titlef(varargin)
%|
%| version of title with built-in sprintf
%| and defaults to latex interpreter
%| also supports default font size from ir_fontsize()
%|
%| Jeff Fessler, University of Michigan

if nargin < 1, ir_usage, end

opt = {'fontsize', ir_fontsize('title')};
%opt = {opt{:}, 'fontname', 'times'};

if ir_is_octave
	opt = {opt{:}, 'fontname', 'Helvetica'};
end

varargin{1} = ir_strrep_tex(varargin{1}); % trick

if ir_is_octave
	tex = {};
	str = varargin{1};
	str = strrep(str, '$', ''); % remove $ needed for latex
	varargin{1} = str;
else
	tex = {'interpreter', 'latex'};
	str = varargin{1};
	str = strrep(str, '\', '\\'); % because of sprintf below
	% trick to replace "|" with "$|$" in strings
	if ~isempty(strfind(str, '|')) && isempty(strfind(str, '$'))
		str = strrep(str, '|', '$|$');
	end
	varargin{1} = str;
end

if isfreemat
	for ii=1:length(varargin)
		if streq(varargin{ii}, 'interpreter') % not supported by freemat
			varargin{ii} = {};
			varargin{ii+1} = {};
		end
	end
end

if im
	tmp = sprintf(varargin{:});
	tmp = strrep(tmp, '%', '\%'); % else latex will ignore %
	hh = title(tmp, tex{:}, opt{:});
else
	hh = [];
end

if nargout
	h = hh;
end


function hist = read_ctf_hist(filename)

% READ_CTF_HIST

% Copyright (C) 2010, Arjen Stolk

[p, f, x] = fileparts(filename);

if strcmp(x, '.ds')
  % the filename should point to the hist file, not the ds
  filename = fullfile(p, [f x], [f '.hist']);
end

fileline = 0;
fid      = fopen(filename,'r');

% the hist file is empty sometimes, in which case the actual reading does not return any useful information
hist = [];

while fileline >= 0
  fileline = fgets(fid);
  if ~isempty(findstr(fileline,'Collection started'))
    startdate = sscanf(fileline(findstr(fileline,'Collection started:'):end),'Collection started: %s');
    hist.starttime = sscanf(fileline(findstr(fileline,startdate):end),strcat(startdate, '%s'));
    hist.startdate = startdate;
  end
  if ~isempty(findstr(fileline,'Collection stopped'))
    stopdate = sscanf(fileline(findstr(fileline,'Collection stopped:'):end),'Collection stopped: %s');
    hist.stoptime = sscanf(fileline(findstr(fileline,stopdate):end),strcat(stopdate, '%s'));
    hist.stopdate = stopdate;
  end
  if ~isempty(findstr(fileline,'Dataset name'))
    hist.datasetname = sscanf(fileline(findstr(fileline,'Dataset name'):end),'Dataset name %s');
  end
end

fclose(fid);


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

%%
clear; close all; clc;

%% Syntax
% |dcmFolder2MATobject_MRE(PathName,MaxVarSize);|

%% 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 orig_path = mrtrix_set_ld_path
% Set the library path for mrtrix libraries

% Save origional environment path
orig_path = getenv('LD_LIBRARY_PATH');
% Get mrtrix path
[status, pathstr] = system('which csdeconv');
if status~=0
    error('Please install mrtrix')
end
% This will be the path to the mrtrix libraries
pathstr = fullfile(pathstr(1:end-13),'lib');
% set the environment path
setenv('LD_LIBRARY_PATH',pathstr)


function varargout = midiOut(varargin)

% midiOut -- connect to a MIDI output device and send notes
%
% >> S = midiOut('L')
% Returns a list of MIDI devices as a structure array. Fields are 'index',
% 'name', 'input' and 'output'. The last two are flags (1 or 0) that determine
% whether the device can be used as an input, or output, or both.
%
% >> midiOut('O', index)
% Opens a MIDI device by its index (as returned by aforementioned 'L' call).
% If the device is already opened, nothing will happen. If another device is
% opened, that one will be closed first.
%
% >> midiOut('C')
% Closes the current connection.
%
% >> midiOut('+', channel, notes, velocities)
% Send one or more 'note on' messages at the given channel (1..16).
% 'notes' and 'velocities' must be given as double-precision arrays with
% equal number of elements. Messages will be transmitted in order.
%
% >> midiOut('-', channel, notes, velocities)
% Send one or more 'note off' messages, same parameters as for 'note on'.
%
% >> midiOut('.', channel)
% Send an 'all notes off' message at the given channel.
%
% >> midiOut('P', channel, program)
% Send a 'program change' to the given channel.
%
% >> midiOut(msg)
% Send raw data. 'msg' must be of type 'uint8' and have a multiple of 3 elements.
%
% For example, play the note C4 (261.63 Hz) on the piano
% >> midiOut('O', 2)
% >> midiOut('+', 1, 60, 127)
%
% See also MIDIIN

% Copyright (C) 2010, Stefan Klanke
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% 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$

error('the %s mex file is not available for your platform (%s)', mfilename, mexext);


%this class retrieves a preprocessing algorithm from the UI
classdef PreprocessingConfigurator < handle

    properties (Access = private)
        %data
        signalNames;

        %algorithms
        algorithms;
        currentAlgorithms;
        algorithmStrings;

        %ui
        signalsList;
        algorithmsList;
        algorithmVariablesTable;

        %state
        currentAlgorithmVariables;

        %observer
        delegate;
    end

    methods (Access = public)
        function obj = PreprocessingConfigurator(signalNames,algorithms, signalsList,...
                algorithmsList,algorithmVariablesTable,delegate)

            obj.signalNames = signalNames;
            obj.algorithms = algorithms;
            obj.signalsList = signalsList;
            obj.algorithmsList = algorithmsList;
            obj.algorithmVariablesTable = algorithmVariablesTable;
            obj.signalsList.ValueChangedFcn = @obj.handleSelectedSignalChanged;
            obj.algorithmsList.ValueChangedFcn = @obj.handleSelectedAlgorithmChanged;

            if nargin > 5
                obj.delegate = delegate;
            end

            if ~isempty(obj.algorithmsList)
                obj.updateSignalsList();
                obj.updateAlgorithmsList();
                obj.selectFirstAlgorithm();

                obj.updateSelectedAlgorithm();
                obj.updateAlgorithmVariablesTable();
            end
        end

        function setSignals(obj,signals)
            obj.signalNames = signals;
            obj.updateSignalsList();
        end

        function algorithm = getCurrentAlgorithm(obj)
            idxStr = obj.algorithmsList.Value;
            [~,idx] = ismember(idxStr,obj.algorithmsList.Items);
            if isempty(idx)
                algorithm = [];
            else
                algorithm = obj.currentAlgorithms{idx};
            end
        end

        function signalIdxs = getSelectedSignalIdxs(obj)
            idxStr = obj.signalsList.Value;
            [~,signalIdxs] = ismember(idxStr,obj.signalsList.Items);
        end

        function algorithm = createPreprocessingAlgorithmWithUIParameters(obj)
            axisSelector = obj.createAxisSelectorWithUIParameters();
            if isempty(axisSelector)
                algorithm = [];
            else
                algorithm = obj.createAlgorithmWithUIParameters();
                if isempty(algorithm)
                    algorithm = [];
                else
                    axisSelector.addNextAlgorithm(algorithm);
                    algorithm = CompositeAlgorithm(axisSelector,{algorithm});
                end
            end
        end

        function axisSelector = createAxisSelectorWithUIParameters(obj)
            selectedSignalIndices = obj.getSelectedSignalIdxs();
            if isempty(selectedSignalIndices)
                axisSelector = [];
            else
                axisSelector = AxisSelector();
                axisSelector.axes = selectedSignalIndices;
            end
        end

        function algorithm = createAlgorithmWithUIParameters(obj)
            algorithm = obj.getCurrentAlgorithm();
            if isa(algorithm,'NoOp')
                algorithm = [];
            elseif ~isempty(algorithm)
                algorithm = algorithm.copy();
                data = obj.algorithmVariablesTable.Data;
                for i = 1 : size(data,1)
                    variableName = data{i,1};
                    variableValue = data{i,2};
                    property = Property(variableName,variableValue);
                    algorithm.setProperty(property);
                end
            end
        end

    end

    methods (Access = private)

        %ui
        function updateSignalsList(obj)
            obj.signalsList.Items = obj.signalNames;
        end

        function signals = getSelectedSignals(obj)
            %returns signals in order
            [~, signalIndices] = ismember(obj.signalsList.Value,obj.signalsList.Items);
            signalIndices = sort(signalIndices);
            signals = obj.signalsList.Items(signalIndices);
        end

        function selectFirstAlgorithm(obj)
            if ~isempty(obj.algorithmsList.Items)
                obj.algorithmsList.Value = obj.algorithmsList.Items{1};
            end
        end

        function selectFirstSignal(obj)
            obj.signalsList.Value = obj.signalsList.Items{1};
        end

        function updateAlgorithmVariablesTable(obj)
            obj.algorithmVariablesTable.Data = Helper.PropertyArrayToCellArray(obj.currentAlgorithmVariables);
        end

        function updateSelectedAlgorithm(obj)
            algorithm = obj.getCurrentAlgorithm();
            if isempty(algorithm)
                obj.currentAlgorithmVariables = [];
            else
                obj.currentAlgorithmVariables = algorithm.getEditableProperties();
            end
        end

        %methods
        function updateAlgorithmsList(obj)
            nSelectedSignals = length(obj.signalsList.Value);
            switch nSelectedSignals
                case 1
                    obj.currentAlgorithms = Palette.FilterAlgorithmsToInputType(obj.algorithms, DataType.kSignal);
                case 2
                    obj.currentAlgorithms = Palette.FilterAlgorithmsToInputType(obj.algorithms, DataType.kSignal2);
                case 3
                    obj.currentAlgorithms = Palette.FilterAlgorithmsToInputType(obj.algorithms, DataType.kSignal3);
                otherwise
                    obj.currentAlgorithms = Palette.FilterAlgorithmsToInputType(obj.algorithms, DataType.kSignalN);
            end

            obj.algorithmsList.Items = Helper.GenerateAlgorithmNamesArray(obj.currentAlgorithms);
        end

        %% handles
        function handleSelectedSignalChanged(obj,~,~)
            obj.updateAlgorithmsList();
        end

        function handleSelectedAlgorithmChanged(obj,~,~)
            obj.updateSelectedAlgorithm();
            obj.updateAlgorithmVariablesTable();

            selectedAlgorithm = obj.getCurrentAlgorithm();
            if ~isempty(obj.delegate)
                obj.delegate.handlePreprocessingAlgorithmChanged(selectedAlgorithm,obj);
            end
        end
    end
end


%IMWRITE  Saves an image to a specified file
%
%     cv.imwrite(filename, img)
%     cv.imwrite(filename, imgs)
%     cv.imwrite(filename, img, 'OptionName', optionValue, ...)
%     success = cv.imwrite(...)
%
% ## Input
% * __filename__ Name of the file.
% * __img__ Image to be saved.
% * __imgs__ A cell-array of images, to be saved as one multi-page image
%   (currently only supported by Tiff encoder).
%
% ## Output
% * __success__ optional output flag, true on success, false otherwise. If not
%   requested, the function throws an error on fail.
%
% ## Options
% * __FlipChannels__ in case the input is color image, flips the color order
%   from MATLAB's RGB/RGBA to OpenCV's BGR/BGRA order. default true
%
% The following format-specific save parameters are currently supported:
%
% * __JpegQuality__ For JPEG, it can be a quality from 0 to 100 (the higher is
%   the better). Default value is 95.
% * __JpegProgressive__ Enable JPEG features, 0 or 1, default is false.
% * __JpegOptimize__ Enable JPEG features, 0 or 1, default is false.
% * __JpegResetInterval__ JPEG restart interval, 0 - 65535, default is 0
%   (no restart).
% * __JpegLumaQuality__ Separate luma quality level, 0 - 100, default is 0
%   (don't use).
% * __JpegChromaQuality__ Separate chroma quality level, 0 - 100, default is 0
%   (don't use).
% * __PngCompression__ For PNG, it can be the compression level from 0 to 9.
%   A higher value means a smaller size and longer compression time. If
%   specified, `PngStrategy` is changed to `Default`. Default value is 1
%   (best speed setting).
% * __PngStrategy__ For PNG; used to tune the compression algorithm. These
%   flags will be modify the way of PNG image compression and will be passed
%   to the underlying zlib processing stage. The strategy parameter only
%   affects the compression ratio but not the correctness of the compressed
%   output even if it is not set appropriately. One of:
%   * __Default__ Use this value for normal data.
%   * __Filtered__ Use this value for data produced by a filter (or predictor).
%     Filtered data consists mostly of small values with a somewhat random
%     distribution. In this case, the compression algorithm is tuned to
%     compress them better. The effect of `Filtered` is to force more Huffman
%     coding and less string matching; it is somewhat intermediate between
%     `Default` and `HuffmanOnly`.
%   * __HuffmanOnly__ Use this value to force Huffman encoding only
%     (no string match).
%   * __RLE__ (default) Use this value to limit match distances to one
%     (run-length encoding). `RLE` is designed to be almost as fast as
%     `HuffmanOnly`, but give better compression for PNG image data.
%   * __Fixed__ Using this value prevents the use of dynamic Huffman codes,
%     allowing for a simpler decoder for special applications.
% * __PngBilevel__ Binary level PNG, 0 or 1, controls packing of pixels per
%   bytes. If false, PNG files pack pixels of bit-depths 1, 2, and 4 into
%   bytes as small as possible. default is false.
% * __PxmBinary__ For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1,
%   to specify ASCII or binary encoding. default is true.
% * __ExrType__ override EXR storage type. Note that the EXR encoder only
%   accepts `single` images. One of:
%   * __Half__ store as half precision (FP16), see cv.convertFp16
%   * __Float__ store as single precision (FP32), this is the default.
% * __WebpQuality__ For WEBP, it can be a quality from 1 to 100 (the higher is
%   the better). By default (without any parameter) and for quality above 100
%   the lossless compression is used.
% * __PamTupleType__ For PAM, sets the TUPLETYPE field to the corresponding
%   string value that is defined for the format. One of:
%   * __Null__
%   * __BlackWhite__
%   * __Grayscale__
%   * __GrayscaleAlpha__
%   * __RGB__
%   * __RGBA__
%
% For advanced uses, you can directly pass a vector of parameters:
%
% * __Params__ Format-specific save parameters encoded as pairs:
%   `[paramId_1, paramValue_1, paramId_2, paramValue_2, ...]`.
%
% The function cv.imwrite saves the image to the specified file. The image
% format is chosen based on the filename extension (see cv.imread for the list
% of extensions). Only 8-bit (or 16-bit unsigned `uint16` in case of PNG,
% JPEG 2000, and TIFF) single-channel or 3-channel (with RGB channel order)
% images can be saved using this function. If the format, depth or channel
% order is different, use cv.cvtColor to convert it before saving. Or, use the
% universal cv.FileStorage I/O functions to save the image to XML or YAML
% format.
%
% (If the chosen encoder does not support the depth of the input image, the
% image will be implicitly cast to 8-bit).
%
% If the image cannot be saved (because of IO errors, improper permissions,
% unsupported or invalid format), the function throws an error.
%
% It is possible to store PNG images with an alpha channel using this function.
% To do this, create 8-bit (or 16-bit) 4-channel image RGBA, where the alpha
% channel goes last. Fully transparent pixels should have alpha set to 0,
% fully opaque pixels should have alpha set to 255/65535.
% Note: WEBP format can also store images with alpha channel.
% See `rgba_png_demo.m` sample for an example.
%
% See also: cv.imread, cv.imencode, imwrite, dicomwrite, hdrwrite
%


function planC = removeItemsFromDICOM(planC)
% "removeItemsFromDICOM"
%   Reformats the DICOM planC data structure so that struct arrays
%   consisting of fields Item_1, Item_2, ... Item_n are concatenated
%   into a struct array 1...n under the same parent.
%   See help condenseFields for details on how this is done.
%
%   JRA 11/3/03
%
% Usage: planC = removeItemsFromDICOM(planC)
%
% 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};
planC = condenseFields(planC, 'Item_\d', 'N/A');


% define global paths
global CBTDIR
global GUROBI_PATH
global ILOG_CPLEX_PATH
global TOMLAB_PATH

c = clock;
fprintf('\n\n      _____   _____   _____   _____     _____     |\n');
fprintf('     /  ___| /  _  \\ |  _  \\ |  _  \\   / ___ \\    |   COnstraint-Based Reconstruction and Analysis\n');
fprintf(['     | |     | | | | | |_| | | |_| |  | |___| |   |   The COBRA Toolbox - ' num2str(c(1)) '\n']);
fprintf('     | |     | | | | |  _  { |  _  /  |  ___  |   |\n');
fprintf('     | |___  | |_| | | |_| | | | \\ \\  | |   | |   |   Test Suite\n');
fprintf(['     \\_____| \\_____/ |_____/ |_|  \\_\\ |_|   |_|   |\n']);
fprintf('                                                  | \n\n');

% request explicitly from the user to launch test suite locally
if contains(getenv('HOME'), 'vmhadmin') || contains(getenv('HOME'), 'jenkins')
    % Running in CI environment
    fprintf('Running test in Jenkins/CI environment\n');

    % on the CI, always reset the path to make absolutely sure, that we test
    % the current version
    restoredefaultpath;
    launchTestSuite = true;
else
    reply = '';
    while isempty(reply)
        reply = input([' -> Do you want to launch the test suite locally? Time estimate: more than 60 minutes Y/N: '], 's');
    end

    if strcmpi(reply, 'y') || strcmpi(reply, 'yes')
        launchTestSuite = true;
    else
        launchTestSuite = false;
    end
end

% save the current folder
origDir = pwd;

% if the location of initCobraToolbox is not yet known
if isempty(which('initCobraToolbox.m'))
    % move back to the root of the repository
    cd([fileparts(which('testAll.m')) filesep '..'])

    % assign the path
    CBTDIR = pwd;
else
    CBTDIR = fileparts(which('initCobraToolbox.m'));
    cd(CBTDIR);
end

% change to the root folder of The COBRA TOolbox
cd(CBTDIR);

% run the official initialisation script
if launchTestSuite

    if ~isempty(getenv('MOCOV_PATH')) && ~isempty(getenv('JSONLAB_PATH'))
        addpath(genpath(getenv('MOCOV_PATH')))
        addpath(genpath(getenv('JSONLAB_PATH')))
        COVERAGE = true;
        fprintf('MoCov and JsonLab are on path, coverage will be computed.\n')
    else
        COVERAGE = false;
    end

    initCobraToolbox;

    % initialize the cleanup
    currentDir = cd('test');
    testDirContent = getFilesInDir('type', 'all');  % Get all currently present files in the folder.
    testDirPath = pwd;
    cd(currentDir);
%{
    if ~isempty(strfind(getenv('HOME'), 'jenkins')) || ~isempty(strfind(getenv('USERPROFILE'), 'jenkins'))
        WAITBAR_TYPE = 0;

        % add CellNetAnalyzer for testing purposes
        addpath(genpath(getenv('CNA_PATH')));

        % check the CNA installation
        checkCNAinstallation(0);
    else
        WAITBAR_TYPE = 1;
    end
%}
    if verLessThan('matlab', '8.2')
        error('The testsuite of The COBRA Toolbox can only be run with MATLAB R2014b+.')
    end

    % define a success exit code
    exit_code = 0;

    % enable profiler
    profile on;

    if COVERAGE
        % Get the ignored Files from gitIgnore
        % only retain the lines that end with .txt and .m and
        % are not comments and point to files in the /src folder
        ignoredPatterns = {'^.{0,3}$', ...  % Is smaller than four.
                        ['^[^s][^r][^c][^' regexptranslate('escape', filesep) ']']};  % does not start with src/
        filterPatterns = {'\.txt$', '\.m$'};  % Is either a .m file or a .txt file.
        ignoreFiles = getIgnoredFiles(ignoredPatterns, filterPatterns);

        % check the code quality
        listFiles = getFilesInDir('type', 'tracked', 'restrictToPattern', '^.*\.m$', 'checkSubFolders', true);

        % count the number of failed code quality checks per file
        nMsgs = 0;
        nCodeLines = 0;
        nEmptyLines = 0;
        nCommentLines = 0;

        for i = 1:length(listFiles)
            nMsgs = nMsgs + length(checkcode(listFiles{i}));
            fid = fopen(listFiles{i});

            while ~feof(fid)
                lineOfFile = strtrim(char(fgetl(fid)));
                if length(lineOfFile) > 0 && length(strfind(lineOfFile(1), '%')) ~= 1  ...
                    && length(strfind(lineOfFile, 'end')) ~= 1 && length(strfind(lineOfFile, 'otherwise')) ~= 1 ...
                    && length(strfind(lineOfFile, 'switch')) ~= 1 && length(strfind(lineOfFile, 'else')) ~= 1  ...
                    && length(strfind(lineOfFile, 'case')) ~= 1 && length(strfind(lineOfFile, 'function')) ~= 1
                        nCodeLines = nCodeLines + 1;

                elseif length(lineOfFile) == 0
                    nEmptyLines = nEmptyLines + 1;

                elseif length(strfind(lineOfFile(1), '%')) == 1
                    nCommentLines = nCommentLines + 1;
                end
            end
            fclose(fid);
        end

        % average number of messages per codeLines
        avMsgsPerc = floor(nMsgs / nCodeLines * 100);

        grades = {'A', 'B', 'C', 'D', 'E', 'F'};
        intervals = [0, 3;
                    3, 6;
                    6, 9;
                    9, 12;
                    12, 15;
                    15, 100];

        grade = 'F';
        for i = 1:length(intervals)
            if avMsgsPerc >= intervals(i, 1) && avMsgsPerc < intervals(i, 2)
                grade = grades{i};
            end
        end

        fprintf('\n\n -> The code grade is %s (%1.2f%%).\n\n', grade, avMsgsPerc);

        % set the new badge
        if ~isempty(strfind(getenv('HOME'), 'jenkins'))
            coverageBadgePath = [getenv('ARTENOLIS_DATA_PATH') filesep 'cobratoolbox' filesep 'codegrade' filesep];
            system(['cp ' coverageBadgePath 'codegrade-', grade, '.svg '  coverageBadgePath 'codegrade.svg']);
        end
    end
end

fprintf ('force-setting launchTestSuite = true\n');
launchTestSuite = true;
fprintf ('launchTestSuite=%s\n', string(launchTestSuite));

try
    if launchTestSuite
        % save the userpath
        originalUserPath = path;

        % run the tests in the subfolder verifiedTests/ recursively
        [result, resultTable] = runTestSuite();

        sumSkipped = sum(resultTable.Skipped);
        sumFailed = sum(resultTable.Failed);

        fprintf(['\n > ', num2str(sumFailed), ' tests failed. ', num2str(sumSkipped), ' tests were skipped due to missing requirements.\n\n']);

        % count the number of covered lines of code
        if COVERAGE
            % write coverage based on profile('info')
            fprintf('Running MoCov ... \n')
            mocov('-cover', 'src', ...
                '-profile_info', ...
                '-cover_json_file', 'coverage.json', ...
                '-cover_html_dir', 'coverage_html', ...
                '-cover_method', 'profile', ...
                '-verbose');

            % load the coverage file
            data = loadjson('coverage.json', 'SimplifyCell', 1);

            sf = data.source_files;
            clFiles = zeros(length(sf), 1);
            tlFiles = zeros(length(sf), 1);

            for i = 1:length(sf)
                clFiles(i) = nnz(sf(i).coverage);
                tlFiles(i) = length(sf(i).coverage);
            end

            % average the values for each file
            cl = sum(clFiles);
            tl = sum(tlFiles);

            % print out the coverage
            fprintf('Covered Lines: %i, Total Lines: %i, Coverage: %f%%.\n', cl, tl, cl / tl * 100);
        end

        % print out a summary table
        resultTable

        % Print some information on failed and skipped tests.
        skippedTests = find(resultTable.Skipped);
        if sum(skippedTests > 0)
            fprintf('The following tests were skipped:\n%s\n\n', strjoin(resultTable.TestName(skippedTests), '\n'));
            fprintf('The reasons were as follows:\n')
            for i = 1:numel(skippedTests)
                fprintf('------------------------------------------------\n')
                fprintf('%s:\n', resultTable.TestName{skippedTests(i)});
                fprintf('%s\n', resultTable.Details{skippedTests(i)});
                fprintf('------------------------------------------------\n')
            end
            fprintf('\n\n')
        end

        failedTests = find(resultTable.Failed & ~resultTable.Skipped);
        if sum(failedTests > 0)
            fprintf('The following tests failed:\n%s\n\n', strjoin(resultTable.TestName(failedTests), '\n'));
            fprintf('The reasons were as follows:\n')
            for i = 1:numel(failedTests)
                fprintf('------------------------------------------------\n')
                fprintf('%s:\n', resultTable.TestName{failedTests(i)});
                trace = result(failedTests(i)).Error.getReport();
                tracePerLine = strsplit(trace, '\n');
                testSuitePosition = find(cellfun(@(x) ~isempty(strfind(x, 'runTestSuite')), tracePerLine));
                trace = sprintf(strjoin(tracePerLine(1:(testSuitePosition - 7)), '\n'));  % Remove the testSuiteTrace.
                fprintf('%s\n', trace);
                fprintf('------------------------------------------------\n')
            end
            fprintf('\n\n')
        end

        % restore the original path
        restoredefaultpath;
        addpath(originalUserPath);

        if sumFailed > 0
            exit_code = 1;
        end

        fprintf(['\n > The exit code is ', num2str(exit_code), '.\n\n']);

        % clean up temporary files.
        removeTempFiles(testDirPath, testDirContent);

        % ensure that we ALWAYS call exit
        if ~isempty(strfind(getenv('HOME'), 'jenkins')) || ~isempty(strfind(getenv('USERPROFILE'), 'jenkins'))
            %exit(exit_code);
        end
    end
catch ME

    fprintf('exception %s while running test: %s\n', ME.identifier, ME.message);

    % Also clean up temporary files in case of an error.
    removeTempFiles(testDirPath, testDirContent);
    if ~isempty(strfind(getenv('HOME'), 'jenkins')) || ~isempty(strfind(getenv('USERPROFILE'), 'jenkins'))
        % only exit on jenkins.
        exit(1);
    else
        % switch back to the folder we were in and rethrow the error
        cd(origDir);
        rethrow(ME);
    end
end

% switch back to the original directory
cd(origDir)
if contains(getenv('HOME'), 'vmhadmin') || contains(getenv('HOME'), 'jenkins')
    % Running in CI environment
    fprintf('Running test in Jenkins/CI environment\n');
    % explicit 'exit' required for R2018b in non-interactive mode to avoid SEGV near end of test
    exit
end


classdef(SharedTestFixtures = {DownloadGPT2Fixture}) tGPT2Tokenizer < matlab.unittest.TestCase
    % tGPT2Tokenizer   Tests for the text encoder class

    % Copyright 2020 The MathWorks, Inc.

    properties
        % Setup a default encoder for testing
        Encoder
    end

    properties(TestParameter)
        % UnicodeTextAndEncodedText
        UnicodeTextAndEncodedText = iGetUnicodeTextAndEncodedText()

        % Strings to be tokenized by the regex and expected results
        StringToTokenize = iStringToTokenize()

        % Test strings for encoding
        StringToEncode = iStringToEncode()
    end

    methods(TestClassSetup)
        function setup(test)
            test.setupEncoder();
        end
    end

    methods(Test)
        function encodeGivesCorrectResults(test, UnicodeTextAndEncodedText)
            % Unpack the test parameter
            inputText = UnicodeTextAndEncodedText.UnicodeText;
            expectedOutputText = UnicodeTextAndEncodedText.EncodedText;

            % Create the encoder
            enc = gpt2.tokenizer.GPT2Tokenizer(iModelName(), iModelPath());

            % Get the output text
            actualOutputText = enc.encode(inputText);

            % Verify the output is correct
            test.verifyThat( ...
                actualOutputText, iIsEqualTo(expectedOutputText) );
        end

        function decodeGivesCorrectResults(test, UnicodeTextAndEncodedText)
            % Unpack the test parameter
            inputText = UnicodeTextAndEncodedText.EncodedText;
            expectedOutputText = UnicodeTextAndEncodedText.UnicodeText;

            % Create the encoder
            enc = gpt2.tokenizer.GPT2Tokenizer(iModelName(), iModelPath());

            % Get the output text
            actualOutputText = enc.decode(inputText);

            % Verify the output is correct
            test.verifyThat( ...
                actualOutputText, iMatches(expectedOutputText) );
        end

        function testTokenization(test, StringToTokenize)
            % Test the regex tokenization used by the Encoder.
            enc = test.Encoder;
            toks = iTokenize(StringToTokenize.string,enc);
            test.verifyEqual(toks,StringToTokenize.exp);
        end

        function byteEncoderSize(test)
            % Verify the expected size of the byte encoder.
            enc = test.Encoder;
            test.verifyEqual(numel(unique(enc.ByteEncoder)),256);
        end

        function independenceOfInputClass(test, StringToEncode)
            % Verify that it doesn't matter if input text is string or char
            enc = test.Encoder;
            str = convertCharsToStrings(StringToEncode);
            ch = convertStringsToChars(StringToEncode);
            test.verifyEqual(enc.encode(str),enc.encode(ch));
        end

        function commentNotInBPE(test)
            % The vocab.bpe includes a comment that we must manually strip
            % out. Ensure we do that.
            vocabFile = gpt2.internal.getSupportFilePath("gpt2_vocab.bpe");
            fid = fopen(vocabFile,'r','n','utf-8');
            s = textscan(fid,'%s', 'Delimiter', '\n');
            fclose(fid);
            s = s{1};
            % first line of vocab.bpe is the comment
            firstLine = s(1);
            % split as in Encoder and check we don't accidentally add these
            % values to BPERanks.
            splitfirstLine = split(convertCharsToStrings(firstLine));
            enc = test.Encoder;
            actBPE = enc.BPERanks;
            % splitfirstLine is a string, ensure actBPE is
            test.assertClass(actBPE,'string');
            actBPEMatchesComment = any(actBPE==splitfirstLine(1),'all') || any(actBPE==splitfirstLine(2),'all');
            test.verifyFalse(actBPEMatchesComment, "A match was found between the encoder's BPERanks and the comment in vocab.bpe");
        end

        function decodeInvertsEncode(test,StringToEncode)
            % Ensure decoding inverts encoding
            enc = test.Encoder;
            encoded = enc.encode(StringToEncode);
            decoded = enc.decode(encoded);
            test.verifyMatches(decoded,StringToEncode);
        end
    end

    methods(Access=private)
        function setupEncoder(test)
            % Setup an encoder to be used by multiple tests.
            % Note this is a handle.
            test.Encoder = gpt2.tokenizer.GPT2Tokenizer(iModelName(),iModelPath());
        end
    end
end

function modelName = iModelName()
modelName = 'gpt2-355M';
end

function modelPath = iModelPath()
modelPath = fullfile(getRepoRoot());
end

function constraint = iIsEqualTo(varargin)
constraint = matlab.unittest.constraints.IsEqualTo(varargin{:});
end

function constraint = iMatches(varargin)
constraint = matlab.unittest.constraints.Matches(varargin{:});
end

function parameter = iGetUnicodeTextAndEncodedText()

parameter = struct;

parameter.NormalSentenceFragment1 = struct( ...
    'UnicodeText', 'In this tutorial we will see', ...
    'EncodedText', [818 428 11808 356 481 766] + 1 );

parameter.NonsenseFragment1 = struct( ...
    'UnicodeText', 'esgarghr', ...
    'EncodedText', [274 4563 456 81] + 1 );

% Weird edge case I found when I wasn't doing the Unicode decoding
% correctly. If you set "k=1" and input the sentence "In this tutorial ",
% into GPT-2 the first output is a special Unicode character known as a
% "Non-breaking space". After thinking about this, this weird behaviour is
% likely due to the fact that the tokenizer for GPT-2 tokenizes words so
% that they are preceded by spaces.
parameter.NonBreakingSpace = struct( ...
    'UnicodeText', native2unicode([194 160], 'UTF-8'), ...
    'EncodedText', 1849 + 1 );

end

function c = iStringToEncode()
% A test parameter of strings to be passed to the encoder.
c = {
    'In this tutorial we will see'
    'esgarghr'
    'foo bar baz'
    'A word and numbers 123 or 456word and decimal 7.89'
    'particles like don''t do that'
    'multiple white    space characters'
    };
end

function s = iStringToTokenize()
% A test parameter of strings to be tokenized using the regular expression
% attached to tokenizer.GPT2Tokenizer, and the expected output tokens.
s = struct( ...
    'oneWord', iStringToTokenizeStruct("foo","foo"), ...
    'twoWords', iStringToTokenizeStruct("foo bar",["foo"," bar"]), ...
    'possessive', iStringToTokenizeStruct("foo's",["foo","'s"]), ...
    'not', iStringToTokenizeStruct("foo't", ["foo","'t"]), ...
    'are', iStringToTokenizeStruct("foo're", ["foo","'re"]), ...
    'have', iStringToTokenizeStruct("foo've", ["foo","'ve"]), ...
    'm', iStringToTokenizeStruct("foo'm",["foo","'m"]), ...
    'will', iStringToTokenizeStruct("foo'll",["foo","'ll"]), ...
    'would', iStringToTokenizeStruct("foo'd",["foo","'d"]), ...
    'numbers', iStringToTokenizeStruct("foo 123bar",["foo"," 123","bar"]), ...
    'multiWS', iStringToTokenizeStruct("foo   bar",["foo", "  ", " bar"]));
end

function s = iStringToTokenizeStruct(str,expTokens)
% A struct for a case of the StringToTokenize test parameter.
s = struct('string',str,'exp',expTokens);
end

function toks = iTokenize(str,enc)
% Tokenize equivalently to tokenizer.GPT2Tokenizer
[toks,~] = regexp(str,enc.TokenizationExpression,'match','split');
end


function [rest] = mne_omit_first_line(str)
%
% [rest] = mne_omit_first_line(str)
%
% Omit the first line in a multi-line string (useful for handling
% error messages)
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%
%   Revision 1.2  2006/04/23 15:29:40  msh
%   Added MGH to the copyright
%
%   Revision 1.1  2006/04/17 11:52:15  msh
%   Added coil definition stuff
%
%
me='MNE:mne_omit_first_line';

lf = findstr(10,str);
if isempty(lf)
    rest = str;
else
    rest = str(lf+1:size(str,2));
end

return;

end


function Data = Hash2Struct(hashMap)
% This function converts object of type java.util.HashMap to matlab struct.
% Inputs:
%   - hashMap : java.util.HashMap object
% Outputs:
%   - Data    : matlab struct
% This code is based on template provided by Jan Siroky on
% http://stackoverflow.com/questions/1638018/is-there-already-a-yaml-library-parser-for-matlab

%  %======================================================================
%{
		Copyright (c) 2011
		This program is a result of a joined cooperation of Energocentrum
		PLUS, s.r.o. and Czech Technical University (CTU) in Prague.
        The program is maintained by Energocentrum PLUS, s.r.o. and
        licensed under the terms of MIT license. Full text of the license
        is included in the program release.

        Author(s):
		Jiri Cigler, Dept. of Control Engineering, CTU Prague
		Jan  Siroky, Energocentrum PLUS s.r.o.

        Implementation and Revisions:

        Auth  Date        Description of change
        ----  ---------   --------------------------------------------------
        jc    01-Mar-11   First implementation
        jc    03-Mar-11   Arrays of struct support
        jc    09-Mar-11   DateTime support extended
        jc    15-Mar-11   Support for different encodings
        jc    08-May-11   Support for yaml read of cell of structs
%}
%======================================================================

if isa(hashMap,'java.util.ArrayList')
    iterator = hashMap.iterator();
    index = 0;
    while (iterator.hasNext())
        index = index +1;
        %Data(index)= Hash2Struct(iterator.next());
        res   = Hash2Struct(iterator.next());
        if index==1
            Data = res;
        else
            if iscell(Data)
                Data{index} = res;
            elseif isequal(fieldnames(res),fieldnames(Data))
                Data(index) = res;
            else % convert array to cell
                Data = num2cell(Data);
                Data{index}= res;
            end
        end
    end
else
    Data = [];
    iterator = hashMap.keySet().iterator();
    while (iterator.hasNext())
        field = iterator.next();
        if ~isempty(field)
            d =  hashMap.get(java.lang.String(field));
            switch class(d)
                case {'java.util.LinkedHashMap'}
                    Data.(field) = Hash2Struct(d);
                case {'java.util.ArrayList'}
                    switch class(d.get(0))
                        case {'char' ,'double','java.util.Date'}
                            it = d.iterator();
                            val={};
                            while (it.hasNext())
                                val(end+1)={it.next()};
                                if isa(val{end},'java.util.Date')
                                    val{end} = DateTime(val{end});
                                end
                                if ischar(val{end})
                                    val{end} = DecodeUnicode(val{end});
                                end
                            end
                            if all(cellfun(@(x) isnumeric(x),val))
                                val = cell2mat(val);
                            end
                        case {'java.util.ArrayList'}
                            itr = d.iterator();
                            val={};
                            r=1;
                            while (itr.hasNext())
                                row=itr.next();
                                itc = row.iterator();
                                c=1;
                                while(itc.hasNext())
                                    val{r,c}=itc.next();
                                    if isa(val{r,c},'java.util.Date')
                                        val{r,c} = DateTime(val{r,c});
                                    end
                                    if ischar(val{r,c})
                                        val{r,c} = DecodeUnicode(val{r,c});
                                    end
                                    c=c+1;
                                end
                                r=r+1;
                            end
                            if all(cellfun(@(x) isnumeric(x),val))
                                val = cell2mat(val);
                            end
                        case {'java.util.LinkedHashMap'}
                            for hh=0:(d.size-1)
                                hm=d.get(hh);
                                h2sres = Hash2Struct(hm);
                                h2sres_fn = fieldnames(h2sres);

                                if isfield(Data,field)
                                    if iscell(Data.(field))
                                        Data.(field){hh+1}= h2sres;
                                    elseif isequal(h2sres_fn,fieldnames(Data.(field)))
                                        Data.(field)(hh+1)= h2sres;
                                    else % convert array to cell
                                        Data.(field) = num2cell(Data.(field));
                                        Data.(field){hh+1}= h2sres;
                                    end
                                else
                                    Data.(field)= h2sres;
                                end
                            end
                            continue;

                        otherwise
                            error('unknown  java datatype');
                    end

                    Data.(field) = val;
                otherwise
                    if isa(d,'java.util.Date')
                        d = DateTime(d);
                    end
                    if ischar(d)
                        d = DecodeUnicode(d);
                    end
                    Data.(field) = d;
            end
        end
    end
end


function [evtNum, varLocType] = getEventNumberForVar(var, lvdData)
    evtNum = [];
    varLocType = '';

    numEvents = lvdData.script.getTotalNumOfEvents();
    for(i=1:numEvents)
        event = lvdData.script.getEventForInd(i);

        [~, eVars] = event.hasActiveOptVars();

        for(j=1:length(eVars)) %#ok<*NO4LP>
            eVar = eVars(j);

            if(strcmpi(class(var), class(eVar)) && var == eVar)
                evtNum = i;
                varLocType = 'Event';
                break;
            end
        end

        if(not(isempty(evtNum)))
            break;
        end
    end

    if(isempty(evtNum))
        if(lvdData.initStateModel.isVarFromInitialState(var))
            varLocType = 'Initial State';

        elseif(lvdData.launchVehicle.isVarFromLaunchVehicle(var))
            varLocType = 'Launch Vehicle';

        elseif(lvdData.pluginVars.isVarAPluginVar(var))
            varLocType = 'Plugins';

        else
            varLocType = '';

        end
    end
end


function create(obj,wrt)
% Create a NIFTI-1 file
% FORMAT create(obj)
% Write out the header information for the nifti object
%
% FORMAT create(obj,wrt)
% Also write out an empty image volume if wrt==1
%__________________________________________________________________________
% Copyright (C) 2005-2013 Wellcome Trust Centre for Neuroimaging

%
% $Id: create.m 5451 2013-04-26 14:03:05Z guillaume $

for i=1:numel(obj)

    o = obj(i);

    if ~isa(o.dat,'file_array'), error('Data must be a file_array.'); end

    fname = o.dat.fname;
    if isempty(fname), error('No filename to write to.'); end

    %-Write NIFTI header
    sts = write_hdr_raw(fname, o.hdr, o.dat.dtype(end-1)=='B');
    if ~sts, error('Unable to write header for "%s".',fname); end

    %-Write extra information
    write_extras(fname,o.extras);

    %-Create an empty image file if necessary
    if nargin>1 && any(wrt==1)
        [pth,nam] = fileparts(fname);
        if any(strcmp(o.hdr.magic(1:3),{'n+1','n+2'}))
            ext = '.nii';
        else
            ext = '.img';
        end
        o.dat.fname = fullfile(pth,[nam ext]);

        initialise(o.dat);
    end

end


function [s] = find_first_path(guesses,quiet)
  si = find(cellfun(@(guess) exist(guess,'file'),guesses),1,'first');
  if isempty(si)
    if nargin>1 && quiet
      s = [];
      return;
    else
      error('Could not find path');
    end
  end
  s = guesses{si};
end