source: trunk/src/series.m @ 869

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

bug_repaired

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