function varargout = shear_gui(varargin)
% This program has been created by Jean-Nicolas Dumez and Corentin Jacquemmoz, 
% CEISAM, CNRS, Université de Nantes, France
% The authors are not responsible for the results obtained with this program
% This program can be used, modified and shared as long as the authors are
% credited and the program is share under the same conditions
% Please do not delete this header from the file.
%
% ktdata_sheared = shear_gui(ktdata)
% This function is used to shear data in kt space in case the acquisition
% gradient were not perfectly equals. It usually lead to shifting peaks.
% The shear GUI will allow to correct the shifting as long as it is LINEAR.
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Last Modified by GUIDE v2.5 07-Jul-2020 16:47:59

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @shear_gui_OpeningFcn, ...
                   'gui_OutputFcn',  @shear_gui_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 shear_gui is made visible.
function shear_gui_OpeningFcn(hObject, eventdata, handles, varargin)
%Get data
handles.data = varargin{1};

%Prepare the zoom slider
set(handles.zoomSlider,'max',size(handles.data,1));
set(handles.zoomSlider,'min',1);
handles.middlePos = round((size(handles.data,1)+1)/2);
handles.diffPos = 0;
set(handles.zoomSlider,'Value',handles.middlePos);
set(handles.zoomSlider,'SliderStep',[1/(size(handles.data,1)-1) 3/(size(handles.data,1)-1)]);


handles.dataph = handles.data;
handles.linshearmax = 0;
handles.c = pi/180;
axes(handles.axes1);
imagesc(abs(handles.data));
ax = gca;
set(ax,'Ydir','normal');
hold on
[~,kmax]=max(handles.data(:,1));
plot([1 size(handles.data,2)],[kmax kmax],'r','LineWidth',2);

axes(handles.axes4);
plot(abs(handles.dataph(:,1))./max(abs(handles.dataph(:,1))));
hold on
plot(abs(handles.dataph(:,end))./max(abs(handles.dataph(:,end))));
hold off
xlim([1 size(handles.dataph,1)]);
ylim([0 1.1]);
% set(handles.axes4,'YTickLabel',[],'XTickLabel',[]);

handles.phc0 = 0;
handles.phc1 = 0;
handles.zoom = 0;
handles.zoomInc = round(size(handles.data,1)/50);

% Choose default command line output for she    ar_gui
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

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

function varargout = shear_gui_OutputFcn(hObject, eventdata, handles) 
% Generate the ouputs 
varargout{1} = handles.dataph;
varargout{2} = handles.linshearmax;
delete(handles.figure1)

function figure1_CloseRequestFcn(hObject, eventdata, handles)
% Executes when user attempts to close figure1.
if isequal(get(hObject,'waitstatus'),'waiting')
    uiresume(hObject);
else
    delete(hObject);
end

% ========================== SLIDERS FUNCTIONS =============================
function shearSlider_Callback(hObject, eventdata, handles)
% Generate a shearing of the data by doing a FT, applying a order 1 phasing
% and inverse FT before plotting. See CJshear for the code.
handles.linshearmax = get(hObject,'Value');
handles.linshear = linspace(0,handles.linshearmax,size(handles.data,2)); 
for i=1:size(handles.data,2)
    handles.dataph(:,i) = CJshear(handles.data(:,i),0,handles.linshear(i));
end
handles.ft = fftshift(fft(fftshift(handles.dataph,2),size(handles.dataph,2),2),2);
axes(handles.axes1);
imagesc(abs(handles.dataph));
ax = gca;
set(ax,'Ydir','normal');
hold on
handles.guideline = get(handles.guideRadio,'Value');
if handles.guideline == 1
    [~,kmax]=max(handles.data(:,1));
    plot([1 size(handles.data,2)],[kmax kmax],'r','LineWidth',2);
end

axes(handles.axes4);
ax4=gca;
zoom_xlim=ax4.XLim;
plot(zoom_xlim(1):zoom_xlim(end),abs(handles.dataph(zoom_xlim(1):zoom_xlim(end),1))./max(abs(handles.dataph(zoom_xlim(1):zoom_xlim(end),1))));
hold on
plot(zoom_xlim(1):zoom_xlim(end),abs(handles.dataph(zoom_xlim(1):zoom_xlim(end),end))./max(abs(handles.dataph(zoom_xlim(1):zoom_xlim(end),end))));
hold off
% xlim([1 size(handles.dataph,1)]);
ylim([0 1.1]);
% set(handles.axes4,'YTickLabel',[],'XTickLabel',[]);
guidata(hObject, handles)

function zoomSlider_Callback(hObject, eventdata, handles)
% Change the center of the observed data if a zoom button has been used
% before.
if handles.zoom == 0
    set(handles.zoomSlider,'Value',round((size(handles.data,1)+1)/2));
end
handles.diffPos = get(handles.zoomSlider,'Value') - handles.middlePos;
setLim(hObject, eventdata, handles)
guidata(hObject, handles)

% ========================== RADIO BUTTON FUNCTIONS =============================

function guideRadio_Callback(hObject, eventdata, handles)
% Generate a guideline to help shearing the data.
handles.guideline = get(hObject,'Value');
axes(handles.axes1);
imagesc(abs(handles.dataph));
hold on
handles.guideline = get(handles.guideRadio,'Value');
if handles.guideline == 1
    [~,kmax]=max(handles.data(:,1));
    plot([1 size(handles.data,2)],[kmax kmax],'r','LineWidth',2);
end

%=============================== ZOOM BUTTONS FUNCTIONS  ===============================
function tPlusButton_Callback(hObject, eventdata, handles)
% Zoom on the data on the Y-axis
handles.zoom = handles.zoom+3*handles.zoomInc;
setLim(hObject, eventdata, handles)
guidata(hObject, handles)


function plusButton_Callback(hObject, eventdata, handles)
% Zoom on the data on the Y-axis
handles.zoom = handles.zoom+handles.zoomInc;
setLim(hObject, eventdata, handles)
guidata(hObject, handles)

function minusButton_Callback(hObject, eventdata, handles)
% Unzoom on the data on the Y-axis
handles.zoom = handles.zoom-handles.zoomInc;
setLim(hObject, eventdata, handles)
guidata(hObject, handles)

function tMinusButton_Callback(hObject, eventdata, handles)
% Unzoom on the data on the Y-axis
handles.zoom = handles.zoom-3*handles.zoomInc;
setLim(hObject, eventdata, handles)
guidata(hObject, handles)

% ======================== FUNCTION TO SET LIMITS =========================
function setLim(hObject, eventdata, handles)
% Set the Y limits acording to what has been set with the sliders / zoom
% buttons
axes(handles.axes1);
lowLim = 1 + handles.zoom + handles.diffPos;
if lowLim < 1
    lowLim = 1;
end
upLim = size(handles.dataph,1) - handles.zoom + handles.diffPos;
if upLim > size(handles.data,1)
    upLim = size(handles.data,1);
end
if lowLim<upLim
ylim([lowLim upLim]);
else
    errordlg('Error on the axis, you cannot zoom more.');
end
axes(handles.axes4);
lowLim = 1 + handles.zoom + handles.diffPos;
if lowLim < 1
    lowLim = 1;
end
upLim = size(handles.dataph,1) - handles.zoom + handles.diffPos;
if upLim > size(handles.data,1)
    upLim = size(handles.data,1);
end
if lowLim<upLim
xlim([lowLim upLim]);
else
    errordlg('Error on the axis, you cannot zoom more.');
end
guidata(hObject, handles)


%====================================== UNUSED FUNCTIONS  =========================
% Not sure what they are doing, but if ereased, the GUI bugs
function shearSlider_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end
function zoomSlider_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end
