function varargout = GUI_final(varargin)
% Graphical user interface for TDMS data processing.
% Author: Anton Ļuri 
% GUI_FINAL MATLAB code for GUI_final.fig
% Needs a TDMS Reader from Mathworks File Exchange: 
% https://www.mathworks.com/matlabcentral/fileexchange/30023-tdms-reader
%% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @GUI_final_OpeningFcn, ...
                   'gui_OutputFcn',  @GUI_final_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 GUI_final is made visible.
function GUI_final_OpeningFcn(hObject, eventdata, handles, varargin)
%%initial variables
handles.dataset_path = [];
handles.my_tdms_struct = 0;
handles.file_index = [];
%Choose default command line output for GUI_final
handles.output = hObject;
%names in pop-up window for data menu
menu_list = char('Trim data','Save more selections','Graph position t=0','Windowing and zero padding','FFT','Delete dataset');
set(handles.single_data_menu, 'String', menu_list); 
% Update handles structure
guidata(hObject, handles);
%%

%% --- Outputs from this function are returned to the command line.
function varargout = GUI_final_OutputFcn(hObject, eventdata, handles) 
varargout{1} = handles.output;
%%

% --- Executes on button press in browse_button.
function browse_button_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%%Remove data from previous selection
if isfield(handles,'single_data_trimmed')
    handles = rmfield(handles, 'single_data_trimmed');
end
if isfield(handles,'winpad_data_y_zeropad')
    handles = rmfield(handles, 'winpad_data_y_zeropad');
end
if isfield(handles,'trim_index')
    handles = rmfield(handles, 'trim_index');
end
if isfield(handles,'table_names_final')
    handles = rmfield(handles, 'table_names_final');
end
%
set(handles.file_listbox,'Value', 1);
set(handles.dataset_popup, 'Value', 1);
set(handles.channel_popup, 'Value', 1);
set(handles.fft_checkbox,'value',0);
set(handles.sample_rate,'value',0);
set(handles.align_max,'value',0);
set(handles.align_value,'value',0);
cla(handles.axes1,'reset');
%%
%quest dialog for single TDMS file or folder with more TDMS files
file_selection = questdlg('Select one from following','Menu','select file','select folder','select folder');

if strcmp(file_selection,'select file') == 1 %if one file is selected
    %TDMS file selection
    [filepath,filefolder]=uigetfile({'*.tdms';'*.tdm'},'Select a TDM or TDMS file');
    %used in folder selection for extracting file names and folder paths,
    %needs '1' for creating a struct fith data 
    subdirinfo = 1;
    %fileparts of selected TDMS 
    [filepath,name,ext] = fileparts(strcat(filefolder,filepath));
    %fiedlnames -- names of files in folder
    handles.fns = cellstr(genvarname(name));
    %struct with paths to files
    path_str.(genvarname(name)) = strcat(filepath,'\',name,ext);
else %if folder is selected
    %folder selection
    dir_path = uigetdir;
    %generate path to folder
    paths = genpath(dir_path);
    %split all paths separated with ';'
    path_names = split(paths,';');
    %make a struct of information about all files in folder
    for K = 1 : length(path_names)
        %for extracting file names and folder paths
        subdirinfo{K} = dir(fullfile(char(path_names(K)),'*.tdms'));
    end
    %remove empty struct with unnecessary data
    idx=cellfun(@isempty,subdirinfo);
    subdirinfo(idx)=[];
    %generate struct with paths to all files
    for i = 1 : length(subdirinfo{1,1})
        path_str.(genvarname((subdirinfo{1,1}(i).name(1:strfind(subdirinfo{1,1}(i).name,'.')-1))))=[];
    end
    
    for i = 1 : length (subdirinfo)
        for j = 1 : length(subdirinfo{1,1})
            %fiedlnames -- names of files in folder
            handles.fns = fieldnames(path_str);
            %struct with paths to all files
            path_str.(handles.fns{j}){i,1} = strcat(subdirinfo{1,i}(j).folder,'\',subdirinfo{1,i}(j).name);
        end
    end
end
%%
%make a organized struct with all files
for j = 1 : length(handles.fns)
    %creating struct with fields named by names of files in folder(measuremet types)
    tdms_data.(handles.fns{j})=[];
    %save to workspace 
        %assignin('base','tdms_data',tdms_data);
    %filling struct with data from all files
    for i = 1 : length(subdirinfo)
        cycle_paths = cellstr(path_str.(char(handles.fns(j))));
        %load data from TDMS file in this loop  
        cycle_data = TDMS_getStruct(char(cycle_paths{i}));
        %fieldname in struct from data description or datetime
        if isempty(cycle_data.Props.Description)
            name = genvarname(cycle_data.Props.DateTime);
        else
            name = strcat('data_',genvarname(cycle_data.Props.Description));
        end
        %filling cycle data to struct, with all channels
        tdms_data.(handles.fns{j}) = setfield(tdms_data.(char(handles.fns{j})),name,cycle_data);
    end
end
%%
%names of fields in (tdms_data.*),from tdms file description
%for saving FFT data next to right measurement type 
handles.tdms_data_fields = fieldnames(tdms_data.(handles.fns{1}));
%%
%find out time constant for all measurements    
for j = 1:length(handles.fns)
for i = 1:length(handles.tdms_data_fields)
    %finding log_dt or Samples_per_second in data props to create
    %handles.dt
    if isfield(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))).Props,'log_dt')
        handles.dt(i,j) = tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))).Props.log_dt;
    elseif isfield(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))).Props,'Samples_per_second')
        handles.dt(i,j) = 1 / eval(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))).Props.Samples_per_second);
    else %if there are no data in file props
        time_info = inputdlg({'Samples per second','Log duration[s]'},sprintf('Time addition for dataset %d', i),[1 50;1 50]);  
        if strcmp(time_info(1),'')
            f = fieldnames(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))));
            g = fieldnames(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields(i))).(char(f{2,1})));
            handles.dt(i,j) = eval(cell2mat(time_info(2))) / length(tdms_data.(handles.fns{j}).(char(handles.tdms_data_fields{i})).(char(f{2,1})).(char(g{3,1})).data);
        else
            %all time constants for all measurement, each time constant field correspond
            %to data field in handles.data
            handles.dt(i,j) = 1 / eval(cell2mat(time_info(1)));
        end    
    end
end
end
%%
%make a table of GUI data, without unnecesarry data, first channel just used
for k = 1 : length(handles.fns)
for i = 1 : length(handles.tdms_data_fields)
    %loop variables
    time_data = [];
    names = fieldnames(tdms_data.(handles.fns{k}).(handles.tdms_data_fields{i}));
    %path in tdms_data to file data
    data_path{i,k} = strcat('tdms_data','.',(handles.fns{k}),'.',(handles.tdms_data_fields{i}));
    %path in tdms_data to largest dataset 
    dataset_path = strcat('tdms_data','.',(handles.fns{k}),'.',(handles.tdms_data_fields{i}),'.',names(2));
    %channel fields in largest dataset
    channel_fields = fieldnames(eval(char(dataset_path)));
    %filling largest datasets to handles.data
    for n = 3 : length(channel_fields)
        time_data = [];
        data_ampl = [];
        data_ampl = eval(char(strcat(dataset_path,'.',channel_fields(n),'.data')));
            %making time vector
            for j = 1 : length(data_ampl)-1
                time_data(j)=handles.dt(i,k)*j;
            end
            time_data = [0,time_data];
        %    
        if length(channel_fields) > 3
            handles.data{i,k+n-3} = [time_data;data_ampl]';
        else
            handles.data{i,k} = [time_data;data_ampl]';
        end
    end
    handles.channel_fields{i,k} = channel_fields;
end
end
%%
%if dataset have more than 1 channel, data_path and handles.dt are expanded  
for n = 3 : length(channel_fields)-1
    data_path = [data_path data_path(:,end)];
    handles.dt = [handles.dt handles.dt(:,end)];
end
%%
%creating matrix of file names for table row and column names
for j = 1:length(handles.data(1,:))
    for i = 1:length(handles.data(:,1))
        handles.props{i,j} = eval(strcat(data_path{i,j},'.Props'));
        handles.table_fft_names{1,j} = strcat(genvarname(strcat('fft_',handles.props{1,j}.name)),'_',num2str(j));
        handles.table_names{1,j} = strcat(genvarname(handles.props{1,j}.name),'_',num2str(j));
    end
end
%option for saving data and props
    %assignin('base','data',handles.data);
    %assignin('base','props',handles.props);
%writing list of files into listbox
set(handles.file_listbox,'String', handles.fns);
%remove struct with all data
tdms_data = [];
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on selection change in file_listbox.
function file_listbox_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%%
%remove data from previous single selection
if isfield(handles,'single_data_trimmed')
    handles = rmfield(handles, 'single_data_trimmed');
end
if isfield(handles,'winpad_data_y_zeropad')
    handles = rmfield(handles, 'winpad_data_y_zeropad');
end
%initialization
cla(handles.axes1,'reset');
set(handles.dataset_popup, 'Value', 1);
set(handles.channel_popup, 'Value', 1);
%getting value of selected dataset
handles.file_value = get(handles.file_listbox,'Value');
channel_fields = handles.channel_fields{1,handles.file_value};
channel_fields = channel_fields(~ismember(channel_fields(:,1),'Props'),:);
handles.channel_fields_selected = channel_fields(~ismember(channel_fields(:,1),'name'),:);
%plotting data of selected dataset
if handles.file_value > length(handles.fns)-1
    [handles.file_index,~] = listdlg('PromptString','Select channel:','SelectionMode','single','ListString',handles.channel_fields_selected);
        if handles.file_index == 1
            if isfield(handles,'trim_index')
                for i = 1:length(handles.data(:,1))
                    plot(handles.final_data{i,handles.file_value}(:,1),handles.final_data{i,handles.file_value}(:,2))
                    hold on
                end
            else
                for l = 1 : length(handles.tdms_data_fields)  
                    plot(handles.data{l,handles.file_value}(:,1),handles.data{l,handles.file_value}(:,2))
                    hold on
                end
            end    
        else
            if isfield(handles,'trim_index')
                for i = 1:length(handles.data(:,1))
                    plot(handles.final_data{i,handles.file_value+1}(:,1),handles.final_data{i,handles.file_value+1}(:,2))
                    hold on
                end
            else            
                for l = 1 : length(handles.tdms_data_fields)  
                    plot(handles.data{l,handles.file_value+1}(:,1),handles.data{l,handles.file_value+1}(:,2))
                    hold on
                end    
            end
        end
else
    if isfield(handles,'trim_index')
        for i = 1:length(handles.data(:,1))
            plot(handles.final_data{i,handles.file_value}(:,1),handles.final_data{i,handles.file_value}(:,2))
            hold on
        end
    else
        for l = 1 : length(handles.tdms_data_fields)  
            plot(handles.data{l,handles.file_value}(:,1),handles.data{l,handles.file_value}(:,2))
            hold on
        end
    end
end
%labels 
xlabel('time[s]')
ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
%writing names of datasets to pop-up menu
set(handles.dataset_popup,'string',{char(handles.tdms_data_fields)});
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes during object creation, after setting all properties.
function file_listbox_CreateFcn(hObject, eventdata, ~)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
%%

% --- Executes on selection change in dataset_popup.
function dataset_popup_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%set channel popup to first value
set(handles.channel_popup, 'Value', 1);
%remove handles.single_data_trimmed
if isfield(handles,'single_data_trimmed')
    handles = rmfield(handles, 'single_data_trimmed');
end
%remove handles.winpad_data_y_zeropad
if isfield(handles,'winpad_data_y_zeropad')
    handles = rmfield(handles, 'winpad_data_y_zeropad');
end
%getting value of selected dataset
handles.dataset_value = get(handles.dataset_popup,'Value');
%writing channels of selected dataset to channel popup
set(handles.channel_popup,'string',{char(handles.channel_fields_selected)});
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes during object creation, after setting all properties.
function dataset_popup_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
%%

% --- Executes on selection change in channel_popup.
function channel_popup_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%remove handles.single_data_trimmed
if isfield(handles,'single_data_trimmed')
    handles = rmfield(handles, 'single_data_trimmed');
end
%remove handles.winpad_data_y_zeropad
if isfield(handles,'winpad_data_y_zeropad')
    handles = rmfield(handles, 'winpad_data_y_zeropad');
end
%getting value of selected channel
channel_value = get(handles.channel_popup,'Value');
%selected data
if channel_value == 1
    selected_data = [handles.data{handles.dataset_value,handles.file_value}(:,1),handles.data{handles.dataset_value,handles.file_value}(:,2)];
else
    selected_data = [handles.data{handles.dataset_value,handles.file_value+1}(:,1),handles.data{handles.dataset_value,handles.file_value+1}(:,2)];
end
%save data to workspace
    %assignin('base','selected_data',selected_data);
%plot selected data
cla(handles.axes1,'reset');
plot(selected_data(:,1),selected_data(:,2));
%add labels 
xlabel('time[s]')
ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes during object creation, after setting all properties.
function channel_popup_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
%%

% --- Executes on selection change in info.
function info_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%generate table with TDMS file metadata
names = fieldnames(handles.props{handles.dataset_value,handles.file_value});
values = struct2cell(handles.props{handles.dataset_value,handles.file_value});
output = [names,values];
f = uifigure;
t = uitable(f,'Position',[20 20 500 70],'data',output);
pos = get(f,'position');
t.Position = [0 0 pos(3) pos(4)];
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes during object creation, after setting all properties.
function info_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
%%

% --- Executes on selection change in single_data_menu.
function single_data_menu_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%getting selected menu value
menu_value = get(handles.single_data_menu,'Value');
%1 -- Trim data, 2 -- Save more selections, 3 -- Graph position t=0, 4 -- Windowing and zero padding,5 -- FFT, 6 -- Delete dataset
switch menu_value
    %% Trim data
    case 1 
            if isfield(handles,'winpad_data_y_zeropad')
                handles = rmfield(handles, 'winpad_data_y_zeropad');
            end
            if isfield(handles,'single_data_trimmed')
                handles = rmfield(handles, 'single_data_trimmed');
            end
            brush( handles.figure1, 'on' ); 
            % Start brushing mode and specify callback for when complete
            brushing = brush(handles.figure1);
            w = waitforbuttonpress;
            w = waitforbuttonpress;
            hLine = get(gca,'Children');            
            hBrushHandles = hLine.BrushHandles;
            trimmed_data = hBrushHandles.Children(1, 1).VertexData;
            handles.single_data_trimmed = [(trimmed_data(1,:))',(trimmed_data(2,:))'];
            assignin('base','data_trimmed',handles.single_data_trimmed);
            brush( handles.figure1, 'off' );
            %plot trimmed data
            cla(handles.axes1,'reset');
            plot(handles.single_data_trimmed(:,1),handles.single_data_trimmed(:,2));
            %add labels 
            xlabel('time[s]')
            ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
    %% Save more selections           
    case 2 
            w = 0;
            b = 0;
            while w == 0
                [xm,~] = ginput(1);
                hold on 
                line([xm xm],get(handles.axes1,'YLim'),'Color',[1 0 0]);
                b = b+1;
                ind(b)=xm;
                w = waitforbuttonpress;
            end
            %    
            for i = 1:length(ind)
                ix(i) = find(handles.data{handles.dataset_value,handles.file_value}>ind(i),1);
            end
            %
            b=0;
            for j = 1:2:length(ix)
                b = b+1;
                selected_data{b} = [handles.data{handles.dataset_value,handles.file_value}(ix(j):ix(j+1),1),handles.data{handles.dataset_value,handles.file_value}(ix(j):ix(j+1),2)];
            end
            assignin('base','selections',selected_data);
    %% Graph position t=0
    case 3 
            if isfield(handles,'single_data_trimmed')
                for i = 1 : length(handles.single_data_trimmed)-1
                    handles.single_data_trimmed(1,1) = 0;
                    handles.single_data_trimmed(i+1,1) = handles.dt(handles.dataset_value,handles.file_value)*i;
                end
                if isfield(handles,'winpad_data_y_zeropad')
                    handles = rmfield(handles, 'winpad_data_y_zeropad');
                end
                assignin('base','data_trimmed',handles.single_data_trimmed);
                cla(handles.axes1,'reset');
                plot(handles.single_data_trimmed(:,1),handles.single_data_trimmed(:,2));
                %add labels 
                xlabel('time[s]')
                ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
            else
                disp('Trim data first');
            end
    %% Windowing and zero padding        
    case 4 
            zeropad_length = inputdlg({'Length of zeros'},'Zero padding input',[1 50]);
            if isfield(handles,'single_data_trimmed')
                winpad_data = handles.single_data_trimmed;
            else
                winpad_data = handles.data{handles.dataset_value,handles.file_value};
            end
            winpad_data_x = winpad_data (:,1);
            winpad_data_y = winpad_data (:,2);
            winpad_data_y_window = winpad_data_y.*hanning(length(winpad_data));
            handles.winpad_data_y_zeropad = [winpad_data_y_window;zeros(str2double(zeropad_length),1)];
            if isfield(handles,'single_data_trimmed')
                handles = rmfield(handles, 'single_data_trimmed');
            end
            %assignin('base','data_win_ZP',handles.winpad_data_y_zeropad);
    %% FFT        
    case 5 
            fft_data = [];                
            if isfield(handles,'winpad_data_y_zeropad')
                fft_data = handles.winpad_data_y_zeropad;
                Y = fft(fft_data);
                if isfield(handles.props{handles.dataset_value,handles.file_value},'log_dt')
                    Fs = length(handles.data{handles.dataset_value,handles.file_value}) / handles.props{handles.dataset_value,handles.file_value}.log_duration;
                else isfield(handles.props{handles.dataset_value,handles.file_value},'Samples_per_second')
                    Fs = handles.props{handles.dataset_value,handles.file_value}.Samples_per_second;
                end                  
            else
                fft_data = handles.data{handles.dataset_value,handles.file_value};  
                Y = fft(fft_data(:,2));
                if isfield(handles.props{handles.dataset_value,handles.file_value},'log_dt')
                    Fs = length(fft_data) / handles.props{handles.dataset_value,handles.file_value}.log_duration;
                else isfield(handles.props{handles.dataset_value,handles.file_value},'Samples_per_second')
                    Fs = handles.props{handles.dataset_value,handles.file_value}.Samples_per_second;
                end        
            end                   
            L = length(Y);       
            P2 = abs(Y/Fs);
            P1 = P2(1:L/2+1);
            P1(2:end-1) = 2*P1(2:end-1);
            f = (0:L/2)*(Fs/L); 
            figure
            plot(f,P1) 
            title('Single-Sided Amplitude Spectrum of X(t)')
            xlabel('Fs (Hz)')
            ylabel('|P1(f)|')
    %% Delete dataset        
    case 6 
            %remove it from the list
            handles.tdms_data_fields(handles.dataset_value) = [];
            handles.data(handles.dataset_value,:)=[];
            %writing list of channels to listbox
            set(handles.dataset_popup,'string',{char(handles.tdms_data_fields)});
            %clean channel listbox
            set(handles.dataset_popup, 'Value', 1);
            set(handles.channel_popup, 'Value', 1);
end
%%
handles.output = hObject;
guidata(hObject, handles);
%%      

% --- Executes during object creation, after setting all properties.
function single_data_menu_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
%%

% --- Executes on button press in align_max.
function align_max_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%input dialog for align
line_max_min = inputdlg({'Points before max','Points after max'},'Align by max value',[1 50;1 50]);
%reset axis
cla(handles.axes1,'reset');
%align data and save them to handles.final_data
for j = 1:length(handles.data(1,:))
for i = 1:length(handles.data(:,1))
    time_data = [];
    %finding max index for each measurement
    if handles.file_index == 2
        [~,I]=(max(handles.data{i,handles.file_value+1}(:,2)));
    else
        [~,I]=(max(handles.data{i,handles.file_value}(:,2)));
    end
    %matrix of max value indexes for all data
    handles.trim_index{i,j} = I;
    amplitude = (handles.data{i,j}(:,2));
    %align handles.data by max value and trim them 
    amplitude = amplitude((handles.trim_index{i,j}-(str2double(line_max_min(1)))):handles.trim_index{i,j}+(str2double(line_max_min(2))));
    %making new time vector
    for k = 1 : length(amplitude)-1
        time_data(k)=handles.dt(i,j)*k;
    end
    time_data = [0,time_data];
    %save aligned data to handles.final_data
    handles.final_data{i,j} = [time_data',amplitude];
end
end
%plot aligned data
for i = 1:length(handles.data(:,1))
plot(handles.final_data{i,handles.file_value}(:,1),handles.final_data{i,handles.file_value}(:,2))
hold on
end
%add labels 
xlabel('time[s]')
ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on button press in align_value.
function align_value_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%input dialog for align by value
align_value = inputdlg({'Value','Points before','Points after'},'Align by value',[1 50;1 50;1 50]);
%reset axis
cla(handles.axes1,'reset');
%align data and save them to handles.final_data
for j = 1:length(handles.data(1,:))
for i = 1:length(handles.data(:,1))
    time_data = [];
    %finding index of selected value
    if handles.file_index == 2
       [~,I] = max((handles.data{i,handles.file_value+1}(:,2))>(str2double(align_value(1))), [], 1);
    else
       [~,I] = max((handles.data{i,handles.file_value}(:,2))>(str2double(align_value(1))), [], 1); 
    end
    %matrix of max value indexes for all data
    handles.trim_index{i,j} = I;
    amplitude = (handles.data{i,j}(:,2));
    %align handles.data by index and trim them 
    amplitude = amplitude((handles.trim_index{i,j}-(str2double(align_value(2)))):(handles.trim_index{i,j}+(str2double(align_value(3)))));
    %making new time vector
    for k = 1 : length(amplitude)-1
        time_data(k)=handles.dt(i,j)*k;
    end
    time_data = [0,time_data];
    %save aligned data to handles.final_data
    handles.final_data{i,j} = [time_data;amplitude']';
end
end
%plot aligned data
for i = 1:length(handles.data(:,1))
plot(handles.final_data{i,handles.file_value}(:,1),handles.final_data{i,handles.file_value}(:,2))
hold on
end
%add labels 
xlabel('time[s]')
ylabel(strcat(handles.props{1,handles.file_value}.name,' [',handles.props{1,handles.file_value}.unit_string,']'))
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on button press in fft_checkbox.
function fft_checkbox_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%%
%Check, if data are aligned or decimated. That functions create
%handles.final_data. If not, raw data (handles.data) are used.
if isfield(handles,'final_data')
else
    handles.final_data = handles.data;
end
%%
%Measuremet type selection for FFT
[fft_index,~] = listdlg('PromptString','Select from channels:','SelectionMode','multi','ListString',handles.fns);
%Max frequency selection
freq_value = inputdlg({'Max frequency:'},'max frequency',[1 50]);
%Create FFT for all measerements on selected data type
for j = fft_index:length(handles.final_data(1,:))
for i = 1:length(handles.final_data(:,1))
    %Y axis of selected measurement
    fft_data_ampl = (handles.final_data{i,j}(:,2));
    %FFT
    Y = fft(fft_data_ampl);
    %Finding correct sampling frequency 
    if isfield(handles.props{i,j},'log_dt')
        Fs = length(fft_data_ampl) / handles.props{i,j}.log_duration;
    else isfield(handles.props{i,j},'Samples_per_second')
        Fs = handles.props{i,j}.Samples_per_second;
    end
    %Make a single side FFT
    L = length(fft_data_ampl);       
    P2 = abs(Y/Fs);
    P1 = P2(1:round(L/2)+1);
    P1(2:end-1) = 2*P1(2:end-1);
    frequency = (0:L/2)*(Fs/length(handles.final_data{i}));
    %Trim FFT data by selected maximal value of frequency
    if str2double(freq_value) > 0
        ix = find(frequency>str2double(freq_value),1);
        fft_data{i,j}(:,1) = frequency(1:ix);
        fft_data{i,j}(:,2) = P1(1:ix);
    else
        fft_data{i,j}(:,1) = frequency;
        fft_data{i,j}(:,2) = P1;
    end
end
end
%%
%initial variables for writing fft to final table
handles.table_names_final = handles.table_names;
inc = 0;
%writing FFT data next to selected measurement types
for j = fft_index
    if j > length(handles.fns)-1
        for i = j:length(handles.data(1,:))
        handles.final_data = [handles.final_data(:,1:i+inc) fft_data(:,i) handles.final_data(:,i+inc+1:end)];
        handles.table_names_final = [handles.table_names_final(1:i+inc) handles.table_fft_names(i) handles.table_names_final(i+inc+1:end)];
        inc = inc+1;
        end
    else
        handles.final_data = [handles.final_data(:,1:j+inc) fft_data(:,j) handles.final_data(:,j+inc+1:end)];
        handles.table_names_final = [handles.table_names_final(1:j+inc) handles.table_fft_names(j) handles.table_names_final(j+inc+1:end)];
    end
    inc = inc+1;
end
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on button press in sample_rate.
function sample_rate_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%Check, if data are aligned or decimated. That functions create
%handles.final_data. If not, raw data (handles.data) are used.
if isfield(handles,'final_data')
else
    handles.final_data = handles.data;
end
%Selection of downsampling factor
downsampling_factor = inputdlg({'Downsampling factor:'},'Downsampling factor',[1 50]);
%Decimate all data
for j = 1:length(handles.final_data(1,:))
    for i = 1:length(handles.final_data(:,1))
        ampl = decimate(handles.final_data{i,j}(:,2),str2double(downsampling_factor),'fir');
        time = decimate(handles.final_data{i,j}(:,1),str2double(downsampling_factor),'fir');
        handles.final_data{i,j} = [time,ampl];
    end
end
%
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on button press in clear_selection.
function clear_selection_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%remove handles.final_data -- aligned, downsampled data and FFT data
if isfield(handles,'final_data')
    handles = rmfield(handles, 'final_data');
end
%remove handles.trim_index -- used in align functions
if isfield(handles,'trim_index')
    handles = rmfield(handles, 'trim_index');
end
%remove handles.table_names_final -- used in FFT function for right
%assignment of FFT data to measuremet type
if isfield(handles,'table_names_final')
    handles = rmfield(handles, 'table_names_final');
end
%remove ticks from checkbox
set(handles.fft_checkbox,'value',0);
set(handles.sample_rate,'value',0);
set(handles.align_max,'value',0);
set(handles.align_value,'value',0);
cla(handles.axes1,'reset');
handles.output = hObject;
guidata(hObject, handles);
%%

% --- Executes on button press in save.
function save_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
%Check, if handles.table_names_final/table names with FFT columns/ exist,
%if not, use raw table names
if isfield(handles,'table_names_final')
else
    handles.table_names_final = handles.table_names;
end
%Check, if data are aligned or decimated. That functions create
%handles.final_data. If not, raw data (handles.data) are used.
if isfield(handles,'final_data')
else
    handles.final_data = handles.data;
end
%save handles.final_data to workspace
tdms_table = array2table(handles.final_data,'RowNames',handles.tdms_data_fields,'VariableNames',handles.table_names_final);
assignin('base','tdms_table',tdms_table);
%
handles.output = hObject;
guidata(hObject, handles);
%%