source: trunk/src/series.m @ 932

Last change on this file since 932 was 932, checked in by sommeria, 5 years ago

writting access improved

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