source: trunk/src/series.m @ 970

Last change on this file since 970 was 970, checked in by sommeria, 4 years ago

various

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