source: trunk/src/series.m @ 954

Last change on this file since 954 was 954, checked in by sommeria, 8 years ago

update calib modfied + 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')% set the frame InputFields visible
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    end
2349   
2350    set(handles_coord,'Visible','on')
2351    FieldList=[FieldList;{'get_field...'}];
2352    if FieldNameRequest_1 && numel(iview_netcdf)>=2
2353        set(handles.FieldName_1,'Visible','on')
2354        if CheckList_1==0        % not civ input made
2355            ListVarName=SeriesData.FileInfo{iview_netcdf(2)}.ListVarName;
2356            ind_var=get(handles.FieldName,'Value');%indices of previously selected variables
2357            for ilist=1:numel(ind_var)
2358                if isempty(find(strcmp(FieldList{ind_var(ilist)},ListVarName)))
2359                    FieldList_1={};% previous choice not consistent with new input field
2360                    set(handles.FieldName_1,'Value',1)
2361                    break
2362                end
2363            end
2364            warn_coord=0;
2365            if isempty(find(strcmp(get(handles.Coord_x,'String'),ListVarName)))||...
2366                    isempty(find(strcmp(get(handles.Coord_y,'String'),ListVarName)))
2367                warn_coord=1;
2368            end
2369            if ~isempty(Coord_z) && isempty(find(strcmp(Coord_z,ListVarName)))
2370                FieldList_1={};
2371                warn_coord=1;
2372            end
2373            if warn_coord
2374                msgbox_uvmat('WARNING','coordiante names do not exist in the second netcdf input file')
2375            end
2376           
2377            set(handles.FieldName_1,'Visible','on')
2378            set(handles.FieldName_1,'Value',1)
2379            set(handles.FieldName_1,'String',FieldList_1)
2380        end
2381    else
2382        set(handles.FieldName_1,'Visible','off')
2383    end
2384    if isempty(FieldList)
2385        set(handles.FieldName,'Visible','off')
2386    else
2387        set(handles.FieldName,'Visible','on')
2388        set(handles.FieldName,'String',FieldList)
2389    end
2390else
2391    set(handles.InputFields,'Visible','off')
2392end
2393
2394%% Introduce visibility of file overwrite option
2395if isfield(ParamOut,'CheckOverwriteVisible')&& strcmp(ParamOut.CheckOverwriteVisible,'on')
2396    set(handles.CheckOverwrite,'Visible','on')
2397else
2398    set(handles.CheckOverwrite,'Visible','off')
2399end
2400
2401%% Check whether alphabetical sorting of input Subdir is allowed by the Action fct  (for multiples series entries)
2402if isfield(ParamOut,'AllowInputSort')&&isequal(ParamOut.AllowInputSort,'on')&& size(Param.InputTable,1)>1
2403    [tild,iview]=sort(InputTable(:,2)); %subdirectories sorted in alphabetical order
2404    set(handles.InputTable,'Data',InputTable(iview,:));
2405    MinIndex_i=get(handles.MinIndex_i,'Data');
2406    MinIndex_j=get(handles.MinIndex_j,'Data');
2407    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2408    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2409    set(handles.MinIndex_i,'Data',MinIndex_i(iview,:));
2410    set(handles.MinIndex_j,'Data',MinIndex_j(iview,:));
2411    set(handles.MaxIndex_i,'Data',MaxIndex_i(iview,:));
2412    set(handles.MaxIndex_j,'Data',MaxIndex_j(iview,:));
2413    TimeTable=get(handles.TimeTable,'Data');
2414    set(handles.TimeTable,'Data',TimeTable(iview,:));
2415    PairString=get(handles.PairString,'Data');
2416    set(handles.PairString,'Data',PairString(iview,:));
2417end
2418
2419%% Impose the whole input file index range if requested
2420if isfield(ParamOut,'WholeIndexRange')&&isequal(ParamOut.WholeIndexRange,'on')
2421    MinIndex_i=get(handles.MinIndex_i,'Data');
2422    MinIndex_j=get(handles.MinIndex_j,'Data');
2423    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2424    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2425    set(handles.num_first_i,'String',num2str(MinIndex_i(1)))% set first as the min index (for the first line)
2426    set(handles.num_last_i,'String',num2str(MaxIndex_i(1)))% set last as the max index (for the first line)
2427    set(handles.num_incr_i,'String','1')
2428    set(handles.num_first_j,'String',num2str(MinIndex_j(1)))% set first as the min index (for the first line)
2429    set(handles.num_last_j,'String',num2str(MaxIndex_j(1)))% set last as the max index (for the first line)
2430    set(handles.num_incr_j,'String','1')
2431else  % check index ranges
2432    first_i=1;last_i=1;first_j=1;last_j=1;
2433    if isfield(Param.IndexRange,'first_i')
2434        first_i=Param.IndexRange.first_i;
2435        last_i=Param.IndexRange.last_i;
2436    end
2437    if isfield(Param.IndexRange,'first_j')
2438        first_j=Param.IndexRange.first_j;
2439        last_j=Param.IndexRange.last_j;
2440    end
2441    if last_i < first_i || last_j < first_j , msgbox_uvmat('ERROR','last field number must be larger than the first one'),...
2442            set(handles.RUN, 'Enable','On'), set(handles.RUN,'BackgroundColor',[1 0 0]),return,end;
2443end
2444
2445%% enable or desable j index visibility
2446status_j='on';%default
2447if isfield(ParamOut,'Desable_j_index')&&isequal(ParamOut.Desable_j_index,'on')
2448    status_j='off';
2449end
2450if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
2451    status_j='off'; % no j index needed
2452elseif strcmp(get(handles.PairString,'Visible'),'on')
2453    check_burst=cellfun(@isempty,regexp(get(handles.PairString,'Data'),'^j'));%=0 for burst case, 1 otherwise
2454    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
2455        status_j='off'; % no j index needed for bust case
2456    end
2457end
2458enable_j(handles,status_j) % no j index needed
2459
2460
2461%% NbSlice visibility
2462%NbSliceVisible='off';%default
2463if isfield(ParamOut,'NbSlice') && (strcmp(ParamOut.NbSlice,'on')||isnumeric(ParamOut.NbSlice))
2464    set(handles.num_NbSlice,'Visible','on')
2465    set(handles.NbSlice_title,'Visible','on')
2466else
2467    set(handles.num_NbSlice,'Visible','off')
2468    set(handles.NbSlice_title,'Visible','off')
2469    %     set(handles.num_NbProcess,'String',get(handles.num_NbSlice,'String'))% the nbre of processes is imposed as the nbre of slices
2470    % else
2471    %     set(handles.num_NbProcess,'String','')% free nbre of processes
2472end
2473if isnumeric(ParamOut.NbSlice)
2474    set(handles.num_NbSlice,'String',num2str(ParamOut.NbSlice))
2475    set(handles.num_NbSlice,'Enable','off'); % NbSlice set by the activation of the Action function
2476else
2477    set(handles.num_NbSlice,'Enable','on'); % NbSlice can be modified on the GUI series
2478end
2479% set(handles.num_NbSlice,'Visible',NbSliceVisible)
2480% set(handles.NbSlice_title,'Visible',NbSliceVisible)
2481
2482
2483
2484%% Visibility of FieldTransform menu
2485FieldTransformVisible='off';  %hidden by default
2486if isfield(ParamOut,'FieldTransform')
2487    FieldTransformVisible=ParamOut.FieldTransform; 
2488    TransformName_Callback([],[], handles)
2489end
2490set(handles.FieldTransform,'Visible',FieldTransformVisible)
2491if isfield(ParamOut,'TransformPath')
2492    set(handles.ActionExt,'UserData',ParamOut.TransformPath)
2493else
2494    set(handles.ActionExt,'UserData',[])
2495end
2496
2497%% Visibility of projection object
2498ProjObjectVisible='off';  %hidden by default
2499if isfield(ParamOut,'ProjObject')
2500    ProjObjectVisible=ParamOut.ProjObject;
2501end
2502set(handles.CheckObject,'Visible',ProjObjectVisible)
2503if ~get(handles.CheckObject,'Value')
2504    ProjObjectVisible='off';
2505end
2506set(handles.ProjObject,'Visible',ProjObjectVisible)
2507set(handles.DeleteObject,'Visible',ProjObjectVisible)
2508set(handles.ViewObject,'Visible',ProjObjectVisible)
2509set(handles.EditObject,'Visible',ProjObjectVisible)
2510
2511%% Visibility of mask input
2512MaskVisible='off';  %hidden by default
2513if isfield(ParamOut,'Mask')
2514    MaskVisible=ParamOut.Mask;
2515end
2516set(handles.CheckMask,'Visible',MaskVisible);
2517
2518%% definition of the directory containing the output files
2519if  ~(isfield(SeriesData,'ActionName') && strcmp(ActionName,SeriesData.ActionName))
2520    OutputDirExt='.series'; %default
2521    if isfield(ParamOut,'OutputDirExt')&&~isempty(ParamOut.OutputDirExt)
2522        OutputDirExt=ParamOut.OutputDirExt;
2523    end
2524    set(handles.OutputDirExt,'String',OutputDirExt)
2525end
2526OutputDirVisible='off';
2527OutputSubDirMode='auto';%default
2528SubDirOut='';
2529if isfield(ParamOut,'OutputSubDirMode')
2530    OutputSubDirMode=ParamOut.OutputSubDirMode;
2531end
2532switch OutputSubDirMode
2533    case 'auto';%default
2534        OutputDirVisible='on';
2535        SubDir=InputTable(1:end,2); %set of subdirectories
2536        SubDirOut=SubDir{1};
2537        if numel(SubDir)>1
2538            for ilist=2:numel(SubDir)
2539                SubDirOut=[SubDirOut '-' regexprep(SubDir{ilist},'^/','')];
2540            end
2541        end
2542    case 'one'
2543        OutputDirVisible='on';
2544        SubDirOut=InputTable{1,2}; %use the first subdir name (+OutputDirExt) as output  subdirectory
2545    case 'two'
2546        OutputDirVisible='on';   
2547        SubDir=InputTable(1:2,2); %set of subdirectories
2548        SubDirOut=SubDir{1};
2549        if numel(SubDir)>1
2550                SubDirOut=[SubDirOut '-' regexprep(SubDir{2},'^/','')];
2551        end
2552    case 'last'
2553        OutputDirVisible='on';
2554        SubDirOut=InputTable{end,2}; %use the last subdir name (+OutputDirExt) as output  subdirectory
2555end
2556set(handles.OutputSubDir,'String',SubDirOut)
2557set(handles.OutputSubDir,'BackgroundColor',[1 1 1])% set edit box to white color to indicate refreshment
2558set(handles.OutputDirExt,'Visible',OutputDirVisible)
2559set(handles.OutputSubDir,'Visible',OutputDirVisible)
2560%set(handles.CheckOverwrite,'Visible',OutputDirVisible)
2561set(handles.OutputDir_title,'Visible',OutputDirVisible)
2562SeriesData.ActionName=ActionName;%record ActionName for next use
2563
2564
2565%% visibility of the run mode (local or background or cluster)
2566if strcmp(OutputSubDirMode,'none')
2567    RunModeVisible='off';% only local mode available if no output file is produced
2568else
2569    RunModeVisible='on';
2570end
2571set(handles.RunMode,'Visible',RunModeVisible)
2572set(handles.ActionExt,'Visible',RunModeVisible)
2573set(handles.RunMode_title,'Visible',RunModeVisible)
2574set(handles.ActionExt_title,'Visible',RunModeVisible)
2575
2576
2577%% Expected nbre of output files
2578if isfield(ParamOut,'OutputFileMode')
2579    StatusData.OutputFileMode=ParamOut.OutputFileMode;
2580    set(handles.status,'UserData',StatusData)
2581end
2582
2583%% definition of an additional parameter set, determined by an ancillary GUI
2584if isfield(ParamOut,'ActionInput')
2585    set(handles.ActionInput,'Visible','on')
2586    ParamOut.ActionInput.Program=ActionName; % record the program in ActionInput
2587    SeriesData.ActionInput=ParamOut.ActionInput;
2588else
2589    set(handles.ActionInput,'Visible','off')
2590    if isfield(SeriesData,'ActionInput')
2591        SeriesData=rmfield(SeriesData,'ActionInput');
2592    end
2593end
2594set(handles.series,'UserData',SeriesData)
2595set(handles.ActionName,'BackgroundColor',[1 1 1])
2596
2597%------------------------------------------------------------------------
2598% --- Executes on selection change in FieldName.
2599function FieldName_Callback(hObject, eventdata, handles)
2600%------------------------------------------------------------------------
2601field_str=get(handles.FieldName,'String');
2602field_index=get(handles.FieldName,'Value');
2603field=field_str{field_index(1)};
2604if isequal(field,'get_field...')
2605    SeriesData=get(handles.series,'UserData');
2606    % input line for which the field choice is relevant
2607    iview=find(ismember(SeriesData.FileType,{'netcdf','civx','civdata'}));% all nc files, icluding civ
2608    hget_field=findobj(allchild(0),'name','get_field');
2609    if ~isempty(hget_field)
2610        delete(hget_field)%delete opened versions of get_field
2611    end
2612    Param=read_GUI(handles.series);
2613    InputTable=Param.InputTable(iview,:);
2614    % check the existence of the first file in the series
2615    first_j=[];last_j=[];MinIndex_j=1;MaxIndex_j=1;%default setting for index j
2616    if isfield(Param.IndexRange,'first_j');% if index j is used     
2617        first_j=Param.IndexRange.first_j;
2618        last_j=Param.IndexRange.last_j;
2619        MinIndex_j=Param.IndexRange.MinIndex_j(iview);
2620        MaxIndex_j=Param.IndexRange.MaxIndex_j(iview);
2621    end
2622    PairString='';
2623    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString{iview}; end
2624    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2625    LineIndex=iview(1);
2626    if numel(iview)>1     
2627        answer=msgbox_uvmat('INPUT_TXT',['select the line of the input table:' num2str(iview)] ,num2str(iview(1)));
2628        LineIndex=str2num(answer);
2629%         InputLine=str2num(get(handles.InputLine,'String'));
2630%         if ismember(InputLine,iview)
2631%             LineIndex=InputLine;
2632%         end
2633    end
2634    FirstFileName=fullfile_uvmat(InputTable{LineIndex,1},InputTable{LineIndex,2},InputTable{LineIndex,3},...
2635        InputTable{LineIndex,5},InputTable{LineIndex,4},i1,i2,j1,j2);
2636    if exist(FirstFileName,'file')
2637        ParamIn.Title='get_field: pick input variables and coordinates for series processing';
2638        ParamIn.SeriesInput=1;
2639        GetFieldData=get_field(FirstFileName,ParamIn);
2640        FieldList={};
2641        if isfield(GetFieldData,'FieldOption')% if a field has been selected
2642        switch GetFieldData.FieldOption
2643            case 'vectors'
2644                UName=GetFieldData.PanelVectors.vector_x;
2645                VName=GetFieldData.PanelVectors.vector_y;
2646                YName={GetFieldData.Coordinates.Coord_y};
2647                FieldList={['vec(' UName ',' VName ')'];...
2648                    ['norm(' UName ',' VName ')'];...
2649                    UName;VName};
2650            case {'scalar'}
2651                FieldList=GetFieldData.PanelScalar.scalar;
2652                YName={GetFieldData.Coordinates.Coord_y};
2653                if ischar(FieldList)
2654                    FieldList={FieldList};
2655                end
2656            case 'civdata...'
2657                FieldList=[set_field_list('U','V') ;{'C'}];
2658                set(handles.FieldName,'Value',1) % set menu to 'velocity
2659                XName='X';
2660                YName='y';
2661        end
2662        set(handles.FieldName,'Value',1)
2663        set(handles.FieldName,'String',[FieldList; {'get_field...'}]);
2664        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2665           if ~isempty(regexp(FieldList{1},'^vec'))
2666                set(handles.FieldName,'Value',1)
2667           else
2668                set(handles.FieldName,'Value',1:numel(FieldList))%select all input fields by default
2669           end
2670            XName=GetFieldData.Coordinates.Coord_x;
2671            YName=GetFieldData.Coordinates.Coord_y;
2672            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2673            % get the time info                     
2674            TimeTable=get(handles.TimeTable,'Data');
2675            switch TimeNameStr
2676                case 'file index'
2677                    TimeName='';
2678                case 'attribute'
2679                    TimeName=['att:' GetFieldData.Time.TimeName];
2680                    % update the time table
2681                    TimeTable{LineIndex,2}=get_time(Param.IndexRange.MinIndex_i(LineIndex),MinIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Min time     
2682                    TimeTable{LineIndex,3}=get_time(Param.IndexRange.first_i,first_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % first time             
2683                    TimeTable{LineIndex,4}=get_time(Param.IndexRange.last_i,last_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % last time                     
2684                    TimeTable{LineIndex,5}=get_time(Param.IndexRange.MaxIndex_i(LineIndex),MaxIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Max time
2685                case 'variable'
2686                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2687                    set(handles.NomType,'String','*')
2688                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2689                    set(handles.FileIndex,'String','')
2690                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2691                case 'matrix_index'
2692                    TimeName=['dim:' GetFieldData.Time.TimeName];
2693                    set(handles.NomType,'String','*')
2694                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2695                    set(handles.FileIndex,'String','')
2696                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2697            end
2698            TimeTable{LineIndex,1}=TimeName;
2699            set(handles.TimeTable,'Data',TimeTable);
2700        end
2701        set(handles.Coord_x,'String',XName)
2702        set(handles.Coord_y,'String',YName)
2703        set(handles.Coord_x,'Visible','on')
2704        set(handles.Coord_y,'Visible','on')
2705        end
2706    else
2707        msgbox_uvmat('ERROR',[FirstFileName ' does not exist'])
2708    end
2709end
2710
2711function [TimeValue,DtValue]=get_time(ref_i,ref_j,PairString,InputTable,FileInfo,TimeName,DtName)
2712[i1,i2,j1,j2] = get_file_index(ref_i,ref_j,PairString);
2713FileName=fullfile_uvmat(InputTable{1},InputTable{2},InputTable{3},InputTable{5},InputTable{4},i1,i2,j1,j2);
2714Data=nc2struct(FileName,[]);
2715TimeValue=[];
2716DtValue=[];
2717if isequal(FileInfo.FileType,'civdata')
2718    if ismember(TimeName,{'civ1','filter1'})
2719        TimeValue=Data.Civ1_Time;
2720        DtValue=Data.Civ1_Dt;
2721    else
2722        TimeValue=Data.Civ2_Time;
2723        DtValue=Data.Civ2_Dt;
2724    end
2725else
2726    if ~isempty(TimeName)&& isfield(Data,TimeName)
2727        TimeValue=Data.(TimeName);
2728    end
2729    if exist('DtName','var') && isfield(Data,DtName)
2730        DtValue=Data.(DtName);
2731    end
2732end
2733
2734%------------------------------------------------------------------------
2735% --- Executes on selection change in FieldName_1.
2736function FieldName_1_Callback(hObject, eventdata, handles)
2737%------------------------------------------------------------------------
2738field_str=get(handles.FieldName_1,'String');
2739field_index=get(handles.FieldName_1,'Value');
2740field=field_str{field_index(1)};
2741if isequal(field,'get_field...')
2742    hget_field=findobj(allchild(0),'name','get_field');
2743    if ~isempty(hget_field)
2744        delete(hget_field)%delete opened versions of get_field
2745    end
2746    Param=read_GUI(handles.series);
2747    Param.InputTable=Param.InputTable(1,:);
2748    % check the existence of the first file in the series
2749    first_j=[];
2750    if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
2751    if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
2752    PairString='';
2753    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
2754    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2755    FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
2756        Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
2757    if exist(FirstFileName,'file')
2758        ParamIn.SeriesInput=1;
2759        GetFieldData=get_field(FirstFileName,ParamIn);
2760        FieldList={};
2761        switch GetFieldData.FieldOption
2762            case 'vectors'
2763                UName=GetFieldData.PanelVectors.vector_x;
2764                VName=GetFieldData.PanelVectors.vector_y;
2765                FieldList={['vec(' UName ',' VName ')'];...
2766                    ['norm(' UName ',' VName ')'];...
2767                    UName;VName};
2768            case {'scalar','pick variables'}
2769                FieldList=GetFieldData.PanelScalar.scalar;
2770                if ischar(FieldList)
2771                    FieldList={FieldList};
2772                end
2773            case '1D plot'
2774
2775            case 'civdata...'
2776                FieldList=set_field_list('U','V','C');
2777                set(handles.FieldName,'Value',2) % set menu to 'velocity
2778        end
2779        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2780            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2781            switch TimeNameStr
2782                case 'file index'
2783                    set(handles.TimeName,'String','');
2784                case 'attribute'
2785                    set(handles.TimeName,'String',['att:' GetFieldData.Time.TimeName]);
2786                case 'variable'
2787                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2788                    set(handles.NomType,'String','*')
2789                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2790                    set(handles.FileIndex,'String','')
2791                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2792                case 'matrix_index'
2793                    set(handles.TimeName,'String',['dim:' GetFieldData.Time.TimeName]);
2794                    set(handles.NomType,'String','*')
2795                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2796                    set(handles.FileIndex,'String','')
2797                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2798            end
2799        end
2800        set(handles.FieldName_1,'Value',1)
2801        set(handles.FieldName_1,'String',[FieldList; {'get_field...'}]);
2802    end
2803end   
2804
2805
2806%%%%%%%%%%%%%
2807function [ind_remove]=find_pairs(dirpair,ind_i,last_i)
2808indsel=ind_i;
2809indiff=diff(ind_i); %test index increment to detect multiplets (several pairs with the same index ind_i) and holes in the series
2810indiff=[1 indiff last_i-ind_i(end)+1];%for testing gaps with the imposed bounds
2811if ~isempty(indiff)
2812    indiff2=diff(indiff);
2813    indiffp=[indiff2 1];
2814    indiffm=[1 indiff2];
2815    ind_multi_m=find((indiff==0)&(indiffm<0))-1;%indices of first members of multiplets
2816    ind_multi_p=find((indiff==0)&(indiffp>0));%indices of last members of multiplets
2817    %for each multiplet, select the most recent file
2818    ind_remove=[];
2819    for i=1:length(ind_multi_m)
2820        ind_pairs=ind_multi_m(i):ind_multi_p(i);
2821        for imulti=1:length(ind_pairs)
2822            datepair(imulti)=datenum(dirpair(ind_pairs(imulti)).date);%dates of creation
2823        end
2824        [datenew,indsort2]=sort(datepair); %sort the multiplet by creation date
2825        ind_s=indsort2(1:end-1);%
2826        ind_remove=[ind_remove ind_pairs(ind_s)];%remove these indices, leave the last one
2827    end
2828end
2829
2830%------------------------------------------------------------------------
2831% --- determine the list of index pairstring of processing file
2832function [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)
2833%------------------------------------------------------------------------
2834num_i1=num_i;% set of first image numbers by default
2835num_i2=num_i;
2836num_j1=num_j;
2837num_j2=num_j;
2838num_i_out=num_i;
2839num_j_out=num_j;
2840% if isequal (NomType,'_1-2_1') || isequal (NomType,'_1-2')
2841if isequal(mode,'series(Di)')
2842    num_i1_line=num_i+ind_shift(3);% set of first image numbers
2843    num_i2_line=num_i+ind_shift(4);
2844    % adjust the first and last field number
2845        indsel=find(num_i1_line >= 1);
2846    num_i_out=num_i(indsel);
2847    num_i1_line=num_i1_line(indsel);
2848    num_i2_line=num_i2_line(indsel);
2849    num_j1=meshgrid(num_j,ones(size(num_i1_line)));
2850    num_j2=meshgrid(num_j,ones(size(num_i1_line)));
2851    [xx,num_i1]=meshgrid(num_j,num_i1_line);
2852    [xx,num_i2]=meshgrid(num_j,num_i2_line);
2853elseif isequal (mode,'series(Dj)')||isequal (mode,'bursts')
2854    if isequal(mode,'bursts') %case of bursts (png_old or png_2D)
2855        num_j1=ind_shift(1)*ones(size(num_i));
2856        num_j2=ind_shift(2)*ones(size(num_i));
2857    else
2858        num_j1_col=num_j+ind_shift(1);% set of first image numbers
2859        num_j2_col=num_j+ind_shift(2);
2860        % adjust the first field number
2861        indsel=find((num_j1_col >= 1));   
2862        num_j_out=num_j(indsel);
2863        num_j1_col=num_j1_col(indsel);
2864        num_j2_col=num_j2_col(indsel);
2865        [num_i1,num_j1]=meshgrid(num_i,num_j1_col);
2866        [num_i2,num_j2]=meshgrid(num_i,num_j2_col);
2867    end   
2868end
2869
2870%------------------------------------------------------------------------
2871% --- Executes on button press in CheckObject.
2872function CheckObject_Callback(hObject, eventdata, handles)
2873%------------------------------------------------------------------------
2874hset_object=findobj(allchild(0),'tag','set_object');%find the set_object interface handle
2875if get(handles.CheckObject,'Value')
2876    SeriesData=get(handles.series,'UserData');
2877    if isfield(SeriesData,'ProjObject') && ~isempty(SeriesData.ProjObject)
2878        set(handles.ViewObject,'Value',1)
2879        ViewObject_Callback(hObject, eventdata, handles)
2880    else
2881        if ishandle(hset_object)
2882            uistack(hset_object,'top')% show the GUI set_object if opened
2883        else
2884            %get the object file
2885            InputTable=get(handles.InputTable,'Data');
2886            defaultname=InputTable{1,1};
2887            if isempty(defaultname)
2888                defaultname={''};
2889            end
2890            fileinput=uigetfile_uvmat('pick a xml object file (or use uvmat to create it)',defaultname,'.xml');
2891            if isempty(fileinput)% exit if no object file is selected
2892                set(handles.CheckObject,'Value',0)
2893                return
2894            end
2895            %read the file
2896            data=xml2struct(fileinput);
2897            if ~isfield(data,'Type')
2898                msgbox_uvmat('ERROR',[fileinput ' is not an object xml file'])
2899                set(handles.CheckObject,'Value',0)
2900                return
2901            end
2902            if ~isfield(data,'ProjMode')
2903                data.ProjMode='none';
2904            end
2905            hset_object=set_object(data);% call the set_object interface
2906            set(hset_object,'Name','set_object_series')% name to distinguish from set_object used with uvmat
2907        end
2908        ProjObject=read_GUI(hset_object);
2909        set(handles.ProjObject,'String',ProjObject.Name);%display the object name
2910        SeriesData=get(handles.series,'UserData');
2911        SeriesData.ProjObject=ProjObject;
2912        set(handles.series,'UserData',SeriesData);
2913    end
2914    set(handles.EditObject,'Visible','on');
2915    set(handles.DeleteObject,'Visible','on');
2916    set(handles.ViewObject,'Visible','on');
2917    set(handles.ProjObject,'Visible','on');
2918else
2919    set(handles.EditObject,'Visible','off');
2920    set(handles.DeleteObject,'Visible','off');
2921    set(handles.ViewObject,'Visible','off');
2922    if ~ishandle(hset_object)
2923        set(handles.ViewObject,'Value',0);
2924    end
2925    set(handles.ProjObject,'Visible','off');
2926end
2927
2928%------------------------------------------------------------------------
2929% --- Executes on button press in ViewObject.
2930%------------------------------------------------------------------------
2931function ViewObject_Callback(hObject, eventdata, handles)
2932
2933UserData=get(handles.series,'UserData');
2934hset_object=findobj(allchild(0),'Tag','set_object');
2935if ~isempty(hset_object)
2936    delete(hset_object)% refresh set_object if already opened
2937end
2938hset_object=set_object(UserData.ProjObject);
2939set(hset_object,'Name','view_object_series')
2940
2941
2942%------------------------------------------------------------------------
2943% --- Executes on button press in EditObject.
2944function EditObject_Callback(hObject, eventdata, handles)
2945%------------------------------------------------------------------------
2946if get(handles.EditObject,'Value')
2947    set(handles.ViewObject,'Value',0)
2948        UserData=get(handles.series,'UserData');
2949    hset_object=set_object(UserData.ProjObject);
2950    set(hset_object,'Name','edit_object_series')
2951    set(get(hset_object,'Children'),'Enable','on')
2952else
2953    hset_object=findobj(allchild(0),'Tag','set_object');
2954    if ~isempty(hset_object)
2955        set(get(hset_object,'Children'),'Enable','off')
2956    end
2957end
2958
2959%------------------------------------------------------------------------
2960% --- Executes on button press in DeleteObject.
2961function DeleteObject_Callback(hObject, eventdata, handles)
2962%------------------------------------------------------------------------
2963SeriesData=get(handles.series,'UserData');
2964SeriesData.ProjObject=[];
2965set(handles.series,'UserData',SeriesData)
2966set(handles.ProjObject,'String','')
2967set(handles.ProjObject,'Visible','off')
2968set(handles.CheckObject,'Value',0)
2969set(handles.ViewObject,'Visible','off')
2970set(handles.EditObject,'Visible','off')
2971hset_object=findobj(allchild(0),'name','set_object_series');
2972if ~isempty(hset_object)
2973    delete(hset_object)
2974end
2975set(handles.DeleteObject,'Visible','off')
2976
2977%------------------------------------------------------------------------
2978% --- Executed when CheckMask is activated
2979%------------------------------------------------------------------------
2980function CheckMask_Callback(hObject, eventdata, handles)
2981
2982if get(handles.CheckMask,'Value')
2983    InputTable=get(handles.InputTable,'Data');
2984    nbview=size(InputTable,1);
2985    MaskTable=cell(nbview,1);%default
2986    ListMask=cell(nbview,1);%default
2987    MaskData=get(handles.MaskTable,'Data');
2988    MaskData(size(MaskData,1):nbview,1)=cell(size(MaskData,1):nbview,1);%complement if undefined lines
2989    for iview=1:nbview
2990        ListMask{iview,1}=num2str(iview);
2991        RootPath=InputTable{iview,1};
2992        if ~isempty(RootPath)
2993            if isempty(MaskData{iview})
2994                SubDir=InputTable{iview,2};
2995                MaskPath=fullfile(RootPath,[regexprep(SubDir,'\..*','') '.mask']);%take the root part of SubDir, before the first dot '.'
2996                if exist(MaskPath,'dir')
2997                    ListStruct=dir(MaskPath);%look for a mask file
2998                    ListCells=struct2cell(ListStruct);% transform dir struct to a cell arrray
2999                    check_dir=cell2mat(ListCells(4,:));% =1 for directories, =0 for files
3000                    ListFiles=ListCells(1,:);%list of file and dri names
3001                    ListFiles=ListFiles(~check_dir);%list of file names (excluding dir)
3002                    mdetect=0;
3003                    if ~isempty(ListFiles)
3004                        for ifile=1:numel(ListFiles)
3005                            [tild,tild,MaskFile{ifile},i1_series,i2_series,j1_series,j2_series,MaskNomType,MaskFileType]=find_file_series(MaskPath,ListFiles{ifile},0);
3006                            if strcmp(MaskFileType,'image') && isempty(i2_series) && isempty(j2_series)
3007                                mdetect=1;
3008                                MaskName=ListFiles{ifile};
3009                            end
3010                            if ~strcmp(MaskFile{ifile},MaskFile{1})
3011                                mdetect=0;% cancel detection test in case of multiple masks, use the brower for selection
3012                                break
3013                            end
3014                        end
3015                    end
3016                    if mdetect==1
3017                        MaskName=fullfile(MaskPath,'mask_1.png');
3018                    else
3019                        MaskName=uigetfile_uvmat('select a mask file:',MaskPath,'image');
3020                    end
3021                else
3022                    MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3023                end
3024                MaskTable{iview,1}=MaskName ;
3025                ListMask{iview,1}=num2str(iview);
3026            end
3027        end
3028    end
3029    set(handles.MaskTable,'Data',MaskTable)
3030    set(handles.MaskTable,'Visible','on')
3031    set(handles.MaskBrowse,'Visible','on')
3032    set(handles.ListMask,'Visible','on')
3033    set(handles.ListMask,'String',ListMask)
3034    set(handles.ListMask,'Value',1)
3035else
3036    set(handles.MaskTable,'Visible','off')
3037    set(handles.MaskBrowse,'Visible','off')
3038    set(handles.ListMask,'Visible','off')
3039end
3040
3041%------------------------------------------------------------------------
3042% --- Executes on button press in MaskBrowse.
3043%------------------------------------------------------------------------
3044function MaskBrowse_Callback(hObject, eventdata, handles)
3045
3046InputTable=get(handles.InputTable,'Data');
3047iview=get(handles.ListMask,'Value');
3048RootPath=InputTable{iview,1};
3049MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3050if ~isempty(MaskName)
3051    MaskTable=get(handles.MaskTable,'Data');
3052    MaskTable{iview,1}=MaskName ;
3053    set(handles.MaskTable,'Data',MaskTable)
3054end
3055
3056%------------------------------------------------------------------------
3057% --- Executes when selected cell(s) is changed in MaskTable.
3058%------------------------------------------------------------------------
3059function MaskTable_CellSelectionCallback(hObject, eventdata, handles)
3060
3061if numel(eventdata.Indices)>=1
3062set(handles.ListMask,'Value',eventdata.Indices(1))
3063end
3064
3065%-------------------------------------------------------------------
3066function MenuHelp_Callback(hObject, eventdata, handles)
3067%-------------------------------------------------------------------
3068
3069
3070% path_to_uvmat=which ('uvmat');% check the path of uvmat
3071% pathelp=fileparts(path_to_uvmat);
3072% helpfile=fullfile(pathelp,'uvmat_doc','uvmat_doc.html');
3073% 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')
3074% else
3075%     addpath (fullfile(pathelp,'uvmat_doc'))
3076%     web([helpfile '#series'])
3077% end
3078
3079%-------------------------------------------------------------------
3080% --- Executes on selection change in TransformName.
3081function TransformName_Callback(hObject, eventdata, handles)
3082%----------------------------------------------------------------------
3083TransformList=get(handles.TransformName,'String');
3084TransformIndex=get(handles.TransformName,'Value');
3085TransformName=TransformList{TransformIndex};
3086TransformPathList=get(handles.TransformName,'UserData');
3087nb_builtin_transform=4;
3088if isequal(TransformName,'more...');     
3089    FileName=uigetfile_uvmat('Pick a transform function',get(handles.TransformPath,'String'),'.m');
3090    if isempty(FileName)
3091        return     %browser closed without choice
3092    end
3093    [TransformPath,TransformName,TransformExt]=fileparts(FileName);% removes extension .m
3094    if ~strcmp(TransformExt,'.m')
3095        msgbox_uvmat('ERROR','a Matlab function .m must be introduced');
3096        return
3097    end
3098     % insert the choice in the menu
3099    TransformIndex=find(strcmp(TransformName,TransformList),1);% look for the selected function in the menu Action
3100    if isempty(TransformIndex)%the input string does not exist in the menu
3101        TransformIndex= length(TransformList);
3102        TransformList=[TransformList(1:end-1);{TransformName};TransformList(end)];% the selected function is appended in the menu, before the last item 'more...'
3103        set(handles.TransformName,'String',TransformList)
3104        TransformPathList=[TransformPathList;{TransformPath}];
3105    else% the input function already exist, we update its path (possibly new)
3106        TransformPathList{TransformIndex}=TransformPath;%
3107        set(handles.TransformName,'Value',TransformIndex)
3108    end
3109   % save the new menu in the personal file 'uvmat_perso.mat'
3110   dir_perso=prefdir;%personal Matalb directory
3111   profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3112   if exist(profil_perso,'file')
3113       for ilist=nb_builtin_transform+1:numel(TransformPathList)
3114           TransformListUser{ilist-nb_builtin_transform}=TransformList{ilist};
3115           TransformPathListUser{ilist-nb_builtin_transform}=TransformPathList{ilist};
3116       end
3117       TransformPathListUser=TransformPathListUser';
3118       TransformListUser=TransformListUser';
3119       save (profil_perso,'TransformPathListUser','TransformListUser','-append'); %store the root name for future opening of uvmat
3120   end
3121end
3122
3123%display the current function path
3124set(handles.TransformPath,'String',TransformPathList{TransformIndex}); %show the path to the senlected function
3125set(handles.TransformName,'UserData',TransformPathList);
3126
3127%% create the function handle of the selected fct
3128if ~isempty(TransformName)
3129    if ~exist(TransformPathList{TransformIndex},'dir')
3130        msgbox_uvmat('ERROR',['The prescribed transform function path ' TransformPathList{TransformIndex} ' does not exist']);
3131        return
3132    end
3133    current_dir=pwd;%current working dir
3134    cd(TransformPathList{TransformIndex})
3135    transform_handle=str2func(TransformName);
3136    cd(current_dir)
3137    Field.Action.RUN=0;% indicate that the transform fct is called only to get input param
3138    DataOut=feval(transform_handle,Field,[]);% execute the transform fct to get the required conditions
3139    if isfield(DataOut,'TransformInput')%  used to add transform parameters at selection of the transform fct
3140        SeriesData=get(handles.series,'UserData');
3141        SeriesData.TransformInput=DataOut.TransformInput;
3142        set(handles.series,'UserData',SeriesData)
3143    end
3144end
3145
3146%------------------------------------------------------------------------
3147% --- fct activated by the upper bar menu ExportConfig
3148%------------------------------------------------------------------------
3149function MenuDisplayConfig_Callback(hObject, eventdata, handles)
3150
3151global Param
3152Param=read_GUI_series(handles);
3153evalin('base','global Param')%make CurData global in the workspace
3154display('current series config :')
3155evalin('base','Param') %display CurData in the workspace
3156commandwindow; %brings the Matlab command window to the front
3157
3158%------------------------------------------------------------------------
3159% --- fct activated by the upper bar menu InportConfig: import
3160%     menu settings from an xml file (stored in /0_XML for each run)
3161%------------------------------------------------------------------------
3162function MenuImportConfig_Callback(hObject, eventdata, handles)
3163
3164%% use a browser to choose the xml file containing the processing config
3165InputTable=get(handles.InputTable,'Data');
3166oldfile=InputTable{1,1};%current path in InputTable
3167if isempty(oldfile)
3168    % use a file name stored in prefdir
3169    dir_perso=prefdir;
3170    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3171    if exist(profil_perso,'file')
3172        h=load (profil_perso);
3173        if isfield(h,'RootPath') && ischar(h.RootPath)
3174            oldfile=h.RootPath;
3175        end
3176    end
3177end
3178filexml=uigetfile_uvmat('pick a xml parameter file',oldfile,'.xml');% get the xml file containing processing parameters
3179if isempty(filexml), return, end % quit function if an xml file has not been opened
3180
3181%% fill the GUI series with the content of the xml file
3182Param=xml2struct(filexml);% read the input xml file as a Matlab structure
3183
3184% ask to stop current Action if button RUN is in action (another process is already running)
3185if isequal(get(handles.RUN,'Value'),1)
3186    answer= msgbox_uvmat('INPUT_Y-N','stop current Action process?');
3187    if strcmp(answer,'Yes')
3188        STOP_Callback(hObject, eventdata, handles)
3189    else
3190        return
3191    end
3192end
3193Param.Action.RUN=0; %desactivate the input RUN=1
3194
3195fill_GUI(Param,handles.series)% fill the elements of the GUI series with the input parameters
3196SeriesData=get(handles.series,'UserData');
3197if isfield(Param,'InputFields')
3198    ListField=Param.InputFields.FieldName;
3199    if ischar(ListField),ListField={ListField}; end
3200    set(handles.FieldName,'String',[ListField;{'get-field...'}])
3201     set(handles.FieldName,'Value',1:numel(ListField))
3202     set(handles.FieldName,'Visible','on')
3203end       
3204if isfield(Param,'ActionInput')%  introduce  parameters specific to an Action fct, for instance PIV parameters
3205    set(handles.ActionInput,'Visible','on')
3206    set(handles.ActionInput,'Value',0)
3207    Param.ActionInput.ConfigSource=filexml;% record the source of config for future info
3208    SeriesData.ActionInput=Param.ActionInput;
3209end
3210if isfield(Param,'TransformInput')%  introduce  parameters specific to a transform fct
3211    SeriesData.TransformInput=Param.TransformInput;
3212end
3213if isfield(Param,'ProjObject') %introduce projection object if relevant
3214    SeriesData.ProjObject=Param.ProjObject;
3215end
3216set(handles.series,'UserData',SeriesData)
3217if isfield(Param,'CheckObject') && isequal(Param.CheckObject,1)
3218    set(handles.ProjObject,'String',Param.ProjObject.Name)
3219    set(handles.ViewObject,'Visible','on')
3220    set(handles.EditObject,'Visible','on')
3221    set(handles.DeleteObject,'Visible','on')
3222else     
3223    set(handles.ProjObject,'String','')
3224    set(handles.ProjObject,'Visible','off')
3225    set(handles.ViewObject,'Visible','off')
3226    set(handles.EditObject,'Visible','off')
3227    set(handles.DeleteObject,'Visible','off')     
3228end     
3229set(handles.REFRESH,'BackgroundColor',[1 0 1]); %paint REFRESH button in magenta to indicate that it should be activated
3230
3231
3232%------------------------------------------------------------------------
3233% --- Executes when the GUI series is resized.
3234%------------------------------------------------------------------------
3235function series_ResizeFcn(hObject, eventdata, handles)
3236
3237%% input table
3238set(handles.InputTable,'Unit','pixel')
3239Pos=get(handles.InputTable,'Position');
3240set(handles.InputTable,'Unit','normalized')
3241ColumnWidth=round([0.5 0.14 0.14 0.14 0.08]*(Pos(3)-52));
3242ColumnWidth=num2cell(ColumnWidth);
3243set(handles.InputTable,'ColumnWidth',ColumnWidth)
3244
3245%% MinIndex_j and MaxIndex_i
3246unit=get(handles.MinIndex_i,'Unit');
3247set(handles.MinIndex_i,'Unit','pixel')
3248Pos=get(handles.MinIndex_i,'Position');
3249set(handles.MinIndex_i,'Unit',unit)
3250set(handles.MinIndex_i,'ColumnWidth',{Pos(3)-18})
3251set(handles.MaxIndex_i,'ColumnWidth',{Pos(3)-18})
3252set(handles.MinIndex_j,'ColumnWidth',{Pos(3)-18})
3253set(handles.MaxIndex_j,'ColumnWidth',{Pos(3)-18})
3254
3255%% TimeTable
3256set(handles.TimeTable,'Unit','pixel')
3257Pos=get(handles.TimeTable,'Position');
3258set(handles.TimeTable,'Unit','normalized')
3259% ColumnWidth=get(handles.TimeTable,'ColumnWidth');
3260ColumnWidth=num2cell(floor([0.2 0.2 0.2 0.2 0.2]*(Pos(3)-20)));
3261set(handles.TimeTable,'ColumnWidth',ColumnWidth)
3262
3263
3264%% PairString
3265set(handles.PairString,'Unit','pixel')
3266Pos=get(handles.PairString,'Position');
3267set(handles.PairString,'Unit','normalized')
3268set(handles.PairString,'ColumnWidth',{Pos(3)-5})
3269
3270%% MaskTable
3271set(handles.MaskTable,'Unit','pixel')
3272Pos=get(handles.MaskTable,'Position');
3273set(handles.MaskTable,'Unit','normalized')
3274set(handles.MaskTable,'ColumnWidth',{Pos(3)-5})
3275
3276%------------------------------------------------------------------------
3277% --- Executes on button press in status.
3278%------------------------------------------------------------------------
3279function status_Callback(hObject, eventdata, handles)
3280
3281if get(handles.status,'Value')
3282    set(handles.status,'BackgroundColor',[1 1 0])
3283    drawnow
3284    Param=read_GUI(handles.series);
3285    RootPath=Param.InputTable{1,1};
3286    if ~isfield(Param,'OutputSubDir')   
3287        msgbox_uvmat('ERROR','no standard sub-directory definition for output files, use a browser to check the output')
3288        set(handles.status,'BackgroundColor',[0 1 0])
3289        return
3290    end
3291    OutputSubDir=[Param.OutputSubDir Param.OutputDirExt];% subdirectory for output files
3292    OutputDir=fullfile(RootPath,OutputSubDir);
3293    if exist(OutputDir,'dir')
3294        uigetfile_uvmat('status_display',OutputDir)
3295    else
3296        msgbox_uvmat('ERROR','output folder not created yet: calculation did not start')
3297        set(handles.status,'BackgroundColor',[0 1 0])
3298    end
3299else
3300    %% delete current display fig if selection is off
3301    set(handles.status,'BackgroundColor',[0 1 0])
3302    hfig=findobj(allchild(0),'name','status_display');
3303    if ~isempty(hfig)
3304        delete(hfig)
3305    end
3306    return
3307end
3308
3309
3310%------------------------------------------------------------------------   
3311% launched by selecting a file on the list
3312%------------------------------------------------------------------------
3313function view_file(hObject, eventdata)
3314
3315list=get(hObject,'String');
3316index=get(hObject,'Value');
3317rootroot=get(hObject,'UserData');
3318selectname=list{index};
3319ind_dot=regexp(selectname,'\.\.\.');
3320if ~isempty(ind_dot)
3321    selectname=selectname(1:ind_dot-1);
3322end
3323FullSelectName=fullfile(rootroot,selectname);
3324if exist(FullSelectName,'dir')% a directory has been selected
3325    ListFiles=dir(FullSelectName);
3326    ListDisplay=cell(numel(ListFiles),1);
3327    for ilist=2:numel(ListDisplay)% suppress the first line '.'
3328        ListDisplay{ilist-1}=ListFiles(ilist).name;
3329    end
3330    set(hObject,'Value',1)
3331    set(hObject,'String',ListDisplay)
3332    if strcmp(selectname,'..')
3333        FullSelectName=fileparts(fileparts(FullSelectName));
3334    end
3335    set(hObject,'UserData',FullSelectName)
3336    hfig=get(hObject,'parent');
3337    htitlebox=findobj(hfig,'tag','titlebox');   
3338    set(htitlebox,'String',FullSelectName)
3339elseif exist(FullSelectName,'file')%visualise the vel field if it exists
3340    FileInfo=get_file_info(FullSelectName);   
3341    if strcmp(FileInfo.FileType,'txt')
3342        edit(FullSelectName)
3343    elseif strcmp(FileInfo.FileType,'xml')
3344        editxml(FullSelectName)
3345    else
3346        uvmat(FullSelectName)
3347    end
3348    set(gcbo,'Value',1)
3349end
3350
3351
3352%------------------------------------------------------------------------   
3353% launched by refreshing the status figure
3354%------------------------------------------------------------------------
3355function refresh_GUI(hfig)
3356
3357htitlebox=findobj(hfig,'tag','titlebox');
3358hlist=findobj(hfig,'tag','list');
3359hseries=findobj(allchild(0),'tag','series');
3360hstatus=findobj(hseries,'tag','status');
3361StatusData=get(hstatus,'UserData');
3362OutputDir=get(htitlebox,'String');
3363if ischar(OutputDir),OutputDir={OutputDir};end
3364ListFiles=dir(OutputDir{1});
3365if numel(ListFiles)<1
3366    return
3367end
3368ListFiles(1)=[];%removes the first line ='.'
3369ListDisplay=cell(numel(ListFiles),1);
3370testrecent=0;
3371datnum=zeros(numel(ListDisplay),1);
3372for ilist=1:numel(ListDisplay)
3373    ListDisplay{ilist}=ListFiles(ilist).name;
3374      if ~ListFiles(ilist).isdir && isfield(ListFiles(ilist),'datenum')
3375            datnum(ilist)=ListFiles(ilist).datenum;%only available in recent matlab versions
3376            testrecent=1;
3377       end
3378end
3379set(hlist,'String',ListDisplay)
3380
3381%% Look at date of creation
3382ListDisplay=ListDisplay(datnum~=0);
3383datnum=datnum(datnum~=0);%keep the non zero values corresponding to existing files
3384NbOutputFile=[];
3385if isempty(datnum)
3386    if testrecent
3387        message='no civ result created yet';
3388    else
3389        message='';
3390    end
3391else
3392    [first,indfirst]=min(datnum);
3393    [last,indlast]=max(datnum);
3394    NbOutputFile_str='?';
3395    NbOutputFile=[];
3396    if isfield(StatusData,'NbOutputFile')
3397        NbOutputFile=StatusData.NbOutputFile;
3398        NbOutputFile_str=num2str(NbOutputFile);
3399    end
3400    message={[num2str(numel(datnum)) ' file(s) done over ' NbOutputFile_str] ;['oldest modification:  ' ListDisplay{indfirst} ' : ' datestr(first)];...
3401        ['latest modification:  ' ListDisplay{indlast} ' : ' datestr(last)]};
3402end
3403set(htitlebox,'String', [OutputDir{1};message])
3404
3405%% update the waitbar
3406hwaitbar=findobj(hfig,'tag','waitbar');
3407if ~isempty(NbOutputFile)
3408    BarPosition=get(hwaitbar,'Position');
3409    BarPosition(3)=0.9*numel(datnum)/NbOutputFile;
3410    set(hwaitbar,'Position',BarPosition)
3411end
3412
3413%------------------------------------------------------------------------
3414% --- Executes on selection change in ActionExt.
3415%------------------------------------------------------------------------
3416function ActionExt_Callback(hObject, eventdata, handles)
3417
3418ActionExtList=get(handles.ActionExt,'String');
3419ActionExt=ActionExtList{get(handles.ActionExt,'Value')};
3420if strcmp(ActionExt,'.py (in dev.)')
3421    set(handles.RunMode,'Value',2)
3422end
3423
3424%function num_NbProcess_Callback(hObject, eventdata, handles)
3425
3426
3427function num_NbSlice_Callback(hObject, eventdata, handles)
3428NbSlice=str2num(get(handles.num_NbSlice,'String'));
3429%set(handles.num_NbProcess,'String',num2str(NbSlice))
3430
3431%------------------------------------------------------------------------
3432% --- set the visibility of relevant velocity type menus:
3433function menu=set_veltype_display(Civ,FileType)
3434%------------------------------------------------------------------------
3435if ~exist('FileType','var')
3436    FileType='civx';
3437end
3438switch FileType
3439    case 'civx'
3440        menu={'civ1';'interp1';'filter1';'civ2';'interp2';'filter2'};
3441        if isequal(Civ,0)
3442            imax=0;
3443        elseif isequal(Civ,1) || isequal(Civ,2)
3444            imax=1;
3445        elseif isequal(Civ,3)
3446            imax=3;
3447        elseif isequal(Civ,4) || isequal(Civ,5)
3448            imax=4;
3449        elseif isequal(Civ,6) %patch2
3450            imax=6;
3451        end
3452    case 'civdata'
3453        menu={'civ1';'filter1';'civ2';'filter2'};
3454        if isequal(Civ,0)
3455            imax=0;
3456        elseif isequal(Civ,1) || isequal(Civ,2)
3457            imax=1;
3458        elseif isequal(Civ,3)
3459            imax=2;
3460        elseif isequal(Civ,4) || isequal(Civ,5)
3461            imax=3;
3462        else%if isequal(Civ,6) %patch2
3463            imax=4;
3464        end
3465end
3466menu=menu(1:imax);
3467
3468
3469% --- Executes on mouse motion over figure - except title and menu.
3470function series_WindowButtonMotionFcn(hObject, eventdata, handles)
3471set(hObject,'Pointer','arrow');
3472
3473
3474% --- Executes on button press in SetPairs.
3475function SetPairs_Callback(hObject, iview, handles)
3476
3477%% delete previous occurrence of 'set_pairs'
3478hfig=findobj(allchild(0),'Tag','set_pairs');
3479if ~isempty(hfig)
3480delete(hfig)
3481end
3482
3483%% create the GUI set_pairs
3484set(0,'Unit','points')
3485ScreenSize=get(0,'ScreenSize');% get the size of the screen, to put the fig on the upper right
3486Width=220;% fig width in points (1/72 inch)
3487Height=min(0.8*ScreenSize(4),300);
3488Left=ScreenSize(3)- Width-40; %right edge close to the right, with margin=40
3489Bottom=ScreenSize(4)-Height-40; %put fig at top right
3490hfig=findobj(allchild(0),'Tag','set_slice');
3491if ~isempty(hfig),delete(hfig), end; %delete existing version of the GUI
3492hfig=figure('name','set_pairs','tag','set_pairs','MenuBar','none','NumberTitle','off','Unit','points','Position',[Left,Bottom,Width,Height]);
3493BackgroundColor=get(hfig,'Color');
3494SeriesData=get(handles.series,'UserData');
3495TimeUnit=get(handles.TimeUnit,'String');
3496PairString=get(handles.PairString,'Data');
3497ListViewLines=find(cellfun('isempty',PairString)==0);%find list of non empty pairs
3498ListViewMenu=cell(numel(ListViewLines),1);
3499for ilist=1:numel(ListViewLines)
3500    ListViewMenu{ilist}=num2str(ListViewLines(ilist));
3501end
3502if isempty(iview)
3503    ListViewValue=numel(ListViewLines);% we work by default on the pair option for the last line which requires pairs
3504    iview=ListViewLines(end);
3505else
3506    ListViewValue=find(ListViewLines==iview);
3507end
3508ref_i=str2num(get(handles.num_first_i,'String'));
3509ref_j=1;%default
3510if strcmp(get(handles.num_first_j,'String'),'Visible')
3511    ref_j=str2num(get(handles.num_first_j,'String'));
3512end
3513[ModeMenu,ModeValue]=update_mode(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j2_series{iview});
3514displ_pair=update_listpair(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j1_series{iview},SeriesData.j2_series{iview},ModeMenu{ModeValue},...
3515                                                     SeriesData.Time{iview},TimeUnit,ref_i,ref_j,SeriesData.FileInfo{iview});
3516% first raw of the GUI
3517uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.88 0.5 0.1],'BackgroundColor',BackgroundColor,...
3518    'String','row to edit #','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','right');%title
3519uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.54 0.8 0.3 0.2],'BackgroundColor',[1 1 1],...
3520    'Callback',@(hObject,eventdata)ListView_Callback(hObject,eventdata),'String',ListViewMenu,'Value',ListViewValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3521    'Tag','ListView','TooltipString','''ListView'':choice of the file series w for pair display');
3522% second raw of the GUI
3523uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.79 0.7 0.1],'BackgroundColor',BackgroundColor,...
3524    'String','mode of index pairing:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3525uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.05 0.62 0.9 0.2],'BackgroundColor',[1 1 1],...
3526    'Callback',@(hObject,eventdata)Mode_Callback(hObject,eventdata),'String',ModeMenu,'Value',ModeValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3527    'Tag','Mode','TooltipString','''Mode'': choice of the image pair mode');
3528% third raw
3529uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.6 0.7 0.1],'BackgroundColor',BackgroundColor,...
3530    'String','pair choice:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3531uicontrol('Style','listbox','Units','normalized', 'Position', [0.05 0.42 0.9 0.2],'BackgroundColor',[1 1 1],...
3532    'Callback',@(hObject,eventdata)ListPair_Callback(hObject,eventdata),'String',displ_pair,'Value',1,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3533    'Tag','ListPair','TooltipString','''ListPair'': menu for selecting the image pair');
3534uicontrol('Style','text','Units','normalized', 'Position', [0.1 0.22 0.8 0.1],'BackgroundColor',BackgroundColor,...
3535    'String','ref_i           ref_j','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','center');%title
3536uicontrol('Style','edit','Units','normalized', 'Position', [0.15 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3537    'Callback',@(hObject,eventdata)num_ref_i_Callback(hObject,eventdata),'String',num2str(ref_i),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3538    'Tag','num_ref_i','TooltipString','''num_ref_i'': reference field index i used to display dt in ''list_pair_civ''');
3539uicontrol('Style','edit','Units','normalized', 'Position', [0.55 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3540    'Callback',@(hObject,eventdata)num_ref_j_Callback(hObject,eventdata),'String',num2str(ref_j),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3541    'Tag','num_ref_j','TooltipString','''num_ref_j'': reference field index i used to display dt in ''list_pair_civ''');
3542uicontrol('Style','pushbutton','Units','normalized', 'Position', [0.01 0.01 0.3 0.12],'BackgroundColor',[0 1 0],...
3543    'Callback',@(hObject,eventdata)OK_Callback(hObject,eventdata),'String','OK','FontUnits','points','FontSize',12,'FontWeight','bold',...
3544    'Tag','OK','TooltipString','''OK'': validate the choice');
3545%  last raw  of the GUI: pushbuttons
3546% 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),...
3547%     'FontWeight','bold','FontUnits','points','FontSize',12,'TooltipString','''OK'': apply the output to the current field series in uvmat');
3548drawnow
3549
3550%------------------------------------------------------------------------
3551function ListView_Callback(hObject,eventdata)
3552Mode_Callback(hObject,eventdata)
3553
3554%------------------------------------------------------------------------   
3555function Mode_Callback(hObject,eventdata)
3556%% get input info
3557hseries=findobj(allchild(0),'tag','series');%handles of the GUI series
3558hhseries=guidata(hseries);%handles of the elements in the GUI series
3559TimeUnit=get(hhseries.TimeUnit,'String');
3560SeriesData=get(hseries,'UserData');
3561mode_list=get(hObject,'String');
3562mode=mode_list{get(hObject,'Value')};
3563hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3564iview=get(hListView,'Value');
3565i1_series=SeriesData.i1_series{iview};
3566i2_series=SeriesData.i2_series{iview};
3567j1_series=SeriesData.j1_series{iview};
3568j2_series=SeriesData.j2_series{iview};
3569
3570%% enable j index visibility after the new choice
3571status_j='on';%default
3572if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
3573    status_j='off'; % no j index needed
3574elseif strcmp(get(handles.PairString,'Visible'),'on')
3575    check_burst=cellfun(@isempty,regexp(PairString,'^j'));%=0 for burst case, 1 otherwise
3576    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
3577        status_j='off'; % no j index needed for bust case
3578    end
3579end
3580enable_j(handles,status_j) % no j index needed
3581
3582%% get the reference indices for the time interval Dt
3583href_i=findobj(get(hObject,'parent'),'Tag','ref_i');
3584ref_i=[];ref_j=[];
3585if strcmp(get(href_i,'Visible'),'on')
3586    ref_i=str2num(get(href_i,'String'));
3587end
3588if isempty(ref_i)
3589    ref_i=1;
3590end
3591if isempty(ref_j)
3592    ref_j=1;
3593end
3594
3595%% update the menu ListPair
3596Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,SeriesData.Time{iview},TimeUnit,ref_i,ref_j,FileInfo);
3597hlist_pairs=findobj(get(hObject,'parent'),'Tag','ListPair');
3598set(hlist_pairs,'Value',1)% set the first choice by default in ListPair
3599set(hlist_pairs,'String',Menu)% set the menu in ListPair
3600ListPair_Callback(hlist_pairs,[])% apply the default choice in ListPair
3601
3602%-------------------------------------------------------------
3603% --- Executes on selection in ListPair.
3604function ListPair_Callback(hObject,eventdata)
3605%------------------------------------------------------------
3606list_pair=get(hObject,'String');%get the menu of image pairs
3607if isempty(list_pair)
3608    string='';
3609else
3610    string=list_pair{get(hObject,'Value')};
3611   % string=regexprep(string,',.*','');%removes time indication (after ',')
3612end
3613hseries=findobj(allchild(0),'tag','series');
3614hPairString=findobj(hseries,'tag','PairString');
3615PairString=get(hPairString,'Data');
3616hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3617iview=get(hListView,'Value');
3618PairString{iview,1}=string;
3619% report the selected pair string to the table PairString
3620set(hPairString,'Data',PairString)
3621
3622
3623%------------------------------------------------------------------------
3624function num_ref_i_Callback(hObject, eventdata)
3625%------------------------------------------------------------------------
3626Mode_Callback([],[])
3627
3628%------------------------------------------------------------------------
3629function num_ref_j_Callback(hObject, eventdata)
3630%------------------------------------------------------------------------
3631Mode_Callback([],[])
3632
3633%------------------------------------------------------------------------
3634function OK_Callback(hObject, eventdata)
3635%------------------------------------------------------------------------
3636delete(get(hObject,'parent'))
3637
3638
3639%------------------------------------------------------------------------
3640% --- Executes on button press in ClearLine.
3641%------------------------------------------------------------------------
3642function ClearLine_Callback(hObject, eventdata, handles)
3643InputTable=get(handles.InputTable,'Data');
3644iline=str2double(get(handles.InputLine,'String'));
3645if size(InputTable,1)>1
3646    InputTable(iline,:)=[];% suppress the current line if not the first
3647    set(handles.InputTable,'Data',InputTable);
3648end
3649set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refr
3650
3651
3652% --- Executes on button press in MonitorCluster.
3653function MonitorCluster_Callback(hObject, eventdata, handles)
3654web('https://www.legi.grenoble-inp.fr/servload/monika')
3655
3656
3657
3658function OutputSubDir_Callback(hObject, eventdata, handles)
3659set(handles.OutputSubDir,'BackgroundColor',[1 1 1])
3660
3661
3662% --- Executes on button press in CheckOverwrite.
3663function CheckOverwrite_Callback(hObject, eventdata, handles)
3664
3665
3666
3667% --- Executes on button press in TestCPUTime.
3668function TestCPUTime_Callback(hObject, eventdata, handles)
3669% hObject    handle to TestCPUTime (see GCBO)
3670% eventdata  reserved - to be defined in a future version of MATLAB
3671% handles    structure with handles and user data (see GUIDATA)
3672
3673
3674
3675
3676
Note: See TracBrowser for help on using the repository browser.