source: trunk/src/series.m @ 1170

Last change on this file since 1170 was 1170, checked in by sommeria, 6 days ago

Library Teleops infrared camera added

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