function varargout = camera_pipeline(varargin)
% CAMERA_PIPELINE MATLAB code for camera_pipeline.fig
%      CAMERA_PIPELINE, by itself, creates a new CAMERA_PIPELINE or raises the existing
%      singleton*.
%
%      H = CAMERA_PIPELINE returns the handle to a new CAMERA_PIPELINE or the handle to
%      the existing singleton*.
%
%      CAMERA_PIPELINE('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in CAMERA_PIPELINE.M with the given input arguments.
%
%      CAMERA_PIPELINE('Property','Value',...) creates a new CAMERA_PIPELINE or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before camera_pipeline_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to camera_pipeline_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 camera_pipeline

% Last Modified by GUIDE v2.5 03-Nov-2016 22:15:06

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @camera_pipeline_OpeningFcn, ...
                   'gui_OutputFcn',  @camera_pipeline_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 camera_pipeline is made visible.
function camera_pipeline_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 camera_pipeline (see VARARGIN)

% Choose default command line output for camera_pipeline
handles.output = hObject;
%TODO
% maximize the GUI
set(0, 'Unit', 'pixel');
winsize = get(0, 'ScreenSize');

% Set the Gui position
winsize(1) = winsize(1) + 100;
winsize(2) = winsize(2) + 100;
winsize(3) = winsize(3) - 150;
winsize(4) = winsize(4) - 150;
set(gcf, 'Position', winsize);

step = winsize(4) / 16;
% Set the Panel position
set(handles.uipanel1, 'Position', [3/4* winsize(3) + 100, 10, 1/4*winsize(3) - 20, winsize(4) + 50]);
% Set the Axes position disappear
set(handles.axes1, 'Position', [-10, -10, 5, 5]);
% Update handles structure
handles.myData.winsize = winsize;

%current stage in pipeline
handles.myData.current_stage = zeros(1,1);

pipeline_image = im2double(imread(fullfile('.','Adobe_DNG_SDK_Pipeline_v4.bmp')));
% set the slider range and step size
numSteps = 11;
set(handles.slider1, 'Min', 1);
set(handles.slider1, 'Max', numSteps);
set(handles.slider1, 'Value', 1);
set(handles.slider1, 'SliderStep', [1/(numSteps-1) , 1/(numSteps-1) ]);
% save the current/last slider value
handles.lastSliderVal = get(handles.slider1,'Value');

 % Update handles structure
handles.pushbutton1Pressed = 0;

guidata(hObject, handles);
% UIWAIT makes camera_pipeline wait for user response (see UIRESUME)
% uiwait(handles.figure1);
showImage(handles, pipeline_image);
% prompt = {'Enter matrix size:','Enter colormap name:'};
% dlg_title = 'Input';
% num_lines = 1;
% defaultans = {'20','hsv'};
% answer = inputdlg(prompt,dlg_title,num_lines,defaultans);

% Get all the handles to everything we want to set in a single array.
handleArray = [handles.pushbutton1, handles.pushbutton12, handles.radiobutton3, handles.radiobutton8, handles.radiobutton15, handles.radiobutton16];
% Set them all disabled.
set(handleArray, 'Enable', 'off');

% --- Outputs from this function are returned to the command line.
function varargout = camera_pipeline_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} = handles.output;

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
%%
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[filename, pathname] = uigetfile( ...
{'*.*',  'All Files (*.*)';
'*.cr2;*.nef;*.pef;','RAW Image Files (*.cr2,*.nef, *.pef)';
'*.dat','Spectral data files (*.dat)'}, ...
   'Pick a file');
if isequal(filename,0) || isequal(pathname,0)
else
    handles.myData.fileName = [pathname filename];

    a = [get(handles.radiobutton15,'Value') get(handles.radiobutton16,'Value') get(handles.radiobutton3,'Value') get(handles.radiobutton8,'Value')];
    fileID = fopen('wbAndGainSettings.txt','w');
    fprintf(fileID,'%d\n',a);
    fclose(fileID);

    rwSettings = [0];
    if (get(handles.radiobutton17,'Value') == 1)
        rwSettings(1) = 1;
    end
    if ((get(handles.radiobutton17,'Value') == 0) && (get(handles.radiobutton18,'Value') == 0))
        rwSettings(1) = 2;
    end
    fileID = fopen('rwSettings.txt','w');
    fprintf(fileID,'%d\n',rwSettings);
    fclose(fileID);

    cam_settings = [0];
    if (get(handles.radiobutton20,'Value') == 1)
        cam_settings(1) = 1;
    end
    if ((get(handles.radiobutton20,'Value') == 0) && (get(handles.radiobutton19,'Value') == 0))
        cam_settings(1) = 2;
    end
    fileID = fopen('cam_settings.txt','w');
    fprintf(fileID,'%d\n',cam_settings);
    fclose(fileID);

    my_waitbar = waitbar(0, 'Rendering Image...');

    inputFileName = [pathname filename];
    if (handles.lastSliderVal == 1)
        stage1OutputFileName = [inputFileName(1:end-4) '_stage1.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -1 ') stage1OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage1OutputFileName);
        %imtool(uint8(handles.myData.image/256))
        delete(stage1OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 2)

        a = [0 1 0 1]; % without gain [0 1 ...
        fileID = fopen('wbAndGainSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        stageSettings_indicator = [2];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',stageSettings_indicator);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',stageSettings_indicator);
            fclose(fileID);
        end

        stage2OutputFileName = [inputFileName(1:end-4) '_stage2.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -2 ')  stage2OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage2OutputFileName);
        delete(stage2OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 3)

        a = [1 0 0 1]; % with gain [1 0 ...
        fileID = fopen('wbAndGainSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        stageSettings_indicator = [3];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',stageSettings_indicator);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',stageSettings_indicator);
            fclose(fileID);
        end

        stage3OutputFileName = [inputFileName(1:end-4) '_stage3.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -2 ')  stage3OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage3OutputFileName);
        delete(stage3OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 4)
        a = [4];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        stage4OutputFileName = [inputFileName(1:end-4) '_stage4.tif'];

        if (get(handles.radiobutton17,'Value') == 0 && get(handles.radiobutton18,'Value') == 1 )
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
            system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ')  stage4OutputFileName ' ' inputFileName];
            system(system_command);
            delete(stage4OutputFileName);
        end

        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -3 ')  stage4OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage4OutputFileName);
        delete(stage4OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 5)

        a = [5];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end
        %
        stage5OutputFileName = [inputFileName(1:end-4) '_stage5.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ')  stage5OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage5OutputFileName);
        delete(stage5OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 6)

        a = [6];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage6OutputFileName = [inputFileName(1:end-4) '_stage6.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ')  stage6OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage6OutputFileName);
        delete(stage6OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 7)

        a = [7];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage7OutputFileName = [inputFileName(1:end-4) '_stage7.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ') stage7OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage7OutputFileName);
        delete(stage7OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 8)

        a = [8];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage8OutputFileName = [inputFileName(1:end-4) '_stage8.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ') stage8OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage8OutputFileName);
        delete(stage8OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 9)

        a = [9];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage9OutputFileName = [inputFileName(1:end-4) '_stage9.tif'];
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ') stage9OutputFileName ' ' inputFileName];
        system(system_command);
        handles.myData.image = imread(stage9OutputFileName);
        delete(stage9OutputFileName);
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 10)

        a = [10];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage10OutputFileName = [inputFileName(1:end-4) '_stage10.tif'];%comment here when dng save tests.
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ') stage10OutputFileName ' ' inputFileName];%comment here when dng save tests.
%         stage10OutputFileName = [inputFileName(1:end-4) '_stage10_V3.dng']; %comment out here when dng save tests.
%         system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -dng ') stage10OutputFileName ' ' inputFileName]; %comment out here when dng save tests.

        system(system_command);
        handles.myData.image = imread(stage10OutputFileName);%comment here when dng save tests.
        delete(stage10OutputFileName);        %comment here when dng save tests.
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

    if (handles.lastSliderVal == 11)

        a = [11];
        fileID = fopen('stageSettings.txt','w');
        fprintf(fileID,'%d\n',a);
        fclose(fileID);

        if (get(handles.radiobutton17,'Value') == 0)
            fileID = fopen('lastStage.txt','w');
            fprintf(fileID,'%d\n',a);
            fclose(fileID);
        end

        stage11OutputFileName = [inputFileName(1:end-4) '_stage11.tif'];%comment here when dng save tests.
        system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -16 -cs1 -tif ') stage11OutputFileName ' ' inputFileName];%comment here when dng save tests.
%         stage11OutputFileName = [inputFileName(1:end-4) '_stage11_V3.dng']; %comment out here when dng save tests.
%         system_command = [fullfile('.','dngOneExeSDK','dng_validate.exe -dng ') stage11OutputFileName ' ' inputFileName]; %comment out here when dng save tests.
        system(system_command);
        handles.myData.image = imread(stage11OutputFileName);
        delete(stage11OutputFileName);   %comment here when dng save tests.
        delete(my_waitbar)       % DELETE the waitbar; don't try to CLOSE it.
    end

%     if (handles.lastSliderVal <= 9)
%         set(handles.pushbutton3, 'Enable', 'on');
%     end
    set(handles.pushbutton1, 'Enable', 'off');
    set(handles.pushbutton12, 'Enable', 'on');
    set(handles.slider1, 'Enable', 'off');
    % Update handles structure
    guidata(hObject, handles);
    if (handles.lastSliderVal >= 4)
        showImage(handles, uint16(handles.myData.image));
    else
        showImage(handles, handles.myData.image);
    end
end

function showImage(handles, I)
% I = handles.myData.image;
winsize = handles.myData.winsize;
[wi, hi, ~] = size(I);
ws = winsize(4);
hs = 3/4*winsize(3);
if (ws/hs > wi/hi)
    ws = hs * (wi/hi);
else
    hs = ws * (hi/wi);
end

set(handles.axes1, 'Position', [10, 100, hs - 20, ws - 20]);
set(handles.pushbutton1, 'Parent', handles.uipanel1);
axes(handles.axes1);
% I(:,:,1) = I(:,:,1) fullfile('.', max(max(I(:,:,1)));
% I(:,:,2) = I(:,:,2) fullfile('.', max(max(I(:,:,2)));
% I(:,:,3) = I(:,:,3) fullfile('.', max(max(I(:,:,3)));
imshow(I);
% guidata(hObject, handles);

% --- Executes on button press in radiobutton3.
function radiobutton3_Callback(hObject, eventdata, handles)
%%
% hObject    handle to radiobutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes on button press in pushbutton12.
function pushbutton12_Callback(hObject, eventdata, handles)
%%
% hObject    handle to pushbutton12 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

saved_image =handles.myData.image;

% outputFileName = 'current_result.dng';
outputFileName = 'current_result.tif';
t = Tiff(outputFileName,'w');
% 8 bit save works well
output_unit16 = saved_image;

sliderValue =  handles.lastSliderVal;

tagstruct.ImageLength = size(output_unit16,1);
tagstruct.ImageWidth = size(output_unit16,2);
tagstruct.BitsPerSample = 16;
if sliderValue == 1 || sliderValue == 2 || sliderValue == 3
    tagstruct.SamplesPerPixel = 1;
    tagstruct.Photometric = Tiff.Photometric.MinIsBlack;
else
    tagstruct.SamplesPerPixel = 3;
    tagstruct.Photometric = Tiff.Photometric.RGB;
end
% tagstruct.RowsPerStrip = 16;
tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
tagstruct.Software = 'MATLAB';
% tagstruct.DNGVersion = [1; 4; 0; 0];
t.setTag(tagstruct);

t.write(output_unit16);
t.close();

% 16 bit save does not work well
% output_unit16 = uint16(saved_image*255);
%
% tagstruct.ImageLength = size(output_unit16,1);
% tagstruct.ImageWidth = size(output_unit16,2);
% tagstruct.Photometric = Tiff.Photometric.RGB;
% tagstruct.BitsPerSample = 16;
% tagstruct.SamplesPerPixel = 3;
% tagstruct.RowsPerStrip = 8; %16 and 32 are also tried. cannot save 16
% bit.
% tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
% tagstruct.Software = 'MATLAB';
% t.setTag(tagstruct);
%
% t.write(output_unit16);
% t.close();

% --- Executes on button press in radiobutton8.
function radiobutton8_Callback(hObject, eventdata, handles)
%%
% hObject    handle to radiobutton8 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton8

% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
% hObject    handle to slider1 (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,'Value') returns position of slider
%        get(hObject,'Min') and get(hObject,'Max') to determine range of slider

% set(handles.edit32,'String',num2str( get( get(handles.slider1,'Value'))));
%

  handles = guidata(hObject);
 % get the slider value and convert it to the nearest integer that is less
 % than this value
 newVal = floor(get(hObject,'Value'));
 % set the slider value to this integer which will be in the set {1,2,3,...,12,13}
 set(hObject,'Value',newVal);
 % now only do something in response to the slider movement if the
 % new value is different from the last slider value
 if newVal ~= handles.lastSliderVal
     % it is different, so we have moved up or down from the previous integer
     % save the new value
     handles.lastSliderVal = newVal;
     guidata(hObject,handles);
    % display the current value of the slider
    disp(['at slider value ' num2str(get(hObject,'Value'))]);
 end

 sliderValue =  handles.lastSliderVal;
 set(handles.text3,'String',num2str(sliderValue));

if sliderValue >= 4
    % Get all the handles to everything we want to set in a single array.
    handleArray = [handles.radiobutton15, handles.radiobutton16];
    % Set them all disabled.
    set(handleArray, 'Enable', 'on');
    if sliderValue >= 5
        % Get all the handles to everything we want to set in a single array.
        handleArray = [handles.radiobutton3, handles.radiobutton8, handles.radiobutton15, handles.radiobutton16];
        % Set them all disabled.
        set(handleArray, 'Enable', 'on');
    end
end
if sliderValue < 4
    % Get all the handles to everything we want to set in a single array.
    handleArray = [handles.radiobutton3, handles.radiobutton8, handles.radiobutton15, handles.radiobutton16];
    % Set them all disabled.
    set(handleArray, 'Enable', 'off');
end
if sliderValue < 5
    % Get all the handles to everything we want to set in a single array.
    handleArray = [handles.radiobutton3, handles.radiobutton8];
    % Set them all disabled.
    set(handleArray, 'Enable', 'off');
end

% if sliderValue >= 4
%     % Set them all disabled.
%     set(handles.pushbutton3, 'Enable', 'off');
% end
if sliderValue >= 1
    % Set them all disabled.
    set(handles.pushbutton1, 'Enable', 'on');
end
% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to slider1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end

% --- Executes on button press in radiobutton16.
function radiobutton16_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton16 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton16

% --- Executes on button press in radiobutton15.
function radiobutton15_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton15 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton15

% --- Executes on button press in radiobutton18.
function radiobutton18_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton18 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton18

% --- Executes on button press in radiobutton17.
function radiobutton17_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton17 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton17

% --- Executes on button press in radiobutton20.
function radiobutton20_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton20 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton20

% --- Executes on button press in radiobutton19.
function radiobutton19_Callback(hObject, eventdata, handles)
% hObject    handle to radiobutton19 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of radiobutton19


function [cfg] = ft_rejectartifact(cfg, data)

% FT_REJECTARTIFACT removes data segments containing artifacts. It returns a
% configuration structure with a modified trial definition which can be used for
% preprocessing of only the clean data.
%
% You should start by detecting the artifacts in the data using the function
% FT_ARTIFACT_xxx where xxx is the type of artifact. Subsequently FT_REJECTARTIFACT
% looks at the detected artifacts and removes them from the trial definition or from
% the data. In case you wish to replace bad parts by nans, you have to specify data
% as an input parameter.
%
% Use as
%   cfg = ft_rejectartifact(cfg)
% with the cfg as obtained from FT_DEFINETRIAL, or as
%   data = ft_rejectartifact(cfg, data)
% with the data as obtained from FT_PREPROCESSING
%
% The following configuration options are supported:
%   cfg.artfctdef.reject          = 'none', 'partial', 'complete', 'nan', or 'value' (default = 'complete')
%   cfg.artfctdef.minaccepttim    = when using partial rejection, minimum length
%                                   in seconds of remaining trial (default = 0.1)
%   cfg.artfctdef.crittoilim      = when using complete rejection, reject trial only when artifacts occur within
%                                   this time window (default = whole trial). This only works with in-memory data,
%                                   since trial time axes are unknown for data on disk.
%   cfg.artfctdef.feedback        = 'yes' or 'no' (default = 'no')
%   cfg.artfctdef.invert          = 'yes' or 'no' (default = 'no')
%   cfg.artfctdef.value           = scalar value to replace the data in the artifact segments (default = nan)
%   cfg.artfctdef.eog.artifact    = Nx2 matrix with artifact segments, this is added to the cfg by using FT_ARTIFACT_EOG
%   cfg.artfctdef.jump.artifact   = Nx2 matrix with artifact segments, this is added to the cfg by using FT_ARTIFACT_JUMP
%   cfg.artfctdef.muscle.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using FT_ARTIFACT_MUSCLE
%   cfg.artfctdef.zvalue.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using FT_ARTIFACT_ZVALUE
%   cfg.artfctdef.visual.artifact = Nx2 matrix with artifact segments, this is added to the cfg by using FT_DATABROWSER
%   cfg.artfctdef.xxx.artifact    = Nx2 matrix with artifact segments, this could be added by your own artifact detection function
%
% A trial that contains an artifact can be rejected completely or partially. In case
% of partial rejection, a minimum length of the resulting sub-trials can be
% specified using minaccepttim.
%
% Output:
%   If cfg is used as the only input parameter, the output is a cfg structure with an updated trl.
%   If cfg and data are both input parameters, the output is an updated raw data structure with only the clean data segments.
%
% To facilitate data-handling and distributed computing you can use
%   cfg.inputfile   =  ...
% If you specify this option the input data will be read from a *.mat
% file on disk. This mat files should contain only a single variable named 'data',
% corresponding to the input structure.
%
% See also FT_ARTIFACT_EOG, FT_ARTIFACT_MUSCLE, FT_ARTIFACT_JUMP, FT_ARTIFACT_THRESHOLD,
% FT_ARTIFACT_CLIP, FT_ARTIFACT_ECG, FT_DATABROWSER, FT_REJECTVISUAL

% Undocumented local options:
% cfg.headerfile
% cfg.reject
% cfg.trl
% cfg.trlold
% cfg.version
%
% These old configuration options are still supported
% cfg.rejectmuscle      = 'no' or 'yes'
% cfg.rejecteog         = 'no' or 'yes'
% cfg.rejectjump        = 'no' or 'yes'
% cfg.rejectfile        = string with filename
% cfg.artfctdef.writerej = filename of rejection file
% cfg.artfctdef.type    = cell-array with strings, e.g. {'eog', 'muscle' 'jump'}

% Copyright (C) 2003-2018, Robert Oostenveld
%
% 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$

% FIXME this function contains a lot of lines of code that pertain to backward
% compatibility support that dates back to 2004/2005. It would be good to strip
% that code and only keep the relevant parts

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble loadvar data
ft_preamble provenance data
ft_preamble trackconfig

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% ft_checkdata is done further down

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'dataset2files', 'yes');

% set the defaults
cfg.artfctdef              = ft_getopt(cfg, 'artfctdef');
cfg.artfctdef.type         = ft_getopt(cfg.artfctdef, 'type', {});
cfg.artfctdef.reject       = ft_getopt(cfg.artfctdef, 'reject', 'complete');
cfg.artfctdef.minaccepttim = ft_getopt(cfg.artfctdef, 'minaccepttim', 0.1);
cfg.artfctdef.crittoilim   = ft_getopt(cfg.artfctdef, 'crittoilim', []);
cfg.artfctdef.feedback     = ft_getopt(cfg.artfctdef, 'feedback', 'no');
cfg.artfctdef.invert       = ft_getopt(cfg.artfctdef, 'invert', 'no');
cfg.artfctdef.value        = ft_getopt(cfg.artfctdef, 'value', nan);

% convert from old-style to new-style configuration
if isfield(cfg,'reject')
  ft_warning('converting from old-style artifact configuration to new-style');
  cfg.artfctdef.reject = cfg.reject;
  cfg = rmfield(cfg, 'reject');
end

% convert from old-style to new-style configuration
if isfield(cfg.artfctdef,'common')
  ft_warning('converting from old-style artifact configuration to new-style');
  if isfield(cfg.artfctdef.common,'minaccepttim')
    cfg.artfctdef.minaccepttim = cfg.artfctdef.common.minaccepttim;
    cfg.artfctdef = rmfield(cfg.artfctdef, 'common');
  end
end

% ensure that it is a cell-array
if ischar(cfg.artfctdef.type)
  cfg.artfctdef.type = {cfg.artfctdef.type};
end

% support the rejectXXX cfg settings for backward compatibility
if isfield(cfg, 'rejectmuscle')
  dum = find(strcmp('muscle', cfg.artfctdef.type));
  if strcmp(cfg.rejectmuscle,'yes') && isempty(dum)
    % this overrules the other setting, add it to the type-list
    cfg.artfctdef.type = cat(1, {'muscle'}, cfg.artfctdef.type(:));
  elseif strcmp(cfg.rejectmuscle,'no') && ~isempty(dum)
    % this overrules the other setting, remove it from the type-list
    cfg.artfctdef.type(dum) = [];
  end
  cfg = rmfield(cfg, 'rejectmuscle');
end

% support the rejectXXX cfg settings for backward compatibility
if isfield(cfg, 'rejecteog')
  dum = find(strcmp('eog', cfg.artfctdef.type));
  if strcmp(cfg.rejecteog,'yes') && isempty(dum)
    % this overrules the other setting, add it to the type-list
    cfg.artfctdef.type = cat(1, {'eog'}, cfg.artfctdef.type(:));
  elseif strcmp(cfg.rejecteog,'no') && ~isempty(dum)
    % this overrules the other setting, remove it from the type-list
    cfg.artfctdef.type(dum) = [];
  end
  cfg = rmfield(cfg, 'rejecteog');
end

% support the rejectXXX cfg settings for backward compatibility
if isfield(cfg, 'rejectjump')
  dum = find(strcmp('jump', cfg.artfctdef.type));
  if strcmp(cfg.rejectjump,'yes') && isempty(dum)
    % this overrules the other setting, add it to the type-list
    cfg.artfctdef.type = cat(1, {'jump'}, cfg.artfctdef.type(:));
  elseif strcmp(cfg.rejectjump,'no') && ~isempty(dum)
    % this overrules the other setting, remove it from the type-list
    cfg.artfctdef.type(dum) = [];
  end
  cfg = rmfield(cfg, 'rejectjump');
end

% support the rejectXXX cfg settings for backward compatibility
if isfield(cfg, 'rejectfile')
  % this is slightly different to the ones above, since rejectfile is either 'no' or contains the filename
  dum = find(strcmp('file', cfg.artfctdef.type));
  if ~strcmp(cfg.rejectfile,'no') && isempty(dum)
    % this overrules the other setting, add it to the type-list
    cfg.artfctdef.type = cat(1, {'file'}, cfg.artfctdef.type(:));
  elseif strcmp(cfg.rejectfile,'no') && ~isempty(dum)
    % this overrules the other setting, remove it from the type-list
    cfg.artfctdef.type(dum) = [];
  end
end

% the data can be specified as input variable or through cfg.inputfile
hasdata = exist('data', 'var');

if hasdata
  % check if the input data is valid for this function
  data = ft_checkdata(data, 'hassampleinfo', 'yes');

  if isfield(data, 'sampleinfo')
    trl = zeros(numel(data.trial), 3);
    trl(:,[1 2]) = data.sampleinfo;

    % recreate offset vector (artifact functions depend on this)
    % TODO: the artifact rejection stuff should be rewritten to avoid
    % needing this workaround
    for ntrl = 1:numel(data.trial)
      trl(ntrl,3) = time2offset(data.time{ntrl}, data.fsample);
    end

    if isfield(data, 'trialinfo')
      if istable(data.trialinfo)
        % convert table into normal array, keep the column labels
        VariableNames = data.trialinfo.Properties.VariableNames;
        data.trialinfo = table2array(data.trialinfo);
      end
      trl = [trl data.trialinfo];
    end
  else
    trl = [];
  end

elseif isfield(cfg, 'trl')
  trl = cfg.trl;
end

% ensure the crittoilim input argument is valid
if ~isempty(cfg.artfctdef.crittoilim)

  if (size(cfg.artfctdef.crittoilim,2) ~= 2 ...
      || (size(cfg.artfctdef.crittoilim,1) ~= size(trl,1) ...
      && size(cfg.artfctdef.crittoilim,1) ~= 1))
    ft_error('if specified, cfg.artfctdef.crittoilim should be a 1x2 or Nx2 vector');
  end

  % if specified as 1x2 vector, expand into Nx2
  if (size(cfg.artfctdef.crittoilim,1) == 1)
    cfg.artfctdef.crittoilim = repmat(cfg.artfctdef.crittoilim,size(trl,1),1);
  end

  checkCritToi = 1; % flag for convenience
else
  checkCritToi = 0;
end

% ensure that there are trials that can be scanned for artifacts and/or rejected
if isempty(trl)
  ft_error('no trials were selected, cannot perform artifact detection/rejection');
end

% prevent double occurences of artifact types, ensure that the order remains the same
[dum, i] = unique(cfg.artfctdef.type);
cfg.artfctdef.type = cfg.artfctdef.type(sort(i));
% ensure that it is a row vector
cfg.artfctdef.type = cfg.artfctdef.type(:)';

% If bad parts are to be filled with nans, make sure data is available
if ~hasdata && (strcmp(cfg.artfctdef.reject, 'nan') || strcmp(cfg.artfctdef.reject, 'value'))
  ft_error('If bad parts are to be filled with nans or another value, the input data has to be specified');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% call the appropriate function for each of the artifact types
% this will produce a Nx2 matrix with the begin and end sample of artifacts
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for type=1:length(cfg.artfctdef.type)
  funhandle = ft_getuserfun(cfg.artfctdef.type{type}, 'artifact');
  fprintf('evaluating %s\n', func2str(funhandle));
  % each call to artifact_xxx adds cfg.artfctdef.xxx.artifact
  if hasdata
    cfg = feval(funhandle, cfg, data);
  else
    cfg = feval(funhandle, cfg);
  end
end

% collect the artifacts that have been detected from cfg.artfctdef.xxx.artifact
dum = fieldnames(cfg.artfctdef);
sel = false(size(dum));
artifact = {};
for i=1:length(dum)
  sel(i) = issubfield(cfg.artfctdef, dum{i}) && issubfield(cfg.artfctdef, [dum{i} '.artifact']);
  if sel(i)
    artifact{end+1} = getsubfield(cfg.artfctdef, [dum{i} '.artifact']);
    num = size(artifact{end}, 1);
    if isempty(num)
      num = 0;
    end
    fprintf('detected %3d %s artifacts\n', num, dum{i});
  end
end

% update the configuration to reflect the artifacts types that were scanned
cfg.artfctdef.type = dum(sel);

% combine all trials into a single boolean vector
trialall = convert_event(trl(:,1:2), 'boolvec');

% combine all artifacts into a single vector
rejectall = zeros(1, max(trl(:,2)));
for i=1:length(cfg.artfctdef.type)
  dum = artifact{i};
  for j=1:size(dum,1)
    rejectall(dum(j,1):dum(j,2)) = i;  % the artifact type is coded here
  end
end

% ensure that both vectors are the same length
if length(trialall)>length(rejectall)
  rejectall(length(trialall)) = 0;
elseif length(trialall)<length(rejectall)
  trialall(length(rejectall)) = 0;
end

% make header, needed only for sampling frequency
if hasdata
  hdr = ft_fetch_header(data);
else
  if isfield(cfg, 'headerformat')
    hdr = ft_read_header(cfg.headerfile, 'headerformat', cfg.headerformat);
  else
    hdr = ft_read_header(cfg.headerfile);
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% give visual feedback on the trial definition and the artifacts
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if strcmp(cfg.artfctdef.feedback, 'yes')
  COLOR = 'grcmykgrcmykgrcmykgrcmyk';
  % use the trial definition present in the local configuration
  trl  = trl;
  % compute the time axis that corresponds with each trial
  time = {};
  for i=1:size(trl,1)
    time{i} = offset2time(trl(i,3), hdr.Fs, trl(i,2)-trl(i,1)+1);
  end

  figure
  title('linear display of the continuous data')
  xlabel('sample number');
  hold on
  x = 1:length(trialall);
  y = ones(size(trialall)) * 0.53;
  y(~trialall) = nan;
  plot(x, y, 'b');
  for i=1:length(cfg.artfctdef.type)
    x = 1:length(rejectall);
    y = ones(size(rejectall)) * (0.5 - i*0.03);
    y(~(rejectall==i)) = nan;
    plot(x, y, COLOR(i));
  end
  set(gca, 'ytick', []);
  dum = (trialall~=0) | (rejectall~=0);
  [dum2, dum] = find(dum);
  smpbeg = dum(1)   - hdr.Fs;
  smpend = dum(end) + hdr.Fs;
  axis([smpbeg smpend 0 1]);
  legend({'defined trials', cfg.artfctdef.type{:}});

  figure
  title('individual trials after alignment')
  xlabel('time (s)');
  ylabel('trial number');
  hold on
  for i=1:size(trl,1)
    x = [time{i}(1) time{i}(end)];
    y = [i i];
    plot(x, y, 'b')
    for j=1:length(cfg.artfctdef.type)
      x = time{i};
      y = rejectall(trl(i,1):trl(i,2));
      y(y~=j) = nan;
      y(y==j) = i + j*0.03;
      plot(x, y, COLOR(j));
    end
    timebeg(i) = time{i}(1);
    timeend(i) = time{i}(end);
  end
  axis([min(timebeg)-0.1 max(timeend)+0.1 0.5 size(trl,1)+0.5]);
  axis ij
  legend({'defined trials', cfg.artfctdef.type{:}});
end % feedback

% convert to logical, this is required for the subsequent code
rejectall = (rejectall~=0);

% invert the artifact selection
if istrue(cfg.artfctdef.invert)
  fprintf('inverting selection of clean/artifactual data\n');
  rejectall = ~rejectall;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% write the rejection to an EEP format file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if isfield(cfg.artfctdef, 'writerej') && ~isempty(cfg.artfctdef.writerej)
  fid = fopen(cfg.artfctdef.writerej, 'w');
  if fid<0
    ft_error('could not open rejection file for writing');
  else
    % determine the begin and end of each rejected period (in samples)
    rejectonset = find(diff([0 rejectall])== 1);
    rejectofset = find(diff([rejectall 0])==-1);
    % determine the begin and end of each rejected period (in seconds)
    rejectonset = (rejectonset-1)/hdr.Fs;
    rejectofset = (rejectofset-1)/hdr.Fs;
    for rejlop=1:length(rejectonset)
      fprintf(fid, '%f-%f\n', rejectonset(rejlop), rejectofset(rejlop));
    end
    fclose(fid);
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% remove the trials that (partially) coincide with a rejection mark
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if any(strcmp(cfg.artfctdef.reject, {'partial', 'complete', 'nan', 'value'}))
  trialok = [];

  count_complete_reject = 0;
  count_partial_reject  = 0;
  count_nan             = 0;
  count_value           = 0;
  count_outsidecrit     = 0;

  trlCompletelyRemovedInd = [];
  trlPartiallyRemovedInd  = [];

  for trial=1:size(trl,1)
    % cut out the part of the rejection-axis corresponding with this trial
    rejecttrial = rejectall(trl(trial,1):trl(trial,2));

    if all(not(rejecttrial))
      % the whole trial is good
      trialok = [trialok; trl(trial,:)];

    elseif all(rejecttrial) && strcmp(cfg.artfctdef.reject, 'nan')
      % the whole trial is bad, but it is requested to be replaced with nans
      data.trial{trial}(:,rejecttrial) = nan;
      count_nan = count_nan + 1;
      trialok = [trialok; trl(trial,:)]; % Mark the trial as good as nothing will be removed

    elseif all(rejecttrial) && strcmp(cfg.artfctdef.reject, 'value')
      % the whole trial is bad, but it is requested to be replaced with a specific value
      data.trial{trial}(:,rejecttrial) = cfg.artfctdef.value;
      count_value = count_value + 1;
      trialok = [trialok; trl(trial,:)]; % Mark the trial as good as nothing will be removed

    elseif all(rejecttrial)
      % the whole trial is bad
      count_complete_reject = count_complete_reject + 1;
      trlCompletelyRemovedInd = [trlCompletelyRemovedInd trial];

    elseif any(rejecttrial) && strcmp(cfg.artfctdef.reject, 'complete')
      % some part of the trial is bad, check if within crittoilim?
      if (checkCritToi)
        critInd = (data.time{trial} >= cfg.artfctdef.crittoilim(trial,1) ...
          & data.time{trial} <= cfg.artfctdef.crittoilim(trial,2));
        if (any(critInd & rejecttrial))
          count_complete_reject = count_complete_reject + 1;
          trlCompletelyRemovedInd = [trlCompletelyRemovedInd trial];
          continue;
        else
          trialok = [trialok; trl(trial,:)];
          count_outsidecrit = count_outsidecrit + 1;
        end
      else % no crittoilim checking required
        count_complete_reject = count_complete_reject + 1;
        trlCompletelyRemovedInd = [trlCompletelyRemovedInd trial];
        continue;
      end

    elseif any(rejecttrial) && strcmp(cfg.artfctdef.reject, 'partial')
      % some part of the trial is bad, reject only the bad part
      trialnew = [];
      rejecttrial = [0 not(rejecttrial) 0];
      % the first column is the begin sample, the second the end sample and the third is the offset
      trialnew(:,1) = find(diff(rejecttrial(:))== 1) + trl(trial,1) - 1;
      trialnew(:,2) = find(diff(rejecttrial(:))==-1) + trl(trial,1) - 2;
      trialnew(:,3) = find(diff(rejecttrial(:))== 1) - 1 + trl(trial,3);
      % some people use additional columns in the trl matrix to store trigger values and/or reaction times
      % these should remain linked to the original trial, i.e. they should be copied for each new fragment
      for i=4:size(trl,2)
        trialnew(:,i) = trl(trial,i);
      end
      minacceptnumsmp = round(cfg.artfctdef.minaccepttim .* hdr.Fs);
      trialnew((trialnew(:,2)-trialnew(:,1))<minacceptnumsmp,:) = [];
      count_partial_reject = count_partial_reject + 1;
      trialok = [trialok; trialnew];
      trlPartiallyRemovedInd = [trlPartiallyRemovedInd trial];

    elseif any(rejecttrial) && strcmp(cfg.artfctdef.reject, 'nan')
      % Some part of the trial is bad, replace bad part with nans
      data.trial{trial}(:,rejecttrial) = nan;
      count_nan = count_nan + 1;
      trialok = [trialok; trl(trial,:)]; % Mark the trial as good as nothing will be removed

    elseif any(rejecttrial) && strcmp(cfg.artfctdef.reject, 'value')
      % Some part of the trial is bad, replace bad part with specified value
      data.trial{trial}(:,rejecttrial) = cfg.artfctdef.value;
      count_value = count_value + 1;
      trialok = [trialok; trl(trial,:)]; % Mark the trial as good as nothing will be removed

    end
  end % for each trial

  fprintf('rejected  %3d trials completely\n', count_complete_reject);
  fprintf('rejected  %3d trials partially\n', count_partial_reject);
  fprintf('filled parts of  %3d trials with nans\n', count_nan);
  fprintf('filled parts of  %3d trials with the specified value\n', count_value);
  if (checkCritToi)
    fprintf('retained  %3d trials with artifacts outside critical window\n', count_outsidecrit);
  end
  fprintf('resulting %3d trials\n', size(trialok,1));
  cfg.trlold = trl;      % return the original trial definition in the configuration
  cfg.trl    = trialok;  % return the cleaned trial definition in the configuration

  if strcmp(cfg.artfctdef.feedback, 'yes')
    fprintf('the following trials were completely removed: ');
    for k = trlCompletelyRemovedInd
      fprintf('%d ', k);
    end
    fprintf('\nthe following trials were partially removed: ');
    for k = trlPartiallyRemovedInd
      fprintf('%d ', k);
    end
    fprintf('\n');
  end

else
  fprintf('not rejecting any data, only marking the artifacts\n');
end

if isempty(cfg.trl)
  ft_error('No trials left after artifact rejection.')
else
  if hasdata && ~strcmp(cfg.artfctdef.reject, 'nan') % Skip this step to avoid removing parts that should be filled with nans
    % apply the updated trial definition on the data
    tmpcfg      = keepfields(cfg, {'trl', 'showcallinfo'});
    data        = removefields(data, {'trialinfo'});
    data        = ft_redefinetrial(tmpcfg, data);
    % restore the provenance information
    [cfg, data] = rollback_provenance(cfg, data);
  end
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble trackconfig
ft_postamble provenance
if hasdata
  ft_postamble previous data
  ft_postamble history data
  ft_postamble savevar data
  % return the data, the output variable is called cfg instead of data
  cfg = data;
end


function chrpak_test016 ( )

%*****************************************************************************80
%
%% TEST016 tests CH_LOW.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 June 2007
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST016\n' );
  fprintf ( 1, '  CH_LOW lowercases a character.\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  C  CH_LOW(C)\n' );
  fprintf ( 1, '\n' );

  c = 'F';
  fprintf ( 1, '  %c      %c\n', c, ch_low ( c ) );
  c = 'f';
  fprintf ( 1, '  %c      %c\n', c, ch_low ( c ) );
  c = '1';
  fprintf ( 1, '  %c      %c\n', c, ch_low ( c ) );
  c = 'b';
  fprintf ( 1, '  %c      %c\n', c, ch_low ( c ) );
  c = '&';
  fprintf ( 1, '  %c      %c\n', c, ch_low ( c ) );

  return
end


classdef (Abstract) mme_load < mp.mm_element

%   MATPOWER
%   Copyright (c) 2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

%     properties
%     end

    methods
        function name = name(obj)
            name = 'load';
        end
    end     %% methods
end         %% classdef


function [uids, patient_ids] = MimImageImporter(filename_or_root_directory, database, reporting)
    % MimImageImporter. Recrusively imports image files into a MimImageDatabase object
    %
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    reporting.ShowProgress('Importing data');
    tags_to_get = DMDicomDictionary.GroupingDictionary;

    [import_folder, filename_only] = CoreDiskUtilities.GetFullFileParts(filename_or_root_directory);

    % Find out file type. 0=does not exist; 2=file; 7=directory
    exist_result = exist(filename_or_root_directory, 'file');

    if exist_result == 7
        % For a directory, we import every file
        [uids, patient_ids] = ImportDirectoryRecursive(database, import_folder, tags_to_get, reporting);

    elseif exist_result == 2
        % For a single file, we check if it is Dicom.
        single_image_metainfo = MimGetSingleImageInfo(import_folder, filename_only, [], tags_to_get, reporting);
        if single_image_metainfo.ImageFileFormat == MimImageFileFormat.Dicom
            % For a Dicom file we import the whole folder
            [uids, patient_ids] = ImportDirectoryRecursive(database, import_folder, tags_to_get, reporting);
        else
            % For a non-Dicom file we import only the primary file
            database.AddImage(single_image_metainfo);
            uids = {single_image_metainfo.SeriesUid};
            patient_ids = {single_image_metainfo.PatientId};
        end

    else
        reporting.Error('MimImageImporter:FileDoesNotExist', ['The file or directory ' filename_or_root_directory ' does not exist.']);
    end

    reporting.CompleteProgress;
end

function [uids, patient_ids] = ImportDirectoryRecursive(database, import_folder, tags_to_get, reporting)
    uids = [];
    patient_ids = [];
    directories_to_do = CoreStack(import_folder);

    while ~directories_to_do.IsEmpty
        current_dir = directories_to_do.Pop;

        reporting.UpdateProgressMessage(['Importing data from: ' current_dir]);

        if reporting.HasBeenCancelled
            reporting.Error(CoreReporting.CancelErrorId, 'User cancelled');
        end

        [new_uids, new_patient_ids] = ImportFilesInDirectory(database, current_dir, tags_to_get, reporting);
        uids = [uids, new_uids];
        patient_ids = [patient_ids, new_patient_ids];
        next_dirs = CoreDiskUtilities.GetListOfDirectories(current_dir);
        for dir_to_add = next_dirs
            new_dir = fullfile(current_dir, dir_to_add{1});
            directories_to_do.Push(new_dir);
        end
    end
    uids = unique(uids);
end

function [uids, patient_ids] = ImportFilesInDirectory(database, directory, tags_to_get, reporting)
    uids = [];
    patient_ids = [];
    all_filenames = CoreTextUtilities.SortFilenames(CoreDiskUtilities.GetDirectoryFileList(directory, '*'));
    for filename = all_filenames
        if ~strcmp(filename{1}, 'DICOMDIR')
            try
                single_image_metainfo = MimGetSingleImageInfo(directory, filename{1}, [], tags_to_get, reporting);
                if ~isempty(single_image_metainfo.ImageFileFormat)
                    database.AddImage(single_image_metainfo);
                    new_uid = single_image_metainfo.SeriesUid;
                    new_patient_id = single_image_metainfo.PatientId;
                    if ~ismember(new_uid, uids)
                        uids{end + 1} = new_uid;
                    end
                    if ~ismember(new_patient_id, patient_ids)
                        patient_ids{end + 1} = new_patient_id;
                    end
                end
            catch ex
                reporting.ShowWarning('MimImageImporter:ImportFileFailed', ['Failed to import file ' filename{1} ' due to error: ' ex.message]);
            end
        end
    end
end


function [abaqusData]=importAbaqusDat(varargin)

% function [abaqusData]=importAbaqusDat(fileName,optionStruct)
%-------------------------------------------------------------------------
%
% Form:
%         NODE FOOT-  COOR1          COOR2          COOR3
%         NOTE
%
%         1     -5.0000000E+00 -5.0000000E+00 -5.0000000E+00
%         2     -5.0000000E+00 -1.1555553E+00 -5.0000000E+00
%         ....
%         n     -5.0000000E+00 -1.1555553E+00 -5.0000000E+00
%
%         MAXIMUM          6.533       6.533       2.000
%         AT NODE                13          20          49
%
%         MINIMUM         -5.000      -5.000      -5.000
%         AT NODE                 1           1           111

% Form:
%         ELEMENT  PT FOOT-       E11         E22         E33         E12         E13         E23
%         NOTE
%
%         1   1         0.1427      0.1427     -0.3566      3.0358E-18  1.9120E-17  1.7250E-18
%         1   2         0.1427      0.1427     -0.3566      2.0817E-17  3.9274E-17 -2.5351E-17
%         ....
%         n   8         0.1427      0.1427     -0.3566      6.5052E-17  3.6108E-17 -4.4747E-17
%
%         MAXIMUM                0.1427      0.1427     -0.3566      9.8446E-17  2.0358E-16  2.1077E-16
%         ELEMENT                     6           1           3          24           7          15
%
%         MINIMUM                0.1427      0.1427     -0.3566     -8.8471E-17 -1.6717E-16 -1.7420E-16
%         ELEMENT                     8           3          10           2          12          11
%
%-------------------------------------------------------------------------

%% Parse input

switch nargin
    case 1
        fileName=varargin{1};
        optionStruct=[];
    case 2
        fileName=varargin{1};
        optionStruct=varargin{2};
end

defaultOptionStruct.nodeData.dataTypeStr='N O D E   O U T P U T';
defaultOptionStruct.nodeData.startTarget='    NODE FOOT-';
defaultOptionStruct.elementData.dataTypeStr='E L E M E N T   O U T P U T';
defaultOptionStruct.elementData.startTarget='    ELEMENT  PT';
defaultOptionStruct.stopTarget=' MAXIMUM';
defaultOptionStruct.getElementData=1;
defaultOptionStruct.getNodeData=1;

[optionStruct]=structComplete(optionStruct,defaultOptionStruct,1); %Complement provided with default if missing or empty

%%

T=txtfile2cell(fileName);

for qStep=1:1:1

    incrementLines = find(~cellfun(@isempty,regexp(T,'INCREMENT.*SUMMARY')));
    incrementLines(end+1)=numel(T);

    for qIncrement=1:1:numel(incrementLines)-1

        %Get increment data
        s=T{incrementLines(qIncrement)};
        %Scans this type of line: '                                INCREMENT     1 SUMMARY'
        abaqusData.STEP(qStep).INCREMENT(qIncrement).id=str2double(cell2mat(regexp(s,'\d+\.?\d*|-\d+\.?\d*|\.?\d+|-\.?\d+','match')));

        %Scans this type of line: ' TIME INCREMENT COMPLETED  5.000E-02,  FRACTION OF STEP COMPLETED  5.000E-02'
        s=T{incrementLines(qIncrement)+3};
        d=cellfun(@str2double,regexp(s,'([\+-]?((\d*\.\d+)|\d+))(E[\+-]?\d+)?','match'));
        abaqusData.STEP(qStep).INCREMENT(qIncrement).TIME_INCREMENT_COMPLETED=d(1);
        abaqusData.STEP(qStep).INCREMENT(qIncrement).FRACTION_OF_STEP_COMPLETED=d(2);

        %Scans this type of line: '  STEP TIME COMPLETED       5.000E-02,  TOTAL TIME COMPLETED        5.000E-02'
        s=T{incrementLines(qIncrement)+4};
        d=cellfun(@str2double,regexp(s,'([\+-]?((\d*\.\d+)|\d+))(E[\+-]?\d+)?','match'));
        abaqusData.STEP(qStep).INCREMENT(qIncrement).STEP_TIME_COMPLETED=d(1);
        abaqusData.STEP(qStep).INCREMENT(qIncrement).TOTAL_TIME_COMPLETED=d(2);

        %Get current data containing part
        T_sub=T(incrementLines(qIncrement):incrementLines(qIncrement+1)-1);

        %Get data
        stopTarget=optionStruct.stopTarget;
        if optionStruct.getNodeData==1 %Get node data
            dataTypeStr=optionStruct.nodeData.dataTypeStr;
            startTarget=optionStruct.nodeData.startTarget;
            try
                abaqusData.STEP(qStep).INCREMENT(qIncrement).nodeOutput=getDataField(T_sub,dataTypeStr,startTarget,stopTarget);
            catch
                abaqusData.STEP(qStep).INCREMENT(qIncrement).nodeOutput=NaN;
            end
        end
        if optionStruct.getElementData==1 %Get element data
            dataTypeStr=optionStruct.elementData.dataTypeStr;
            startTarget=optionStruct.elementData.startTarget;
            try
                abaqusData.STEP(qStep).INCREMENT(qIncrement).elementOutput=getDataField(T_sub,dataTypeStr,startTarget,stopTarget);
            catch
                abaqusData.STEP(qStep).INCREMENT(qIncrement).elementOutput=NaN;
            end
        end
    end
end
end

%%

function S=getDataField(T_sub,dataTypeStr,startTarget,stopTarget)

dataOutput = any(~cellfun(@isempty,regexp(T_sub,dataTypeStr)));
if dataOutput==1 %Element data found
    dataOutputStartLines = find(~cellfun(@isempty,regexp(T_sub,startTarget))); %Start lines
    dataOutputEndLines = find(~cellfun(@isempty,regexp(T_sub,stopTarget)))-2; %End lines
    dataOutputEndLines=dataOutputEndLines(dataOutputEndLines>dataOutputStartLines(1));
    ignoreSet={'FOOT-'};
    for q_dataOutput=1:1:numel(dataOutputStartLines)
        s=T_sub{dataOutputStartLines(q_dataOutput)}; %Header line
        s = regexprep(s,'\s+',' '); %Remove excessive spaces
        s=s(2:end-1); %Remove initial and final space
        headerSet=strsplit(s,' '); %Header set in cell
        %         numHeadersAll=numel(headerSet);
        logicRemove=gcontains(headerSet,ignoreSet);
        headerSet=headerSet(~logicRemove);
        numHeadersKeep=numel(headerSet);
        s=T_sub(dataOutputStartLines(q_dataOutput)+3:dataOutputEndLines(q_dataOutput)); %Data text field
        try
            D=cell2mat(cellfun(@(x) sscanf(x,'%f')',s,'uniformOutput',0)); %Data array
        catch %Alternative which ignores character components
            D=cell2mat(cellfun(@str2double,regexp(s,'([\+-]?((\d*\.\d+)|\d+))(E[\+-]?\d+)?','match'),'UniformOutput',0)); %Data array
        end

        %Create output structure with subfields names after headers
        for q=1:1:numHeadersKeep
            fieldNameNow=headerSet{q} ;
            S(q_dataOutput).data.(fieldNameNow)=D(:,q);
        end

    end
end
end

%%
% _*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 test_bug629

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_read_header ft_read_data ft_read_event read_mff_header read_mff_data

% note that read_mff_event does not exist, handling of the events is coded in ft_read_event

datadir = dccnpath('/home/common/matlab/fieldtrip/data/test/bug629');

cd(datadir);
dataset = 'pilot05_test 20110120 1433.mff';

hdr   = ft_read_header(dataset, 'headerformat', 'egi_mff_v1');
event = ft_read_event(dataset, 'eventformat', 'egi_mff_v1');