source: trunk/src/series.m @ 950

Last change on this file since 950 was 950, checked in by sommeria, 9 years ago

various updates

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