source: trunk/src/series.m @ 975

Last change on this file since 975 was 975, checked in by sommeria, 4 years ago

various update

File size: 161.6 KB
Line 
1%'series': master function associated to the GUI series.m for analysis field series 
2%------------------------------------------------------------------------
3% function varargout = series(varargin)
4% associated with the GUI series.fig
5%
6%INPUT
7% param: structure with input parameters (link with the GUI uvmat)
8%      .menu_coord_str: string for the TransformName (menu for coordinate transforms)
9%      .menu_coord_val: value for TransformName (menu for coordinate transforms)
10%      .FileName: input file name
11%      .FileName_1: second input file name
12%      .list_field: menu of input fields
13%      .index_fields: chosen index
14%      .civ1=0 or 1, .interp1,  ... : input civ field type
15%
16
17%=======================================================================
18% Copyright 2008-2016, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
19%   http://www.legi.grenoble-inp.fr
20%   Joel.Sommeria - Joel.Sommeria (A) legi.cnrs.fr
21%
22%     This file is part of the toolbox UVMAT.
23%
24%     UVMAT is free software; you can redistribute it and/or modify
25%     it under the terms of the GNU General Public License as published
26%     by the Free Software Foundation; either version 2 of the license,
27%     or (at your option) any later version.
28%
29%     UVMAT is distributed in the hope that it will be useful,
30%     but WITHOUT ANY WARRANTY; without even the implied warranty of
31%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32%     GNU General Public License (see LICENSE.txt) for more details.
33%=======================================================================
34
35%------------------------------------------------------------------------
36%------------------------------------------------------------------------
37%  I - MAIN FUNCTION series
38%------------------------------------------------------------------------
39%------------------------------------------------------------------------
40function varargout = series(varargin)
41
42% Begin initialization code - DO NOT EDIT
43gui_Singleton = 1;
44gui_State = struct('gui_Name',       mfilename, ...
45                   'gui_Singleton',  gui_Singleton, ...
46                   'gui_OpeningFcn', @series_OpeningFcn, ...
47                   'gui_OutputFcn',  @series_OutputFcn, ...
48                   'gui_LayoutFcn',  [] , ...
49                   'gui_Callback',   []);
50if nargin && ischar(varargin{1})
51    gui_State.gui_Callback = str2func(varargin{1});
52end
53
54if nargout
55    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
56else
57    gui_mainfcn(gui_State, varargin{:});
58end
59% End initialization code - DO NOT EDIT
60
61%--------------------------------------------------------------------------
62% --- Executes just before series is made visible.
63%--------------------------------------------------------------------------
64function series_OpeningFcn(hObject, eventdata, handles,Param)
65
66% Choose default command line output for series
67handles.output = hObject;
68% Update handles structure
69guidata(hObject, handles);
70
71%% initial settings
72% position and  size of the GUI at opening
73set(0,'Unit','points')
74ScreenSize=get(0,'ScreenSize');%size of the current screen, in points (1/72 inch)
75Width=900;% prefered width of the GUI in points (1/72 inch)
76Height=624;% prefered height of the GUI in points (1/72 inch)
77%adjust to screen size (reduced by a min margin)
78RescaleFactor=min((ScreenSize(3)-80)/Width,(ScreenSize(4)-80)/Height);
79if RescaleFactor>1
80    RescaleFactor=min(RescaleFactor,1);
81end
82Width=Width*RescaleFactor;
83Height=Height*RescaleFactor;
84LeftX=80*RescaleFactor;%position of the left fig side, in pixels (put to the left side, with some margin)
85LowY=round(ScreenSize(4)/2-Height/2); % put at the middle height on the screen
86set(hObject,'Units','points')
87set(hObject,'Position',[LeftX LowY Width Height])% position and size of the GUI at opening
88
89% settings of table MinIndex_j
90set(handles.MinIndex_i,'ColumnFormat',{'numeric'})
91set(handles.MinIndex_i,'ColumnEditable',false)
92set(handles.MinIndex_i,'ColumnName',{'i min'})
93set(handles.MinIndex_i,'Data',[])% initiate Data to double (not cell)
94
95% settings of table MinIndex_j
96set(handles.MinIndex_j,'ColumnFormat',{'numeric'})
97set(handles.MinIndex_j,'ColumnEditable',false)
98set(handles.MinIndex_j,'ColumnName',{'j min'})
99set(handles.MinIndex_j,'Data',[])% initiate Data to double (not cell)
100
101% settings of table MaxIndex_i
102set(handles.MaxIndex_i,'ColumnFormat',{'numeric'})
103set(handles.MaxIndex_i,'ColumnEditable',false)
104set(handles.MaxIndex_i,'ColumnName',{'i max'})
105set(handles.MaxIndex_i,'Data',[])% initiate Data to double (not cell)
106
107% settings of table MaxIndex_j
108set(handles.MaxIndex_j,'ColumnFormat',{'numeric'})
109set(handles.MaxIndex_j,'ColumnEditable',false)
110set(handles.MaxIndex_j,'ColumnName',{'j max'})
111set(handles.MaxIndex_j,'Data',[])% initiate Data to double (not cell)
112
113% settings of table PairString
114set(handles.PairString,'ColumnName',{'pairs'})
115set(handles.PairString,'ColumnEditable',false)
116set(handles.PairString,'ColumnFormat',{'char'})
117set(handles.PairString,'Data',{''})
118
119% settings of table MaskTable
120set(handles.MaskTable,'ColumnName',{'mask name'})
121set(handles.PairString,'ColumnEditable',false)
122set(handles.PairString,'ColumnFormat',{'char'})
123set(handles.PairString,'Data',{''})
124
125series_ResizeFcn(hObject, eventdata, handles)%resize table according to series GUI size
126set(hObject,'WindowButtonDownFcn',{'mouse_down'})%allows mouse action with right button (zoom for uicontrol display)
127set(hObject,'DeleteFcn',{@closefcn})%
128
129% check default input data
130if ~exist('Param','var')
131    Param=[]; %default
132end
133
134%% list of builtin functions in the mebu ActionName
135ActionList={'check_data_files';'aver_stat';'time_series';'civ_series';'merge_proj'};% WARNING: fits with nb_builtin_ACTION=4 in ActionName_callback
136NbBuiltinAction=numel(ActionList);
137set(handles.Action,'UserData',NbBuiltinAction)
138[path_series,name,ext]=fileparts(which('series'));% path to the GUI series
139path_series_fct=fullfile(path_series,'series');%path of the functions in subdirectroy 'series'
140[code, message] = system...
141    ('LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') |... [s for s in p if ''matlab'' not in s] | '':''.join(p)") python -c "import fluidimage"');
142if code==0
143    ActionExtList={'.m';'.sh';'.py (in dev.)'};% default choice of extensions (Matlab fct .m or compiled version .sh
144else
145    ActionExtList={'.m';'.sh'};  % python options not installed
146end
147ActionPathList=cell(NbBuiltinAction,1);%initiate the cell matrix of Action fct paths
148ActionPathList(:)={path_series_fct}; %set the default path to series fcts to all list members
149RunModeList={'local';'background'};% default choice of extensions (Matlab fct .m or compiled version .sh)
150[s,w]=system('oarstat');% look for cluster system 'oar'
151if isequal(s,0)
152    RunModeList=[RunModeList;{'cluster_oar'}];
153    set(handles.MonitorCluster,'Visible','on'); % make visible button for access to Monika
154    set(handles.num_CPUTime,'Visible','on'); % make visible button for access to Monika
155    set(handles.CPUTime_txt,'Visible','on'); % make visible button for access to Monika
156end
157[s,w]=system('qstat --version');% look for cluster system 'sge'
158if isequal(s,0)
159    if regexp(w,'^pbs')
160        RunModeList=[RunModeList;{'cluster_pbs'}];
161    else
162        RunModeList=[RunModeList;{'cluster_sge'}];
163    end
164end
165set(handles.RunMode,'String',RunModeList)
166
167%% list of builtin transform functions in the menu TransformName
168TransformList={'';'sub_field';'phys';'phys_polar'};% WARNING: must fit with the corresponding menu in uvmat and nb_builtin_transform=4 in  TransformName_callback
169NbBuiltinTransform=numel(TransformList);
170path_transform_fct=fullfile(path_series,'transform_field');
171TransformPathList=cell(NbBuiltinTransform,1);%initiate the cell matrix of Action fct paths
172TransformPathList(:)={path_transform_fct}; %set the default path to series fcts to all list members
173
174%% get the user defined functions stored in the personal file uvmat_perso.mat
175dir_perso=prefdir;
176profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
177if exist(profil_perso,'file')
178    h=load (profil_perso);
179    %get the list of previous input files in the upper bar menu Open
180    if isfield(h,'MenuFile')
181        for ifile=1:min(length(h.MenuFile),5)
182            set(handles.(['MenuFile_' num2str(ifile)]),'Label',h.MenuFile{ifile});
183            set(handles.(['MenuFile_' num2str(ifile+5)]),'Label',h.MenuFile{ifile});
184        end
185    end
186    %get the list of previous campaigns in the upper bar menu Open campaign
187    if isfield(h,'MenuCampaign')
188        for ifile=1:min(length(h.MenuCampaign),5)
189            set(handles.(['MenuCampaign_' num2str(ifile)]),'Label',h.MenuCampaign{ifile});
190        end
191    end
192    %get the menu of actions
193%     if isfield(h,'ActionExtListUser') && iscell(h.ActionExtListUser)
194%         ActionExtList=[ActionExtList; h.ActionExtListUser];
195%     end
196    if isfield(h,'ActionListUser') && iscell(h.ActionListUser) && isfield(h,'ActionPathListUser') && iscell(h.ActionPathListUser)
197        ActionList=[ActionList;h.ActionListUser];
198        ActionPathList=[ActionPathList;h.ActionPathListUser(:,1)];
199    end
200    %get the menu of transform fct
201    if isfield(h,'TransformListUser') && iscell(h.TransformListUser) && isfield(h,'TransformPathListUser') && iscell(h.TransformPathListUser)
202        TransformList=[TransformList;h.TransformListUser];
203        TransformPathList=[TransformPathList;h.TransformPathListUser];
204    end
205end
206
207%% selection of the input Action fct
208ActionCheckExist=true(size(ActionList));%initiate the check of the path to the listed action fct
209for ilist=NbBuiltinAction+1:numel(ActionList)%check  the validity of the path of the user defined Action fct
210    ActionCheckExist(ilist)=exist(fullfile(ActionPathList{ilist},[ActionList{ilist} '.m']),'file');
211end
212ActionPathList=ActionPathList(ActionCheckExist,:);% suppress the menu options which are not valid anymore
213ActionList=ActionList(ActionCheckExist);
214set(handles.ActionName,'String',[ActionList;{'more...'}])
215set(handles.ActionName,'UserData',ActionPathList)
216ActionIndex=[];
217if isfield(Param,'ActionName')% copy the selected menu index transferred in Param from uvmat
218    ActionIndex=find(strcmp(Param.ActionName,ActionList),1);
219end
220if isempty(ActionIndex)
221    ActionIndex=1;
222end
223set(handles.ActionName,'Value',ActionIndex)
224set(handles.ActionPath,'String',ActionPathList{ActionIndex})
225set(handles.ActionExt,'Value',1)
226set(handles.ActionExt,'String',ActionExtList)
227
228%% selection of the input transform fct
229TransformCheckExist=true(size(TransformList));
230for ilist=NbBuiltinTransform+1:numel(TransformList)
231    TransformCheckExist(ilist)=exist(fullfile(TransformPathList{ilist},[TransformList{ilist} '.m']),'file');
232end
233TransformPathList=TransformPathList(TransformCheckExist);
234TransformList=TransformList(TransformCheckExist);
235set(handles.TransformName,'String',[TransformList;{'more...'}])
236set(handles.TransformName,'UserData',TransformPathList)
237TransformIndex=[];
238if isfield(Param,'TransformName')% copy the selected menu index transferred in Param from uvmat
239    TransformIndex=find(strcmp(Param.TransformName,TransformList),1);
240end
241if isempty(TransformIndex)
242    TransformIndex=1;
243end
244set(handles.TransformName,'Value',TransformIndex)
245set(handles.TransformPath,'String',TransformPathList{TransformIndex})
246   
247%% fields input initialisation
248if isfield(Param,'list_fields')&& isfield(Param,'index_fields') &&~isempty(Param.list_fields) &&~isempty(Param.index_fields)
249    set(handles.FieldName,'String',Param.list_fields);% list menu fields
250    set(handles.FieldName,'Value',Param.index_fields);% selected string index
251end
252if isfield(Param,'Coordinates')
253    if isfield(Param.Coordinates,'Coord_x')
254        set(handles.Coord_x,'String',Param.Coordinates.Coord_x)
255    end
256    if isfield(Param.Coordinates,'Coord_y')
257        set(handles.Coord_y,'String',Param.Coordinates.Coord_y)
258    end
259    if isfield(Param.Coordinates,'Coord_z')
260        set(handles.Coord_z,'String',Param.Coordinates.Coord_z)
261    end
262end
263% if isfield(Param,'Coord_x_str') && ischar(Param.Coord_x_str)
264%         set(handles.Coord_x,'String',Param.Coord_x_str);% list menu fields
265% end
266% if isfield(Param,'Coord_y_str')&& ischar(Param.Coord_y_str)
267%         set(handles.Coord_y,'String',Param.Coord_y_str);% list menu fields
268% end
269
270%% introduce the input file name(s) if defined from input Param,
271set(handles.series,'UserData',[])% initiate Userdata
272if isfield(Param,'InputFile')
273   
274    %% fill the list of file series
275    InputTable=[{Param.InputFile.RootPath},{Param.InputFile.SubDir},{Param.InputFile.RootFile},{Param.InputFile.NomType},{Param.InputFile.FileExt}];
276    if isempty(find(cellfun('isempty',InputTable)==0));% if there is no input file, do not introduce input info
277        set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
278        return
279    end
280    TimeTable=[{Param.InputFile.TimeName},{[]},{[]},{[]},{[]}];
281    if isfield(Param.InputFile,'RootPath_1')
282        InputTable=[InputTable;[{Param.InputFile.RootPath_1},{Param.InputFile.SubDir_1},{Param.InputFile.RootFile_1},{Param.InputFile.NomType_1},{Param.InputFile.FileExt_1}]];
283        TimeTable=[TimeTable; [{Param.InputFile.TimeName_1},{[]},{[]},{[]},{[]}]];
284    end
285    set(handles.InputTable,'Data',InputTable)
286    %% determine the selected reference field indices for pair display
287   
288    [tild,tild,tild,i1,i2,j1,j2]=fileparts_uvmat(Param.InputFile.FileIndex);
289    if isempty(i1)
290        i1=1;
291    end
292    if isempty(i2)
293        i2=i1;
294    end
295    ref_i=floor((i1+i2)/2);% reference image number corresponding to the file
296    % set(handles.num_ref_i,'String',num2str(ref_i));
297    if isempty(j1)
298        j1=1;
299    end
300    if isempty(j2)
301        j2=j1;
302    end
303    ref_j=floor((j1+j2)/2);% reference image number corresponding to the file
304    SeriesData.ref_i=ref_i;
305    SeriesData.ref_j=ref_j;
306    set(handles.series,'UserData',SeriesData)
307    update_rootinfo(handles,Param.HiddenData.i1_series{1},Param.HiddenData.i2_series{1},Param.HiddenData.j1_series{1},Param.HiddenData.j2_series{1},...
308        Param.HiddenData.FileInfo{1},Param.HiddenData.MovieObject{1},1)
309    if isfield(Param,'FileName_1')
310        %         display_file_name(handles,Param,2)
311        update_rootinfo(handles,Param.HiddenData.i1_series{2},Param.HiddenData.i2_series{2},Param.HiddenData.j1_series{2},Param.HiddenData.j2_series{2},...
312            Param.HiddenData.FileInfo{2},Param.HiddenData.MovieObject{2},2)
313    end
314    %% enable field and veltype menus, in accordance with the current action
315    ActionName_Callback([],[], handles)
316   
317    %% set length of waitbar
318    displ_time(handles)
319   
320else
321    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
322end
323if isfield(Param,'incr_i')
324    set(handles.num_incr_i,'String',num2str(Param.incr_i))
325else
326    set(handles.num_incr_i,'String','1')
327end
328if isfield(Param,'incr_j')
329    set(handles.num_incr_j,'String',num2str(Param.incr_j))
330else
331    set(handles.num_incr_j,'String','1')
332end
333
334%------------------------------------------------------------------------
335% --- Outputs from this function are returned to the command line.
336function varargout = series_OutputFcn(hObject, eventdata, handles)
337%------------------------------------------------------------------------
338varargout{1} = handles.output;
339
340%------------------------------------------------------------------------
341% --- executed when closing uvmat: delete or desactivate the associated figures if exist
342function closefcn(gcbo,eventdata)
343%------------------------------------------------------------------------
344
345% delete set_object_series if detected
346hh=findobj(allchild(0),'name','view_object_series');
347if ~isempty(hh)
348    delete(hh)
349end
350hh=findobj(allchild(0),'name','edit_object_series');
351if ~isempty(hh)
352    delete(hh)
353end
354
355%delete the bowser if detected
356hh=findobj(allchild(0),'tag','browser');
357if ~isempty(hh)
358    delete(hh)
359end
360
361
362%------------------------------------------------------------------------
363%------------------------------------------------------------------------
364%  II - FUNCTIONS FOR INTRODUCING THE INPUT FILES
365% automatically sets the global properties when the rootfile name is introduced
366% then activate the view-field actionname if selected
367% it is activated either by clicking on the RootPath window or by the
368% browser
369%------------------------------------------------------------------------
370%------------------------------------------------------------------------
371% --- fct activated by the browser under 'Open'
372%------------------------------------------------------------------------ 
373function MenuBrowse_Callback(hObject, eventdata, handles)
374%% look for the previously opened file 'oldfile'
375InputTable=get(handles.InputTable,'Data');
376oldfile=InputTable{1,1};
377if isempty(oldfile)
378    % use a file name stored in prefdir
379    dir_perso=prefdir;
380    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
381    if exist(profil_perso,'file')
382        h=load (profil_perso);
383        if isfield(h,'RootPath') && ischar(h.RootPath)
384            oldfile=h.RootPath;
385        end
386    end
387end
388%% launch the browser
389fileinput=uigetfile_uvmat('pick an input file in the series',oldfile);
390hh=dir(fileinput);
391if numel(hh)>1
392    msgbox_uvmat('ERROR','invalid input, probably a broken link');
393else
394    if ~isempty(fileinput)
395        display_file_name(handles,fileinput,'one')
396    end
397end
398
399% --------------------------------------------------------------------
400function MenuBrowseAppend_Callback(hObject, eventdata, handles)
401
402%% look for the previously opened file 'oldfile'
403InputTable=get(handles.InputTable,'Data');
404RootPathCell=InputTable(:,1);
405if isempty(RootPathCell{1})% no input file in the table
406     MenuBrowse_Callback(hObject, eventdata, handles)%refresh the input table, not append
407     return
408end
409SubDirCell=InputTable(:,2);
410oldfile=fullfile(RootPathCell{1},SubDirCell{1});
411
412%% use a file name stored in prefdir
413dir_perso=prefdir;
414profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
415if exist(profil_perso,'file')
416    h=load (profil_perso);
417    if isfield(h,'RootPath') && ischar(h.RootPath)
418        oldfile=h.RootPath;
419    end
420end
421
422%% launch the browser
423fileinput=uigetfile_uvmat('pick a file to append in the input table',oldfile);
424hh=dir(fileinput);
425if numel(hh)>1
426    msgbox_uvmat('ERROR','invalid input, probably a broken link');
427else
428    if ~isempty(fileinput)
429        display_file_name(handles,fileinput,'append')
430    end
431end
432
433%------------------------------------------------------------------------
434% --- fct activated by selecting a previous file under the menu Open
435%------------------------------------------------------------------------
436function MenuFile_Callback(hObject, eventdata, handles)
437
438errormsg=display_file_name(handles,get(hObject,'Label'),'one');
439if ~isempty(errormsg)
440    set(hObject,'Label','')
441    MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
442        {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
443    str_find=strcmp(get(hObject,'Label'),MenuFile);
444    MenuFile(str_find)=[];% suppress the input file to the list
445    for ifile=1:numel(MenuFile)
446        set(handles.(['MenuFile_' num2str(ifile)]),'Label',MenuFile{ifile});
447    end
448end
449
450%------------------------------------------------------------------------
451% --- fct activated by selecting a previous file under the menu Open/append
452%------------------------------------------------------------------------
453function MenuFile_append_Callback(hObject, eventdata, handles)
454
455InputTable=get(handles.InputTable,'Data');
456if isempty(InputTable{1,1})% no input file in the table
457    display_file_name(handles,get(hObject,'Label'),'one') %refresh the input table, not append
458else
459    display_file_name(handles,get(hObject,'Label'),'append')% append the selected file to the current list of InputTable
460end
461
462%------------------------------------------------------------------------
463% --- fct activated by the browser under 'Open campaign/Browse...'
464%------------------------------------------------------------------------
465function MenuBrowseCampaign_Callback(hObject, eventdata, handles)
466
467%% look for the previously opened file 'oldfile'
468InputTable=get(handles.InputTable,'Data');
469if ~isempty(InputTable)
470oldfile=fullfile(InputTable{1,1},InputTable{1,2});
471else
472    % use a file name stored in prefdir
473    dir_perso=prefdir;
474    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
475    if exist(profil_perso,'file')
476        h=load (profil_perso);
477        if isfield(h,'MenuCampaign') && ~isempty(h.MenuCampaign)&& ischar(h.MenuCampaign{1})
478            oldfile=h.MenuCampaign{1};
479        end
480    end
481end
482
483OutPut=browse_data(oldfile,'on','on');% open the GUI browse_data to get select a campaign dir, experiment and device
484NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
485icount=0;
486for iexp=1:numel(OutPut.Experiment)
487    for idevice=1:numel(OutPut.DataSeries)
488        icount=icount+1;
489        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
490        InputTable{icount,2}=OutPut.DataSeries{idevice};
491        if isempty(InputTable{icount,3})
492            if icount>1
493            InputTable{icount,3}=InputTable{icount-1,3};
494            else
495                InputTable{icount,3}='';
496            end
497        end
498        if isempty(InputTable{icount,4})
499            if icount>1
500            InputTable{icount,4}=InputTable{icount-1,4};
501            else
502                InputTable{icount,4}='';
503            end
504        end
505                if isempty(InputTable{icount,5})
506            if icount>1
507            InputTable{icount,5}=InputTable{icount-1,5};
508            else
509                InputTable{icount,5}='';
510            end
511        end
512    end
513end
514if size(InputTable,1)>icount
515    InputTable(icount+1:size(InputTable,1),:)=[];
516end
517set(handles.InputTable,'Data',InputTable)
518REFRESH_Callback(hObject, eventdata, handles)
519
520% --------------------------------------------------------------------
521function MenuCampaign_Callback(hObject, eventdata, handles)
522% --------------------------------------------------------------------
523
524OutPut=browse_data(get(hObject,'Label'),'on','on');% open the GUI browse_data to get select a campaign dir, experiment and device
525if ~isfield(OutPut,'Campaign')
526    return
527end
528NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
529icount=0;
530InputTable=get(handles.InputTable,'Data');
531for iexp=1:numel(OutPut.Experiment)
532    for idevice=1:numel(OutPut.DataSeries)
533        icount=icount+1;
534        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
535        InputTable{icount,2}=OutPut.DataSeries{idevice};
536        if isempty(InputTable{icount,3})
537            if icount>1
538                InputTable{icount,3}=InputTable{icount-1,3};
539            else
540                InputTable{icount,3}='';
541            end
542        end
543        if isempty(InputTable{icount,4})
544            if icount>1
545                InputTable{icount,4}=InputTable{icount-1,4};
546            else
547                InputTable{icount,4}='';
548            end
549        end
550        if isempty(InputTable{icount,5})
551            if icount>1
552                InputTable{icount,5}=InputTable{icount-1,5};
553            else
554                InputTable{icount,5}='';
555            end
556        end
557    end
558end
559if size(InputTable,1)>icount
560    InputTable(icount+1:size(InputTable,1),:)=[];
561end
562set(handles.InputTable,'Data',InputTable)
563REFRESH_Callback(hObject, eventdata, handles)
564
565
566% --- Executes when selected cell(s) is changed in InputTable.
567function InputTable_CellSelectionCallback(hObject, eventdata, handles)
568iline=[];
569if ~isempty(eventdata.Indices)
570    iline=eventdata.Indices(1);
571end
572set(handles.InputLine,'String',num2str(iline));
573% set(handles.InputTable,'UserData',iline);
574
575%------------------------------------------------------------------------
576% --- 'key_press_fcn:' function activated when a key is pressed on the keyboard
577%------------------------------------------------------------------------
578function InputTable_KeyPressFcn(hObject, eventdata, handles)
579set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
580set(handles.OutputSubDir,'BackgroundColor',[1 0 1])% set edit box OutputSubDir to magenta color to indicate that refresh may be needed
581xx=double(get(handles.series,'CurrentCharacter')); %get the keyboard character
582if ~isempty(xx)
583    switch xx
584        case 31 %downward arrow
585            InputTable=get(handles.InputTable,'Data');
586            iline=str2double(get(handles.InputLine,'String'));
587            if isequal(iline,size(InputTable,1))% arrow downward
588                InputTable=[InputTable;InputTable(iline,:)];% create a new line as a copy of the last one
589                set(handles.InputTable,'Data',InputTable);
590            end
591        case 127  %key 'Suppress'
592            ClearLine_Callback(hObject, eventdata, handles)
593    end
594end
595
596%------------------------------------------------------------------------
597% --- Executes on button press in REFRESH.
598function REFRESH_Callback(hObject, eventdata, handles)
599%------------------------------------------------------------------------
600InputTable=get(handles.InputTable,'Data');
601set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
602set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
603drawnow
604empty_line=false(size(InputTable,1),1);
605for iline=1:size(InputTable,1)
606    empty_line(iline)= isempty(cell2mat(InputTable(iline,1:3)));
607end
608if ~isempty(find(empty_line));
609    InputTable(empty_line,:)=[];%remove empty lines
610    set(handles.InputTable,'Data',InputTable)
611    ListTable={'MinIndex_i','MaxIndex_i','MinIndex_j','MaxIndex_j','PairString','TimeTable'};
612    for ilist=1:numel(ListTable)
613        Table=get(handles.(ListTable{ilist}),'Data');
614        Table(empty_line,:)=[];%remove empty lines
615        set(handles.(ListTable{ilist}),'Data',Table);
616    end
617    set(handles.series,'UserData',[])%refresh the stored info
618end
619nbview=size(InputTable,1);
620for iview=1:nbview
621    RootPath=fullfile(InputTable{iview,1},InputTable{iview,2});
622    if ~exist(RootPath,'dir')
623        i1_series=[];
624        RootFile='';
625    else %scan the input folder
626        if strcmp(InputTable{iview,4},'level')
627            [RootPath,~,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileInfo,MovieObject]=...
628                find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2},'level0'),[InputTable{iview,3} '0' InputTable{iview,5}]);
629        else
630            [RootPath,~,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileInfo,MovieObject]=...
631                find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2}),[InputTable{iview,3} InputTable{iview,4} InputTable{iview,5}]);
632        end
633    end
634    % if no file is found, open a browser
635    if isempty(RootFile)&& isempty(i1_series)
636        fileinput=uigetfile_uvmat(['wrong input at line ' num2str(iview) ':pick a new input file'],RootPath);
637        if isempty(fileinput)
638            set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  back to red color
639            return
640        else
641            display_file_name(handles,fileinput,iview)
642        end
643    else
644       update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview)
645    end
646end
647
648%% update MinIndex_i and MaxIndex_i if the input table content has been reduced in line nbre
649MinIndex_i_table=get(handles.MinIndex_i,'Data');%retrieve the min indices in the table MinIndex
650set(handles.MinIndex_i,'Data',MinIndex_i_table(1:nbview,:));
651MinIndex_j_table=get(handles.MinIndex_j,'Data');%retrieve the min indices in the table MinIndex
652set(handles.MinIndex_j,'Data',MinIndex_j_table(1:nbview,:));
653MaxIndex_i_table=get(handles.MaxIndex_i,'Data');%retrieve the min indices in the table MinIndex
654set(handles.MaxIndex_i,'Data',MaxIndex_i_table(1:nbview,:));
655MaxIndex_j_table=get(handles.MaxIndex_j,'Data');%retrieve the min indices in the table MinIndex
656set(handles.MaxIndex_j,'Data',MaxIndex_j_table(1:nbview,:));
657PairString=get(handles.PairString,'Data');%retrieve the min indices in the table MinIndex
658set(handles.PairString,'Data',PairString(1:nbview,:));
659TimeTable=get(handles.TimeTable,'Data');%retrieve the min indices in the table MinIndex
660set(handles.TimeTable,'Data',TimeTable(1:nbview,:));
661
662%% enable field and veltype menus, in accordance with the current action
663ActionName_Callback([],[], handles)
664
665%% set length of waitbar
666displ_time(handles)
667
668set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (indicate activation finished)
669set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch'
670
671%------------------------------------------------------------------------
672% --- Function called when a new file is opened, either by series_OpeningFcn or by the browser
673%------------------------------------------------------------------------
674% INPUT:
675% handles: handles of elements in the GUI
676% Param: structure of input parameters, including  input file name and path
677% iview: line index in the input table
678%       or 'one': refresh the list
679%         'append': add a new line to the input table
680function errormsg=display_file_name(handles,Param,iview)
681 
682set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
683drawnow
684errormsg='';%default
685if ischar(Param)
686    fileinput=Param;
687else% input set when series is opened (called by the GUI uvmat)
688    fileinput=Param.FileName;
689end
690   
691%% get the input root name, indices, file extension and nomenclature NomType
692if ~exist(fileinput,'file')
693    errormsg=['input file ' fileinput  ' does not exist'];
694    msgbox_uvmat('ERROR',errormsg)
695    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (refresh still needed)
696    return
697end
698
699%% detect root name, nomenclature and indices in the input file name:
700[FilePath,FileName,FileExt]=fileparts(fileinput);
701%%%%%%%%%%%%%%%%%%
702%TODO: case of input by uvmat: do not check agai the input seies %%%%%%%
703%%%%%%%%%%%%%%%%%%%
704% detect the file type, get the movie object if relevant, and look for the corresponding file series:
705% the root name and indices may be corrected by including the first index i1 if a corresponding xml file exists
706[RootPath,SubDir,RootFile,i1_series,i2_series,j1_series,j2_series,NomType,FileInfo,MovieObject,i1,i2,j1,j2]=find_file_series(FilePath,[FileName FileExt]);
707FileType=FileInfo.FileType;
708if isempty(RootFile)&&isempty(i1_series)
709    errormsg='no input file in the series';
710    msgbox_uvmat('ERROR',errormsg)
711    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (end of activation)
712    return
713end
714if strcmp(FileType,'txt')
715    edit(fileinput)
716    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to  magenta color (end of activation)
717    return
718elseif strcmp(FileType,'xml')
719    editxml(fileinput)
720    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
721     return
722elseif strcmp(FileType,'figure')
723    open(fileinput)
724    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
725     return
726end
727
728%% enable other menus and uicontrols
729% set(handles.MenuOpenCampaign,'Enable','on')
730set(handles.MenuCampaign_1,'Enable','on')
731set(handles.MenuCampaign_2,'Enable','on')
732set(handles.MenuCampaign_3,'Enable','on')
733set(handles.MenuCampaign_4,'Enable','on')
734set(handles.MenuCampaign_5,'Enable','on')
735set(handles.RUN, 'Enable','On')
736set(handles.RUN,'BackgroundColor',[1 0 0])% set RUN button to red
737set(handles.InputTable,'BackgroundColor',[1 1 0]) % set RootPath edit box  to yellow
738drawnow
739
740
741%% fill the list of file series
742InputTable=get(handles.InputTable,'Data');
743SeriesData=get(handles.series,'UserData');
744if strcmp(iview,'append') % display the input data as a new line in the table
745    iview=size(InputTable,1)+1;% the next line in InputTable becomes the current line
746%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
747elseif strcmp(iview,'one') % refresh the list of  input  file series
748    iview=1; %the first line in InputTable becomes the current line
749    InputTable={'','','','',''};
750%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
751    set(handles.TimeTable,'Data',[{''},{[]},{[]},{[]},{[]}])
752    set(handles.MinIndex_i,'Data',[])
753    set(handles.MaxIndex_i,'Data',[])
754    set(handles.MinIndex_j,'Data',[])
755    set(handles.MaxIndex_j,'Data',[])
756    set(handles.PairString,'Data',{''})
757    SeriesData.CheckPair=0;%reset the list of input lines with pairs
758    SeriesData.i1_series={};
759    SeriesData.i2_series={};
760    SeriesData.j1_series={};
761    SeriesData.j2_series={};
762    SeriesData.FileType={};
763    SeriesData.FileInfo={};
764    SeriesData.Time={};
765end
766if isfield(SeriesData,'i1_series')
767    SeriesData.i1_series(iview+1:end)=[];
768    SeriesData.i2_series(iview+1:end)=[];
769    SeriesData.j1_series(iview+1:end)=[];
770    SeriesData.j2_series(iview+1:end)=[];
771    SeriesData.FileType(iview+1:end)=[];
772    SeriesData.FileInfo(iview+1:end)=[];
773    SeriesData.Time(iview+1:end)=[];
774end
775InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
776if iview >1
777    set(handles.InputLine,'String',num2str(iview))
778end
779set(handles.InputTable,'Data',InputTable)
780
781%% determine the selected reference field indices for pair display
782if isempty(i1)
783    i1=1;
784end
785if isempty(i2)
786    i2=i1;
787end
788ref_i=floor((i1+i2)/2);% reference image number corresponding to the file
789% set(handles.num_ref_i,'String',num2str(ref_i));
790if isempty(j1)
791    j1=1;
792end
793if isempty(j2)
794    j2=j1;
795end
796ref_j=floor((j1+j2)/2);% reference image number corresponding to the file
797SeriesData.ref_i=ref_i;
798SeriesData.ref_j=ref_j;
799
800%% update first and last indices if they do not exist
801Param=read_GUI(handles.series);
802first_j=[];
803if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
804last_j=[];
805if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
806PairString='';
807if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
808[i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
809FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
810    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
811if ~exist(FirstFileName,'file')
812    set(handles.num_first_i,'String',num2str(ref_i))
813    set(handles.num_first_j,'String',num2str(ref_j))
814end
815[i1,i2,j1,j2] = get_file_index(Param.IndexRange.last_i,last_j,PairString);
816LastFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
817    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
818if ~exist(LastFileName,'file')
819    set(handles.num_last_i,'String',num2str(ref_i))
820    set(handles.num_last_j,'String',num2str(ref_j))
821end
822
823%% update the list of recent files in the menubar and save it for future opening
824MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
825    {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
826str_find=strcmp(fileinput,MenuFile);
827if isempty(find(str_find,1))
828    MenuFile=[{fileinput};MenuFile];%insert the current file if not already in the list
829end
830for ifile=1:min(length(MenuFile),5)
831    eval(['set(handles.MenuFile_' num2str(ifile) ',''Label'',MenuFile{ifile});'])
832end
833dir_perso=prefdir;
834profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
835if exist(profil_perso,'file')
836    save (profil_perso,'MenuFile','-append'); %store the file names for future opening of uvmat
837else
838    save (profil_perso,'MenuFile','-V6'); %store the file names for future opening of uvmat
839end
840% save the opened file to initiate future opening
841SeriesData.RefFile{iview}=fileinput;% reference opening file for line iview
842SeriesData.Ref_i1=i1;
843SeriesData.Ref_i2=i2;
844SeriesData.Ref_j1=j1;
845SeriesData.Ref_j2=j2;
846set(handles.series,'UserData',SeriesData)
847
848set(handles.InputTable,'BackgroundColor',[1 1 1])
849
850%% initiate input file series and refresh the current field view:     
851update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview);
852%% enable field and veltype menus, in accordance with the current action
853ActionName_Callback([],[], handles)
854
855%% set length of waitbar
856displ_time(handles)
857
858set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (end of activation)
859
860%------------------------------------------------------------------------
861% --- Update information about a new field series (indices to scan, timing,
862%     calibration from an xml file
863function update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,VideoObject,iview)
864%------------------------------------------------------------------------
865InputTable=get(handles.InputTable,'Data');
866
867%% display the min and max indices for the whole file series
868if size(i1_series,2)==2 && min(min(i1_series(:,1,:)))==0
869    MinIndex_j=1;% index j set to 1 by default
870    MaxIndex_j=1;
871    MinIndex_i=find(i1_series(1,2,:), 1 )-1;% min ref index i detected in the series (corresponding to the first non-zero value of i1_series, except for zero index)
872    MaxIndex_i=find(i1_series(1,2,:),1,'last' )-1;%max ref index i detected in the series (corresponding to the last non-zero value of i1_series)
873else
874    ref_i=squeeze(max(i1_series(1,:,:),[],2));% select ref_j index for each ref_i
875    ref_j=squeeze(max(j1_series(1,:,:),[],3));% select ref_i index for each ref_j
876     MinIndex_i=min(find(ref_i))-1;
877     MaxIndex_i=max(find(ref_i))-1;
878     MaxIndex_j=max(find(ref_j))-1;
879     MinIndex_j=min(find(ref_j))-1;
880    diff_j_max=diff(ref_j);
881    diff_i_max=diff(ref_i);
882    if ~isempty(diff_i_max) && isequal (diff_i_max,diff_i_max(1)*ones(size(diff_i_max)))
883        set(handles.num_incr_i,'String',num2str(diff_i_max(1)))% detect an increment to dispaly by default
884    end
885    if ~isempty(diff_j_max) && isequal (diff_j_max,diff_j_max(1)*ones(size(diff_j_max)))
886        set(handles.num_incr_j,'String',num2str(diff_j_max(1)))
887    end
888end
889if isequal(MinIndex_i,-1)
890    MinIndex_i=0;
891end
892if isequal(MinIndex_j,-1)
893    MinIndex_j=0;
894end
895MinIndex_i_table=get(handles.MinIndex_i,'Data');%retrieve the min indices in the table MinIndex
896MinIndex_j_table=get(handles.MinIndex_j,'Data');%retrieve the min indices in the table MinIndex
897MaxIndex_i_table=get(handles.MaxIndex_i,'Data');%retrieve the min indices in the table MinIndex
898MaxIndex_j_table=get(handles.MaxIndex_j,'Data');%retrieve the min indices in the table MinIndex
899if ~isempty(MinIndex_i)&&~isempty(MaxIndex_i)
900    MinIndex_i_table(iview,1)=MinIndex_i;
901    MaxIndex_i_table(iview,1)=MaxIndex_i;
902end
903if ~isempty(MinIndex_j)&&~isempty(MaxIndex_j)
904    MinIndex_j_table(iview,1)=MinIndex_j;
905    MaxIndex_j_table(iview,1)=MaxIndex_j;
906end
907set(handles.MinIndex_i,'Data',MinIndex_i_table)%display the min indices in the table MinIndex
908set(handles.MinIndex_j,'Data',MinIndex_j_table)%display the max indices in the table MaxIndex
909set(handles.MaxIndex_i,'Data',MaxIndex_i_table)%display the min indices in the table MinIndex
910set(handles.MaxIndex_j,'Data',MaxIndex_j_table)%display the max indices in the table MaxIndex
911SeriesData=get(handles.series,'UserData');
912
913%% adjust the first and last indices for the selected series, only if requested by the bounds
914% i index, compare input to min index i
915first_i=str2num(get(handles.num_first_i,'String'));%retrieve previous first i
916% ref_i=str2num(get(handles.num_ref_i,'String'));%index i given by the input field
917ref_i=1;
918if isfield(SeriesData,'ref_i')
919    ref_i=SeriesData.ref_i;
920end
921if isempty(first_i)
922    first_i=ref_i;% first_i updated by the input value
923elseif first_i < MinIndex_i
924    first_i=MinIndex_i; % first_i set to the min i index (restricted by oter input lines)
925elseif first_i >MaxIndex_i
926    first_i=MaxIndex_i;% first_i set to the max i index (restricted by oter input lines)
927end
928% j index,  compare input to min index j
929first_j=str2num(get(handles.num_first_j,'String'));
930ref_j=1;
931if isfield(SeriesData,'ref_j')
932    ref_j=SeriesData.ref_j;
933end
934if isempty(first_j)
935    first_j=ref_j;% first_j updated by the input value
936elseif first_j<MinIndex_j
937    first_j=MinIndex_j; % first_j set to the min j index (restricted by oter input lines)
938elseif first_j >MaxIndex_j
939    first_j=MaxIndex_j; % first_j set to the max j index (restricted by oter input lines)
940end
941% i index, compare input to max index i
942last_i=str2num(get(handles.num_last_i,'String'));
943if isempty(last_i)
944    last_i=ref_i;
945elseif last_i > MaxIndex_i
946    last_i=MaxIndex_i;
947elseif last_i<first_i
948    last_i=first_i;
949end
950% j index, compare input to max index j
951last_j=str2num(get(handles.num_last_j,'String'));
952if isempty(last_j)
953    last_j=ref_j;
954elseif last_j>MaxIndex_j
955    last_j=MaxIndex_j;
956elseif last_j<first_j
957    last_j=first_j;
958end
959set(handles.num_first_i,'String',num2str(first_i));
960set(handles.num_first_j,'String',num2str(first_j));
961set(handles.num_last_i,'String',num2str(last_i));
962set(handles.num_last_j,'String',num2str(last_j));
963
964%% number of slices set by default
965NbSlice=[];%default
966% read  value set by the first series for the append mode (iwiew >1)
967if iview>1 && strcmp(get(handles.num_NbSlice,'Visible'),'on')
968    NbSlice=str2double(get(handles.num_NbSlice,'String'));
969end
970
971%% default time settings
972TimeUnit='';
973% read  value set by the first series for the append mode (iwiew >1)
974if iview>1
975    TimeUnit=get(handles.TimeUnit,'String');
976end
977TimeName='';
978Time=[];%default
979TimeMin=[];
980TimeFirst=[];
981TimeLast=[];
982TimeMax=[];
983
984%%  read image documentation file if found
985XmlData=[];
986check_calib=0;
987XmlFileName=find_imadoc(InputTable{iview,1},InputTable{iview,2},InputTable{iview,3},InputTable{iview,5});
988if ~isempty(XmlFileName)
989    [XmlData,errormsg]=imadoc2struct(XmlFileName);
990    if ~isempty(errormsg)
991        msgbox_uvmat('WARNING',['error in reading ' XmlFileName ': ' errormsg]);
992    end
993    % read time if available
994    if isfield(XmlData,'Time')
995        Time=XmlData.Time;
996        TimeName='xml';
997%                         if XmlData.Time(1,:)==XmlData.Time(2,:)% case starting with index 1
998%                     sizDti=size(XmlData.Time,1)-1;%size of the time vector explicitly defined in the xml file
999%                     ind_start=1;
1000%                 else
1001%                     sizDti=size(XmlData.Time,1);% case starting with index 0
1002%                     ind_start=0;
1003%                 end
1004%         % complement the input if the whole time series is not defined
1005%             if size(i1_series,3)>size(XmlData.Time,1)-ind_start %only the first time interval is defined, extrapolate to the whole series
1006%                 Dti_total=XmlData.Time(end)-XmlData.Time(1);%total time interval covered by the time vector
1007%                 missing_indices=sizDti+1+ind_start:size(i1_series,3)+1;% remaining set of frame indices for which time needs to be found
1008%                 repeat_nbre=1+floor((missing_indices-sizDti-ind_start)/(sizDti-1));% number of repetitions of Dti
1009%                 time_indices=1+mod(missing_indices-sizDti-1,sizDti-1);
1010%                 for j=1:size(XmlData.Time,2)
1011%                 Time(missing_indices,j)=XmlData.Time(time_indices,j)+repeat_nbre'*Dti_total;
1012%                 end
1013%                 % update the xml file with NbDti
1014%                 t=xmltree(XmlFileName);
1015%                 uid_NbDti=find(t,'ImaDoc/Camera/BurstTiming/NbDti')
1016%                 if isempty(uid_NbDti)
1017%                     uid_BurstTiming=find(t,'ImaDoc/Camera/BurstTiming')
1018%                     [t,uid_NbDti]=add(t,uid_BurstTiming,'element','NbDti');
1019%                 end
1020%                 [t,uid_NbDti]=add(t,uid_NbDti,'chardata',num2str(repeat_nbre(end)-1));
1021%                 save(t,XmlFileName)
1022%             end
1023    end
1024    if isfield(XmlData,'Camera')
1025        %         if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice)
1026        %             if iview>1 && ~isempty(NbSlice) && ~strcmp(NbSlice,XmlData.Camera.NbSlice)
1027        %                 msgbox_uvmat('WARNING','inconsistent number of slices with the first field series');
1028        %             end
1029        %             NbSlice=XmlData.Camera.NbSlice;% Nbre of slices from camera
1030        %         end
1031        if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit)
1032            if iview>1 && ~isempty(TimeUnit) && ~strcmp(TimeUnit,XmlData.Camera.TimeUnit)
1033                msgbox_uvmat('WARNING','inconsistent time unit with the first field series');
1034            end
1035            TimeUnit=XmlData.Camera.TimeUnit;
1036        end
1037    end
1038    % number of slices
1039    if isfield(XmlData,'TranslationMotor')&& isfield(XmlData.TranslationMotor,'NbSlice')
1040        NbSlice_motor=XmlData.TranslationMotor.NbSlice;
1041        if ~isempty(NbSlice) && ~isequal(NbSlice_motor,NbSlice)
1042                msgbox_uvmat('WARNING','inconsistent Z numbers of Z indices');
1043        else
1044            NbSlice=NbSlice_motor;
1045        end
1046    end
1047   
1048    if isfield(XmlData,'GeometryCalib')
1049        check_calib=1;
1050        if isfield(XmlData.GeometryCalib,'SliceCoord')
1051            siz=size(XmlData.GeometryCalib.SliceCoord);
1052            if ~isempty(NbSlice)&& ~isequal(size(1),NbSlice)
1053                msgbox_uvmat('WARNING','inconsistent numbers of Z indices between motor and calibration');
1054            else
1055                NbSlice=siz(1);
1056            end
1057        end
1058    end
1059end
1060if ~isempty(NbSlice)
1061set(handles.num_NbSlice,'String',num2str(NbSlice))
1062set(handles.num_NbSlice,'Visible','on')
1063end
1064
1065%% read timing  from the current file (prioritary)
1066if ~isempty(VideoObject)% case of movies
1067    imainfo=get(VideoObject);
1068    if isempty(j1_series); %frame index along i
1069        Time=zeros(imainfo.NumberOfFrames+1,2);
1070        Time(:,2)=(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate)';
1071    else
1072        Time=[0;ones(size(i1_series,3)-1,1)]*(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate);
1073    end
1074    TimeName='video';
1075end
1076
1077
1078%% determine the min and max times: case of Netcdf files will be treated later in FieldName_Callback
1079if ~isempty(TimeName)
1080    TimeMin=Time(MinIndex_i+1,MinIndex_j+1);
1081    if size(Time)>=[first_i+1 first_j+1]
1082        TimeFirst=Time(first_i+1,first_j+1);
1083    end
1084    if size(Time)>=[last_i+1 last_j+1]
1085        TimeLast=Time(last_i+1,last_j+1);
1086    end
1087    if size(Time)>=[MaxIndex_i+1 MaxIndex_j+1];
1088        TimeMax=Time(MaxIndex_i+1,MaxIndex_j+1);
1089    end
1090end
1091
1092%% update the time table
1093TimeTable=get(handles.TimeTable,'Data');
1094TimeTable{iview,1}=TimeName;
1095TimeTable{iview,2}=TimeMin;
1096TimeTable{iview,3}=TimeFirst;
1097TimeTable{iview,4}=TimeLast;
1098TimeTable{iview,5}=TimeMax;
1099set(handles.TimeTable,'Data',TimeTable)
1100
1101%% update the series info in 'UserData'
1102SeriesData.i1_series{iview}=i1_series;
1103SeriesData.i2_series{iview}=i2_series;
1104SeriesData.j1_series{iview}=j1_series;
1105SeriesData.j2_series{iview}=j2_series;
1106SeriesData.FileType{iview}=FileInfo.FileType;
1107SeriesData.FileInfo{iview}=FileInfo;
1108SeriesData.Time{iview}=Time;
1109% if ~isempty(TimeName)
1110%     SeriesData.TimeSource=TimeSource;
1111% end
1112if check_calib
1113    SeriesData.GeometryCalib{iview}=XmlData.GeometryCalib;
1114end
1115set(handles.series,'UserData',SeriesData)
1116
1117%% update pair menus
1118hset_pair=findobj(allchild(0),'Tag','set_pairs');
1119if ~isempty(hset_pair), delete(hset_pair); end % delete the GUI set_pair if opened
1120CheckPair= ~isempty(i2_series)||~isempty(j2_series); % check whether index pairs need to be defined
1121PairString=get(handles.PairString,'Data');
1122if CheckPair% if pairs need to be display for line iview
1123    [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series);
1124    Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,ModeMenu{ModeValue},Time,TimeUnit,ref_i,ref_j,TimeName,InputTable(iview,:),FileInfo);
1125    PairString{iview,1}=Menu{1};
1126else
1127    PairString{iview,1}='';%no pair for #iview
1128end
1129set(handles.PairString,'Data',PairString)
1130if isempty(find(cellfun('isempty',get(handles.PairString,'Data'))==0, 1))% if all lines of pairs are empty
1131    set(handles.PairString,'Visible','off')
1132    set(handles.SetPairs,'Visible','off')
1133else
1134    set(handles.PairString,'Visible','on')
1135    set(handles.SetPairs,'Visible','on')
1136end
1137
1138
1139%% display the set of existing files as an image
1140set(handles.FileStatus,'Units','pixels')
1141Position=get(handles.FileStatus,'Position');
1142set(handles.FileStatus,'Units','normalized')
1143%xI=0.5:Position(3)-0.5;
1144nbview=numel(SeriesData.i1_series);
1145j_max=cell(1,nbview);
1146MaxIndex_i=ones(1,nbview);%default
1147MinIndex_i=ones(1,nbview);%default
1148for iline=1:nbview
1149    pair_max=squeeze(max(SeriesData.i1_series{iline},[],1)); %max on pair index
1150    j_max{iline}=max(pair_max,[],1);%max on j index
1151    if ~isempty(j_max{iline})
1152    MaxIndex_i(iline)=max(find(j_max{iline}))-1;% max ref index i
1153    MinIndex_i(iline)=min(find(j_max{iline}))-1;% min ref index i
1154    end
1155end
1156MinIndex_i=min(MinIndex_i);
1157MaxIndex_i=max(MaxIndex_i);
1158range_index=MaxIndex_i-MinIndex_i+1;
1159range_y=max(1,floor(Position(4)/nbview));
1160npx=floor(Position(3));
1161file_indices=MinIndex_i+floor(((0.5:npx-0.5)/npx)*range_index)+1;
1162CData=zeros(nbview*range_y,npx);% initiate the image representing the existing files
1163for iline=1:nbview
1164    ind_y=1+(iline-1)*range_y:iline*range_y;
1165    LineData=zeros(size(file_indices));
1166    file_select=file_indices(file_indices<=numel(j_max{iline}));
1167    ind_select=find(file_indices<=numel(j_max{iline}));
1168    LineData(ind_select)=j_max{iline}(file_select)~=0;
1169    CData(ind_y,:)=ones(size(ind_y'))*LineData;
1170end
1171CData=cat(3,zeros(size(CData)),CData,zeros(size(CData)));%make color images r=0,g,b=0
1172set(handles.FileStatus,'CData',CData);
1173
1174%-----------------------------------------------------------guide -------------
1175%------------------------------------------------------------------------
1176%  III - FUNCTIONS ASSOCIATED TO THE FRAME IndexRange
1177%------------------------------------------------------------------------
1178
1179
1180% ---- determine the menu to put in mode and advice a default choice
1181%------------------------------------------------------------------------
1182function [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series)
1183%------------------------------------------------------------------------   
1184ModeMenu={''};
1185if isempty(j2_series)% no j pair
1186    ModeValue=1;
1187    if ~isempty(i2_series)
1188        ModeMenu={'series(Di)'}; % pair menu with only option Di
1189    end
1190else %existence of j pairs
1191    pair_max=squeeze(max(i1_series,[],1)); %max on pair index
1192    j_max=max(pair_max,[],1);
1193    MaxIndex_i=find(j_max, 1, 'last' )-1;% max ref index i
1194    MinIndex_i=find(j_max, 1 )-1;% min ref index i
1195    i_max=max(pair_max,[],2);
1196    MaxIndex_j=find(i_max, 1, 'last' )-1;% max ref index i
1197    MinIndex_j=find(i_max, 1 )-1;% min ref index i
1198    if MaxIndex_j==MinIndex_j
1199        ModeValue=1;
1200        ModeMenu={'bursts'};
1201    elseif MaxIndex_i==MinIndex_i
1202        ModeValue=1;
1203        ModeMenu={'series(Dj)'};
1204    else
1205        ModeMenu={'bursts';'series(Dj)'};
1206        if (MaxIndex_j-MinIndex_j)>10
1207            ModeValue=2;%set mode to series(Dj) if more than 10 j values
1208        else
1209            ModeValue=1;
1210        end
1211    end
1212end
1213
1214
1215%------------------------------------------------------------------------
1216function displ_pair=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,time,TimeUnit,ref_i,ref_j,TimeName,InputTable,FileInfo)
1217%------------------------------------------------------------------------
1218displ_pair={};
1219if isempty(TimeUnit)
1220    dtunit='e-03';
1221else
1222    dtunit=['m' TimeUnit];
1223end
1224switch mode
1225    case 'series(Di)'
1226        diff_i=i2_series-i1_series;
1227        min_diff=min(diff_i(diff_i>0));
1228        max_diff=max(diff_i(diff_i>0));
1229        for ipair=min_diff:max_diff
1230            if numel(diff_i(diff_i==ipair))>0
1231                pair_string=['Di= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1232                if ~isempty(time)
1233                    if ref_i<=floor(ipair/2)
1234                        ref_i=floor(ipair/2)+1;% shift ref_i to get the first pair
1235                    end
1236                    Dt=time(ref_i+ceil(ipair/2),ref_j)-time(ref_i-floor(ipair/2),ref_j);
1237                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1238                end
1239                displ_pair=[displ_pair;{pair_string}];
1240            end
1241        end
1242        if ~isempty(displ_pair)
1243            displ_pair=[displ_pair;{'Di=*|*'}];
1244        end
1245    case 'series(Dj)'
1246        if isempty(j2_series)
1247            msgbox_uvmat('ERROR','no j1-j2 pair available')
1248            return
1249        end
1250        diff_j=j2_series-j1_series;
1251        min_diff=min(diff_j(diff_j>0));
1252        max_diff=max(diff_j(diff_j>0));
1253        for ipair=min_diff:max_diff
1254            if numel(diff_j(diff_j==ipair))>0
1255                pair_string=['Dj= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1256                if ~isempty(time)
1257                    if ref_j<=floor(ipair/2)
1258                        ref_j=floor(ipair/2)+1;% shift ref_i to get the first pair
1259                    end
1260                    Dt=time(ref_i,ref_j+ceil(ipair/2))-time(ref_i,ref_j-floor(ipair/2));
1261                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1262                end
1263                displ_pair=[displ_pair;{pair_string}];
1264            end
1265        end
1266        if ~isempty(displ_pair)
1267            displ_pair=[displ_pair;{'Dj=*|*'}];
1268        end
1269    case 'bursts'
1270        if isempty(j2_series)
1271            msgbox_uvmat('ERROR','no j1-j2 pair available')
1272            return
1273        end
1274        %diff_j=j2_series-j1_series;
1275        min_j1=min(j1_series(j1_series>0));
1276        max_j1=max(j1_series(j1_series>0));
1277        min_j2=min(j2_series(j2_series>0));
1278        max_j2=max(j2_series(j2_series>0));
1279        for pair1=min_j1:min(max_j1,min_j1+20)
1280            for pair2=min_j2:min(max_j2,min_j2+20)
1281                if numel(j1_series(j1_series==pair1))>0 && numel(j2_series(j2_series==pair2))>0
1282                    pair_string=['j= ' num2str(pair1) '-' num2str(pair2)];
1283                    [TimeValue,DtValue]=get_time(ref_i,[],pair_string,InputTable,FileInfo,TimeName,'Dt');
1284                    %Dt=time(ref_i,pair2+1)-time(ref_i,pair1+1);
1285                    pair_string=[pair_string ', Dt=' num2str(DtValue) ' ' dtunit];
1286                    displ_pair=[displ_pair;{pair_string}];
1287                end
1288            end
1289        end
1290        if ~isempty(displ_pair)
1291            displ_pair=[displ_pair;{'j=*-*'}];
1292        end
1293end
1294
1295%------------------------------------------------------------------------
1296function num_first_i_Callback(hObject, eventdata, handles)
1297%------------------------------------------------------------------------
1298num_last_i_Callback(hObject, eventdata, handles)
1299
1300%------------------------------------------------------------------------
1301function num_last_i_Callback(hObject, eventdata, handles)
1302%------------------------------------------------------------------------
1303SeriesData=get(handles.series,'UserData');
1304if ~isfield(SeriesData,'Time')
1305    SeriesData.Time{1}=[];
1306end
1307displ_time(handles);
1308
1309%------------------------------------------------------------------------
1310function num_first_j_Callback(hObject, eventdata, handles)
1311%------------------------------------------------------------------------
1312 num_last_j_Callback(hObject, eventdata, handles)
1313
1314%------------------------------------------------------------------------
1315function num_last_j_Callback(hObject, eventdata, handles)
1316%------------------------------------------------------------------------
1317% first_j=str2num(get(handles.num_first_j,'String'));
1318% last_j=str2num(get(handles.num_last_j,'String'));
1319% ref_j=ceil((first_j+last_j)/2);
1320% set(handles.num_ref_j,'String', num2str(ref_j))
1321% num_ref_j_Callback(hObject, eventdata, handles)
1322SeriesData=get(handles.series,'UserData');
1323if ~isfield(SeriesData,'Time')
1324    SeriesData.Time{1}=[];
1325end
1326displ_time(handles);
1327
1328%------------------------------------------------------------------------
1329% ---- find the times corresponding to the first and last indices of a series
1330function displ_time(handles)
1331%------------------------------------------------------------------------
1332SeriesData=get(handles.series,'UserData');%
1333if ~isfield(SeriesData,'Time')
1334    return
1335end
1336PairString=get(handles.PairString,'Data');
1337ref_i_1=str2num(get(handles.num_first_i,'String'));%first reference index
1338ref_i_2=str2num(get(handles.num_last_i,'String'));%last reference index
1339ref_j_1=[];ref_j_2=[];
1340if strcmp(get(handles.num_first_j,'Visible'),'on')
1341ref_j_1=str2num(get(handles.num_first_j,'String'));
1342ref_j_2=str2num(get(handles.num_last_j,'String'));
1343end
1344[i1_1,i2_1,j1_1,j2_1] = get_file_index(ref_i_1,ref_j_1,PairString);
1345[i1_2,i2_2,j1_2,j2_2] = get_file_index(ref_i_2,ref_j_2,PairString);
1346TimeTable=get(handles.TimeTable,'Data');
1347%%%%%%
1348%TODO: read time in netcdf file, see ActionName_Callback
1349%%%%%%%
1350%Pairs=get(handles.PairString,'Data');
1351for iview=1:size(TimeTable,1)
1352    if size(SeriesData.Time,1)<iview
1353        break
1354    end
1355    TimeTable{iview,3}=[];
1356    TimeTable{iview,4}=[];
1357    if size(SeriesData.Time{iview},1)>=i2_2+1 && (isempty(ref_j_1)||size(SeriesData.Time{iview},2)>=j2_2+1)
1358        if isempty(ref_j_1)
1359            time_first=(SeriesData.Time{iview}(i1_1+1,2)+SeriesData.Time{iview}(i2_1+1,2))/2;
1360            time_last=(SeriesData.Time{iview}(i1_2+1,2)+SeriesData.Time{iview}(i2_2+1,2))/2;
1361        else
1362            time_first=(SeriesData.Time{iview}(i1_1+1,j1_1+1)+SeriesData.Time{iview}(i2_1+1,j2_1+1))/2;
1363            time_last=(SeriesData.Time{iview}(i1_2+1,j1_2+1)+SeriesData.Time{iview}(i2_2+1,j2_1+1))/2;
1364        end
1365        TimeTable{iview,3}=time_first; %TODO: take into account pairs
1366        TimeTable{iview,4}=time_last; %TODO: take into account pairs
1367    end
1368end
1369set(handles.TimeTable,'Data',TimeTable)
1370
1371%% set the waitbar position with respect to the min and max in the series
1372MinIndex_i=min(get(handles.MinIndex_i,'Data'));
1373MaxIndex_i=max(get(handles.MaxIndex_i,'Data'));
1374pos_first=(ref_i_1-MinIndex_i)/(MaxIndex_i-MinIndex_i+1);
1375pos_last=(ref_i_2-MinIndex_i+1)/(MaxIndex_i-MinIndex_i+1);
1376if isempty(pos_first), pos_first=0; end
1377if isempty(pos_last), pos_last=1; end
1378Position=get(handles.Waitbar,'Position');% position of the waitbar:= [ x,y, width, height]
1379Position_status=get(handles.FileStatus,'Position');
1380Position(1)=Position_status(1)+Position_status(3)*pos_first;
1381Position(3)=max(Position_status(3)*(pos_last-pos_first),0.001);% width must remain positive
1382set(handles.Waitbar,'Position',Position)
1383update_waitbar(handles.Waitbar,0)
1384
1385%------------------------------------------------------------------------
1386% --- Executes when selected cell(s) is changed in PairString.
1387function PairString_CellSelectionCallback(hObject, eventdata, handles)
1388%------------------------------------------------------------------------   
1389if numel(eventdata.Indices)>=1
1390    PairString=get(hObject,'Data');
1391    if ~isempty(PairString{eventdata.Indices(1)})
1392        SetPairs_Callback(hObject, eventdata.Indices(1), handles)
1393    end
1394end
1395
1396%-------------------------------------
1397function enable_i(handles,state)
1398set(handles.i_txt,'Visible',state)
1399set(handles.num_first_i,'Visible',state)
1400set(handles.num_last_i,'Visible',state)
1401set(handles.num_incr_i,'Visible',state)
1402
1403%-----------------------------------
1404function enable_j(handles,state)
1405set(handles.j_txt,'Visible',state)
1406set(handles.num_first_j,'Visible',state)
1407set(handles.num_last_j,'Visible',state)
1408set(handles.num_incr_j,'Visible',state)
1409set(handles.MinIndex_j,'Visible',state)
1410set(handles.MaxIndex_j,'Visible',state)
1411
1412
1413%%%%%%%%%%%%%%%%%%%%
1414%%  MAIN ActionName FUNCTIONS
1415%%%%%%%%%%%%%%%%%%%%
1416%------------------------------------------------------------------------
1417% --- Executes on button press in RUN.
1418%------------------------------------------------------------------------
1419function RUN_Callback(hObject, eventdata, handles)
1420
1421%% settings of the button RUN
1422set(handles.RUN,'BusyAction','queue');% activation of STOP button will set BusyAction to 'cancel'
1423set(handles.RUN, 'Enable','Off')% avoid further RUN action until the current one is finished
1424set(handles.RUN,'BackgroundColor',[1 1 0])%show activation of RUN by yellow color
1425drawnow
1426set(handles.status,'Value',0)% desable status display if relevant
1427status_Callback([], eventdata, handles)
1428
1429%% launch action
1430errormsg=launch_action(handles);
1431if ~isempty(errormsg)
1432     msgbox_uvmat('ERROR',errormsg)
1433end
1434
1435%% reset the GUI series
1436update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate launching is finished
1437set(handles.RUN, 'Enable','On')
1438set(handles.RUN,'BackgroundColor',[1 0 0])
1439set(handles.RUN, 'Value',0)
1440
1441%------------------------------------------------------------------------
1442% --- called by RUN_Callback
1443%------------------------------------------------------------------------
1444function errormsg=launch_action(handles)
1445errormsg='';%default
1446
1447%% read the data on the GUI series
1448Param=read_GUI_series(handles);%displayed parameters
1449SeriesData=get(handles.series,'UserData');%hidden parameters
1450if isfield(SeriesData,'TransformInput')
1451    Param.TransformInput=SeriesData.TransformInput;
1452end
1453if ~isfield(SeriesData,'i1_series')
1454    errormsg='The input field series needs to be refreshed: press REFRESH';
1455    return
1456end
1457if isfield(Param,'InputFields')&& isfield(Param.InputFields,'FieldName')&& isequal(Param.InputFields.FieldName,'get_field...')
1458    errormsg='input field name(s) not defined, select get_field...';
1459    return
1460end
1461
1462%% select the Action mode, 'local', 'background' or 'cluster' (if available)
1463RunMode='local';%default (needed for first opening of the GUI series)
1464if isfield(Param.Action,'RunMode')
1465    RunMode=Param.Action.RunMode;
1466    Param.Action=rmfield(Param.Action,'RunMode');%remove from the recorded xml file to avoid interference during ImportConfig
1467end
1468ActionExt='.m';%default
1469if isfield(Param.Action,'ActionExt')
1470    ActionExt=Param.Action.ActionExt;% '.m', '.sh' (compiled)  or '.py' (Python)
1471    Param.Action=rmfield(Param.Action,'ActionExt');%remove from the recorded xml file to avoid interference during ImportConfig
1472end
1473ActionName=Param.Action.ActionName;
1474ActionPath=Param.Action.ActionPath;
1475path_series=fileparts(which('series'));
1476
1477%% create the Action fct handle if RunMode option = 'local'
1478if strcmp(RunMode,'local')
1479    if ~isequal(ActionPath,path_series)
1480        eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
1481        if ~exist(ActionPath,'dir')
1482            errormsg=['The prescribed function path ' ActionPath ' does not exist'];
1483            return
1484        end
1485        if ~isequal(spath,ActionPath)
1486            addpath(ActionPath)% add the prescribed path if not the current one
1487        end
1488    end
1489    eval(['h_fun=@' ActionName ';'])%create a function handle for ACTION
1490    if ~isequal(ActionPath,path_series)
1491        rmpath(ActionPath)% add the prescribed path if not the current one
1492    end
1493end
1494
1495%% Get  PARAM.xml (not used at this stage)
1496errormsg='';%default error message
1497xmlfile=fullfile(path_series,'PARAM.xml');
1498if ~exist(xmlfile,'file')
1499    [success,message]=copyfile(fullfile(path_series,'PARAM.xml.default'),xmlfile);
1500end
1501if strcmp(ActionExt,'.sh')
1502    if exist(xmlfile,'file')
1503        s=xml2struct(xmlfile);
1504        if strcmp(RunMode,'cluster_oar') && isfield(s,'BatchParam')
1505            if isfield(s.BatchParam,'NbCore')
1506                NbCore=s.BatchParam.NbCore;
1507            end
1508        elseif (strcmp(RunMode,'background')||strcmp(RunMode,'local')) && isfield(s,'RunParam')
1509            if isfield(s.RunParam,'NbCore')
1510                NbCore=s.RunParam.NbCore;
1511            end
1512        end
1513    end
1514end
1515ActionFullName=fullfile(get(handles.ActionPath,'String'),ActionName);
1516
1517%% If a compiled version has been selected (ext .sh) check wether it needs to be recompiled
1518if strcmp(ActionExt,'.sh')
1519    TransformPath='';
1520    if ~isempty(get(handles.ActionExt,'UserData'))
1521        TransformPath=get(handles.ActionExt,'UserData');
1522    end
1523    set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
1524    set(handles.ActionExt,'BackgroundColor',[1 1 0])
1525    [mcrmajor, mcrminor] = mcrversion;   
1526    MCRROOT = ['MCRROOT',int2str(mcrmajor),int2str(mcrminor)];
1527    RunTime = getenv(MCRROOT);
1528    ActionNameVersion=[ActionName '_' MCRROOT];
1529    ActionFullName=fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']);
1530    % compile the .m file if the .sh file does not exist yet
1531    if ~exist(ActionFullName,'file')
1532        answer=msgbox_uvmat('INPUT_Y-N','compiled version has not been created: compile now?');
1533        if strcmp(answer,'Yes')
1534            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1535            path_uvmat=fileparts(which('series'));
1536            currentdir=pwd;
1537            cd(get(handles.ActionPath,'String'))% go to the directory of Action
1538            addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1539            compile(ActionName,TransformPath)
1540            cd(currentdir)
1541        else
1542            errormsg='Action launch interrupted';
1543            return
1544        end       
1545    else
1546        sh_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']));
1547        m_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionName '.m']));
1548        if isfield(m_file_info,'datenum') && m_file_info.datenum>sh_file_info.datenum
1549            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1550            drawnow
1551            answer=msgbox_uvmat('INPUT_Y-N',[ActionNameVersion '.sh needs to be updated: recompile now?']);
1552            if strcmp(answer,'Yes')
1553                path_uvmat=fileparts(which('series'));
1554                currentdir=pwd;
1555                cd(get(handles.ActionPath,'String'))% go to the directory of Action
1556                addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1557                addpath(fullfile(path_uvmat,'transform_field'))% add the path to uvmat to run the fct 'compile'
1558                compile(ActionName,TransformPath)
1559                cd(currentdir)
1560            end
1561        end
1562    end
1563
1564    set(handles.ActionExt,'BackgroundColor',[1 1 1])
1565     set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch
1566end
1567
1568%% set nbre of cluster cores and processes:
1569% NbCore is the number of computer processors used
1570% NbProcess is the number of independent processes in which the required calculation is split.
1571switch RunMode
1572    case {'local','background'}
1573        NbCore=1;% no need to split the calculation
1574    case 'cluster_oar'
1575        %%%%% TEST A REMETTRE%%%%%
1576 %       if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1577%             NbCore=1;% one core used only (limitation of Matlab licences)
1578%             answer=msgbox_uvmat('INPUT_Y-N','Number of cores =1: select the compiled version .sh for multi-core processing. Proceed with the .m version?');
1579%             if ~strcmp(answer,'Yes')
1580%                 errormsg='Action launch interrupted by user';
1581%                 return
1582%             end
1583%             extra_oar='';
1584 %       else
1585            answer=inputdlg({'Number of cores (max 36)','extra oar options'},'oarsub parameter',1,{'16',''});
1586            if isempty(answer)
1587                                errormsg='Action launch interrupted by user';
1588                return
1589            end
1590            NbCore=str2double(answer{1});
1591            extra_oar=answer{2};
1592 %       end
1593    case 'cluster_pbs'
1594        if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1595            NbCore=1;% one core used only (limitation of Matlab licences)
1596            answer=msgbox_uvmat('INPUT_Y-N','Number of cores =1: select the compiled version .sh for multi-core processing. Proceed with the .m version?');
1597            if ~strcmp(answer,'Yes')
1598                errormsg='Action launch interrupted';
1599                return
1600            end
1601            extra_oar='';
1602        else
1603            answer=inputdlg({'Number of cores (max 36)','extra oar options'},'oarsub parameter',1,{'12',''});
1604            NbCore=str2double(answer{1});
1605            %extra_oar=answer{2};%TODO : fix this for LMFA cluster. Maybe
1606            %extrs_oar and extra_pbs are not the best names
1607        end
1608end
1609if ~isfield(Param.IndexRange,'NbSlice')
1610    Param.IndexRange.NbSlice=[];
1611end
1612
1613%% create the output data directory if needed
1614OutputDir='';
1615if isfield(Param,'OutputSubDir')
1616    SubDirOut=[get(handles.OutputSubDir,'String') Param.OutputDirExt];
1617    SubDirOutNew=SubDirOut;
1618    detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exist
1619    check_create=1; %need to create the result directory by default
1620    CheckOverwrite=1;
1621    if isfield(Param,'CheckOverwrite')
1622        CheckOverwrite=Param.CheckOverwrite;
1623    end
1624    while detect
1625        if CheckOverwrite
1626            comment=', possibly overwrite previous data';
1627        else
1628            comment=', will complement existing result files (no overwriting)';
1629        end
1630        answer=msgbox_uvmat('INPUT_Y-N-Cancel',['use existing ouput directory: ' fullfile(Param.InputTable{1,1},SubDirOutNew) comment]);
1631        if strcmp(answer,'Cancel')
1632            return
1633        elseif strcmp(answer,'Yes')
1634            detect=0;
1635            check_create=0;
1636        else
1637            r=regexp(SubDirOutNew,'(?<root>.*\D)(?<num1>\d+)$','names');%detect whether name ends by a number
1638            if isempty(r)
1639                r(1).root=[SubDirOutNew '_'];
1640                r(1).num1='0';
1641            end
1642            SubDirOutNew=[r(1).root num2str(str2num(r(1).num1)+1)];%increment the index by 1 or put 1
1643            detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exists
1644            check_create=1;
1645        end
1646    end
1647    Param.OutputDirExt=regexprep(SubDirOutNew,Param.OutputSubDir,'');
1648    Param.OutputRootFile=Param.InputTable{1,3};% the first sorted RootFile taken for output
1649    set(handles.OutputDirExt,'String',Param.OutputDirExt)
1650    OutputDir=fullfile(Param.InputTable{1,1},[Param.OutputSubDir Param.OutputDirExt]);% full name (with path) of output directory
1651    if check_create    % create output directory if it does not exist
1652        [tild,msg1]=mkdir(OutputDir);
1653        if ~strcmp(msg1,'')
1654            errormsg=['cannot create ' OutputDir ': ' msg1];%error message for directory creation
1655            return
1656        end
1657    end
1658   
1659elseif isfield(Param,'ActionInput')&&isfield(Param.ActionInput,'LogPath')% custom definition of the output dir
1660    OutputDir=Param.ActionInput.LogPath;   
1661end
1662DirXml=fullfile(OutputDir,'0_XML');
1663if ~exist(DirXml,'dir')
1664    [~,msg1]=mkdir(DirXml);
1665    if ~strcmp(msg1,'')
1666        errormsg=['cannot create ' DirXml ': ' msg1];%error message for directory creation
1667        return
1668    end
1669end
1670OutputNomType=nomtype2pair(Param.InputTable{1,4});% nomenclature for output files
1671
1672%% get the set of reference input field indices
1673first_i=1;% first i index to process
1674last_i=1;% last i index to process
1675incr_i=1;% increment step in i index
1676first_j=1;% first j index to process
1677last_j=1;% last j index to process
1678incr_j=1;% increment step in j index
1679if isfield(Param.IndexRange,'first_i')
1680    first_i=Param.IndexRange.first_i;
1681    incr_i=Param.IndexRange.incr_i;
1682    last_i=Param.IndexRange.last_i;
1683end
1684if isfield(Param.IndexRange,'first_j')
1685    first_j=Param.IndexRange.first_j;
1686    last_j=Param.IndexRange.last_j;
1687    incr_j=Param.IndexRange.incr_j;
1688end
1689if last_i < first_i || last_j < first_j
1690    errormsg= 'series/Run_Callback:last field index must be larger or equal to the first one';
1691    return
1692end
1693%incr_i must be defined, =1 by default, if NbSlice is active
1694if isempty(incr_i)&& ~isempty(Param.IndexRange.NbSlice)
1695    incr_i=1;
1696    set(handles.num_incr_i,'String','1')
1697end
1698% case of no increment i defined: processing is done on the available files found in i1_series
1699if isempty(incr_i)
1700    if isempty(incr_j)
1701        [ref_j,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1702        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1703        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1704        ref_j=ref_j-1;
1705        ref_i=ref_i-1;
1706    else
1707        ref_j=first_j:incr_j:last_j;
1708        [tild,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1709        ref_i=ref_i-1;
1710        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1711    end
1712    % increment i is defined: processing is done on first_i:incr_i:last_i;
1713else
1714    ref_i=first_i:incr_i:last_i;
1715    if isempty(incr_j)% automatic finding of the existing j indices
1716        [ref_j,tild]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1717        ref_j=ref_j-1;
1718        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1719    else
1720        ref_j=first_j:incr_j:last_j;
1721    end
1722end
1723CPUTime=1;% job time estimated at 1 min per iteration (on index i and j) by default
1724if isfield(Param.Action, 'CPUTime') && ~isempty(Param.Action.CPUTime)
1725    CPUTime=Param.Action.CPUTime;%Note: CpUTime for one iteration ref_i has to be multiplied by the number of j indices nbfield_j
1726end
1727nbfield_j=numel(ref_j); % number of j indices
1728BlockLength=numel(ref_i);% by default, job involves the full set of i field indices
1729NbProcess=1;
1730switch RunMode
1731    case {'cluster_oar','cluster_pbs'}
1732        if isempty(Param.IndexRange.NbSlice)% if NbSlice is not defined
1733            BlockLength= ceil(20/(CPUTime*nbfield_j));% short iterations are grouped such that the minimum time of a process is 20 min.
1734            BlockLength=max(BlockLength,ceil(numel(ref_i)/500));% possibly increase the BlockLength to have less than 500 jobs
1735            NbProcess=ceil(numel(ref_i)/BlockLength) ; % nbre of processes sent to oar
1736        else
1737            NbProcess=Param.IndexRange.NbSlice;% the parameter NbSlice sets the nbre of run processes
1738            NbCore=min(NbCore,NbProcess);% reduces the number of cores if it exceeds the number of processes
1739        end
1740    otherwise
1741        if ~isempty(Param.IndexRange.NbSlice)
1742            NbProcess=Param.IndexRange.NbSlice;% the parameter NbSlice sets the nbre of run processes
1743        end
1744end
1745
1746%% record nbre of output files and starting time for computation for status
1747StatusData=get(handles.status,'UserData');
1748if isfield(StatusData,'OutputFileMode')
1749    switch StatusData.OutputFileMode
1750        case 'NbInput'
1751            StatusData.NbOutputFile=numel(ref_i)*nbfield_j;
1752        case 'NbInput_i'
1753            StatusData.NbOutputFile=numel(ref_i);
1754        case 'NbSlice'
1755            StatusData.NbOutputFile=str2num(get(handles.num_NbSlice,'String'));
1756    end
1757end
1758StatusData.TimeStart=now;
1759set(handles.status,'UserData',StatusData)
1760
1761%% case of a function in Python
1762if strcmp(ActionExt, '.py (in dev.)')
1763    fprintf([
1764        '\n' ...
1765        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n' ...
1766        'The option .py is used. It is still in development.\n' ...
1767        'Do not use it unless you really know what you do!\n' ...
1768        'To try it, first install Pyp and the most recent version of FluidImage.\n' ...
1769        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'])
1770    RunMode = 'python';
1771end
1772
1773
1774%% direct processing on the current Matlab session or creation of command files
1775filexml=cell(1,NbProcess);% initialisation of the names of the files containing the processing parameters
1776extxml=cell(1,NbProcess); % initialisation of the set of labels used for the files documenting each process
1777for iprocess=1:NbProcess
1778    extxml{iprocess}='.xml';
1779end
1780for iprocess=1:NbProcess
1781    if ~strcmp(get(handles.RUN,'BusyAction'),'queue')% allow for STOP action
1782        disp('program stopped by user')
1783        return
1784    end
1785    if isempty(Param.IndexRange.NbSlice)
1786        Param.IndexRange.first_i=first_i+(iprocess-1)*BlockLength*incr_i;
1787        if Param.IndexRange.first_i>last_i
1788            NbProcess=iprocess-1;% leave the loop, we are at the end of the calculation
1789            break
1790        end
1791        Param.IndexRange.last_i=min(last_i,first_i+(iprocess)*BlockLength*incr_i-1);
1792    else %multislices (then incr_i is not empty)
1793        Param.IndexRange.first_i= first_i+iprocess-1;
1794        Param.IndexRange.incr_i=incr_i*Param.IndexRange.NbSlice;
1795    end
1796    for ilist=1:size(Param.InputTable,1)
1797        Param.InputTable{ilist,1}=regexprep(Param.InputTable{ilist,1},'\','/');%correct path name for PCWIN system
1798    end
1799   
1800    if isfield(Param,'OutputSubDir')
1801        t=struct2xml(Param);
1802        t=set(t,1,'name','Series');
1803        extxml{iprocess}=fullfile_uvmat('','',Param.InputTable{1,3},'.xml',OutputNomType,...
1804            Param.IndexRange.first_i,Param.IndexRange.last_i,first_j,last_j);
1805        filexml{iprocess}=fullfile(OutputDir,'0_XML',extxml{iprocess});
1806        try
1807            save(t, filexml{iprocess});% save the xml file containing the processing parameters
1808        catch ME
1809            if ~strcmp (RunMode,'local')
1810                errormsg=['error writting ' filexml{iprocess} ': ' ME.message];
1811                return
1812            end
1813        end
1814    end
1815    if strcmp (RunMode,'local')
1816        switch ActionExt
1817            case '.m'
1818                h_fun(Param);% direct launching
1819               
1820            case '.sh'
1821                switch computer
1822                    case {'PCWIN','PCWIN64'} %Windows system
1823                        filexml=regexprep(filexml,'\\','\\\\');% add '\' so that '\' are left as characters
1824                        system([ActionFullName ' ' RunTime ' ' filexml]);% TODO: adapt to DOS system
1825                    case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1826                        system([ActionFullName ' ' RunTime ' ' filexml]);
1827                end
1828        end
1829    end
1830end
1831
1832if ~strcmp (RunMode,'local') && ~strcmp(RunMode,'python')
1833    %% processing on a different session of the same computer (background) or cluster, create executable files
1834    batch_file_list=cell(NbProcess,1);% initiate the list of executable files
1835    DirExe=fullfile(OutputDir,'0_EXE');%directory name for executable files
1836    switch computer
1837        case {'PCWIN','PCWIN64'} %Windows system
1838            ExeExt='.bat';
1839        case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1840            ExeExt='.sh';
1841    end
1842    %create subdirectory for executable files
1843    if ~exist(DirExe,'dir')
1844        [tild,msg1]=mkdir(DirExe);
1845        if ~strcmp(msg1,'')
1846            errormsg=['cannot create ' DirExe ': ' msg1];%error message for directory creation
1847            return
1848        end
1849    end
1850    %create subdirectory for log files
1851    DirLog=fullfile(OutputDir,'0_LOG');
1852    if ~exist(DirLog,'dir')
1853        [tild,msg1]=mkdir(DirLog);
1854        if ~strcmp(msg1,'')
1855            errormsg=['cannot create ' DirLog ': ' msg1];%error message for directory creation
1856            return
1857        end
1858    end
1859   
1860    %create the executable file
1861    file_exe_global=fullfile_uvmat('','',Param.InputTable{1,3},ExeExt,OutputNomType,...
1862        first_i,last_i,first_j,last_j);
1863    file_exe_global=fullfile(OutputDir,'0_EXE',file_exe_global);
1864    filelog_global=fullfile_uvmat('','',Param.InputTable{1,3},'.log',OutputNomType,...
1865        first_i,last_i,first_j,last_j);
1866    filelog_global=fullfile(OutputDir,'0_LOG',filelog_global);
1867
1868    for iprocess=1:NbProcess
1869       
1870        %create the executable file
1871       
1872        batch_file_list{iprocess}=fullfile(OutputDir,'0_EXE',regexprep(extxml{iprocess},'.xml$',ExeExt));
1873       
1874        % set the log file name
1875        filelog{iprocess}=fullfile(OutputDir,'0_LOG',regexprep(extxml{iprocess},'.xml$','.log'));
1876       
1877    end
1878end
1879
1880%% launch the executable files for background or cluster processing
1881
1882switch RunMode
1883   
1884    case 'background'
1885        [fid,message]=fopen(file_exe_global,'w');
1886        if isequal(fid,-1)
1887            errormsg=['creation of ' file_exe_global ':' message];
1888            return
1889        end
1890        switch ActionExt
1891            case '.m'% Matlab function
1892                switch computer
1893                    case {'GLNX86','GLNXA64','MACI64'}
1894                        cmd=[...
1895                            '#!/bin/bash \n'...
1896                            'source /etc/profile \n'...
1897                            'matlab -nodisplay -nosplash -nojvm -logfile ''' filelog_global ''' <<END_MATLAB \n'...
1898                            'addpath(''' path_series '''); \n'...
1899                            'addpath(''' Param.Action.ActionPath '''); \n'];
1900                        for iprocess=1:NbProcess
1901                            cmd=[cmd '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'];
1902                        end
1903                        cmd=[cmd  'exit \n' 'END_MATLAB \n'];
1904                        fprintf(fid,cmd);%fill the executable file with the  char string cmd
1905                        fclose(fid);% close the executable file
1906                        system(['chmod +x ' file_exe_global]);% set the file to executable
1907                    case {'PCWIN','PCWIN64'}
1908                        cmd=['matlab -automation -logfile ' regexprep(filelog{iprocess},'\\','\\\\')...
1909                            ' -r "addpath(''' regexprep(path_series,'\\','\\\\') ''');'...
1910                            'addpath(''' regexprep(Param.Action.ActionPath,'\\','\\\\') ''');'];
1911                        for iprocess=1:NbProcess
1912                            cmd=[cmd '' Param.Action.ActionName  '( ''' regexprep(filexml{iprocess},'\\','\\\\') ''');']
1913                        end
1914                        cmd=[cmd ';exit"'];
1915                        fprintf(fid,cmd);%fill the executable file with the  char string cmd
1916                        fclose(fid);% close the executable file
1917                end
1918                system([file_exe_global ' &'])% directly execute the command file
1919            case '.sh' % compiled Matlab function
1920                for iprocess=1:NbProcess
1921                    switch computer
1922                        case {'GLNX86','GLNXA64','MACI64'}
1923                            [fid,message]=fopen(batch_file_list{iprocess},'w');% create the executable file
1924                            if isequal(fid,-1)
1925                                errormsg=['creation of .bat file: ' message];
1926                                return
1927                            end
1928                            cmd=['#!/bin/bash \n '...
1929                                '#$ -cwd \n '...
1930                                'hostname && date \n '...
1931                                'umask 002 \n'...
1932                                ActionFullName ' ' RunTime ' ' filexml{iprocess}];%allow writting access to created files for user group
1933                            fprintf(fid,cmd);%fill the executable file with the  char string cmd
1934                            fclose(fid);% close the executable file
1935                            system(['chmod +x ' batch_file_list{iprocess}]);% set the file to executable
1936                            system([batch_file_list{iprocess} ' &'])% directly execute the command file
1937                        case {'PCWIN','PCWIN64'}
1938                            msgbox_uvmat('ERROR','option for compiled Matlab functions not implemented for Windows system')
1939                            return
1940                    end
1941                end
1942                msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched in background: press STATUS to see results'])
1943        end
1944       
1945    case 'cluster_oar' % option 'oar-parexec' used
1946        %create subdirectory for oar commands
1947        for iprocess=1:NbProcess
1948            [fid,message]=fopen(batch_file_list{iprocess},'w');% create the executable file
1949            if isequal(fid,-1)
1950                errormsg=['creation of .bat file: ' message];
1951                return
1952            end
1953            if  strcmp(ActionExt,'.sh')
1954                cmd=['#!/bin/bash \n '...
1955                    '#$ -cwd \n '...
1956                    'hostname && date \n '...
1957                    'umask 002 \n'...
1958                    ActionFullName ' ' RunTime ' ' filexml{iprocess}];%allow writting access to created files for user group
1959            else
1960                matlab_ver = ver('MATLAB');
1961                matlab_version = matlab_ver.Version;
1962                cmd=[...
1963                    '#!/bin/bash \n'...
1964                    'source /etc/profile \n'...
1965                    'module load matlab/''' matlab_version ''' \n'...% CHOICE OF MATLAB VERSION
1966                    'matlab -nodisplay -nosplash -nojvm -singleCompThread -logfile ''' filelog{iprocess} ''' <<END_MATLAB \n'...
1967                    'addpath(''' path_series '''); \n'...
1968                    'addpath(''' Param.Action.ActionPath '''); \n'...
1969                    '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'...
1970                    'exit \n'...
1971                    'END_MATLAB \n'];
1972            end
1973            fprintf(fid,cmd);%fill the executable file with the  char string cmd
1974            fclose(fid);% close the executable file
1975            system(['chmod +x ' batch_file_list{iprocess}]);% set the file to executable
1976        end
1977        DirOAR=fullfile(OutputDir,'0_OAR');
1978        if exist(DirOAR,'dir')% delete the content of the dir 0_LOG to allow new input
1979            curdir=pwd;
1980            cd(DirOAR)
1981            delete('*')
1982            cd(curdir)
1983        else
1984            [tild,msg1]=mkdir(DirOAR);
1985            if ~strcmp(msg1,'')
1986                errormsg=['cannot create ' DirOAR ': ' msg1];%error message for directory creation
1987                return
1988            end
1989        end
1990        % create file containing the list of jobs
1991        filename_joblist=fullfile(DirOAR,'job_list.txt');% name of the file containing the list of executables
1992        fid=fopen(filename_joblist,'w');%open it for writting
1993        for iprocess=1:length(batch_file_list)
1994            fprintf(fid,[batch_file_list{iprocess} '\n']);% write list of exe files
1995        end
1996        fclose(fid);
1997        system(['chmod +x ' filename_joblist]);% set the file to executable
1998       
1999        filename_log=fullfile(DirLog,'job_list.stdout');%file for output messages of the master oar process
2000        filename_errors=fullfile(DirLog,'job_list.stderr');%file for error messages of the master oar process
2001        % the command job_list.txt contains the list of NbProcess independent individual jobs
2002        % in which the total calculation has been split. Those are written as executable files .sh in the folder /O_EXE.
2003        %  These individual jobs are grouped by the system as oar jobs on the NbCore processors.
2004        %  For each processor, the oar job must stop after the walltime which has been set, which is limited to 24 h.
2005        %  However, the oar job is automatically restarted (option 'idempotent') provided the individual jobs are
2006        % shorter than the wall time: in the time interval 'checkpoint' (WallTimeOneJob) before the end of the allowed duration,
2007        %  the oar job restarts when an individual job ends.
2008        JobTime=CPUTime*BlockLength*nbfield_j;% estimated time for one individual job (in minutes)
2009        % wall time (in hours ) for each oar job, allowing 10 individual jobs, but limited to 23 h:
2010        WallTimeTotal=min(23,4*JobTime/60);
2011        %disp(['WallTimeTotal: ' num2str(WallTimeTotal) ' hours'])
2012        % estimated time of an individual job (in min), with a margin of error
2013        WallTimeOneJob=min(4*JobTime+10,WallTimeTotal*60/2);% estimated max time of an individual job for checkpoint
2014        disp(['WallTimeOneJob: ' num2str(WallTimeOneJob) ' minutes'])
2015        oar_command=['oarsub -n UVmat_' ActionFullName ' '...
2016            '-t idempotent --checkpoint ' num2str(WallTimeOneJob*60) ' '...
2017            '-l /core=' num2str(NbCore) ','...
2018            'walltime=' datestr(WallTimeTotal/24,13) ' '...
2019            '-E ' filename_errors ' '...
2020            '-O ' filename_log ' '...
2021            extra_oar ' '...
2022            '"oar-parexec -s -f ' filename_joblist ' '...
2023            '-l ' filename_joblist '.log"'];
2024       
2025        fprintf(oar_command);% display  system command on the Matlab command window
2026        [status,result]=system(oar_command)% execute system command and show the result (ID number of the launched job) on the Matlab command window
2027        filename_oarcommand=fullfile(DirOAR,'0_oar_command');% keep track of the command in file '0-OAR/0_oar_command'
2028        fid=fopen(filename_oarcommand,'w');
2029        fprintf(fid,oar_command); % store the command
2030        fprintf(fid,result);% store the result (job ID number)
2031        fclose(fid);
2032        msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched as  ' num2str(NbProcess) ' processes in cluster: press STATUS to see results'])
2033       
2034    case 'cluster_pbs' % for LMFA Kepler machine
2035        %create subdirectory for pbs command and log files
2036        DirPBS=fullfile(OutputDir,'0_PBS'); %todo : common name OAR/PBS
2037        if exist(DirPBS,'dir')% delete the content of the dir 0_LOG to allow new input
2038            curdir=pwd;
2039            cd(DirPBS)
2040            delete('*')
2041            cd(curdir)
2042        else
2043            [tild,msg1]=mkdir(DirPBS);
2044            if ~strcmp(msg1,'')
2045                errormsg=['cannot create ' DirPBS ': ' msg1];%error message for directory creation
2046                return
2047            end
2048        end
2049        max_walltime=3600*20; % 20h max total calculation (cannot exceed 24 h)
2050        walltime_onejob=1800; % seconds, max estimated time for asingle file index value
2051        filename_joblist=fullfile(DirPBS,'job_list.txt');%create name of the global executable file
2052        fid=fopen(filename_joblist,'w');
2053        for iprocess=1:length(batch_file_list)
2054            fprintf(fid,[batch_file_list{iprocess} '\n']);% list of exe files
2055        end
2056        fclose(fid);
2057        system(['chmod +x ' filename_joblist]);% set the file to executable
2058        pbs_command=['qstat -n CIVX '...
2059            '-t idempotent --checkpoint ' num2str(walltime_onejob+60) ' '...
2060            '-l /core=' num2str(NbCore) ','...
2061            'walltime=' datestr(min(1.05*walltime_onejob/86400*max(NbProcess*BlockLength*nbfield_j,NbCore)/NbCore,max_walltime/86400),13) ' '...
2062            '-E ' regexprep(filename_joblist,'\.txt\>','.stderr') ' '...
2063            '-O ' regexprep(filename_joblist,'\.txt\>','.log') ' '...
2064            extra_oar ' '...
2065            '"oar-parexec -s -f ' filename_joblist ' '...
2066            '-l ' filename_joblist '.log"'];
2067        filename_oarcommand=fullfile(DirPBS,'pbs_command');
2068        fid=fopen(filename_oarcommand,'w');
2069        fprintf(fid,pbs_command);
2070        fclose(fid);
2071        fprintf(pbs_command);% display in command line
2072        %system(pbs_command);
2073        msgbox_uvmat('CONFIRMATION',[ActionFullName ' command ready to be launched in cluster'])
2074    case 'python'
2075        command = [
2076            'LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') | [s for s in p if ''matlab'' not in s] | '':''.join(p)") ' ...
2077            'python -m fluidimage.run_from_xml ' filexml{iprocess}];
2078        % fprintf(['command:\n' command '\n\n'])
2079        system(command, '-echo');
2080end
2081if exist(OutputDir,'dir')
2082    [SUCCESS,MESSAGE,MESSAGEID] = fileattrib (OutputDir)
2083    if MESSAGE.GroupWrite~=1
2084    [success,msg] = fileattrib(OutputDir,'+w','g','s');% allow writing access for the group of users, recursively in the folder
2085    if success==0
2086        msgbox_uvmat('WARNING',{['unable to set group write access to ' OutputDir ':']; msg});%error message for directory creation
2087    end
2088    end
2089end
2090
2091%------------------------------------------------------------------------
2092function STOP_Callback(hObject, eventdata, handles)
2093%------------------------------------------------------------------------
2094set(handles.RUN, 'BusyAction','cancel')
2095set(handles.RUN,'BackgroundColor',[1 0 0])
2096set(handles.RUN,'enable','on')
2097set(handles.RUN, 'Value',0)
2098
2099%------------------------------------------------------------------------
2100% --- read parameters from the GUI series
2101%------------------------------------------------------------------------
2102function Param=read_GUI_series(handles)
2103
2104%% read raw parameters from the GUI series
2105Param=read_GUI(handles.series);
2106
2107%% clean the output structure by removing unused information
2108if isfield(Param,'Pairs')
2109    Param=rmfield(Param,'Pairs'); %info Pairs not needed for output
2110end
2111if isfield(Param,'InputLine')
2112    Param=rmfield(Param,'InputLine');
2113end
2114if isfield(Param,'EditObject')
2115    Param=rmfield(Param,'EditObject');
2116end
2117Param.IndexRange.TimeSource=Param.IndexRange.TimeTable{end,1};
2118Param.IndexRange=rmfield(Param.IndexRange,'TimeTable');
2119empty_line=false(size(Param.InputTable,1),1);
2120for iline=1:size(Param.InputTable,1)
2121    empty_line(iline)=isempty(cell2mat(Param.InputTable(iline,1:3)));
2122end
2123Param.InputTable(empty_line,:)=[];
2124
2125%------------------------------------------------------------------------
2126% --- Executes on selection change in ActionName.
2127function ActionName_Callback(hObject, eventdata, handles)
2128%------------------------------------------------------------------------
2129
2130%% stop any ongoing series processing
2131if isequal(get(handles.RUN,'Value'),1)
2132    answer= msgbox_uvmat('INPUT_Y-N','stop current Action process?');
2133    if strcmp(answer,'Yes')
2134        STOP_Callback(hObject, eventdata, handles)
2135    else
2136        return
2137    end
2138end
2139set(handles.ActionName,'BackgroundColor',[1 1 0])
2140huigetfile=findobj(allchild(0),'tag','status_display');
2141if ~isempty(huigetfile)
2142    delete(huigetfile)
2143end
2144drawnow
2145
2146%% get Action name and path
2147NbBuiltinAction=get(handles.Action,'UserData'); %nbre of functions initially proposed in the menu ActionName (as defined in the Opening fct of series)
2148ActionList=get(handles.ActionName,'String');% list menu fields
2149ActionIndex=get(handles.ActionName,'Value');
2150if ~isequal(ActionIndex,1)% if we are not just opening series
2151    InputTable=get(handles.InputTable,'Data');
2152    if isempty(InputTable{1,4})
2153        msgbox_uvmat('ERROR','no input file available: use Open in the menu bar')
2154        return
2155    end
2156end
2157ActionName= ActionList{get(handles.ActionName,'Value')}; % selected function name
2158ActionPathList=get(handles.ActionName,'UserData');%list of recorded paths to functions of the list ActionName
2159
2160%% add a new function to the menu if 'more...' has been selected in the menu ActionName
2161if isequal(ActionName,'more...')
2162    [FileName, PathName] = uigetfile( ...
2163        {'*.m', ' (*.m)';
2164        '*.m',  '.m files '; ...
2165        '*.*', 'All Files (*.*)'}, ...
2166        'Pick a series processing function ',get(handles.ActionPath,'String'));
2167    if length(FileName)<2
2168        return
2169    end
2170    [tild,ActionName,ActionExt]=fileparts(FileName);
2171   
2172    % insert the choice in the menu ActionName
2173    ActionIndex=find(strcmp(ActionName,ActionList),1);% look for the selected function in the menu Action
2174    PathName=regexprep(PathName,'/$','');
2175    if ~isempty(ActionIndex) && ~strcmp(ActionPathList{ActionIndex},PathName)%compare the path to the existing fct
2176        ActionIndex=[]; % the selected path is different than the recorded one
2177    end
2178    if isempty(ActionIndex)%the qselected fct (with selected path) does not exist in the menu
2179        ActionIndex= length(ActionList);
2180        ActionList=[ActionList(1:end-1);{ActionName};ActionList(end)];% the selected function is appended in the menu, before the last item 'more...'
2181         ActionPathList=[ActionPathList; PathName];
2182    end
2183   
2184    % record the file extension and extend the path list if it is a new extension
2185    ActionExtList=get(handles.ActionExt,'String');
2186    ActionExtIndex=find(strcmp(ActionExt,ActionExtList), 1);
2187    if isempty(ActionExtIndex)
2188        set(handles.ActionExt,'String',[ActionExtList;{ActionExt}])
2189    end
2190
2191    % remove old Action options in the menu (keeping a menu length <nb_builtin_ACTION+5)
2192    if length(ActionList)>NbBuiltinAction+5; %nb_builtin_ACTION=nbre of functions always remaining in the initial menu
2193        nbremove=length(ActionList)-NbBuiltinAction-5;
2194        ActionList(NbBuiltinAction+1:end-5)=[];
2195        ActionPathList(NbBuiltinAction+1:end-4,:)=[];
2196        ActionIndex=ActionIndex-nbremove;
2197    end
2198   
2199    % record action menu, choice and path
2200    set(handles.ActionName,'Value',ActionIndex)
2201    set(handles.ActionName,'String',ActionList)
2202       set(handles.ActionName,'UserData',ActionPathList);
2203    set(handles.ActionExt,'Value',ActionExtIndex)
2204       
2205    %record the user defined menu additions in personal file profil_perso
2206    dir_perso=prefdir;
2207    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
2208    if NbBuiltinAction+1<=numel(ActionList)-1
2209        ActionListUser=ActionList(NbBuiltinAction+1:numel(ActionList)-1);
2210        ActionPathListUser=ActionPathList(NbBuiltinAction+1:numel(ActionList)-1);
2211        ActionExtListUser={};
2212        if numel(ActionExtList)>2
2213            ActionExtListUser=ActionExtList(3:end);
2214        end
2215        if exist(profil_perso,'file')
2216            save(profil_perso,'ActionListUser','ActionPathListUser','ActionExtListUser','-append')
2217        else
2218            save(profil_perso,'ActionListUser','ActionPathListUser','ActionExtListUser','-V6')
2219        end
2220    end
2221end
2222
2223%% check the current ActionPath to the selected function
2224ActionPath=ActionPathList{ActionIndex};%current recorded path
2225set(handles.ActionPath,'String',ActionPath); %show the path to the senlected function
2226
2227%% reinitialise the waitbar
2228update_waitbar(handles.Waitbar,0)
2229
2230%% create the function handle for Action
2231if ~exist(ActionPath,'dir')
2232    msgbox_uvmat('ERROR',['The prescribed function path ' ActionPath ' does not exist']);
2233    return
2234end
2235current_dir=pwd;%current working dir
2236cd(ActionPath)
2237h_fun=str2func(ActionName);
2238cd(current_dir)
2239
2240%
2241% checkaddpath=0;
2242% path_series=which('series');
2243% %eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
2244% spath=fileparts(which(ActionName)); %spath = current path of the selected function ACTION
2245% if ~exist(ActionPath,'dir')
2246%     msgbox_uvmat('ERROR',['The prescribed function path ' ActionPath ' does not exist']);
2247%     return
2248% end
2249% if ~strcmp(spath,ActionPath)
2250%     if strcmp(pwd,spath)
2251%         msgbox_uvmat('ERROR',[ 'a function called ' ActionName ' on your working space oversets the selected one']);
2252%         return
2253%     else
2254%         addpath(ActionPath)% add the prescribed path if not the current one
2255%         checkaddpath=1;
2256%     end
2257% end
2258% eval(['h_fun=@' ActionName ';'])%create a function handle for ACTION
2259% if checkaddpath && ~isequal(ActionPath,path_series)
2260%     rmpath(ActionPath)% add the prescribed path if not the current one
2261% end
2262
2263%% Activate the Action fct to adapt the configuration of the GUI series and bring specific parameters in SeriesData
2264Param=read_GUI_series(handles);% read the parameters from the GUI series
2265ParamOut=h_fun(Param);%run the selected Action function to get the relevant input
2266
2267%% Put the first line of the selected Action fct as tooltip help
2268try
2269    [fid,errormsg] =fopen([ActionName '.m']);
2270    InputText=textscan(fid,'%s',1,'delimiter','\n');
2271    fclose(fid);
2272    set(handles.ActionName,'ToolTipString',InputText{1}{1})% put the first line of the selected function as tooltip help
2273end
2274
2275
2276%% Visibility of VelType and VelType_1 menus asked by ActionName
2277VelTypeRequest=1;%VelType requested by default
2278VelTypeRequest_1=1;%VelType requested by default
2279if isfield(ParamOut,'VelType')
2280    VelTypeRequest=ismember(ParamOut.VelType,{'on','one','two'});
2281    VelTypeRequest_1=strcmp( ParamOut.VelType,'two');
2282end
2283FieldNameRequest=0;  %hidden by default
2284FieldNameRequest_1=0;  %hidden by default
2285if isfield(ParamOut,'FieldName')
2286    FieldNameRequest=ismember(ParamOut.FieldName,{'on','one','two'});
2287    FieldNameRequest_1=strcmp( ParamOut.FieldName,'two');
2288end
2289
2290%% Detect the types of input files and set menus and default options in 'VelType'
2291SeriesData=get(handles.series,'UserData');% info on the input file series
2292iview_civ=find(strcmp('civx',SeriesData.FileType)|strcmp('civdata',SeriesData.FileType));
2293iview_netcdf=find(strcmp('netcdf',SeriesData.FileType)|strcmp('civx',SeriesData.FileType)|strcmp('civdata',SeriesData.FileType));% all nc files, icluding civ
2294FieldList=get(handles.FieldName,'String');% previous list as default
2295if ~iscell(FieldList),FieldList={FieldList};end
2296FieldList_1=get(handles.FieldName_1,'String');% previous list as default
2297if ~iscell(FieldList_1),FieldList_1={FieldList_1};end
2298%CheckList=0;% indicate whether FieldName has been updated
2299CheckList_1=1;% indicate whether FieldName_1 has been updated
2300handles_coord=[handles.Coord_x handles.Coord_y handles.Coord_z handles.Coord_x_title handles.Coord_y_title handles.Coord_z_title];
2301if VelTypeRequest && numel(iview_civ)>=1
2302    menu=set_veltype_display(SeriesData.FileInfo{iview_civ(1)}.CivStage,SeriesData.FileType{iview_civ(1)});
2303    set(handles.VelType,'Value',1)% set first choice by default
2304    set(handles.VelType,'String',[{'*'};menu])
2305    set(handles.VelType,'Visible','on')
2306    set(handles.VelType_title,'Visible','on')
2307    FieldList=[set_field_list('U','V');{'C'};{'get_field...'}];%standard menu for civx data
2308    %CheckList=1;
2309    set(handles.FieldName,'Value',1); %velocity vector choice by default
2310    if  VelTypeRequest_1 && numel(iview_civ)>=2
2311        menu=set_veltype_display(SeriesData.FileInfo{iview_civ(2)}.CivStage,SeriesData.FileType{iview_civ(2)});
2312        set(handles.VelType_1,'Value',1)% set first choice by default
2313        set(handles.VelType_1,'String',[{'*'};menu])
2314        set(handles.VelType_1,'Visible','on')
2315        set(handles.VelType_title_1,'Visible','on')
2316        FieldList_1=[set_field_list('U','V');{'C'};{'get_field...'}];%standard menu for civx data
2317        CheckList_1=1;
2318        set(handles.FieldName_1,'Value',1); %velocity vector choice by default
2319    else
2320        set(handles.VelType_1,'Visible','off')
2321        set(handles.VelType_title_1,'Visible','off')
2322    end
2323else
2324    set(handles.VelType,'Visible','off')
2325    set(handles.VelType_title,'Visible','off')
2326end
2327
2328%% Detect the types of input files and set menus and default options in 'FieldName'
2329if (FieldNameRequest || VelTypeRequest) && numel(iview_netcdf)>=1
2330    set(handles.InputFields,'Visible','on')% set the frame InputFields visible
2331    if FieldNameRequest && isfield(SeriesData.FileInfo{iview_netcdf(1)},'ListVarName')
2332        set(handles.FieldName,'Visible','on')
2333        ListVarName=SeriesData.FileInfo{iview_netcdf(1)}.ListVarName;
2334        ind_var=get(handles.FieldName,'Value');%indices of previously selected variables
2335        for ilist=1:numel(ind_var)
2336            if isempty(find(strcmp(FieldList{ind_var(ilist)},ListVarName)))
2337                FieldList={};% previous choice not consistent with new input field
2338                set(handles.FieldName,'Value',1)
2339                break
2340            end
2341        end
2342        if ~isempty(FieldList)
2343            if isempty(find(strcmp(get(handles.Coord_x,'String'),ListVarName)))||...
2344                    isempty(find(strcmp(get(handles.Coord_y,'String'),ListVarName)))
2345                FieldList={};
2346                set(handles.Coord_x,'String','')
2347                set(handles.Coord_y,'String','')
2348            end
2349            Coord_z=get(handles.Coord_z,'String');
2350            if ~isempty(Coord_z) && isempty(find(strcmp(Coord_z,ListVarName)))
2351                FieldList={};
2352                set(handles.Coord_z,'String','')
2353            end
2354        end
2355    end
2356   
2357    set(handles_coord,'Visible','on')
2358    FieldList=[FieldList;{'get_field...'}];
2359    if FieldNameRequest_1 && numel(iview_netcdf)>=2
2360        set(handles.FieldName_1,'Visible','on')
2361        if CheckList_1==0        % not civ input made
2362            ListVarName=SeriesData.FileInfo{iview_netcdf(2)}.ListVarName;
2363            ind_var=get(handles.FieldName,'Value');%indices of previously selected variables
2364            for ilist=1:numel(ind_var)
2365                if isempty(find(strcmp(FieldList{ind_var(ilist)},ListVarName)))
2366                    FieldList_1={};% previous choice not consistent with new input field
2367                    set(handles.FieldName_1,'Value',1)
2368                    break
2369                end
2370            end
2371            warn_coord=0;
2372            if isempty(find(strcmp(get(handles.Coord_x,'String'),ListVarName)))||...
2373                    isempty(find(strcmp(get(handles.Coord_y,'String'),ListVarName)))
2374                warn_coord=1;
2375            end
2376            if ~isempty(Coord_z) && isempty(find(strcmp(Coord_z,ListVarName)))
2377                FieldList_1={};
2378                warn_coord=1;
2379            end
2380            if warn_coord
2381                msgbox_uvmat('WARNING','coordiante names do not exist in the second netcdf input file')
2382            end
2383           
2384            set(handles.FieldName_1,'Visible','on')
2385            set(handles.FieldName_1,'Value',1)
2386            set(handles.FieldName_1,'String',FieldList_1)
2387        end
2388    else
2389        set(handles.FieldName_1,'Visible','off')
2390    end
2391    if isempty(FieldList)
2392        set(handles.FieldName,'Visible','off')
2393    else
2394        set(handles.FieldName,'Visible','on')
2395        set(handles.FieldName,'String',FieldList)
2396    end
2397else
2398    set(handles.InputFields,'Visible','off')
2399end
2400
2401%% Introduce visibility of file overwrite option
2402if isfield(ParamOut,'CheckOverwriteVisible')&& strcmp(ParamOut.CheckOverwriteVisible,'on')
2403    set(handles.CheckOverwrite,'Visible','on')
2404else
2405    set(handles.CheckOverwrite,'Visible','off')
2406end
2407
2408%% Check whether alphabetical sorting of input Subdir is allowed by the Action fct  (for multiples series entries)
2409if isfield(ParamOut,'AllowInputSort')&&isequal(ParamOut.AllowInputSort,'on')&& size(Param.InputTable,1)>1
2410    [tild,iview]=sort(InputTable(:,2)); %subdirectories sorted in alphabetical order
2411    set(handles.InputTable,'Data',InputTable(iview,:));
2412    MinIndex_i=get(handles.MinIndex_i,'Data');
2413    MinIndex_j=get(handles.MinIndex_j,'Data');
2414    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2415    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2416    set(handles.MinIndex_i,'Data',MinIndex_i(iview,:));
2417    set(handles.MinIndex_j,'Data',MinIndex_j(iview,:));
2418    set(handles.MaxIndex_i,'Data',MaxIndex_i(iview,:));
2419    set(handles.MaxIndex_j,'Data',MaxIndex_j(iview,:));
2420    TimeTable=get(handles.TimeTable,'Data');
2421    set(handles.TimeTable,'Data',TimeTable(iview,:));
2422    PairString=get(handles.PairString,'Data');
2423    set(handles.PairString,'Data',PairString(iview,:));
2424end
2425
2426%% Impose the whole input file index range if requested
2427if isfield(ParamOut,'WholeIndexRange')&&isequal(ParamOut.WholeIndexRange,'on')
2428    MinIndex_i=get(handles.MinIndex_i,'Data');
2429    MinIndex_j=get(handles.MinIndex_j,'Data');
2430    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2431    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2432    set(handles.num_first_i,'String',num2str(MinIndex_i(1)))% set first as the min index (for the first line)
2433    set(handles.num_last_i,'String',num2str(MaxIndex_i(1)))% set last as the max index (for the first line)
2434    set(handles.num_incr_i,'String','1')
2435    set(handles.num_first_j,'String',num2str(MinIndex_j(1)))% set first as the min index (for the first line)
2436    set(handles.num_last_j,'String',num2str(MaxIndex_j(1)))% set last as the max index (for the first line)
2437    set(handles.num_incr_j,'String','1')
2438else  % check index ranges
2439    first_i=1;last_i=1;first_j=1;last_j=1;
2440    if isfield(Param.IndexRange,'first_i')
2441        first_i=Param.IndexRange.first_i;
2442        last_i=Param.IndexRange.last_i;
2443    end
2444    if isfield(Param.IndexRange,'first_j')
2445        first_j=Param.IndexRange.first_j;
2446        last_j=Param.IndexRange.last_j;
2447    end
2448    if last_i < first_i || last_j < first_j , msgbox_uvmat('ERROR','last field number must be larger than the first one'),...
2449            set(handles.RUN, 'Enable','On'), set(handles.RUN,'BackgroundColor',[1 0 0]),return,end;
2450end
2451
2452%% enable or desable j index visibility
2453status_j='on';%default
2454if isfield(ParamOut,'Desable_j_index')&&isequal(ParamOut.Desable_j_index,'on')
2455    status_j='off';
2456end
2457if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
2458    status_j='off'; % no j index needed
2459elseif strcmp(get(handles.PairString,'Visible'),'on')
2460    check_burst=cellfun(@isempty,regexp(get(handles.PairString,'Data'),'^j'));%=0 for burst case, 1 otherwise
2461    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
2462        status_j='off'; % no j index needed for bust case
2463    end
2464end
2465enable_j(handles,status_j) % no j index needed
2466
2467
2468%% NbSlice visibility
2469%NbSliceVisible='off';%default
2470if isfield(ParamOut,'NbSlice') && (strcmp(ParamOut.NbSlice,'on')||isnumeric(ParamOut.NbSlice))
2471    set(handles.num_NbSlice,'Visible','on')
2472    set(handles.NbSlice_title,'Visible','on')
2473else
2474    set(handles.num_NbSlice,'Visible','off')
2475    set(handles.NbSlice_title,'Visible','off')
2476    %     set(handles.num_NbProcess,'String',get(handles.num_NbSlice,'String'))% the nbre of processes is imposed as the nbre of slices
2477    % else
2478    %     set(handles.num_NbProcess,'String','')% free nbre of processes
2479end
2480if isnumeric(ParamOut.NbSlice)
2481    set(handles.num_NbSlice,'String',num2str(ParamOut.NbSlice))
2482    set(handles.num_NbSlice,'Enable','off'); % NbSlice set by the activation of the Action function
2483else
2484    set(handles.num_NbSlice,'Enable','on'); % NbSlice can be modified on the GUI series
2485end
2486% set(handles.num_NbSlice,'Visible',NbSliceVisible)
2487% set(handles.NbSlice_title,'Visible',NbSliceVisible)
2488
2489
2490
2491%% Visibility of FieldTransform menu
2492FieldTransformVisible='off';  %hidden by default
2493if isfield(ParamOut,'FieldTransform')
2494    FieldTransformVisible=ParamOut.FieldTransform; 
2495    TransformName_Callback([],[], handles)
2496end
2497set(handles.FieldTransform,'Visible',FieldTransformVisible)
2498if isfield(ParamOut,'TransformPath')
2499    set(handles.ActionExt,'UserData',ParamOut.TransformPath)
2500else
2501    set(handles.ActionExt,'UserData',[])
2502end
2503
2504%% Visibility of projection object
2505ProjObjectVisible='off';  %hidden by default
2506if isfield(ParamOut,'ProjObject')
2507    ProjObjectVisible=ParamOut.ProjObject;
2508end
2509set(handles.CheckObject,'Visible',ProjObjectVisible)
2510if ~get(handles.CheckObject,'Value')
2511    ProjObjectVisible='off';
2512end
2513set(handles.ProjObject,'Visible',ProjObjectVisible)
2514set(handles.DeleteObject,'Visible',ProjObjectVisible)
2515set(handles.ViewObject,'Visible',ProjObjectVisible)
2516set(handles.EditObject,'Visible',ProjObjectVisible)
2517
2518%% Visibility of mask input
2519MaskVisible='off';  %hidden by default
2520if isfield(ParamOut,'Mask')
2521    MaskVisible=ParamOut.Mask;
2522end
2523set(handles.CheckMask,'Visible',MaskVisible);
2524
2525%% definition of the directory containing the output files
2526if  ~(isfield(SeriesData,'ActionName') && strcmp(ActionName,SeriesData.ActionName))
2527    OutputDirExt='.series'; %default
2528    if isfield(ParamOut,'OutputDirExt')&&~isempty(ParamOut.OutputDirExt)
2529        OutputDirExt=ParamOut.OutputDirExt;
2530    end
2531    set(handles.OutputDirExt,'String',OutputDirExt)
2532end
2533OutputDirVisible='off';
2534OutputSubDirMode='auto';%default
2535SubDirOut='';
2536if isfield(ParamOut,'OutputSubDirMode')
2537    OutputSubDirMode=ParamOut.OutputSubDirMode;
2538end
2539switch OutputSubDirMode
2540    case 'auto';%default
2541        OutputDirVisible='on';
2542        SubDir=InputTable(1:end,2); %set of subdirectories
2543        SubDirOut=SubDir{1};
2544        if numel(SubDir)>1
2545            for ilist=2:numel(SubDir)
2546                SubDirOut=[SubDirOut '-' regexprep(SubDir{ilist},'^/','')];
2547            end
2548        end
2549    case 'one'
2550        OutputDirVisible='on';
2551        SubDirOut=InputTable{1,2}; %use the first subdir name (+OutputDirExt) as output  subdirectory
2552    case 'two'
2553        OutputDirVisible='on';   
2554        SubDir=InputTable(1:2,2); %set of subdirectories
2555        SubDirOut=SubDir{1};
2556        if numel(SubDir)>1
2557                SubDirOut=[SubDirOut '-' regexprep(SubDir{2},'^/','')];
2558        end
2559    case 'last'
2560        OutputDirVisible='on';
2561        SubDirOut=InputTable{end,2}; %use the last subdir name (+OutputDirExt) as output  subdirectory
2562end
2563set(handles.OutputSubDir,'String',SubDirOut)
2564set(handles.OutputSubDir,'BackgroundColor',[1 1 1])% set edit box to white color to indicate refreshment
2565set(handles.OutputDirExt,'Visible',OutputDirVisible)
2566set(handles.OutputSubDir,'Visible',OutputDirVisible)
2567%set(handles.CheckOverwrite,'Visible',OutputDirVisible)
2568set(handles.OutputDir_title,'Visible',OutputDirVisible)
2569SeriesData.ActionName=ActionName;%record ActionName for next use
2570
2571
2572%% visibility of the run mode (local or background or cluster)
2573if strcmp(OutputSubDirMode,'none')
2574    RunModeVisible='off';% only local mode available if no output file is produced
2575else
2576    RunModeVisible='on';
2577end
2578set(handles.RunMode,'Visible',RunModeVisible)
2579set(handles.ActionExt,'Visible',RunModeVisible)
2580set(handles.RunMode_title,'Visible',RunModeVisible)
2581set(handles.ActionExt_title,'Visible',RunModeVisible)
2582
2583
2584%% Expected nbre of output files
2585if isfield(ParamOut,'OutputFileMode')
2586    StatusData.OutputFileMode=ParamOut.OutputFileMode;
2587    set(handles.status,'UserData',StatusData)
2588end
2589
2590%% definition of an additional parameter set, determined by an ancillary GUI
2591if isfield(ParamOut,'ActionInput')
2592    set(handles.ActionInput,'Visible','on')
2593    ParamOut.ActionInput.Program=ActionName; % record the program in ActionInput
2594    SeriesData.ActionInput=ParamOut.ActionInput;
2595else
2596    set(handles.ActionInput,'Visible','off')
2597    if isfield(SeriesData,'ActionInput')
2598        SeriesData=rmfield(SeriesData,'ActionInput');
2599    end
2600end
2601set(handles.series,'UserData',SeriesData)
2602set(handles.ActionName,'BackgroundColor',[1 1 1])
2603
2604%------------------------------------------------------------------------
2605% --- Executes on selection change in FieldName.
2606function FieldName_Callback(hObject, eventdata, handles)
2607%------------------------------------------------------------------------
2608field_str=get(handles.FieldName,'String');
2609field_index=get(handles.FieldName,'Value');
2610field=field_str{field_index(1)};
2611if isequal(field,'get_field...')
2612    SeriesData=get(handles.series,'UserData');
2613    % input line for which the field choice is relevant
2614    iview=find(ismember(SeriesData.FileType,{'netcdf','civx','civdata'}));% all nc files, icluding civ
2615    hget_field=findobj(allchild(0),'name','get_field');
2616    if ~isempty(hget_field)
2617        delete(hget_field)%delete opened versions of get_field
2618    end
2619    Param=read_GUI(handles.series);
2620    InputTable=Param.InputTable(iview,:);
2621    % check the existence of the first file in the series
2622    first_j=[];last_j=[];MinIndex_j=1;MaxIndex_j=1;%default setting for index j
2623    if isfield(Param.IndexRange,'first_j');% if index j is used     
2624        first_j=Param.IndexRange.first_j;
2625        last_j=Param.IndexRange.last_j;
2626        MinIndex_j=Param.IndexRange.MinIndex_j(iview);
2627        MaxIndex_j=Param.IndexRange.MaxIndex_j(iview);
2628    end
2629    PairString='';
2630    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString{iview}; end
2631    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2632    LineIndex=iview(1);
2633    if numel(iview)>1     
2634        answer=msgbox_uvmat('INPUT_TXT',['select the line of the input table:' num2str(iview)] ,num2str(iview(1)));
2635        LineIndex=str2num(answer);
2636%         InputLine=str2num(get(handles.InputLine,'String'));
2637%         if ismember(InputLine,iview)
2638%             LineIndex=InputLine;
2639%         end
2640    end
2641    FirstFileName=fullfile_uvmat(InputTable{LineIndex,1},InputTable{LineIndex,2},InputTable{LineIndex,3},...
2642        InputTable{LineIndex,5},InputTable{LineIndex,4},i1,i2,j1,j2);
2643    if exist(FirstFileName,'file')
2644        ParamIn.Title='get_field: pick input variables and coordinates for series processing';
2645        ParamIn.SeriesInput=1;
2646        GetFieldData=get_field(FirstFileName,ParamIn);
2647        FieldList={};
2648        if isfield(GetFieldData,'FieldOption')% if a field has been selected
2649        switch GetFieldData.FieldOption
2650            case 'vectors'
2651                UName=GetFieldData.PanelVectors.vector_x;
2652                VName=GetFieldData.PanelVectors.vector_y;
2653                YName={GetFieldData.Coordinates.Coord_y};
2654                FieldList={['vec(' UName ',' VName ')'];...
2655                    ['norm(' UName ',' VName ')'];...
2656                    UName;VName};
2657            case {'scalar'}
2658                FieldList=GetFieldData.PanelScalar.scalar;
2659                YName={GetFieldData.Coordinates.Coord_y};
2660                if ischar(FieldList)
2661                    FieldList={FieldList};
2662                end
2663            case 'civdata...'
2664                FieldList=[set_field_list('U','V') ;{'C'}];
2665                set(handles.FieldName,'Value',1) % set menu to 'velocity
2666                XName='X';
2667                YName='y';
2668        end
2669        set(handles.FieldName,'Value',1)
2670        set(handles.FieldName,'String',[FieldList; {'get_field...'}]);
2671        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2672           if ~isempty(regexp(FieldList{1},'^vec'))
2673                set(handles.FieldName,'Value',1)
2674           else
2675                set(handles.FieldName,'Value',1:numel(FieldList))%select all input fields by default
2676           end
2677            XName=GetFieldData.Coordinates.Coord_x;
2678            YName=GetFieldData.Coordinates.Coord_y;
2679            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2680            % get the time info                     
2681            TimeTable=get(handles.TimeTable,'Data');
2682            switch TimeNameStr
2683                case 'file index'
2684                    TimeName='';
2685                case 'attribute'
2686                    TimeName=['att:' GetFieldData.Time.TimeName];
2687                    % update the time table
2688                    TimeTable{LineIndex,2}=get_time(Param.IndexRange.MinIndex_i(LineIndex),MinIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Min time     
2689                    TimeTable{LineIndex,3}=get_time(Param.IndexRange.first_i,first_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % first time             
2690                    TimeTable{LineIndex,4}=get_time(Param.IndexRange.last_i,last_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % last time                     
2691                    TimeTable{LineIndex,5}=get_time(Param.IndexRange.MaxIndex_i(LineIndex),MaxIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Max time
2692                case 'variable'
2693                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2694                    set(handles.NomType,'String','*')
2695                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2696                    set(handles.FileIndex,'String','')
2697                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2698                case 'matrix_index'
2699                    TimeName=['dim:' GetFieldData.Time.TimeName];
2700                    set(handles.NomType,'String','*')
2701                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2702                    set(handles.FileIndex,'String','')
2703                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2704            end
2705            TimeTable{LineIndex,1}=TimeName;
2706            set(handles.TimeTable,'Data',TimeTable);
2707        end
2708        set(handles.Coord_x,'String',XName)
2709        set(handles.Coord_y,'String',YName)
2710        set(handles.Coord_x,'Visible','on')
2711        set(handles.Coord_y,'Visible','on')
2712        end
2713    else
2714        msgbox_uvmat('ERROR',[FirstFileName ' does not exist'])
2715    end
2716end
2717
2718
2719function [TimeValue,DtValue]=get_time(ref_i,ref_j,PairString,InputTable,FileInfo,TimeName,DtName)
2720[i1,i2,j1,j2] = get_file_index(ref_i,ref_j,PairString);
2721FileName=fullfile_uvmat(InputTable{1},InputTable{2},InputTable{3},InputTable{5},InputTable{4},i1,i2,j1,j2);
2722Data=nc2struct(FileName,[]);
2723TimeValue=[];
2724DtValue=[];
2725if isequal(FileInfo.FileType,'civdata')
2726    if ismember(TimeName,{'civ1','filter1'})
2727        if isfield(Data,'Civ1_Time')
2728        TimeValue=Data.Civ1_Time;
2729        end
2730        if isfield(Data,'Civ1_Dt')
2731        DtValue=Data.Civ1_Dt;
2732        end
2733    else
2734        if isfield(Data,'Civ2_Time')
2735        TimeValue=Data.Civ2_Time;
2736        end
2737        if isfield(Data,'Civ2_Dt')
2738        DtValue=Data.Civ2_Dt;
2739        end
2740    end
2741else
2742    if ~isempty(TimeName)&& isfield(Data,TimeName)
2743        TimeValue=Data.(TimeName);
2744    end
2745    if exist('DtName','var') && isfield(Data,DtName)
2746        DtValue=Data.(DtName);
2747    end
2748end
2749
2750%------------------------------------------------------------------------
2751% --- Executes on selection change in FieldName_1.
2752function FieldName_1_Callback(hObject, eventdata, handles)
2753%------------------------------------------------------------------------
2754field_str=get(handles.FieldName_1,'String');
2755field_index=get(handles.FieldName_1,'Value');
2756field=field_str{field_index(1)};
2757if isequal(field,'get_field...')
2758    hget_field=findobj(allchild(0),'name','get_field');
2759    if ~isempty(hget_field)
2760        delete(hget_field)%delete opened versions of get_field
2761    end
2762    Param=read_GUI(handles.series);
2763    Param.InputTable=Param.InputTable(1,:);
2764    % check the existence of the first file in the series
2765    first_j=[];
2766    if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
2767    if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
2768    PairString='';
2769    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
2770    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2771    FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
2772        Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
2773    if exist(FirstFileName,'file')
2774        ParamIn.SeriesInput=1;
2775        GetFieldData=get_field(FirstFileName,ParamIn);
2776        FieldList={};
2777        switch GetFieldData.FieldOption
2778            case 'vectors'
2779                UName=GetFieldData.PanelVectors.vector_x;
2780                VName=GetFieldData.PanelVectors.vector_y;
2781                FieldList={['vec(' UName ',' VName ')'];...
2782                    ['norm(' UName ',' VName ')'];...
2783                    UName;VName};
2784            case {'scalar','pick variables'}
2785                FieldList=GetFieldData.PanelScalar.scalar;
2786                if ischar(FieldList)
2787                    FieldList={FieldList};
2788                end
2789            case '1D plot'
2790
2791            case 'civdata...'
2792                FieldList=set_field_list('U','V','C');
2793                set(handles.FieldName,'Value',2) % set menu to 'velocity
2794        end
2795        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2796            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2797            switch TimeNameStr
2798                case 'file index'
2799                    set(handles.TimeName,'String','');
2800                case 'attribute'
2801                    set(handles.TimeName,'String',['att:' GetFieldData.Time.TimeName]);
2802                case 'variable'
2803                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2804                    set(handles.NomType,'String','*')
2805                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2806                    set(handles.FileIndex,'String','')
2807                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2808                case 'matrix_index'
2809                    set(handles.TimeName,'String',['dim:' GetFieldData.Time.TimeName]);
2810                    set(handles.NomType,'String','*')
2811                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2812                    set(handles.FileIndex,'String','')
2813                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2814            end
2815        end
2816        set(handles.FieldName_1,'Value',1)
2817        set(handles.FieldName_1,'String',[FieldList; {'get_field...'}]);
2818    end
2819end   
2820
2821
2822%%%%%%%%%%%%%
2823function [ind_remove]=find_pairs(dirpair,ind_i,last_i)
2824indsel=ind_i;
2825indiff=diff(ind_i); %test index increment to detect multiplets (several pairs with the same index ind_i) and holes in the series
2826indiff=[1 indiff last_i-ind_i(end)+1];%for testing gaps with the imposed bounds
2827if ~isempty(indiff)
2828    indiff2=diff(indiff);
2829    indiffp=[indiff2 1];
2830    indiffm=[1 indiff2];
2831    ind_multi_m=find((indiff==0)&(indiffm<0))-1;%indices of first members of multiplets
2832    ind_multi_p=find((indiff==0)&(indiffp>0));%indices of last members of multiplets
2833    %for each multiplet, select the most recent file
2834    ind_remove=[];
2835    for i=1:length(ind_multi_m)
2836        ind_pairs=ind_multi_m(i):ind_multi_p(i);
2837        for imulti=1:length(ind_pairs)
2838            datepair(imulti)=datenum(dirpair(ind_pairs(imulti)).date);%dates of creation
2839        end
2840        [datenew,indsort2]=sort(datepair); %sort the multiplet by creation date
2841        ind_s=indsort2(1:end-1);%
2842        ind_remove=[ind_remove ind_pairs(ind_s)];%remove these indices, leave the last one
2843    end
2844end
2845
2846%------------------------------------------------------------------------
2847% --- determine the list of index pairstring of processing file
2848function [num_i1,num_i2,num_j1,num_j2,num_i_out,num_j_out]=find_file_indices(num_i,num_j,ind_shift,NomType,mode)
2849%------------------------------------------------------------------------
2850num_i1=num_i;% set of first image numbers by default
2851num_i2=num_i;
2852num_j1=num_j;
2853num_j2=num_j;
2854num_i_out=num_i;
2855num_j_out=num_j;
2856% if isequal (NomType,'_1-2_1') || isequal (NomType,'_1-2')
2857if isequal(mode,'series(Di)')
2858    num_i1_line=num_i+ind_shift(3);% set of first image numbers
2859    num_i2_line=num_i+ind_shift(4);
2860    % adjust the first and last field number
2861        indsel=find(num_i1_line >= 1);
2862    num_i_out=num_i(indsel);
2863    num_i1_line=num_i1_line(indsel);
2864    num_i2_line=num_i2_line(indsel);
2865    num_j1=meshgrid(num_j,ones(size(num_i1_line)));
2866    num_j2=meshgrid(num_j,ones(size(num_i1_line)));
2867    [xx,num_i1]=meshgrid(num_j,num_i1_line);
2868    [xx,num_i2]=meshgrid(num_j,num_i2_line);
2869elseif isequal (mode,'series(Dj)')||isequal (mode,'bursts')
2870    if isequal(mode,'bursts') %case of bursts (png_old or png_2D)
2871        num_j1=ind_shift(1)*ones(size(num_i));
2872        num_j2=ind_shift(2)*ones(size(num_i));
2873    else
2874        num_j1_col=num_j+ind_shift(1);% set of first image numbers
2875        num_j2_col=num_j+ind_shift(2);
2876        % adjust the first field number
2877        indsel=find((num_j1_col >= 1));   
2878        num_j_out=num_j(indsel);
2879        num_j1_col=num_j1_col(indsel);
2880        num_j2_col=num_j2_col(indsel);
2881        [num_i1,num_j1]=meshgrid(num_i,num_j1_col);
2882        [num_i2,num_j2]=meshgrid(num_i,num_j2_col);
2883    end   
2884end
2885
2886%------------------------------------------------------------------------
2887% --- Executes on button press in CheckObject.
2888function CheckObject_Callback(hObject, eventdata, handles)
2889%------------------------------------------------------------------------
2890hset_object=findobj(allchild(0),'tag','set_object');%find the set_object interface handle
2891if get(handles.CheckObject,'Value')
2892    SeriesData=get(handles.series,'UserData');
2893    if isfield(SeriesData,'ProjObject') && ~isempty(SeriesData.ProjObject)
2894        set(handles.ViewObject,'Value',1)
2895        ViewObject_Callback(hObject, eventdata, handles)
2896    else
2897        if ishandle(hset_object)
2898            uistack(hset_object,'top')% show the GUI set_object if opened
2899        else
2900            %get the object file
2901            InputTable=get(handles.InputTable,'Data');
2902            defaultname=InputTable{1,1};
2903            if isempty(defaultname)
2904                defaultname={''};
2905            end
2906            fileinput=uigetfile_uvmat('pick a xml object file (or use uvmat to create it)',defaultname,'.xml');
2907            if isempty(fileinput)% exit if no object file is selected
2908                set(handles.CheckObject,'Value',0)
2909                return
2910            end
2911            %read the file
2912            data=xml2struct(fileinput);
2913            if ~isfield(data,'Type')
2914                msgbox_uvmat('ERROR',[fileinput ' is not an object xml file'])
2915                set(handles.CheckObject,'Value',0)
2916                return
2917            end
2918            if ~isfield(data,'ProjMode')
2919                data.ProjMode='none';
2920            end
2921            hset_object=set_object(data);% call the set_object interface
2922            set(hset_object,'Name','set_object_series')% name to distinguish from set_object used with uvmat
2923        end
2924        ProjObject=read_GUI(hset_object);
2925        set(handles.ProjObject,'String',ProjObject.Name);%display the object name
2926        SeriesData=get(handles.series,'UserData');
2927        SeriesData.ProjObject=ProjObject;
2928        set(handles.series,'UserData',SeriesData);
2929    end
2930    set(handles.EditObject,'Visible','on');
2931    set(handles.DeleteObject,'Visible','on');
2932    set(handles.ViewObject,'Visible','on');
2933    set(handles.ProjObject,'Visible','on');
2934else
2935    set(handles.EditObject,'Visible','off');
2936    set(handles.DeleteObject,'Visible','off');
2937    set(handles.ViewObject,'Visible','off');
2938    if ~ishandle(hset_object)
2939        set(handles.ViewObject,'Value',0);
2940    end
2941    set(handles.ProjObject,'Visible','off');
2942end
2943
2944%------------------------------------------------------------------------
2945% --- Executes on button press in ViewObject.
2946%------------------------------------------------------------------------
2947function ViewObject_Callback(hObject, eventdata, handles)
2948
2949UserData=get(handles.series,'UserData');
2950hset_object=findobj(allchild(0),'Tag','set_object');
2951if ~isempty(hset_object)
2952    delete(hset_object)% refresh set_object if already opened
2953end
2954hset_object=set_object(UserData.ProjObject);
2955set(hset_object,'Name','view_object_series')
2956
2957
2958%------------------------------------------------------------------------
2959% --- Executes on button press in EditObject.
2960function EditObject_Callback(hObject, eventdata, handles)
2961%------------------------------------------------------------------------
2962if get(handles.EditObject,'Value')
2963    set(handles.ViewObject,'Value',0)
2964        UserData=get(handles.series,'UserData');
2965    hset_object=set_object(UserData.ProjObject);
2966    set(hset_object,'Name','edit_object_series')
2967    set(get(hset_object,'Children'),'Enable','on')
2968else
2969    hset_object=findobj(allchild(0),'Tag','set_object');
2970    if ~isempty(hset_object)
2971        set(get(hset_object,'Children'),'Enable','off')
2972    end
2973end
2974
2975%------------------------------------------------------------------------
2976% --- Executes on button press in DeleteObject.
2977function DeleteObject_Callback(hObject, eventdata, handles)
2978%------------------------------------------------------------------------
2979SeriesData=get(handles.series,'UserData');
2980SeriesData.ProjObject=[];
2981set(handles.series,'UserData',SeriesData)
2982set(handles.ProjObject,'String','')
2983set(handles.ProjObject,'Visible','off')
2984set(handles.CheckObject,'Value',0)
2985set(handles.ViewObject,'Visible','off')
2986set(handles.EditObject,'Visible','off')
2987hset_object=findobj(allchild(0),'name','set_object_series');
2988if ~isempty(hset_object)
2989    delete(hset_object)
2990end
2991set(handles.DeleteObject,'Visible','off')
2992
2993%------------------------------------------------------------------------
2994% --- Executed when CheckMask is activated
2995%------------------------------------------------------------------------
2996function CheckMask_Callback(hObject, eventdata, handles)
2997
2998if get(handles.CheckMask,'Value')
2999    InputTable=get(handles.InputTable,'Data');
3000    nbview=size(InputTable,1);
3001    MaskTable=cell(nbview,1);%default
3002    ListMask=cell(nbview,1);%default
3003    MaskData=get(handles.MaskTable,'Data');
3004    MaskData(size(MaskData,1):nbview,1)=cell(size(MaskData,1):nbview,1);%complement if undefined lines
3005    for iview=1:nbview
3006        ListMask{iview,1}=num2str(iview);
3007        RootPath=InputTable{iview,1};
3008        if ~isempty(RootPath)
3009            if isempty(MaskData{iview})
3010                SubDir=InputTable{iview,2};
3011                MaskPath=fullfile(RootPath,[regexprep(SubDir,'\..*','') '.mask']);%take the root part of SubDir, before the first dot '.'
3012                if exist(MaskPath,'dir')
3013                    ListStruct=dir(MaskPath);%look for a mask file
3014                    ListCells=struct2cell(ListStruct);% transform dir struct to a cell arrray
3015                    check_dir=cell2mat(ListCells(4,:));% =1 for directories, =0 for files
3016                    ListFiles=ListCells(1,:);%list of file and dri names
3017                    ListFiles=ListFiles(~check_dir);%list of file names (excluding dir)
3018                    mdetect=0;
3019                    if ~isempty(ListFiles)
3020                        for ifile=1:numel(ListFiles)
3021                            [tild,tild,MaskFile{ifile},i1_series,i2_series,j1_series,j2_series,MaskNomType,MaskFileType]=find_file_series(MaskPath,ListFiles{ifile},0);
3022                            if strcmp(MaskFileType,'image') && isempty(i2_series) && isempty(j2_series)
3023                                mdetect=1;
3024                                MaskName=ListFiles{ifile};
3025                            end
3026                            if ~strcmp(MaskFile{ifile},MaskFile{1})
3027                                mdetect=0;% cancel detection test in case of multiple masks, use the brower for selection
3028                                break
3029                            end
3030                        end
3031                    end
3032                    if mdetect==1
3033                        MaskName=fullfile(MaskPath,'mask_1.png');
3034                    else
3035                        MaskName=uigetfile_uvmat('select a mask file:',MaskPath,'image');
3036                    end
3037                else
3038                    MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3039                end
3040                MaskTable{iview,1}=MaskName ;
3041                ListMask{iview,1}=num2str(iview);
3042            end
3043        end
3044    end
3045    set(handles.MaskTable,'Data',MaskTable)
3046    set(handles.MaskTable,'Visible','on')
3047    set(handles.MaskBrowse,'Visible','on')
3048    set(handles.ListMask,'Visible','on')
3049    set(handles.ListMask,'String',ListMask)
3050    set(handles.ListMask,'Value',1)
3051else
3052    set(handles.MaskTable,'Visible','off')
3053    set(handles.MaskBrowse,'Visible','off')
3054    set(handles.ListMask,'Visible','off')
3055end
3056
3057%------------------------------------------------------------------------
3058% --- Executes on button press in MaskBrowse.
3059%------------------------------------------------------------------------
3060function MaskBrowse_Callback(hObject, eventdata, handles)
3061
3062InputTable=get(handles.InputTable,'Data');
3063iview=get(handles.ListMask,'Value');
3064RootPath=InputTable{iview,1};
3065MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3066if ~isempty(MaskName)
3067    MaskTable=get(handles.MaskTable,'Data');
3068    MaskTable{iview,1}=MaskName ;
3069    set(handles.MaskTable,'Data',MaskTable)
3070end
3071
3072%------------------------------------------------------------------------
3073% --- Executes when selected cell(s) is changed in MaskTable.
3074%------------------------------------------------------------------------
3075function MaskTable_CellSelectionCallback(hObject, eventdata, handles)
3076
3077if numel(eventdata.Indices)>=1
3078set(handles.ListMask,'Value',eventdata.Indices(1))
3079end
3080
3081%-------------------------------------------------------------------
3082function MenuHelp_Callback(hObject, eventdata, handles)
3083%-------------------------------------------------------------------
3084
3085
3086% path_to_uvmat=which ('uvmat');% check the path of uvmat
3087% pathelp=fileparts(path_to_uvmat);
3088% helpfile=fullfile(pathelp,'uvmat_doc','uvmat_doc.html');
3089% if isempty(dir(helpfile)), msgbox_uvmat('ERROR','Please put the help file uvmat_doc.html in the sub-directory /uvmat_doc of the UVMAT package')
3090% else
3091%     addpath (fullfile(pathelp,'uvmat_doc'))
3092%     web([helpfile '#series'])
3093% end
3094
3095%-------------------------------------------------------------------
3096% --- Executes on selection change in TransformName.
3097function TransformName_Callback(hObject, eventdata, handles)
3098%----------------------------------------------------------------------
3099TransformList=get(handles.TransformName,'String');
3100TransformIndex=get(handles.TransformName,'Value');
3101TransformName=TransformList{TransformIndex};
3102TransformPathList=get(handles.TransformName,'UserData');
3103nb_builtin_transform=4;
3104if isequal(TransformName,'more...');     
3105    FileName=uigetfile_uvmat('Pick a transform function',get(handles.TransformPath,'String'),'.m');
3106    if isempty(FileName)
3107        return     %browser closed without choice
3108    end
3109    [TransformPath,TransformName,TransformExt]=fileparts(FileName);% removes extension .m
3110    if ~strcmp(TransformExt,'.m')
3111        msgbox_uvmat('ERROR','a Matlab function .m must be introduced');
3112        return
3113    end
3114     % insert the choice in the menu
3115    TransformIndex=find(strcmp(TransformName,TransformList),1);% look for the selected function in the menu Action
3116    if isempty(TransformIndex)%the input string does not exist in the menu
3117        TransformIndex= length(TransformList);
3118        TransformList=[TransformList(1:end-1);{TransformName};TransformList(end)];% the selected function is appended in the menu, before the last item 'more...'
3119        set(handles.TransformName,'String',TransformList)
3120        TransformPathList=[TransformPathList;{TransformPath}];
3121    else% the input function already exist, we update its path (possibly new)
3122        TransformPathList{TransformIndex}=TransformPath;%
3123        set(handles.TransformName,'Value',TransformIndex)
3124    end
3125   % save the new menu in the personal file 'uvmat_perso.mat'
3126   dir_perso=prefdir;%personal Matalb directory
3127   profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3128   if exist(profil_perso,'file')
3129       for ilist=nb_builtin_transform+1:numel(TransformPathList)
3130           TransformListUser{ilist-nb_builtin_transform}=TransformList{ilist};
3131           TransformPathListUser{ilist-nb_builtin_transform}=TransformPathList{ilist};
3132       end
3133       TransformPathListUser=TransformPathListUser';
3134       TransformListUser=TransformListUser';
3135       save (profil_perso,'TransformPathListUser','TransformListUser','-append'); %store the root name for future opening of uvmat
3136   end
3137end
3138
3139%display the current function path
3140set(handles.TransformPath,'String',TransformPathList{TransformIndex}); %show the path to the senlected function
3141set(handles.TransformName,'UserData',TransformPathList);
3142
3143%% create the function handle of the selected fct
3144if ~isempty(TransformName)
3145    if ~exist(TransformPathList{TransformIndex},'dir')
3146        msgbox_uvmat('ERROR',['The prescribed transform function path ' TransformPathList{TransformIndex} ' does not exist']);
3147        return
3148    end
3149    current_dir=pwd;%current working dir
3150    cd(TransformPathList{TransformIndex})
3151    transform_handle=str2func(TransformName);
3152    cd(current_dir)
3153    Field.Action.RUN=0;% indicate that the transform fct is called only to get input param
3154    DataOut=feval(transform_handle,Field,[]);% execute the transform fct to get the required conditions
3155    if isfield(DataOut,'TransformInput')%  used to add transform parameters at selection of the transform fct
3156        SeriesData=get(handles.series,'UserData');
3157        SeriesData.TransformInput=DataOut.TransformInput;
3158        set(handles.series,'UserData',SeriesData)
3159    end
3160end
3161
3162%------------------------------------------------------------------------
3163% --- fct activated by the upper bar menu ExportConfig
3164%------------------------------------------------------------------------
3165function MenuDisplayConfig_Callback(hObject, eventdata, handles)
3166
3167global Param
3168Param=read_GUI_series(handles);
3169evalin('base','global Param')%make CurData global in the workspace
3170display('current series config :')
3171evalin('base','Param') %display CurData in the workspace
3172commandwindow; %brings the Matlab command window to the front
3173
3174%------------------------------------------------------------------------
3175% --- fct activated by the upper bar menu InportConfig: import
3176%     menu settings from an xml file (stored in /0_XML for each run)
3177%------------------------------------------------------------------------
3178function MenuImportConfig_Callback(hObject, eventdata, handles)
3179
3180%% use a browser to choose the xml file containing the processing config
3181InputTable=get(handles.InputTable,'Data');
3182oldfile=InputTable{1,1};%current path in InputTable
3183if isempty(oldfile)
3184    % use a file name stored in prefdir
3185    dir_perso=prefdir;
3186    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3187    if exist(profil_perso,'file')
3188        h=load (profil_perso);
3189        if isfield(h,'RootPath') && ischar(h.RootPath)
3190            oldfile=h.RootPath;
3191        end
3192    end
3193end
3194filexml=uigetfile_uvmat('pick a xml parameter file',oldfile,'.xml');% get the xml file containing processing parameters
3195if isempty(filexml), return, end % quit function if an xml file has not been opened
3196
3197%% fill the GUI series with the content of the xml file
3198Param=xml2struct(filexml);% read the input xml file as a Matlab structure
3199
3200% ask to stop current Action if button RUN is in action (another process is already running)
3201if isequal(get(handles.RUN,'Value'),1)
3202    answer= msgbox_uvmat('INPUT_Y-N','stop current Action process?');
3203    if strcmp(answer,'Yes')
3204        STOP_Callback(hObject, eventdata, handles)
3205    else
3206        return
3207    end
3208end
3209Param.Action.RUN=0; %desactivate the input RUN=1
3210
3211fill_GUI(Param,handles.series)% fill the elements of the GUI series with the input parameters
3212SeriesData=get(handles.series,'UserData');
3213if isfield(Param,'InputFields')
3214    ListField=Param.InputFields.FieldName;
3215    if ischar(ListField),ListField={ListField}; end
3216    set(handles.FieldName,'String',[ListField;{'get-field...'}])
3217     set(handles.FieldName,'Value',1:numel(ListField))
3218     set(handles.FieldName,'Visible','on')
3219end       
3220if isfield(Param,'ActionInput')%  introduce  parameters specific to an Action fct, for instance PIV parameters
3221    set(handles.ActionInput,'Visible','on')
3222    set(handles.ActionInput,'Value',0)
3223    Param.ActionInput.ConfigSource=filexml;% record the source of config for future info
3224    SeriesData.ActionInput=Param.ActionInput;
3225end
3226if isfield(Param,'TransformInput')%  introduce  parameters specific to a transform fct
3227    SeriesData.TransformInput=Param.TransformInput;
3228end
3229if isfield(Param,'ProjObject') %introduce projection object if relevant
3230    SeriesData.ProjObject=Param.ProjObject;
3231end
3232set(handles.series,'UserData',SeriesData)
3233if isfield(Param,'CheckObject') && isequal(Param.CheckObject,1)
3234    set(handles.ProjObject,'String',Param.ProjObject.Name)
3235    set(handles.ViewObject,'Visible','on')
3236    set(handles.EditObject,'Visible','on')
3237    set(handles.DeleteObject,'Visible','on')
3238else     
3239    set(handles.ProjObject,'String','')
3240    set(handles.ProjObject,'Visible','off')
3241    set(handles.ViewObject,'Visible','off')
3242    set(handles.EditObject,'Visible','off')
3243    set(handles.DeleteObject,'Visible','off')     
3244end     
3245set(handles.REFRESH,'BackgroundColor',[1 0 1]); %paint REFRESH button in magenta to indicate that it should be activated
3246
3247
3248%------------------------------------------------------------------------
3249% --- Executes when the GUI series is resized.
3250%------------------------------------------------------------------------
3251function series_ResizeFcn(hObject, eventdata, handles)
3252
3253%% input table
3254set(handles.InputTable,'Unit','pixel')
3255Pos=get(handles.InputTable,'Position');
3256set(handles.InputTable,'Unit','normalized')
3257ColumnWidth=round([0.5 0.14 0.14 0.14 0.08]*(Pos(3)-52));
3258ColumnWidth=num2cell(ColumnWidth);
3259set(handles.InputTable,'ColumnWidth',ColumnWidth)
3260
3261%% MinIndex_j and MaxIndex_i
3262unit=get(handles.MinIndex_i,'Unit');
3263set(handles.MinIndex_i,'Unit','pixel')
3264Pos=get(handles.MinIndex_i,'Position');
3265set(handles.MinIndex_i,'Unit',unit)
3266set(handles.MinIndex_i,'ColumnWidth',{Pos(3)-18})
3267set(handles.MaxIndex_i,'ColumnWidth',{Pos(3)-18})
3268set(handles.MinIndex_j,'ColumnWidth',{Pos(3)-18})
3269set(handles.MaxIndex_j,'ColumnWidth',{Pos(3)-18})
3270
3271%% TimeTable
3272set(handles.TimeTable,'Unit','pixel')
3273Pos=get(handles.TimeTable,'Position');
3274set(handles.TimeTable,'Unit','normalized')
3275% ColumnWidth=get(handles.TimeTable,'ColumnWidth');
3276ColumnWidth=num2cell(floor([0.2 0.2 0.2 0.2 0.2]*(Pos(3)-20)));
3277set(handles.TimeTable,'ColumnWidth',ColumnWidth)
3278
3279
3280%% PairString
3281set(handles.PairString,'Unit','pixel')
3282Pos=get(handles.PairString,'Position');
3283set(handles.PairString,'Unit','normalized')
3284set(handles.PairString,'ColumnWidth',{Pos(3)-5})
3285
3286%% MaskTable
3287set(handles.MaskTable,'Unit','pixel')
3288Pos=get(handles.MaskTable,'Position');
3289set(handles.MaskTable,'Unit','normalized')
3290set(handles.MaskTable,'ColumnWidth',{Pos(3)-5})
3291
3292%------------------------------------------------------------------------
3293% --- Executes on button press in status.
3294%------------------------------------------------------------------------
3295function status_Callback(hObject, eventdata, handles)
3296
3297if get(handles.status,'Value')
3298    set(handles.status,'BackgroundColor',[1 1 0])
3299    drawnow
3300    Param=read_GUI(handles.series);
3301    RootPath=Param.InputTable{1,1};
3302    if ~isfield(Param,'OutputSubDir')   
3303        msgbox_uvmat('ERROR','no standard sub-directory definition for output files, use a browser to check the output')
3304        set(handles.status,'BackgroundColor',[0 1 0])
3305        return
3306    end
3307    OutputSubDir=[Param.OutputSubDir Param.OutputDirExt];% subdirectory for output files
3308    OutputDir=fullfile(RootPath,OutputSubDir);
3309    if exist(OutputDir,'dir')
3310        uigetfile_uvmat('status_display',OutputDir)
3311    else
3312        msgbox_uvmat('ERROR','output folder not created yet: calculation did not start')
3313        set(handles.status,'BackgroundColor',[0 1 0])
3314    end
3315else
3316    %% delete current display fig if selection is off
3317    set(handles.status,'BackgroundColor',[0 1 0])
3318    hfig=findobj(allchild(0),'name','status_display');
3319    if ~isempty(hfig)
3320        delete(hfig)
3321    end
3322    return
3323end
3324
3325
3326%------------------------------------------------------------------------   
3327% launched by selecting a file on the list
3328%------------------------------------------------------------------------
3329function view_file(hObject, eventdata)
3330
3331list=get(hObject,'String');
3332index=get(hObject,'Value');
3333rootroot=get(hObject,'UserData');
3334selectname=list{index};
3335ind_dot=regexp(selectname,'\.\.\.');
3336if ~isempty(ind_dot)
3337    selectname=selectname(1:ind_dot-1);
3338end
3339FullSelectName=fullfile(rootroot,selectname);
3340if exist(FullSelectName,'dir')% a directory has been selected
3341    ListFiles=dir(FullSelectName);
3342    ListDisplay=cell(numel(ListFiles),1);
3343    for ilist=2:numel(ListDisplay)% suppress the first line '.'
3344        ListDisplay{ilist-1}=ListFiles(ilist).name;
3345    end
3346    set(hObject,'Value',1)
3347    set(hObject,'String',ListDisplay)
3348    if strcmp(selectname,'..')
3349        FullSelectName=fileparts(fileparts(FullSelectName));
3350    end
3351    set(hObject,'UserData',FullSelectName)
3352    hfig=get(hObject,'parent');
3353    htitlebox=findobj(hfig,'tag','titlebox');   
3354    set(htitlebox,'String',FullSelectName)
3355elseif exist(FullSelectName,'file')%visualise the vel field if it exists
3356    FileInfo=get_file_info(FullSelectName);   
3357    if strcmp(FileInfo.FileType,'txt')
3358        edit(FullSelectName)
3359    elseif strcmp(FileInfo.FileType,'xml')
3360        editxml(FullSelectName)
3361    else
3362        uvmat(FullSelectName)
3363    end
3364    set(gcbo,'Value',1)
3365end
3366
3367
3368%------------------------------------------------------------------------   
3369% launched by refreshing the status figure
3370%------------------------------------------------------------------------
3371function refresh_GUI(hfig)
3372
3373htitlebox=findobj(hfig,'tag','titlebox');
3374hlist=findobj(hfig,'tag','list');
3375hseries=findobj(allchild(0),'tag','series');
3376hstatus=findobj(hseries,'tag','status');
3377StatusData=get(hstatus,'UserData');
3378OutputDir=get(htitlebox,'String');
3379if ischar(OutputDir),OutputDir={OutputDir};end
3380ListFiles=dir(OutputDir{1});
3381if numel(ListFiles)<1
3382    return
3383end
3384ListFiles(1)=[];%removes the first line ='.'
3385ListDisplay=cell(numel(ListFiles),1);
3386testrecent=0;
3387datnum=zeros(numel(ListDisplay),1);
3388for ilist=1:numel(ListDisplay)
3389    ListDisplay{ilist}=ListFiles(ilist).name;
3390      if ~ListFiles(ilist).isdir && isfield(ListFiles(ilist),'datenum')
3391            datnum(ilist)=ListFiles(ilist).datenum;%only available in recent matlab versions
3392            testrecent=1;
3393       end
3394end
3395set(hlist,'String',ListDisplay)
3396
3397%% Look at date of creation
3398ListDisplay=ListDisplay(datnum~=0);
3399datnum=datnum(datnum~=0);%keep the non zero values corresponding to existing files
3400NbOutputFile=[];
3401if isempty(datnum)
3402    if testrecent
3403        message='no civ result created yet';
3404    else
3405        message='';
3406    end
3407else
3408    [first,indfirst]=min(datnum);
3409    [last,indlast]=max(datnum);
3410    NbOutputFile_str='?';
3411    NbOutputFile=[];
3412    if isfield(StatusData,'NbOutputFile')
3413        NbOutputFile=StatusData.NbOutputFile;
3414        NbOutputFile_str=num2str(NbOutputFile);
3415    end
3416    message={[num2str(numel(datnum)) ' file(s) done over ' NbOutputFile_str] ;['oldest modification:  ' ListDisplay{indfirst} ' : ' datestr(first)];...
3417        ['latest modification:  ' ListDisplay{indlast} ' : ' datestr(last)]};
3418end
3419set(htitlebox,'String', [OutputDir{1};message])
3420
3421%% update the waitbar
3422hwaitbar=findobj(hfig,'tag','waitbar');
3423if ~isempty(NbOutputFile)
3424    BarPosition=get(hwaitbar,'Position');
3425    BarPosition(3)=0.9*numel(datnum)/NbOutputFile;
3426    set(hwaitbar,'Position',BarPosition)
3427end
3428
3429%------------------------------------------------------------------------
3430% --- Executes on selection change in ActionExt.
3431%------------------------------------------------------------------------
3432function ActionExt_Callback(hObject, eventdata, handles)
3433
3434ActionExtList=get(handles.ActionExt,'String');
3435ActionExt=ActionExtList{get(handles.ActionExt,'Value')};
3436if strcmp(ActionExt,'.py (in dev.)')
3437    set(handles.RunMode,'Value',2)
3438end
3439
3440%function num_NbProcess_Callback(hObject, eventdata, handles)
3441
3442
3443function num_NbSlice_Callback(hObject, eventdata, handles)
3444NbSlice=str2num(get(handles.num_NbSlice,'String'));
3445%set(handles.num_NbProcess,'String',num2str(NbSlice))
3446
3447%------------------------------------------------------------------------
3448% --- set the visibility of relevant velocity type menus:
3449function menu=set_veltype_display(Civ,FileType)
3450%------------------------------------------------------------------------
3451if ~exist('FileType','var')
3452    FileType='civx';
3453end
3454switch FileType
3455    case 'civx'
3456        menu={'civ1';'interp1';'filter1';'civ2';'interp2';'filter2'};
3457        if isequal(Civ,0)
3458            imax=0;
3459        elseif isequal(Civ,1) || isequal(Civ,2)
3460            imax=1;
3461        elseif isequal(Civ,3)
3462            imax=3;
3463        elseif isequal(Civ,4) || isequal(Civ,5)
3464            imax=4;
3465        elseif isequal(Civ,6) %patch2
3466            imax=6;
3467        end
3468    case 'civdata'
3469        menu={'civ1';'filter1';'civ2';'filter2'};
3470        if isequal(Civ,0)
3471            imax=0;
3472        elseif isequal(Civ,1) || isequal(Civ,2)
3473            imax=1;
3474        elseif isequal(Civ,3)
3475            imax=2;
3476        elseif isequal(Civ,4) || isequal(Civ,5)
3477            imax=3;
3478        else%if isequal(Civ,6) %patch2
3479            imax=4;
3480        end
3481end
3482menu=menu(1:imax);
3483
3484
3485% --- Executes on mouse motion over figure - except title and menu.
3486function series_WindowButtonMotionFcn(hObject, eventdata, handles)
3487set(hObject,'Pointer','arrow');
3488
3489
3490% --- Executes on button press in SetPairs.
3491function SetPairs_Callback(hObject, eventdata, handles)
3492
3493%% delete previous occurrence of 'set_pairs'
3494hfig=findobj(allchild(0),'Tag','set_pairs');
3495if ~isempty(hfig)
3496delete(hfig)
3497end
3498
3499%% create the GUI set_pairs
3500set(0,'Unit','points')
3501ScreenSize=get(0,'ScreenSize');% get the size of the screen, to put the fig on the upper right
3502Width=220;% fig width in points (1/72 inch)
3503Height=min(0.8*ScreenSize(4),300);
3504Left=ScreenSize(3)- Width-40; %right edge close to the right, with margin=40
3505Bottom=ScreenSize(4)-Height-40; %put fig at top right
3506hfig=findobj(allchild(0),'Tag','set_slice');
3507if ~isempty(hfig),delete(hfig), end; %delete existing version of the GUI
3508hfig=figure('name','set_pairs','tag','set_pairs','MenuBar','none','NumberTitle','off','Unit','points','Position',[Left,Bottom,Width,Height]);
3509BackgroundColor=get(hfig,'Color');
3510SeriesData=get(handles.series,'UserData');
3511TimeUnit=get(handles.TimeUnit,'String');
3512PairString=get(handles.PairString,'Data');
3513ListViewLines=find(cellfun('isempty',PairString)==0);%find list of non empty pairs
3514ListViewMenu=cell(numel(ListViewLines),1);
3515iview=get(handles.PairString,'Value');
3516for ilist=1:numel(ListViewLines)
3517    ListViewMenu{ilist}=num2str(ListViewLines(ilist));
3518end
3519if isempty(iview)
3520    ListViewValue=numel(ListViewLines);% we work by default on the pair option for the last line which requires pairs
3521    iview=ListViewLines(end);
3522else
3523    ListViewValue=find(ListViewLines==iview);
3524end
3525ref_i=str2num(get(handles.num_first_i,'String'));
3526ref_j=1;%default
3527if strcmp(get(handles.num_first_j,'String'),'Visible')
3528    ref_j=str2num(get(handles.num_first_j,'String'));
3529end
3530[ModeMenu,ModeValue]=update_mode(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j2_series{iview});
3531displ_pair=update_listpair(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j1_series{iview},SeriesData.j2_series{iview},ModeMenu{ModeValue},...
3532                                                     SeriesData.Time{iview},TimeUnit,ref_i,ref_j,SeriesData.FileInfo{iview});
3533% first raw of the GUI
3534uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.88 0.5 0.1],'BackgroundColor',BackgroundColor,...
3535    'String','row to edit #','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','right');%title
3536uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.54 0.8 0.3 0.2],'BackgroundColor',[1 1 1],...
3537    'Callback',@(hObject,eventdata)ListView_Callback(hObject,eventdata),'String',ListViewMenu,'Value',ListViewValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3538    'Tag','ListView','TooltipString','''ListView'':choice of the file series w for pair display');
3539% second raw of the GUI
3540uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.79 0.7 0.1],'BackgroundColor',BackgroundColor,...
3541    'String','mode of index pairing:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3542uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.05 0.62 0.9 0.2],'BackgroundColor',[1 1 1],...
3543    'Callback',@(hObject,eventdata)Mode_Callback(hObject,eventdata),'String',ModeMenu,'Value',ModeValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3544    'Tag','Mode','TooltipString','''Mode'': choice of the image pair mode');
3545% third raw
3546uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.6 0.7 0.1],'BackgroundColor',BackgroundColor,...
3547    'String','pair choice:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3548uicontrol('Style','listbox','Units','normalized', 'Position', [0.05 0.42 0.9 0.2],'BackgroundColor',[1 1 1],...
3549    'Callback',@(hObject,eventdata)ListPair_Callback(hObject,eventdata),'String',displ_pair,'Value',1,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3550    'Tag','ListPair','TooltipString','''ListPair'': menu for selecting the image pair');
3551uicontrol('Style','text','Units','normalized', 'Position', [0.1 0.22 0.8 0.1],'BackgroundColor',BackgroundColor,...
3552    'String','ref_i           ref_j','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','center');%title
3553uicontrol('Style','edit','Units','normalized', 'Position', [0.15 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3554    'Callback',@(hObject,eventdata)num_ref_i_Callback(hObject,eventdata),'String',num2str(ref_i),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3555    'Tag','num_ref_i','TooltipString','''num_ref_i'': reference field index i used to display dt in ''list_pair_civ''');
3556uicontrol('Style','edit','Units','normalized', 'Position', [0.55 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3557    'Callback',@(hObject,eventdata)num_ref_j_Callback(hObject,eventdata),'String',num2str(ref_j),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3558    'Tag','num_ref_j','TooltipString','''num_ref_j'': reference field index i used to display dt in ''list_pair_civ''');
3559uicontrol('Style','pushbutton','Units','normalized', 'Position', [0.01 0.01 0.3 0.12],'BackgroundColor',[0 1 0],...
3560    'Callback',@(hObject,eventdata)OK_Callback(hObject,eventdata),'String','OK','FontUnits','points','FontSize',12,'FontWeight','bold',...
3561    'Tag','OK','TooltipString','''OK'': validate the choice');
3562%  last raw  of the GUI: pushbuttons
3563% uicontrol('Style','pushbutton','Units','normalized', 'Position', [0.35 0.01 0.3 0.15],'BackgroundColor',[0 1 0],'String','OK','Callback',@(hObject,eventdata)OK_Callback(hObject,eventdata),...
3564%     'FontWeight','bold','FontUnits','points','FontSize',12,'TooltipString','''OK'': apply the output to the current field series in uvmat');
3565drawnow
3566
3567%------------------------------------------------------------------------
3568function ListView_Callback(hObject,eventdata)
3569Mode_Callback(hObject,eventdata)
3570
3571%------------------------------------------------------------------------   
3572function Mode_Callback(hObject,eventdata)
3573%% get input info
3574hseries=findobj(allchild(0),'tag','series');%handles of the GUI series
3575hhseries=guidata(hseries);%handles of the elements in the GUI series
3576TimeUnit=get(hhseries.TimeUnit,'String');
3577SeriesData=get(hseries,'UserData');
3578mode_list=get(hObject,'String');
3579mode=mode_list{get(hObject,'Value')};
3580hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3581iview=get(hListView,'Value');
3582i1_series=SeriesData.i1_series{iview};
3583i2_series=SeriesData.i2_series{iview};
3584j1_series=SeriesData.j1_series{iview};
3585j2_series=SeriesData.j2_series{iview};
3586
3587%% enable j index visibility after the new choice
3588status_j='on';%default
3589if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
3590    status_j='off'; % no j index needed
3591elseif strcmp(get(handles.PairString,'Visible'),'on')
3592    check_burst=cellfun(@isempty,regexp(PairString,'^j'));%=0 for burst case, 1 otherwise
3593    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
3594        status_j='off'; % no j index needed for bust case
3595    end
3596end
3597enable_j(handles,status_j) % no j index needed
3598
3599%% get the reference indices for the time interval Dt
3600href_i=findobj(get(hObject,'parent'),'Tag','ref_i');
3601ref_i=[];ref_j=[];
3602if strcmp(get(href_i,'Visible'),'on')
3603    ref_i=str2num(get(href_i,'String'));
3604end
3605if isempty(ref_i)
3606    ref_i=1;
3607end
3608if isempty(ref_j)
3609    ref_j=1;
3610end
3611
3612%% update the menu ListPair
3613Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,SeriesData.Time{iview},TimeUnit,ref_i,ref_j,FileInfo);
3614hlist_pairs=findobj(get(hObject,'parent'),'Tag','ListPair');
3615set(hlist_pairs,'Value',1)% set the first choice by default in ListPair
3616set(hlist_pairs,'String',Menu)% set the menu in ListPair
3617ListPair_Callback(hlist_pairs,[])% apply the default choice in ListPair
3618
3619%-------------------------------------------------------------
3620% --- Executes on selection in ListPair.
3621function ListPair_Callback(hObject,eventdata)
3622%------------------------------------------------------------
3623list_pair=get(hObject,'String');%get the menu of image pairs
3624if isempty(list_pair)
3625    string='';
3626else
3627    string=list_pair{get(hObject,'Value')};
3628   % string=regexprep(string,',.*','');%removes time indication (after ',')
3629end
3630hseries=findobj(allchild(0),'tag','series');
3631hPairString=findobj(hseries,'tag','PairString');
3632PairString=get(hPairString,'Data');
3633hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3634iview=get(hListView,'Value');
3635PairString{iview,1}=string;
3636% report the selected pair string to the table PairString
3637set(hPairString,'Data',PairString)
3638
3639
3640%------------------------------------------------------------------------
3641function num_ref_i_Callback(hObject, eventdata)
3642%------------------------------------------------------------------------
3643Mode_Callback([],[])
3644
3645%------------------------------------------------------------------------
3646function num_ref_j_Callback(hObject, eventdata)
3647%------------------------------------------------------------------------
3648Mode_Callback([],[])
3649
3650%------------------------------------------------------------------------
3651function OK_Callback(hObject, eventdata)
3652%------------------------------------------------------------------------
3653delete(get(hObject,'parent'))
3654
3655
3656%------------------------------------------------------------------------
3657% --- Executes on button press in ClearLine.
3658%------------------------------------------------------------------------
3659function ClearLine_Callback(hObject, eventdata, handles)
3660InputTable=get(handles.InputTable,'Data');
3661iline=str2double(get(handles.InputLine,'String'));
3662if size(InputTable,1)>1
3663    InputTable(iline,:)=[];% suppress the current line if not the first
3664    set(handles.InputTable,'Data',InputTable);
3665end
3666set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refr
3667
3668
3669% --- Executes on button press in MonitorCluster.
3670function MonitorCluster_Callback(hObject, eventdata, handles)
3671web('https://www.legi.grenoble-inp.fr/servfill/monika')
3672
3673function OutputSubDir_Callback(hObject, eventdata, handles)
3674set(handles.OutputSubDir,'BackgroundColor',[1 1 1])
3675
3676
3677% --- Executes on button press in CheckOverwrite.
3678function CheckOverwrite_Callback(hObject, eventdata, handles)
3679
3680
3681
3682% --- Executes on button press in TestCPUTime.
3683function TestCPUTime_Callback(hObject, eventdata, handles)
3684% hObject    handle to TestCPUTime (see GCBO)
3685% eventdata  reserved - to be defined in a future version of MATLAB
3686% handles    structure with handles and user data (see GUIDATA)
3687
3688
3689
3690
3691
Note: See TracBrowser for help on using the repository browser.