source: trunk/src/series.m @ 994

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

series updated

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