source: trunk/src/series.m @ 913

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

interp range introduced in set_object

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