source: trunk/src/series.m @ 997

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

ActionInput? button introduced in series, use of parameter file series.xml

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