source: trunk/src/series.m @ 905

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

projection with tps corrected + minor changes

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