source: trunk/src/series.m @ 991

Last change on this file since 991 was 991, checked in by sommeria, 7 years ago

various

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