source: trunk/src/series.m @ 934

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

browse data corrected

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