source: trunk/src/series.m @ 867

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

python option added in series and bug corrections

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