source: trunk/src/series.m @ 526

Last change on this file since 526 was 526, checked in by sommeria, 12 years ago

bugs corrected; Posiibility of usual 1D plots introduced with the new way of using get_field. time_series and aver_stat updated

File size: 81.7 KB
RevLine 
[2]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)
[446]8%      .menu_coord_str: string for the TransformName (menu for coordinate transforms)
9%      .menu_coord_val: value for TransformName (menu for coordinate transforms)
[2]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 Joel Sommeria, 2008, LEGI / CNRS-UJF-INPG, sommeria@coriolis-legi.org.
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
[408]32%------------------------------------------------------------------------
33%------------------------------------------------------------------------
34%  I - MAIN FUNCTION series
35%------------------------------------------------------------------------
36%------------------------------------------------------------------------
[2]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)
[205]62global nb_builtin_ACTION nb_builtin_transform
[2]63% Choose default command line output for series
64handles.output = hObject;
65% Update handles structure
66guidata(hObject, handles);
67%default initial parameters
[156]68drawnow
[244]69set(hObject,'Units','pixels')
[526]70set(handles.PairString,'ColumnName',{'pairs'})
[408]71set(handles.PairString,'ColumnEditable',logical(0))
72set(handles.PairString,'ColumnFormat',{'char'})
73set(handles.PairString,'Data',{''})
[526]74series_ResizeFcn(hObject, eventdata, handles)%resize table according to series GUI size
[332]75set(hObject,'WindowButtonDownFcn',{'mouse_down'})%allows mouse action with right button (zoom for uicontrol display)
[2]76dir_perso=prefdir;
[205]77test_profil_perso=0;
[2]78profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
79if exist(profil_perso,'file')
80     h=load (profil_perso);
[460]81     if isfield(h,'MenuFile')
82          for ifile=1:min(length(h.MenuFile),5)
83              eval(['set(handles.MenuFile_' num2str(ifile) ',''Label'',h.MenuFile{ifile});'])
84          end
85     end
[205]86     test_profil_perso=1;
[2]87end
88
89%check default input data
90if ~exist('param','var')
91    param=[]; %default
92end
93
[376]94%% file name and browser initialisation
[526]95if isfield(param,'transform_str')
96    set(handles.TransformName,'String',param.transform_str)
[2]97end
[526]98if isfield(param,'transform_val')
99    set(handles.TransformName,'Value',param.transform_val);
[2]100else
[446]101     set(handles.TransformName,'Value',1);%default
[2]102end
103if isfield(param,'FileName')
[476]104    InputTable={'','','','',''};
105    set(handles.InputTable,'Data',InputTable)
[2]106    if isfield(param,'FileName_1')
[408]107        display_file_name(handles,param.FileName_1,0)
108        display_file_name(handles,param.FileName,1)
[2]109    else
[408]110        display_file_name(handles,param.FileName,0)
[2]111    end
112end 
[523]113if isfield(param,'incr_i')
114    set(handles.num_incr_i,'String',num2str(param.incr_i))
115end
116if isfield(param,'incr_j')
117    set(handles.num_incr_j,'String',num2str(param.incr_j))
118end
[2]119
[376]120%% fields input initialisation
[2]121if isfield(param,'list_fields')&& isfield(param,'index_fields') &&~isempty(param.list_fields) &&~isempty(param.index_fields)
[446]122    set(handles.FieldName,'String',param.list_fields);% list menu fields
123    set(handles.FieldName,'Value',param.index_fields);% selected string index
[2]124end
[526]125if isfield(param,'Coord_x_str')&& isfield(param,'Coord_x_val')
126        set(handles.Coord_x,'String',param.Coord_x_str);% list menu fields
127    set(handles.Coord_x,'Value',param.Coord_x_val);% selected string index
128end
129if isfield(param,'Coord_y_str')&& isfield(param,'Coord_y_val')
130        set(handles.Coord_y,'String',param.Coord_y_str);% list menu fields
131    set(handles.Coord_y,'Value',param.Coord_y_val);% selected string index
132end
[376]133
[446]134%loads the information stored in prefdir to initiate  the list of ActionName functions
[329]135fct_menu={'check_data_files';'aver_stat';'time_series';'merge_proj';'clean_civ_cmx'};
[38]136transform_menu={'';'phys';'px';'phys_polar'};
[205]137nb_builtin_ACTION=numel(fct_menu); %number of functions
[38]138nb_transform=numel(transform_menu);
[26]139[path_series,name,ext]=fileparts(which('series'));
[34]140path_series=fullfile(path_series,'series');%path of the function 'series'
[332]141addpath (path_series) ; %add the path to UVMAT, (useful in case of change of working directory after civ has been s opened in the working directory)
[276]142path_transform=fullfile(path_series,'transform_field');%path to the field transform functions
[38]143for ilist=1:length(fct_menu)
[2]144    fct_path{ilist,1}=path_series;%paths of the fuctions buil-in in 'series.m'
145end
[39]146
[376]147%% TRANSFORM menu: loads the information stored in prefdir to initiate  the list of field transform functions
[523]148menu_str={'';'sub_field';'phys';'phys_polar'};
[205]149nb_builtin_transform=numel(menu_str); %number of functions
[39]150[path_uvmat,name,ext]=fileparts(which('uvmat'));
151addpath(fullfile(path_uvmat,'transform_field'))
152fct_handle{1,1}=[];
153testexist(1)=1;
154for ilist=2:length(menu_str)
155    if exist(menu_str{ilist},'file')
156        fct_handle{ilist,1}=str2func(menu_str{ilist});
157        testexist(ilist)=1;
158    else
159        testexist(ilist)=0;
160    end
[38]161end
[39]162rmpath(fullfile(path_uvmat,'transform_field'))
163
[523]164%% read the list of transform functions stored in the personal file 'uvmat_perso.mat' in prefdir
[205]165if test_profil_perso
[2]166    if isfield(h,'series_fct') && iscell(h.series_fct)
167         for ilist=1:length(h.series_fct)
168             [path,file]=fileparts(h.series_fct{ilist});
169             fct_path=[fct_path; {path}];%concatene the list of paths
[205]170             fct_menu=[fct_menu; {file}];
[2]171         end
172    end
[38]173    if isfield(h,'transform_fct') && iscell(h.transform_fct)
[39]174        for ilist=1:length(h.transform_fct);
[38]175             [path,file]=fileparts(h.transform_fct{ilist});
[39]176             addpath(path)
177             if exist(file,'file')
178                h_func=str2func(file);
179                testexist=[testexist 1];
180             else
181                h_func=[];
182                testexist=[testexist 0];
183             end
184             fct_handle=[fct_handle; {h_func}];%concatene the list of paths
185             rmpath(path)
186             menu_str=[menu_str; {file}];
187        end
[38]188    end
[2]189end
[38]190fct_menu=[fct_menu;{'more...'}];
[446]191set(handles.ActionName,'String',fct_menu)
192set(handles.ActionName,'UserData',fct_path)% store the list of path in UserData of ACTION
[39]193menu_str=menu_str(find(testexist));
194fct_handle=fct_handle(find(testexist));
195menu_str=[menu_str;{'more...'}];
[446]196set(handles.TransformName,'String',menu_str)
197set(handles.TransformName,'UserData',fct_handle)% store the list of path in UserData of ACTION
[39]198
[472]199%% Adjust the GUI according to the binaries available in PARAM.xml
200path_uvmat=fileparts(which('uvmat')); %path to civ
201addpath (path_uvmat) ; %add the path to civ, (useful in case of change of working directory after civ has been s opened in the working directory)
202errormsg=[];%default error message
203xmlfile='PARAM.xml';
204if exist(xmlfile,'file')
205    try
206        t=xmltree(xmlfile);
207        sparam=convert(t);
208    catch ME
209        errormsg={' Unable to read the file PARAM.xml defining the civx binaries:';ME.message};
210    end
211else
212    errormsg=[xmlfile ' not found: path to civx binaries undefined'];
213end
214if ~isempty(errormsg)
215    msgbox_uvmat('WARNING',errormsg);
216end
217test_batch=0;%default: ,no batch mode available
218if isfield(sparam,'BatchParam') && isfield(sparam.BatchParam,'BatchMode')
219    test_batch=strcmp(sparam.BatchParam.BatchMode,'sge'); %sge is currently the only implemented batch mod
220end
221RUNVal=get(handles.RunMode,'Value');
222if test_batch==0
223   if RUNVal>2
224       set(handles.RunMode,'Value',1)
225   end
226   set(handles.RunMode,'String',{'local';'background'})
227else
228    set(handles.RunMode,'String',{'local';'background';'cluster'})
229end
[2]230
[408]231%------------------------------------------------------------------------
[2]232% --- Outputs from this function are returned to the command line.
233function varargout = series_OutputFcn(hObject, eventdata, handles)
[408]234%------------------------------------------------------------------------
[2]235% varargout  cell array for returning output args (see VARARGOUT);
236% hObject    handle to figure
237% eventdata  reserved - to be defined in a future version of MATLAB
238% handles    structure with handles and user data (see GUIDATA)
239% Get default command line output from handles structure
240varargout{1} = handles.output;
241
[408]242%------------------------------------------------------------------------
243%------------------------------------------------------------------------
244%  II - FUNCTIONS FOR INTRODUCING THE INPUT FILES
245% automatically sets the global properties when the rootfile name is introduced
[446]246% then activate the view-field actionname if selected
[408]247% it is activated either by clicking on the RootPath window or by the
248% browser
249%------------------------------------------------------------------------
250%------------------------------------------------------------------------
[2]251function MenuBrowse_Callback(hObject, eventdata, handles)
[408]252%------------------------------------------------------------------------   
[350]253InputTable=get(handles.InputTable,'Data');
[472]254if isempty(InputTable)
255    RootPathCell={};
256else
257    RootPathCell=InputTable(:,1);
258end
[2]259oldfile=''; %default
[329]260if isempty(RootPathCell)||isequal(RootPathCell,{''})%loads the previously stored file name and set it as default in the file_input box
[2]261     dir_perso=prefdir;
262     profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
263     if exist(profil_perso,'file')
264          h=load (profil_perso);
[329]265         if isfield(h,'filebase')&&ischar(h.filebase)
[2]266                 oldfile=h.filebase;
267         end
[329]268         if isfield(h,'RootPath')&&ischar(h.RootPath)
[2]269                 oldfile=h.RootPath;
270         end
271     end
[472]272else
273     SubDirCell=InputTable(:,2);
274    RootFileCell=InputTable(:,3);
[2]275     oldfile=fullfile(RootPathCell{1},SubDirCell{1},RootFileCell{1});
276 end
277[FileName, PathName, filterindex] = uigetfile( ...
278       {'*.xml;*.xls;*.png;*.tif;*.avi;*.AVI;*.nc', ' (*.xml,*.xls, *.png,*.tif, *.avi,*.nc)';
279       '*.xml',  '.xml files '; ...
280        '*.xls',  '.xls files '; ...
281        '*.png','.png image files'; ...
282        '*.tif','.tif image files'; ...
283        '*.avi;*.AVI','.avi movie files'; ...
284        '*.nc','.netcdf files'; ...
285        '*.*',  'All Files (*.*)'}, ...
286        'Pick a file',oldfile);
287fileinput=[PathName FileName];%complete file name
[472]288if isempty(fileinput),return;end %abandon if no file is introduced by the browser
[2]289[path,name,ext]=fileparts(fileinput);
290if isequal(ext,'.xml')
[472]291    [Param,Heading]=xml2struct(fileinput);
292    if ~strcmp(Heading,'Series')
293        msg_box_uvmat('ERROR','xml file heading is not <Series>')
294    else
295        fill_GUI(Param,handles);%fill the GUI with the parameters retrieved from the xml file
296        if isfield(Param,'CheckObject')&& Param.CheckObject
297            set_object(Param.ProjObject)
298        end
299        set(handles.REFRESH,'UserData',[1:size(Param.InputTable,1)])
300        REFRESH_Callback([],[], handles)
301        return
[463]302    end
[2]303elseif isequal(ext,'.xls')
[408]304    msg_box_uvmat('ERROR','input file type not implemented')%A Faire: ouvrir le fichier pour naviguer
[2]305else
[408]306    display_file_name(handles,fileinput,0)
[2]307end
308
309% --------------------------------------------------------------------
310function MenuFile_1_Callback(hObject, eventdata, handles)
311fileinput=get(handles.MenuFile_1,'Label');
[408]312display_file_name(handles,fileinput,0)
[2]313
314% --------------------------------------------------------------------
315function MenuFile_2_Callback(hObject, eventdata, handles)
316fileinput=get(handles.MenuFile_2,'Label');
[408]317display_file_name(handles,fileinput,0)
[2]318
319% --------------------------------------------------------------------
320function MenuFile_3_Callback(hObject, eventdata, handles)
321fileinput=get(handles.MenuFile_3,'Label');
[408]322display_file_name( handles,fileinput,0)
[2]323
324% --------------------------------------------------------------------
325function MenuFile_4_Callback(hObject, eventdata, handles)
326fileinput=get(handles.MenuFile_4,'Label');
[408]327display_file_name(handles,fileinput,0)
[2]328
329% --------------------------------------------------------------------
330function MenuFile_5_Callback(hObject, eventdata, handles)
331fileinput=get(handles.MenuFile_5,'Label');
[408]332display_file_name(handles,fileinput,0)
[2]333
334% --------------------------------------------------------------------
335function MenuBrowse_insert_Callback(hObject, eventdata, handles)
[350]336InputTable=get(handles.InputTable,'Data');
337RootPathCell=InputTable(:,1);
338SubDirCell=InputTable(:,3);
339RootFileCell=InputTable(:,2);
[2]340oldfile=''; %default
[206]341if isempty(RootPathCell)||isequal(RootPathCell,{''})%loads the previously stored file name and set it as default in the file_input box
[2]342     dir_perso=prefdir;
343     profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
344     if exist(profil_perso,'file')
345          h=load (profil_perso);
346         if isfield(h,'filebase')&ischar(h.filebase)
347                 oldfile=h.filebase;
348         end
349         if isfield(h,'RootPath')&ischar(h.RootPath)
350                 oldfile=h.RootPath;
351         end
352     end
353 else
354     oldfile=fullfile(RootPathCell{1},RootFileCell{1});
355 end
356[FileName, PathName, filterindex] = uigetfile( ...
357       {'*.xml;*.xls;*.png;*.avi;*.AVI;*.nc', ' (*.xml,*.xls, *.png, *.avi,*.nc)';
358       '*.xml',  '.xml files '; ...
359        '*.xls',  '.xls files '; ...
360        '*.png','.png image files'; ...
361        '*.avi;*.AVI','.avi movie files'; ...
362        '*.nc','.netcdf files'; ...
363        '*.*',  'All Files (*.*)'}, ...
364        'Pick a file',oldfile);
365fileinput=[PathName FileName];%complete file name
366sizf=size(fileinput);
367if (~ischar(fileinput)|~isequal(sizf(1),1)),return;end
368[path,name,ext]=fileparts(fileinput);
369if isequal(ext,'.xml')
[206]370    msgbox_uvmat('ERROR','input file type not implemented')%A Faire: ouvrir le fichier pour naviguer
[2]371elseif isequal(ext,'.xls')
[206]372    msgbox_uvmat('ERROR','input file type not implemented')%A Faire: ouvrir le fichier pour naviguer
[2]373else
[472]374    display_file_name(handles,fileinput,'append')
[2]375end
376
377% --------------------------------------------------------------------
378function MenuFile_insert_1_Callback(hObject, eventdata, handles)
[408]379% --------------------------------------------------------------------   
[2]380fileinput=get(handles.MenuFile_insert_1,'Label');
[472]381display_file_name(handles,fileinput,'append')
[2]382
383% --------------------------------------------------------------------
384function MenuFile_insert_2_Callback(hObject, eventdata, handles)
[408]385% --------------------------------------------------------------------   
[2]386fileinput=get(handles.MenuFile_insert_2,'Label');
[472]387display_file_name(handles,fileinput,'append')
[2]388
389% --------------------------------------------------------------------
390function MenuFile_insert_3_Callback(hObject, eventdata, handles)
[408]391% --------------------------------------------------------------------   
[2]392fileinput=get(handles.MenuFile_insert_3,'Label');
[472]393display_file_name( handles,fileinput,'append')
[2]394
395% --------------------------------------------------------------------
396function MenuFile_insert_4_Callback(hObject, eventdata, handles)
[408]397% --------------------------------------------------------------------   
[2]398fileinput=get(handles.MenuFile_insert_4,'Label');
[472]399display_file_name( handles,fileinput,'append')
[2]400
401% --------------------------------------------------------------------
402function MenuFile_insert_5_Callback(hObject, eventdata, handles)
[408]403% --------------------------------------------------------------------   
[2]404fileinput=get(handles.MenuFile_insert_5,'Label');
[472]405display_file_name(handles,fileinput,'append')
[2]406
[89]407%------------------------------------------------------------------------
[408]408% --- Executes when entered data in editable cell(s) in InputTable.
409function InputTable_CellEditCallback(hObject, eventdata, handles)
410%------------------------------------------------------------------------
[472]411set(handles.REFRESH,'Visible','on')
[408]412iview=eventdata.Indices(1);
[472]413view_set=get(handles.REFRESH,'UserData');
414if isempty(find(view_set==iview))
415    set(handles.REFRESH,'UserData',[view_set iview])
416end
417%% enable other menus and uicontrols
418set(handles.MenuOpen_insert,'Enable','on')
419set(handles.MenuFile_insert_1,'Enable','on')
420set(handles.MenuFile_insert_2,'Enable','on')
421set(handles.MenuFile_insert_3,'Enable','on')
422set(handles.MenuFile_insert_4,'Enable','on')
423set(handles.MenuFile_insert_5,'Enable','on')
424set(handles.RUN, 'Enable','On')
425set(handles.RUN,'BackgroundColor',[1 0 0])% set RUN button to red
426
427%update the output dir
428% SubDir=sort(InputTable(:,2)); %set of subdirectories sorted in alphabetical order
429% SubDirOut=SubDir{1};
430% if numel(SubDir)>1
431%     for ilist=2:numel(SubDir)
432%         SubDirOut=[SubDirOut '-' SubDir{ilist}];
433%     end
434% end
435% set(handles.OutputSubDir,'String',SubDirOut)
436
437%------------------------------------------------------------------------
438% --- Executes on button press in REFRESH.
439function REFRESH_Callback(hObject, eventdata, handles)
440%------------------------------------------------------------------------
[408]441InputTable=get(handles.InputTable,'Data');
[472]442view_set=get(handles.REFRESH,'UserData');
443set(handles.REFRESH,'BackgroundColor',[0.7 0.7 0.7])% set REFRESH  button to grey color
444drawnow
445for iview=view_set
446    RootPath=fullfile(InputTable{iview,1},InputTable{iview,2});
447    if ~exist(RootPath,'dir')
448        i1_series=[];
449        RootPath=fileparts(RootPath); %will try the upped forldr
450    else
451        [RootPath,SubDir,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileType,MovieObject]=...
452            find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2}),[InputTable{iview,3} InputTable{iview,4} InputTable{iview,5}]);
[446]453    end
[472]454    if isempty(i1_series)
455        [FileName, PathName, filterindex] = uigetfile( ...
456            {'*.xml;*.xls;*.png;*.tif;*.avi;*.AVI;*.nc', ' (*.xml,*.xls, *.png,*.tif, *.avi,*.nc)';
457            '*.xml',  '.xml files '; ...
458            '*.xls',  '.xls files '; ...
459            '*.png','.png image files'; ...
460            '*.tif','.tif image files'; ...
461            '*.avi;*.AVI','.avi movie files'; ...
462            '*.nc','.netcdf files'; ...
463            '*.*',  'All Files (*.*)'}, ...
464            ['unvalid entry at line ' num2str(iview) ', pick a file'],RootPath);
465        fileinput=[PathName FileName];%complete file name
466        if isempty(fileinput),return;end %abandon if the operation has been cancelled: no input from browser
467        [path,name,ext]=fileparts(fileinput);
468        display_file_name(handles,fileinput,iview)
469    else
470        update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileType,MovieObject,iview)
471    end
[446]472end
[472]473set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to grey color
474set(handles.REFRESH,'Visible','off')
475set(handles.REFRESH,'UserData',[])
[408]476
477%------------------------------------------------------------------------
[472]478% --- Function called when a new file is opened, either by series_OpeningFcn or by the browser
479function display_file_name(handles,fileinput,iview)
480%------------------------------------------------------------------------ 
481%
[332]482% INPUT:
[472]483% handles: handles of elements in the GUI
484% fielinput: input file name, including path
485% append =0 (refresh the Input table with the new file), ='append' append a new line in the table
[332]486
[408]487%% get the input root name, indices, file extension and nomenclature NomType
488if ~exist(fileinput,'file')
489    msgbox_uvmat('ERROR',['input file ' fileinput  ' does not exist'])
490    return
491end
492
[332]493%% enable other menus and uicontrols
494set(handles.MenuOpen_insert,'Enable','on')
495set(handles.MenuFile_insert_1,'Enable','on')
496set(handles.MenuFile_insert_2,'Enable','on')
497set(handles.MenuFile_insert_3,'Enable','on')
498set(handles.MenuFile_insert_4,'Enable','on')
499set(handles.MenuFile_insert_5,'Enable','on')
500set(handles.RUN, 'Enable','On')
501set(handles.RUN,'BackgroundColor',[1 0 0])% set RUN button to red
[350]502set(handles.InputTable,'BackgroundColor',[1 1 0]) % set RootPath edit box  to yellow
[332]503drawnow
504
[408]505%% detect root name, nomenclature and indices in the input file name:
506[FilePath,FileName,FileExt]=fileparts(fileinput);
507% detect the file type, get the movie object if relevant, and look for the corresponding file series:
508% the root name and indices may be corrected by including the first index i1 if a corresponding xml file exists
509[RootPath,SubDir,RootFile,i1_series,i2_series,j1_series,j2_series,NomType,FileType,MovieObject,i1,i2,j1,j2]=find_file_series(FilePath,[FileName FileExt]);
510if isempty(RootFile)&&isempty(i1_series)
511    errormsg='no input file in the series';
[29]512    return
513end
[89]514
[376]515%% fill the list of file series
516InputTable=get(handles.InputTable,'Data');
[472]517if strcmp(iview,'append') % display the input data as a new line in the table
518     iview=size(InputTable,1);
519     InputTable(iview+1,:)={'','','','',''};
520     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
521elseif iview==0 % or re-initialise the list of  input  file series
522    iview=1;
523    InputTable=[{'','','','',''};{'','','','',''}];
524     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
[376]525    set(handles.TimeTable,'Data',[{[]},{[]},{[]},{[]}])
526    set(handles.MinIndex,'Data',[{[]},{[]}])
527    set(handles.MaxIndex,'Data',[{[]},{[]}])
[408]528    set(handles.ListView,'Value',1)
529    set(handles.ListView,'String',{'1'})
[376]530end
[472]531nbview=size(InputTable,1);
532set(handles.ListView,'String',mat2cell((1:nbview)',ones(nbview,1)))
533set(handles.ListView,'Value',iview)
[376]534set(handles.InputTable,'Data',InputTable)
535
[472]536%% determine the selected reference field indices for pair display
537ref_i=1; %default ref_i is a reference frame index used to find existing pairs from PIV
538if ~isempty(i1)
539    ref_i=i1;
540    if ~isempty(i2)
541        ref_i=floor((ref_i+i2)/2);% reference image number corresponding to the file
542    end
543end
544set(handles.num_ref_i,'String',num2str(ref_i));
545ref_j=1; %default  ref_j is a reference frame index used to find existing pairs from PIV
546if ~isempty(j1)
547    ref_j=j1;
548    if ~isempty(j2)
549        ref_j=floor((j1+j2)/2);
550    end         
551end
552set(handles.num_ref_j,'String',num2str(ref_j));
553
554%% update the list of recent files in the menubar and save it for future opening
555MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
556    {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
557str_find=strcmp(fileinput,MenuFile);
558if isempty(find(str_find,1))
559    MenuFile=[{fileinput};MenuFile];%insert the current file if not already in the list
560end
561for ifile=1:min(length(MenuFile),5)
562    eval(['set(handles.MenuFile_' num2str(ifile) ',''Label'',MenuFile{ifile});'])
563    eval(['set(handles.MenuFile_insert_' num2str(ifile) ',''Label'',MenuFile{ifile});'])
564end
565dir_perso=prefdir;
566profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
567if exist(profil_perso,'file')
568    save (profil_perso,'MenuFile','-append'); %store the file names for future opening of uvmat
569else
570    save (profil_perso,'MenuFile','-V6'); %store the file names for future opening of uvmat
571end
572
573set(handles.InputTable,'BackgroundColor',[1 1 1])
574
575%% initiate input file series and refresh the current field view:     
576update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileType,MovieObject,iview);
577
578%------------------------------------------------------------------------
579% --- Update information about a new field series (indices to scan, timing,
580%     calibration from an xml file
581function update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileType,VideoObject,iview)
582%------------------------------------------------------------------------
583%% update the output dir
584InputTable=get(handles.InputTable,'Data');
585SubDir=sort(InputTable(1:end-1,2)); %set of subdirectories sorted in alphabetical order
586SubDirOut=SubDir{1};
587if numel(SubDir)>1
588    for ilist=2:numel(SubDir)
589        SubDirOut=[SubDirOut '-' SubDir{ilist}];
590    end
591end
592set(handles.OutputSubDir,'String',SubDirOut)
593
[521]594%% display the min and max indices for the file series
[526]595if size(i1_series,2)==1
596    MinIndex_j=1;
597    MaxIndex_j=1;
598    MinIndex_i=min(find(i1_series));
599    MaxIndex_i=max(find(i1_series));
600else
[521]601pair_max=squeeze(max(i1_series,[],1)); %max on pair index
602j_max=max(pair_max,[],1);
603%i_sum=sum(sum(i1_series,2),1);%sum of i1_series on the last index
604MaxIndex_i=max(find(j_max))-1;% max ref index i
605MinIndex_i=min(find(j_max))-1;% min ref index i
[526]606diff_i_max=diff(j_max);
607    if isequal (diff_i_max,diff_i_max(1)*ones(size(diff_i_max)))
608        set(handles.num_incr_i,'String',num2str(diff_i_max(1)))
609    end
[521]610i_max=max(pair_max,[],2);
611MaxIndex_j=max(find(i_max))-1;% max ref index i
612MinIndex_j=min(find(i_max))-1;% min ref index i
[526]613diff_j_max=diff(i_max);
614    if isequal (diff_j_max,diff_j_max(1)*ones(size(diff_j_max)))
615        set(handles.num_incr_j,'String',num2str(diff_j_max(1)))
616    end
617end
[460]618MinIndex=get(handles.MinIndex,'Data');%retrieve the min indices in the table MinIndex
619MaxIndex=get(handles.MaxIndex,'Data');%retrieve the max indices in the table MaxIndex
[472]620MinIndex{iview,1}=MinIndex_i;
621MinIndex{iview,2}=MinIndex_j;
622MaxIndex{iview,1}=MaxIndex_i;
623MaxIndex{iview,2}=MaxIndex_j;
[460]624
625set(handles.MinIndex,'Data',MinIndex)%display the min indices in the table MinIndex
626set(handles.MaxIndex,'Data',MaxIndex)%display the max indices in the table MaxIndex
627
628%% adjust the first and last indices if requested by the bounds
629first_i=str2num(get(handles.num_first_i,'String'));
630ref_i=str2num(get(handles.num_ref_i,'String'));
631ref_j=str2num(get(handles.num_ref_j,'String'));
632if isempty(first_i)
633    first_i=ref_i;
634elseif first_i < MinIndex_i
635    first_i=MinIndex_i;
[526]636elseif first_i >MaxIndex_i
637    first_i=MinIndex_i;
[460]638end
639first_j=str2num(get(handles.num_first_j,'String'));
640if isempty(first_j)
641    first_j=ref_j;
642elseif first_j<MinIndex_j
643    first_j=MinIndex_j;
[526]644elseif first_j >MaxIndex_j
645    first_j=MinIndex_j;
[460]646end
647last_i=str2num(get(handles.num_last_i,'String'));
648if isempty(last_i)
649    last_i=ref_i;
650elseif last_i > MaxIndex_i
651    last_i=MaxIndex_i;
[526]652elseif last_i<first_i
653    last_i=first_i;
[460]654end
655last_j=str2num(get(handles.num_first_j,'String'));
656if isempty(last_j)
657    last_j=ref_j;
658elseif last_j>MaxIndex_j
659    last_j=MaxIndex_j;
[526]660elseif last_i<first_i
661    last_i=first_i;
[460]662end
663set(handles.num_first_i,'String',num2str(first_i));
664set(handles.num_first_j,'String',num2str(first_j));
665set(handles.num_last_i,'String',num2str(last_i));
666set(handles.num_last_j,'String',num2str(last_j));
667
[526]668%% read timing and total frame number from the current file (movie files) may be overrid by xml file
[408]669InputTable=get(handles.InputTable,'Data');
670FileBase=fullfile(InputTable{iview,1},InputTable{iview,3});
671time=[];%default
672% case of movies
673if strcmp(InputTable{iview,4},'*')
674    if ~isempty(VideoObject)
675        imainfo=get(VideoObject);
676        time=(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames-1)/imainfo.FrameRate)';
[526]677       % set(handles.Dt_txt,'String',['Dt=' num2str(1000/imainfo.FrameRate) 'ms']);%display the elementary time interval in millisec
[408]678        ColorType='truecolor';
679    elseif ~isempty(imformats(regexprep(InputTable{iview,5},'^.',''))) || isequal(InputTable{iview,5},'.vol')%&& isequal(NomType,'*')% multi-frame image
680        if ~isempty(InputTable{iview,2})
681            imainfo=imfinfo(fullfile(InputTable{iview,1},InputTable{iview,2},[InputTable{iview,3} InputTable{iview,5}]));
682        else
683            imainfo=imfinfo([FileBase InputTable{iview,5}]);
684        end
685        ColorType=imainfo.ColorType;%='truecolor' for color images
686        if length(imainfo) >1 %case of image with multiple frames
687            nbfield=length(imainfo);
688            nbfield_j=1;
689        end
690    end
691end
692
693%%  read image documentation file  if found%%%%%%%%%%%%%%%%%%%%%%%%%%%
694XmlData=[];
695NbSlice_calib={};
[525]696XmlFileName=find_imadoc(InputTable{iview,1},InputTable{iview,2},InputTable{iview,3},InputTable{iview,5});
697if ~isempty(XmlFileName)
698        [XmlData,warntext]=imadoc2struct(XmlFileName);
[408]699        if isfield(XmlData,'Heading') && isfield(XmlData.Heading,'ImageName') && ischar(XmlData.Heading.ImageName)
700            [PP,FF,ext_ima_read]=fileparts(XmlData.Heading.ImageName);
701        end
702        if isfield(XmlData,'Time')
703            time=XmlData.Time;
704        end
705        if isfield(XmlData,'Camera')
706            if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice)
707                NbSlice_calib{iview}=XmlData.Camera.NbSlice;% Nbre of slices for Zindex in phys transform
708                if ~isequal(NbSlice_calib{iview},NbSlice_calib{1})
709                    msgbox_uvmat('WARNING','inconsistent number of Z indices for the two field series');
710                end
711            end
712            if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit)
713                TimeUnit=XmlData.Camera.TimeUnit;
714            end
715        end
716        if ~isempty(warntext)
717            msgbox_uvmat('WARNING',warntext)
718        end 
719end
720
721%% update time table
[456]722if ~isempty(time)
[523]723    TimeTable=get(handles.TimeTable,'Data');
724    first_i=str2num(get(handles.num_first_i,'String'));
725    last_i=str2num(get(handles.num_last_i,'String'));
726    first_j=str2num(get(handles.num_first_j,'String'));
727    last_j=str2num(get(handles.num_last_j,'String'));
728    MinIndexTable=get(handles.MinIndex,'Data');
729    MinIndex_i=MinIndexTable{iview,1};
730    MinIndex_j=MinIndexTable{iview,2};
731    MaxIndexTable=get(handles.MaxIndex,'Data');
732    MaxIndex_i=MaxIndexTable{iview,1};
733    MaxIndex_j=MaxIndexTable{iview,2};
734    if isempty(MinIndex_j)
735        if MinIndex_i>0
736            TimeTable{iview,1}=time(MinIndex_i);
737        end
738        TimeTable{iview,2}=time(first_i);
739        TimeTable{iview,3}=time(last_i);
740        TimeTable{iview,4}=time(MaxIndex_i);
741    elseif ~isempty(time)
742        if MinIndex_i>0
743            TimeTable{iview,1}=time(MinIndex_i,MinIndex_j);
744        end
745        TimeTable{iview,2}=time(first_i,first_j);
746        TimeTable{iview,3}=time(last_i,last_j);
747        TimeTable{iview,4}=time(MaxIndex_i,MaxIndex_j);
[456]748    end
[523]749    set(handles.TimeTable,'Data',TimeTable)
[408]750end
751
752%% number of slices
[460]753NbSlice=1;%default
[408]754if isfield(XmlData,'GeometryCalib') && isfield(XmlData.GeometryCalib,'SliceCoord')
755    siz=size(XmlData.GeometryCalib.SliceCoord);
756    if siz(1)>1
757        NbSlice=siz(1);
758    end
759end
[450]760set(handles.num_NbSlice,'String',num2str(NbSlice))
761   
[408]762%% update pair menus
[441]763set(handles.Pairs,'Visible','on')
764set(handles.PairString,'Visible','on')
[408]765ListView=get(handles.ListView,'String');
766ListView{iview}=num2str(iview);
[472]767set(handles.ListView,'String',ListView);
[408]768set(handles.ListView,'Value',iview)
769update_mode(handles,i1_series,i2_series,j1_series,j2_series,time)
770
[472]771%% update the series info in 'UserData'
[408]772SeriesData=get(handles.series,'UserData');
773SeriesData.i1_series{iview}=i1_series;
774SeriesData.i2_series{iview}=i2_series;
775SeriesData.j1_series{iview}=j1_series;
776SeriesData.j2_series{iview}=j2_series;
777SeriesData.FileType{iview}=FileType;
778SeriesData.Time{iview}=time;
779set(handles.series,'UserData',SeriesData)
780
[521]781%% enable j index visibilitycellfun(@isempty,regexp(PairString,'^j'))
[472]782state='off';
783check_jindex=~cellfun(@isempty,SeriesData.j1_series); %look for non empty j indices
784if isempty(find(check_jindex))
785    enable_j(handles,'off') % no j index needed
786else
[521]787    PairString=get(handles.PairString,'Data');
788    if isempty(find(cellfun(@isempty,regexp(PairString,'^j'))))% if all pair string begins by j (burst)
789        enable_j(handles,'off') % no j index needed
790    else
791        enable_j(handles,'on')
792    end
[472]793end
794
[477]795%% display the set of existing files as an image
796set(handles.FileStatus,'Units','pixels')
797Position=get(handles.FileStatus,'Position');
798set(handles.FileStatus,'Units','normalized')
799xI=0.5:Position(3)-0.5;
800nbview=numel(SeriesData.i1_series);
[523]801pair_max=cell(1,nbview);
[477]802for iview=1:nbview
[523]803    pair_max{iview}=squeeze(max(SeriesData.i1_series{iview},[],1)); %max on pair index
[526]804    if (strcmp(get(handles.num_first_j,'Visible'),'off')&& size(pair_max{iview},2)~=1)
[525]805        pair_max{iview}=squeeze(max(pair_max{iview},[],1)); % consider only the i index
806    end
[523]807    index_min(iview)=find(pair_max{iview}>0, 1 );
808    index_max(iview)=find(pair_max{iview}>0, 1, 'last' );
[477]809end
810index_min=min(index_min);
811index_max=max(index_max);
812range_index=index_max-index_min+1;
813scale_y=Position(4)/nbview;
814scale_x=Position(3)/range_index;
815x=(0.5:range_index-0.5)*Position(3)/range_index;
816% y=(0.5:nbview-0.5)*Position(4)/nbview;
817range_y=max(1,floor(Position(4)/nbview));
818CData=zeros(nbview*range_y,Position(3));
819for iview=1:nbview
820    ind_y=1+(iview-1)*range_y:iview*range_y;
821    LineData=zeros(1,range_index);
[523]822    x_index=find(pair_max{iview}>0)-index_min+1;
[477]823    LineData(x_index)=1;
824    LineData=interp1(x,LineData,xI,'nearest');
825    CData(ind_y,:)=ones(size(ind_y'))*LineData;
826end
827CData=cat(3,zeros(size(CData)),CData,zeros(size(CData)));
828set(handles.FileStatus,'CData',CData);
829
830
[472]831%% enable field and veltype menus, in accordance with the current action
832ActionName_Callback([],[], handles)
833
[441]834%% check for pair display
835check_pairs=0;
836for iview=1:numel(SeriesData.i2_series)
837    if ~isempty(SeriesData.i2_series{iview})||~isempty(SeriesData.j2_series{iview})
838        check_pairs=1;
839    end
840end
841if check_pairs
842    set(handles.Pairs,'Visible','on')
843    set(handles.PairString,'Visible','on')
844else
845    set(handles.Pairs,'Visible','off')
846    set(handles.PairString,'Visible','off')
847end
[408]848
[477]849%% set length of waitbar
850displ_time(handles)
851
852
[525]853%% set default options in menu 'Fields'
854switch FileType
855    case {'civx','civdata'}
856        [FieldList,ColorList]=calc_field;
857        set(handles.FieldName,'String',[{'image'};FieldList;{'get_field...'}]);%standard menu for civx data
858        set(handles.FieldName,'Value',2) % set menu to 'velocity
859        set(handles.Coord_x,'Value',1);
860        set(handles.Coord_x,'String',{'X'});
861        set(handles.Coord_y,'Value',1);
862        set(handles.Coord_y,'String',{'Y'});
863    case 'netcdf'
[526]864        set(handles.FieldName,'Value',1)
865        set(handles.FieldName,'String',{'get_field...'})
866        if isempty(i2_series)
867            i2=[];
868        else
869            i2=i2_series(1,ref_j+1,ref_i+1);
870        end
871        if isempty(j1_series)
872            j1=[];j2=[];
873        else
874            j1=j1_series(1,ref_j+1,ref_i+1);
875            if isempty(j2_series)
876                j2=[];
877            else
878                j2=j2_series(1,ref_j+1,ref_i+1);
879            end
880        end
881        FileName=fullfile_uvmat(InputTable{iview,1},InputTable{iview,2},InputTable{iview,3},InputTable{iview,5},InputTable{iview,4},i1_series(1,ref_j+1,ref_i+1),i2,j1,j2);
[525]882        hget_field=get_field(FileName);
883        hhget_field=guidata(hget_field);
884        get_field('RUN_Callback',hhget_field.RUN,[],hhget_field);
885    otherwise
[526]886        set(handles.FieldName,'Value',1) % set menu to 'image'
887        set(handles.FieldName,'String',{'image'})
[525]888        set(handles.Coord_x,'Value',1);
889        set(handles.Coord_x,'String',{'AX'});
890        set(handles.Coord_y,'Value',1);
891        set(handles.Coord_y,'String',{'AY'});
892end
[408]893
[446]894%------------------------------------------------------------------------
895function num_first_i_Callback(hObject, eventdata, handles)
896%------------------------------------------------------------------------
897num_last_i_Callback(hObject, eventdata, handles)
[408]898
899%------------------------------------------------------------------------
[446]900function num_last_i_Callback(hObject, eventdata, handles)
901%------------------------------------------------------------------------
902SeriesData=get(handles.series,'UserData');
903if ~isfield(SeriesData,'Time')
904    SeriesData.Time{1}=[];
905end
906displ_time(handles);
907
908%------------------------------------------------------------------------
909function num_first_j_Callback(hObject, eventdata, handles)
910%------------------------------------------------------------------------
911 num_last_j_Callback(hObject, eventdata, handles)
912
913%------------------------------------------------------------------------
914function num_last_j_Callback(hObject, eventdata, handles)
915%------------------------------------------------------------------------
916first_j=str2num(get(handles.num_first_j,'String'));
917last_j=str2num(get(handles.num_last_j,'String'));
918ref_j=ceil((first_j+last_j)/2);
919set(handles.num_ref_j,'String', num2str(ref_j))
920num_ref_j_Callback(hObject, eventdata, handles)
921SeriesData=get(handles.series,'UserData');
922if ~isfield(SeriesData,'Time')
923    SeriesData.Time{1}=[];
924end
925displ_time(handles);
926
[477]927
[446]928%------------------------------------------------------------------------
929% ---- find the times corresponding to the first and last indices of a series
930function displ_time(handles)
931%------------------------------------------------------------------------
932SeriesData=get(handles.series,'UserData');%
933ref_i=[str2num(get(handles.num_first_i,'String')) str2num(get(handles.num_last_i,'String'))];
934ref_j=[str2num(get(handles.num_first_j,'String')) str2num(get(handles.num_last_j,'String'))];
935TimeTable=get(handles.TimeTable,'Data');
936Pairs=get(handles.PairString,'Data');
937for iview=1:size(TimeTable,1)
938    if size(SeriesData.Time,1)<iview
939        break
940    end
941    i1=ref_i;
942    j1=ref_j;
943    i2=ref_i;
944    j2=ref_j;
945    % case of pairs
946    if ~isempty(Pairs{iview,1})
947        r=regexp(Pairs{iview,1},'(?<mode>(Di=)|(Dj=)) -*(?<num1>\d+)\|(?<num2>\d+)','names');
948        if isempty(r)
949            r=regexp(Pairs{iview,1},'(?<num1>\d+)(?<mode>-)(?<num2>\d+)','names');
950        end
951        switch r.mode
952            case 'Di='  %  case 'series(Di)')
953                i1=ref_i-str2num(r.num1);
954                i2=ref_i+str2num(r.num2);
955            case 'Dj='  %  case 'series(Dj)'
956                j1=ref_j-str2num(r.num1);
957                j2=ref_j+str2num(r.num2);
958            case '-'  % case 'bursts'
959                j1=str2num(r.num1)*ones(size(ref_i));
960                j2=str2num(r.num2)*ones(size(ref_i));
961        end
962    end
963    TimeTable{iview,2}=[];
964    TimeTable{iview,3}=[];
965    if size(SeriesData.Time{iview},1)>=i2(2)&&size(SeriesData.Time{iview},1)>=j2(2)
966        if isempty(ref_j)
967            time_first=(SeriesData.Time{iview}(i1(1))+SeriesData.Time{iview}(i2(1)))/2;
968            time_last=(SeriesData.Time{iview}(i1(2))+SeriesData.Time{iview}(i2(2)))/2;
969        else
970            time_first=(SeriesData.Time{iview}(i1(1),j1(1))+SeriesData.Time{iview}(i2(1),j2(1)))/2;
971            time_last=(SeriesData.Time{iview}(i1(2),j1(2))+SeriesData.Time{iview}(i2(2),j2(2)))/2;
972        end
973        TimeTable{iview,2}=time_first; %TODO: take into account pairs
974        TimeTable{iview,3}=time_last; %TODO: take into account pairs
975    end
976end
977set(handles.TimeTable,'Data',TimeTable)
978
[477]979%% set the waitbar position with respect to the min and max in the series
980% for iview=1:numel(SeriesData.i1_series)
981% [tild,index_min(iview)]=min(SeriesData.i1_series{iview}(SeriesData.i1_series{iview}>0));
982% [tild,index_max(iview)]=max(SeriesData.i1_series{iview}(SeriesData.i1_series{iview}>0));
983% end
984for iview=1:numel(SeriesData.i1_series)
[526]985    pair_max{iview}=squeeze(max(SeriesData.i1_series{iview},[],1)); %max on pair index
986    if (strcmp(get(handles.num_first_j,'Visible'),'off')&& size(pair_max{iview},2)~=1)
987        pair_max{iview}=squeeze(max(pair_max{iview},[],1)); % consider only the i index
988    end
989    pair_max{iview}=reshape(pair_max{iview},1,[]);
990    index_min(iview)=find(pair_max{iview}>0, 1 );
991    index_max(iview)=find(pair_max{iview}>0, 1, 'last' );
[477]992end
993[index_min,iview_min]=min(index_min);
994[index_max,iview_max]=min(index_max);
[526]995if size(SeriesData.i1_series{iview_min},2)==1% movie
996  index_first=ref_i(1);
997  index_last=ref_i(2);
998else
999%index_first=(ref_i(1)-1)*(size(SeriesData.i1_series{iview_min},2)-1)+ref_j(1);
1000%index_last=(ref_i(2)-1)*(size(SeriesData.i1_series{iview_max},2)-1)+ref_j(2);
1001index_first=(ref_i(1))*(size(SeriesData.i1_series{iview_min},2))+ref_j(1)+1;
1002index_last=(ref_i(2))*(size(SeriesData.i1_series{iview_max},2))+ref_j(2)+1;
1003end
[477]1004range=index_max-index_min+1;
1005coeff_min=(index_first-index_min)/range;
1006coeff_max=(index_last-index_min+1)/range;
1007Position=get(handles.Waitbar,'Position');
1008Position_status=get(handles.FileStatus,'Position');
1009Position(1)=coeff_min*Position_status(3)+Position_status(1);
1010Position(3)=Position_status(3)*(coeff_max-coeff_min);
1011set(handles.Waitbar,'Position',Position)
1012update_waitbar(handles.Waitbar,0)
1013
[446]1014%------------------------------------------------------------------------
[408]1015% --- Executes when selected cell(s) is changed in PairString.
1016function PairString_CellSelectionCallback(hObject, eventdata, handles)
1017%------------------------------------------------------------------------   
1018set(handles.ListView,'Value',eventdata.Indices(1))% detect the selected raw index
1019ListView_Callback ([],[],handles) % update the list of available pairs
1020
1021%------------------------------------------------------------------------
1022%------------------------------------------------------------------------
1023%  III - FUNCTIONS ASSOCIATED TO THE FRAME SET PAIRS
1024%------------------------------------------------------------------------
1025%------------------------------------------------------------------------
1026% --- Executes on selection change in ListView.
1027function ListView_Callback(hObject, eventdata, handles)
1028%------------------------------------------------------------------------   
1029SeriesData=get(handles.series,'UserData');
1030i2_series=[];
1031j2_series=[];
1032iview=get(handles.ListView,'Value');
1033if ~isempty(SeriesData.i2_series{iview})
1034    i2_series=SeriesData.i2_series{iview};
1035end
1036if ~isempty(SeriesData.j2_series{iview})
1037    j2_series=SeriesData.j2_series{iview};
1038end
1039update_mode(handles,SeriesData.i1_series{iview},SeriesData.i2_series{iview},...
1040    SeriesData.j1_series{iview},SeriesData.j2_series{iview},SeriesData.Time{iview})
1041
1042%------------------------------------------------------------------------
[2]1043% --- Executes on button press in mode.
[376]1044function mode_Callback(hObject, eventdata, handles)
[408]1045%------------------------------------------------------------------------       
[376]1046SeriesData=get(handles.series,'UserData');
[408]1047iview=get(handles.ListView,'Value');
[376]1048mode_list=get(handles.mode,'String');
[408]1049mode=mode_list{get(handles.mode,'Value')};
[376]1050if isequal(mode,'bursts')
1051    enable_i(handles,'On')
1052    enable_j(handles,'Off') %do not display j index scanning in burst mode (j is fixed by the burst choice)
1053else
1054    enable_i(handles,'On')
1055    enable_j(handles,'Off')
1056end
[408]1057fill_ListPair(handles,SeriesData.i1_series{iview},SeriesData.i2_series{iview},...
1058    SeriesData.j1_series{iview},SeriesData.j2_series{iview},SeriesData.Time{iview})
1059ListPairs_Callback([],[],handles)
[339]1060
[408]1061%-------------------------------------------------------------
1062% --- Executes on selection in ListPairs.
1063function ListPairs_Callback(hObject,eventdata,handles)
1064%------------------------------------------------------------
1065list_pair=get(handles.ListPairs,'String');%get the menu of image pairs
[441]1066if isempty(list_pair)
1067    string='';
1068else
1069    string=list_pair{get(handles.ListPairs,'Value')};
1070    string=regexprep(string,',.*','');%removes time indication (after ',')
1071end
[408]1072PairString=get(handles.PairString,'Data');
1073iview=get(handles.ListView,'Value');
1074PairString{iview,1}=string;
1075% report the selected pair string to the table PairString
1076set(handles.PairString,'Data',PairString)
[2]1077
[408]1078%------------------------------------------------------------------------
1079function num_ref_i_Callback(hObject, eventdata, handles)
1080%------------------------------------------------------------------------
1081mode_list=get(handles.mode,'String');
1082mode=mode_list{get(handles.mode,'Value')};
1083SeriesData=get(handles.series,'UserData');
1084iview=get(handles.ListView,'Value');
1085fill_ListPair(handles,SeriesData.i1_series{iview},SeriesData.i2_series{iview},...
[446]1086    SeriesData.j1_series{iview},SeriesData.j2_series{iview},SeriesData.Time{iview});% update the menu of pairs depending on the available netcdf files
[408]1087ListPairs_Callback([],[],handles)
[2]1088
[408]1089%------------------------------------------------------------------------
1090function num_ref_j_Callback(hObject, eventdata, handles)
1091%------------------------------------------------------------------------
1092num_ref_i_Callback(hObject, eventdata, handles)
[2]1093
[408]1094%------------------------------------------------------------------------
1095function update_mode(handles,i1_series,i2_series,j1_series,j2_series,time)
1096%------------------------------------------------------------------------   
[521]1097% check_burst=0;
1098if isempty(j2_series)% no j pair
[408]1099    if isempty(i2_series)
1100        set(handles.mode,'Value',1)
[521]1101        set(handles.mode,'String',{''})% no pair menu to display
1102    else   
1103        set(handles.mode,'Value',1)
1104        set(handles.mode,'String',{'series(Di)'}) % pair menu with only option Di
[408]1105    end
[521]1106else %existence of j pairs
1107    pair_max=squeeze(max(i1_series,[],1)); %max on pair index
1108    j_max=max(pair_max,[],1);
1109    MaxIndex_i=max(find(j_max))-1;% max ref index i
1110    MinIndex_i=min(find(j_max))-1;% min ref index i
1111    i_max=max(pair_max,[],2);
1112    MaxIndex_j=max(find(i_max))-1;% max ref index i
1113    MinIndex_j=min(find(i_max))-1;% min ref index i
1114    if MaxIndex_j==MinIndex_j
[408]1115        set(handles.mode,'Value',1);
[521]1116        set(handles.mode,'String',{'bursts'})
1117%         check_burst=1;
1118    elseif MaxIndex_i==MinIndex_i
1119        set(handles.mode,'Value',1);
1120        set(handles.mode,'String',{'series(Dj)'})
[456]1121    else
[521]1122        set(handles.mode,'String',{'bursts';'series(Dj)'})
1123        if (MaxIndex_j-MinIndex_j)>10
1124            set(handles.mode,'Value',2);%set mode to series(Dj) if more than 10 j values
1125        else
1126            set(handles.mode,'Value',1);
1127%             check_burst=1;
1128        end
[456]1129    end
[408]1130end
[521]1131% if check_burst
1132%     enable_i(handles,'On')
1133%     enable_j(handles,'Off') %do not display j index scanning in burst mode (j is fixed by the burst choice)
1134% else
1135%     enable_i(handles,'On')
1136%     if isempty(j1_series)
1137%          enable_j(handles,'Off')
1138%     else
1139%         enable_j(handles,'On')
1140%     end
1141% end
[408]1142fill_ListPair(handles,i1_series,i2_series,j1_series,j2_series,time)
1143ListPairs_Callback([],[],handles)
[2]1144
1145%--------------------------------------------------------------
[408]1146% determine the menu for civ1 pairstring depending on existing netcdf files
1147% with the reference indices num_ref_i and num_ref_j
[2]1148%----------------------------------------------------------------
[408]1149function fill_ListPair(handles,i1_series,i2_series,j1_series,j2_series,time)
1150
[2]1151mode_list=get(handles.mode,'String');
[408]1152mode=mode_list{get(handles.mode,'Value')};
1153ref_i=str2num(get(handles.num_ref_i,'String'));
1154if isempty(ref_i)
1155    ref_i=1;
1156end
[472]1157if strcmp(get(handles.num_ref_j,'Visible'),'on')
1158    ref_j=str2num(get(handles.num_ref_j,'String'));
1159    if isempty(ref_j)
1160        ref_j=1;
1161    end
1162else
[408]1163    ref_j=1;
1164end
[2]1165TimeUnit=get(handles.TimeUnit,'String');
1166if length(TimeUnit)>=1
1167    dtunit=['m' TimeUnit];
1168else
1169    dtunit='e-03';
1170end
[339]1171
1172displ_pair={};
[118]1173if strcmp(mode,'series(Di)')
[339]1174    if isempty(i2_series)
1175        msgbox_uvmat('ERROR','no i1-i2 pair available')
1176        return
1177    end
1178    diff_i=i2_series-i1_series;
1179    min_diff=min(diff_i(diff_i>0));
1180    max_diff=max(diff_i(diff_i>0));
1181    for ipair=min_diff:max_diff
1182        if numel(diff_i(diff_i==ipair))>0
[408]1183            pair_string=['Di= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1184            if ~isempty(time)
[472]1185                if ref_i<=floor(ipair/2)
1186                    ref_i=floor(ipair/2)+1;% shift ref_i to get the first pair
1187                end
[408]1188                Dt=time(ref_i+ceil(ipair/2),ref_j)-time(ref_i-floor(ipair/2),ref_j);
1189                pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1190            end
1191            displ_pair=[displ_pair;{pair_string}];
[339]1192        end
1193    end
1194    if ~isempty(displ_pair)
1195        displ_pair=[displ_pair;{'Di=*|*'}];
1196    end
1197elseif strcmp(mode,'series(Dj)')
1198    if isempty(j2_series)
1199        msgbox_uvmat('ERROR','no j1-j2 pair available')
1200        return
1201    end
1202    diff_j=j2_series-j1_series;
1203    min_diff=min(diff_j(diff_j>0));
1204    max_diff=max(diff_j(diff_j>0));
1205    for ipair=min_diff:max_diff
1206        if numel(diff_j(diff_j==ipair))>0
[408]1207            pair_string=['Dj= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1208            if ~isempty(time)
[472]1209                if ref_j<=floor(ipair/2)
1210                    ref_j=floor(ipair/2)+1;% shift ref_i to get the first pair
1211                end
[408]1212                Dt=time(ref_i,ref_j+ceil(ipair/2))-time(ref_i,ref_j-floor(ipair/2));
1213                pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1214            end
1215            displ_pair=[displ_pair;{pair_string}];
[339]1216        end
1217    end
1218    if ~isempty(displ_pair)
1219        displ_pair=[displ_pair;{'Dj=*|*'}];
1220    end
1221elseif strcmp(mode,'bursts')
1222    if isempty(j2_series)
1223        msgbox_uvmat('ERROR','no j1-j2 pair available')
1224        return
1225    end
1226    diff_j=j2_series-j1_series;
1227    min_j1=min(j1_series(j1_series>0));
1228    max_j1=max(j1_series(j1_series>0));
1229    min_j2=min(j2_series(j2_series>0));
1230    max_j2=max(j2_series(j2_series>0));
1231    for pair1=min_j1:min(max_j1,min_j1+20)
1232        for pair2=min_j2:min(max_j2,min_j2+20)
1233        if numel(j1_series(j1_series==pair1))>0 && numel(j2_series(j2_series==pair2))>0
1234            displ_pair=[displ_pair;{['j= ' num2str(pair1) '-' num2str(pair2)]}];
1235        end
1236        end
1237    end
1238    if ~isempty(displ_pair)
1239        displ_pair=[displ_pair;{'j=*-*'}];
1240    end
1241end
[472]1242set(handles.num_ref_i,'String',num2str(ref_i)) % update ref_i and ref_j
1243set(handles.num_ref_j,'String',num2str(ref_j))
[408]1244
1245%% display list of pairstring
1246displ_pair_list=get(handles.ListPairs,'String');
[339]1247NewVal=[];
1248if ~isempty(displ_pair_list)
[408]1249Val=get(handles.ListPairs,'Value');
[419]1250NewVal=find(strcmp(displ_pair_list{Val},displ_pair),1);% look at the previous display in the new menu displ_pï¿œir
[339]1251end
1252if ~isempty(NewVal)
[408]1253    set(handles.ListPairs,'Value',NewVal)
[339]1254else
[408]1255    set(handles.ListPairs,'Value',1)
[339]1256end
[408]1257set(handles.ListPairs,'String',displ_pair)
[339]1258
[408]1259%-------------------------------------
1260function enable_i(handles,state)
1261set(handles.i_txt,'Visible',state)
1262set(handles.num_first_i,'Visible',state)
1263set(handles.num_last_i,'Visible',state)
1264set(handles.num_incr_i,'Visible',state)
1265% set(handles.num_MaxIndex_i,'Visible',state)
1266set(handles.num_ref_i,'Visible',state)
1267set(handles.ref_i_text,'Visible',state)
[2]1268
[408]1269%-----------------------------------
1270function enable_j(handles,state)
1271set(handles.j_txt,'Visible',state)
1272set(handles.num_first_j,'Visible',state)
1273set(handles.num_last_j,'Visible',state)
1274set(handles.num_incr_j,'Visible',state)
1275set(handles.num_ref_j,'Visible',state)
1276set(handles.ref_j_text,'Visible',state)
[526]1277% if strcmp(state,'off')
1278%     set(handles.MinIndex,'ColumnName',{'imax'})
1279% set(handles.MinIndex,'ColumnEditable',logical(0))
1280% else
1281%         set(handles.MinIndex,'ColumnName',{'imax','jmax'})
1282% end
[41]1283
[408]1284
[446]1285%%%%%%%%%%%%%%%%%%%%
1286%%  MAIN ActionName FUNCTIONS
1287%%%%%%%%%%%%%%%%%%%%
[41]1288%------------------------------------------------------------------------
[2]1289% --- Executes on button press in RUN.
1290function RUN_Callback(hObject, eventdata, handles)
[41]1291%------------------------------------------------------------------------
[2]1292set(handles.RUN,'BusyAction','queue');
[332]1293set(0,'CurrentFigure',handles.series)
[446]1294set(handles.RUN, 'Enable','Off')
1295set(handles.RUN,'BackgroundColor',[0.831 0.816 0.784])
[456]1296drawnow
[453]1297[h_fun,Series,filexml,errormsg]=prepare_jobs(handles);
[446]1298if ~isempty(errormsg)
1299    msgbox_uvmat('ERROR',errormsg)
[472]1300    return
[2]1301end
[472]1302RunModeList=get(handles.RunMode,'String');
1303RunMode=RunModeList{get(handles.RunMode,'Value')};
1304
1305switch RunMode
1306    case 'local'
1307        Series=h_fun(Series);
1308        if ~isempty(filexml)
1309            t=struct2xml(Series);
1310            t=set(t,1,'name','Series');
1311            save(t,filexml);
1312        end
1313    case 'background'
1314        if isempty(filexml)
1315            Series=h_fun(Series);% no background in the absence of output file
1316        else
[477]1317            % update the xml file after interactive input with the function
1318            Series.Specific='?';
1319            Series=h_fun(Series);
1320            t=struct2xml(Series);
1321            t=set(t,1,'name','Series');
1322            save(t,filexml);
1323            path_uvmat=fileparts(which('uvmat'));
1324           
1325            filename_bat=regexprep(filexml,'.xml$','.bat');
1326            [fid,message]=fopen(filename_bat,'w');
1327            if isequal(fid,-1)
1328                msgbox_uvmat('ERROR', ['creation of .bat file: ' message]);
1329                return
1330            end
1331            path_fct=get(handles.ActionPath,'String');
1332            filelog=regexprep(filexml,'.xml$','.log');
[495]1333       
1334            switch computer
1335                case {'GLNX86','GLNXA64','MACI64'}
1336                    text_matlabscript=[...
1337                        '#!/bin/bash \n'...
1338                        '. /etc/sysprofile \n'...
1339                        'matlab -nodisplay -nosplash -nojvm -logfile ''' filelog ''' <<END_MATLAB \n'...
1340                        'addpath(''' path_uvmat '''); \n'...
1341                        'addpath(''' Series.Action.ActionPath '''); \n'...
1342                        '' Series.Action.ActionName  '( ''' filexml '''); \n'...
1343                        'exit \n'...
1344                        'END_MATLAB \n'];
1345                    fprintf(fid,text_matlabscript);
1346                    fclose(fid);
1347                    system(['chmod +x ' filename_bat]);% set the file to executable
1348                    system(['. ' filename_bat ' &']);%execute fct
1349                   
1350                case {'PCWIN','PCWIN64'}
1351                    text_matlabscript=['matlab -automation -logfile ' regexprep(filelog,'\\','\\\\')...
1352                        ' -r "addpath(''' regexprep(path_uvmat,'\\','\\\\') ''');'...
1353                        'addpath(''' regexprep(Series.Action.ActionPath,'\\','\\\\') ''');'...
1354                        '' Series.Action.ActionName  '( ''' regexprep(filexml,'\\','\\\\') ''');exit"'];
1355                    fprintf(fid,text_matlabscript);
1356                    fclose(fid);
1357                    dos([filename_bat ' &']);
[477]1358            end
[472]1359        end
[477]1360        update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate lounching is finished
[472]1361end
1362
[446]1363set(handles.RUN, 'Enable','On')
1364set(handles.RUN,'BackgroundColor',[1 0 0])
[2]1365
[446]1366%------------------------------------------------------------------------
1367function STOP_Callback(hObject, eventdata, handles)
1368%------------------------------------------------------------------------
1369set(handles.RUN, 'BusyAction','cancel')
1370set(handles.RUN,'BackgroundColor',[1 0 0])
1371set(handles.RUN,'enable','on')
[472]1372% set(handles.BATCH,'BackgroundColor',[1 0 0])
1373% set(handles.BATCH,'enable','on')
[446]1374
1375%------------------------------------------------------------------------
1376% --- Executes on button press in BATCH.
1377function BATCH_Callback(hObject, eventdata, handles)
1378%------------------------------------------------------------------------   
[456]1379
[472]1380
1381% %------------------------------------------------------------------------
1382% % --- Executes on button press in BIN.
1383% function BIN_Callback(hObject, eventdata, handles)
1384% %------------------------------------------------------------------------
1385%     cmd=['#!/bin/bash \n '...
1386%         '#$ -cwd \n '...
1387%         'hostname && date \n '...
1388%         'umask 002 \n'...
1389%         Param.xml.CivmBin ' ' Param.xml.RunTime ' ' filename_xml ' ' OutputFile '.nc'];
1390%     
[446]1391%------------------------------------------------------------------------
[456]1392% --- Main launch command, called by RUN and BATCH
[461]1393function [h_fun,Series,filexml,errormsg]=prepare_jobs(handles,run)
[472]1394%INPUT:
1395% handles: handles of graphic objects on the GUI series
1396% run=0, just to display parameters for MenuExport/GUI config
1397% run=1 (default) prepare the computation
1398
[446]1399%------------------------------------------------------------------------
[461]1400h_fun=[];
[456]1401filexml='';
[446]1402errormsg='';
[461]1403if ~exist('run','var')
1404    run=1;
1405end
[446]1406%% Read parameters from series
1407Series=read_GUI(handles.series);
1408if isfield(Series,'Pairs')
1409Series=rmfield(Series,'Pairs'); %info Pairs not needed for output
1410end
1411
[456]1412%% read index ranges
[446]1413first_i=1;
1414last_i=1;
1415incr_i=1;
1416first_j=1;
1417last_j=1;
1418incr_j=1;
[339]1419if isfield(Series.IndexRange,'first_i')
1420    first_i=Series.IndexRange.first_i;
1421    incr_i=Series.IndexRange.incr_i;
1422    last_i=Series.IndexRange.last_i;
1423end
1424if isfield(Series.IndexRange,'first_j')
1425    first_j=Series.IndexRange.first_j;
1426    incr_j=Series.IndexRange.incr_j;
1427    last_j=Series.IndexRange.last_j;
1428end
1429
1430%% read input file parameters and set menus
[446]1431menu_coord_state=get(handles.TransformName,'Visible');
[2]1432if isequal(menu_coord_state,'on')
[446]1433    menu_index=get(handles.TransformName,'Value');
1434    transform_list=get(handles.TransformName,'UserData');
1435    Series.FieldTransform.TransformHandle=transform_list{menu_index};% transform function handles
[2]1436end
1437
1438if last_i < first_i | last_j < first_j , msgbox_uvmat('ERROR','last field number must be larger than the first one'),...
1439    set(handles.RUN, 'Enable','On'), set(handles.RUN,'BackgroundColor',[1 0 0]),return,end;
1440
[446]1441%% projection object
1442if isfield(Series,'CheckObject')
1443    if Series.CheckObject
1444        hset_object=findobj(allchild(0),'tag','set_object');
1445        Series.ProjObject=read_GUI(hset_object);
[458]1446        CheckObject_Callback([], [], handles)
[446]1447    end
1448else
1449    Series.CheckObject=0;
1450end
[2]1451
[446]1452%% get_field GUI
1453if isfield(Series,'InputFields')&&isfield(Series.InputFields,'Field')
1454    if strcmp(Series.InputFields.Field,'get_field...')
1455        hget_field=findobj(allchild(0),'name','get_field');
1456        Series.GetField=read_GUI(hget_field);
1457    end
1458end
[2]1459
[461]1460if ~run
1461    return
1462end
1463
[446]1464%% defining the ActionName function handle
1465list_action=get(handles.ActionName,'String');% list menu action
1466index=get(handles.ActionName,'Value');
1467action= list_action{index}; % selected string
[461]1468%Series.Action=action;%name of the processing programme
[446]1469Series.hseries=handles.series; % handles to the series GUI
[2]1470path_series=which('series');
[446]1471list_path=get(handles.ActionName,'UserData');
[2]1472fct_path=list_path{index}; %path stored for the function ACTION
1473if ~isequal(fct_path,path_series)
1474    eval(['spath=which(''' action ''');']) %spath = current path of the selected function ACTION
[41]1475    if ~exist(fct_path,'dir')
[461]1476        errormsg=['The prescribed function path ' fct_path ' does not exist'];
[41]1477        return
1478    end
1479    if ~isequal(spath,fct_path)
[2]1480        addpath(fct_path)% add the prescribed path if not the current one
1481    end
1482end
[41]1483eval(['h_fun=@' action ';'])%create a function handle for ACTION
[26]1484if ~isequal(fct_path,path_series)
1485        rmpath(fct_path)% add the prescribed path if not the current one   
1486end
1487
[446]1488%% create the output data directory and write in it the xml file from the GUI config
1489%determine the root file corresponding to the first sub dir
1490if isfield(Series,'OutputSubDir')
1491    SubDirOut=[Series.OutputSubDir Series.OutputDirExt];
1492    SubDirOutNew=SubDirOut;
1493    iview=1;
1494    SeriesData=get(handles.series,'UserData');
1495    if size(Series.InputTable,1)>1 && isfield(SeriesData,'AllowInputSort') && isfield(SeriesData.AllowInputSort)
1496        [tild,iview]=sort(Series.InputTable(:,2)); %subdirectories sorted in alphabetical order
1497        Series.InputTable=Series.InputTable(iview,:);
[421]1498    end
[448]1499    detect=exist(fullfile(Series.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exist
[450]1500    check_create=1; %need to create the result directory by default
[446]1501    while detect
[448]1502        answer=msgbox_uvmat('INPUT_Y-N',['use existing ouput directory: ' fullfile(Series.InputTable{1,1},SubDirOutNew) ', possibly delete previous data']);
1503        if isequal(answer,'Yes')
1504            detect=0;
1505            check_create=0;
1506        else
1507            r=regexp(SubDirOutNew,'(?<root>.*\D)(?<num1>\d+)$','names');%detect whether name ends by a number
1508            if isempty(r)
1509                r(1).root=[SubDirOutNew '_'];
1510                r(1).num1='0';
1511            end
1512            SubDirOutNew=[r(1).root num2str(str2num(r(1).num1)+1)];%increment the index by 1 or put 1
1513            detect=exist(fullfile(Series.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exists   
1514            check_create=1;
[408]1515        end
1516    end
[448]1517    Series.OutputDirExt=regexprep(SubDirOutNew,Series.OutputSubDir,'');
[472]1518 %   Series.OutputSubDir=SubDirOutNew;
1519 %   Series.OutputDir=fullfile(Series.InputTable{1,1},Series.OutputSubDir);%directory set for output results
[446]1520    Series.OutputRootFile=Series.InputTable{1,3};% the first sorted RootFile taken for output
[448]1521    set(handles.OutputDirExt,'String',Series.OutputDirExt)
[446]1522    % create output directory
[472]1523    OutputDir=fullfile(Series.InputTable{1,1},[Series.OutputSubDir Series.OutputDirExt]);
[448]1524    if check_create
[472]1525        [tild,msg1]=mkdir(OutputDir);
[446]1526        if ~strcmp(msg1,'')
[472]1527            errormsg=['cannot create ' OutputDir ': ' msg1];%error message for directory creation
[446]1528            return
[421]1529        end
[408]1530    end
[472]1531    filexml=fullfile(OutputDir,[Series.InputTable{1,3} '.xml']);% name of the parameter xml file set in this directory
[408]1532end
[472]1533%removes redondant information
1534Series.IndexRange=rmfield(Series.IndexRange,'TimeTable');
1535Series.IndexRange=rmfield(Series.IndexRange,'MinIndex');
1536Series.IndexRange=rmfield(Series.IndexRange,'MaxIndex');
1537%removes empty lines of InputTable
1538empty_line=zeros(size(Series.InputTable,1),1);
1539for iline=1:size(Series.InputTable,1)
1540    empty_line(iline)=isequal(Series.InputTable(iline,1:3),{'','',''});
1541end
1542Series.InputTable(find(empty_line),:)=[];
[408]1543
[41]1544%------------------------------------------------------------------------
[446]1545% --- Executes on selection change in ActionName.
1546function ActionName_Callback(hObject, eventdata, handles)
[41]1547%------------------------------------------------------------------------
[205]1548global nb_builtin_ACTION
[446]1549list_ACTION=get(handles.ActionName,'String');% list menu fields
1550index_ACTION=get(handles.ActionName,'Value');% selected string index
[2]1551ACTION= list_ACTION{index_ACTION}; % selected function name
1552path_series=which('series');%path to series.m
[446]1553list_path=get(handles.ActionName,'UserData');%list of recorded paths to functions of the list ACTION
[39]1554default_file=fullfile(list_path{end},ACTION);
[29]1555% add a new function to the menu if the selected item is 'more...'
[2]1556if isequal(ACTION,'more...')
1557    pathfct=fileparts(path_series);
1558    [FileName, PathName, filterindex] = uigetfile( ...
1559       {'*.m', ' (*.m)';
1560        '*.m',  '.m files '; ...
1561        '*.*', 'All Files (*.*)'}, ...
[39]1562        'Pick a file',default_file);
[2]1563    if length(FileName)<2
1564        return
[29]1565    end
1566    [pp,ACTION,ext_fct]=fileparts(FileName);%(end-1:end);
[2]1567    if ~isequal(ext_fct,'.m')
1568        msgbox_uvmat('ERROR','a Matlab function .m must be introduced');
1569        return
1570    end
1571   
[446]1572   % insert the choice in the actionname menu
1573   menu_str=update_menu(handles.ActionName,ACTION);%new action menu in which the new item has been appended if needed
1574   index_ACTION=get(handles.ActionName,'Value');% currently selected index in the list
[2]1575   list_path{index_ACTION}=PathName;
[205]1576   if length(menu_str)>nb_builtin_ACTION+5; %nb_builtin=nbre of functions always remaining in the initial menu
1577       nbremove=length(menu_str)-nb_builtin_ACTION-5;
1578       menu_str(nb_builtin_ACTION+1:end-5)=[];
1579       list_path(nb_builtin_ACTION+1:end-4)=[];
[2]1580       index_ACTION=index_ACTION-nbremove;
[446]1581       set(handles.ActionName,'Value',index_ACTION)
1582       set(handles.ActionName,'String',menu_str)
[2]1583   end
1584   list_path{index_ACTION}=PathName;
[446]1585   set(handles.ActionName,'UserData',list_path);
1586   set(handles.ActionPath,'enable','inactive')% indicate that the current path is accessible (not 'off')
[2]1587   
1588   %record the current menu in personal file profil_perso
1589   dir_perso=prefdir;
1590   profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
[205]1591   for ilist=nb_builtin_ACTION+1:length(menu_str)-1
1592       series_fct{ilist-nb_builtin_ACTION}=fullfile(list_path{ilist},[menu_str{ilist} '.m']);     
[2]1593   end
[206]1594   if nb_builtin_ACTION+1<=length(menu_str)-1
1595       if exist(profil_perso,'file')% && nb_builtin_ACTION+1>=length(menu_str)-1
1596           save(profil_perso,'series_fct','-append')
1597       else
1598           txt=ver('MATLAB');
1599           Release=txt.Release;
1600           relnumb=str2num(Release(3:4));
1601           if relnumb >= 14%recent relaese of Matlab
1602               save(profil_perso,'series_fct','-V6')
1603           else
1604               save(profil_perso, 'series_fct')
1605           end
1606       end
[2]1607   end
1608end
1609
[446]1610%check the current ActionPath to the selected function
[2]1611PathName=list_path{index_ACTION};%current recorded path
[446]1612set(handles.ActionPath,'String',PathName); %show the path to the senlected function
[2]1613
[477]1614%reinitialise the waitbar
1615update_waitbar(handles.Waitbar,0)
1616
[2]1617%default setting for the visibility of the GUI elements
[339]1618set(handles.num_NbSlice,'Visible','off')
[2]1619set(handles.NbSlice_title,'Visible','off')
[446]1620set(handles.VelType,'Visible','off');
[2]1621set(handles.VelType_text,'Visible','off');
[446]1622set(handles.VelType_1,'Visible','off');
[2]1623set(handles.VelType_text_1,'Visible','off');
[472]1624set(handles.InputFields,'Visible','off')
1625set(handles.FieldName_1,'Visible','off')
1626%view_FieldMenu_1(handles,'off')
[339]1627set(handles.FieldTransform,'Visible','off')
[446]1628set(handles.CheckObject,'Visible','off');
1629set(handles.ProjObject,'Visible','off');
1630set(handles.CheckMask,'Visible','off')
[2]1631set(handles.Mask,'Visible','off')
[446]1632set(handles.OutputDirExt,'Visible','off')
1633set(handles.OutputSubDir,'Visible','off')
1634set(handles.OutputDir_title,'Visible','off')
[2]1635%set the displayed GUI item needed for input parameters
[29]1636if ~isequal(path_series,PathName)
1637    addpath(PathName)
1638end
1639eval(['h_function=@' ACTION ';']);
[244]1640try
1641    [fid,errormsg] =fopen([ACTION '.m']);
1642    InputText=textscan(fid,'%s',1,'delimiter','\n');
1643    fclose(fid)
[456]1644    set(handles.ActionName,'ToolTipString',InputText{1}{1})% put the first line of the selected function as tooltip help
[244]1645end
[29]1646if ~isequal(path_series,PathName)
1647    rmpath(PathName)
1648end
1649varargout=h_function();
[2]1650Param_list={};
1651
[372]1652InputTable=get(handles.InputTable,'Data');
[472]1653nbview=size(InputTable,1);
1654SeriesData=get(handles.series,'UserData');
1655nb_civ=numel(find(strcmp('civx',SeriesData.FileType)|strcmp('civdata',SeriesData.FileType)));
1656nb_netcdf=numel(find(strcmp('netcdf',SeriesData.FileType)));
[2]1657for ilist=1:length(varargout)-1
1658    switch varargout{ilist}
[446]1659        case 'AllowInputSort'
1660            if isequal(lower(varargout{ilist+1}),'on')% sort the input table by alphabetical order of the SubDir
1661                SeriesData.AllowInputSort=1;
1662                set(handles.series,'UserData',SeriesData)
[456]1663            end                     
1664        case 'WholeIndexRange'
[472]1665            if isequal(lower(varargout{ilist+1}),'on')% set by default the input index range from min to max
[456]1666                MinIndex=get(handles.MinIndex,'Data');
1667                MaxIndex=get(handles.MaxIndex,'Data');
1668                if ~isempty(MinIndex)
1669                    set(handles.num_first_i,'String',num2str(MinIndex{1}))
1670                    set(handles.num_last_i,'String',num2str(MaxIndex{1}))
1671                    set(handles.num_incr_i,'String','1')
1672                    if size(MinIndex,2)>=2
1673                        set(handles.num_first_j,'String',num2str(MinIndex{1,2}))
1674                        set(handles.num_last_j,'String',num2str(MaxIndex{1,2}))
1675                        set(handles.num_incr_j,'String','1')
1676                    end
1677                end
1678            end           
[2]1679        case 'NbSlice'   %hidden by default
1680            if isequal(lower(varargout{ilist+1}),'on')
[339]1681                set(handles.num_NbSlice,'Visible','on')
[2]1682                set(handles.NbSlice_title,'Visible','on')
1683            end
[446]1684        case 'VelType'   %hidden by default
[372]1685             if isequal(lower(varargout{ilist+1}),'one') || isequal(lower(varargout{ilist+1}),'two')
[472]1686                if nb_civ>=1
[446]1687                    set(handles.VelType,'Visible','on')
[2]1688                    set(handles.VelType_text,'Visible','on');
1689                end
[372]1690             end
[2]1691            if isequal(lower(varargout{ilist+1}),'two')
[472]1692                if nb_civ>=2
[446]1693                    set(handles.VelType_1,'Visible','on')
[2]1694                    set(handles.VelType_text_1,'Visible','on');
1695                end
1696            end
[446]1697        case 'FieldName'   %hidden by default
[2]1698            if isequal(lower(varargout{ilist+1}),'one')||isequal(lower(varargout{ilist+1}),'two')
[472]1699                if (nb_civ+nb_netcdf)>=1
1700                 set(handles.FieldName,'Visible','on') % test for MenuBorser
1701                 set(handles.InputFields,'Visible','on')
[2]1702                end
1703            end
1704            if isequal(lower(varargout{ilist+1}),'two')
[472]1705                if (nb_civ+nb_netcdf)>=1
1706                set(handles.FieldName_1,'Visible','on')
[2]1707                end
1708            end
[446]1709        case 'FieldTransform'   %hidden by default
[2]1710            if isequal(lower(varargout{ilist+1}),'on')
[446]1711                set(handles.TransformName,'Enable','on')
[339]1712                set(handles.FieldTransform,'Visible','on')
[494]1713                TransformName_Callback([],[], handles)
[2]1714            end
[446]1715        case 'ProjObject'   %hidden by default
[2]1716            if isequal(lower(varargout{ilist+1}),'on')   
[446]1717                set(handles.CheckObject,'Visible','on')
1718                set(handles.ProjObject,'Visible','on')
[2]1719            end
1720        case 'Mask'   %hidden by default
1721            if isequal(lower(varargout{ilist+1}),'on')   
[446]1722                set(handles.Mask,'Visible','on')
1723                 set(handles.CheckMask,'Visible','on');
[472]1724            end 
[446]1725        case 'OutputDirExt'
1726            if ~isempty(varargout{ilist+1})
1727            set(handles.OutputDirExt,'String',varargout{ilist+1})
1728            set(handles.OutputDirExt,'Visible','on')
1729            set(handles.OutputSubDir,'Visible','on')
1730            set(handles.OutputDir_title,'Visible','on') 
1731            end
[2]1732    end
1733end
1734if ~isempty(Param_list)
1735    set(handles.ParamKey,'String',Param_list)
1736    set(handles.ParamVal,'Visible','on')
1737end
1738
[41]1739%------------------------------------------------------------------------
[446]1740% --- Executes on selection change in FieldName.
1741function FieldName_Callback(hObject, eventdata, handles)
[41]1742%------------------------------------------------------------------------
[446]1743field_str=get(handles.FieldName,'String');
1744field_index=get(handles.FieldName,'Value');
[2]1745field=field_str{field_index(1)};
1746if isequal(field,'get_field...')   
1747     hget_field=findobj(allchild(0),'name','get_field');
1748     if ~isempty(hget_field)
1749         delete(hget_field)%delete opened versions of get_field
1750     end
[453]1751     filecell=get_file_series(read_GUI(handles.series));
[428]1752     if exist(filecell{1,1},'file')
1753        get_field(filecell{1,1})
[2]1754     end
1755elseif isequal(field,'more...')
1756    str=calc_field;
1757    [ind_answer,v] = listdlg('PromptString','Select a file:',...
1758                'SelectionMode','single',...
1759                'ListString',str);
[446]1760       % edit the choice in the fields and actionname menu
[2]1761     scalar=cell2mat(str(ind_answer));
[446]1762     update_menu(handles.FieldName,scalar)
[2]1763end
1764
[41]1765%------------------------------------------------------------------------
[446]1766% --- Executes on selection change in FieldName_1.
1767function FieldName_1_Callback(hObject, eventdata, handles)
[41]1768%------------------------------------------------------------------------
[446]1769field_str=get(handles.FieldName_1,'String');
1770field_index=get(handles.FieldName_1,'Value');
[2]1771field=field_str{field_index};
1772if isequal(field,'get_field...')   
1773     hget_field=findobj(allchild(0),'name','get_field_1');
1774     if ~isempty(hget_field)
1775         delete(hget_field)
1776     end
[332]1777     SeriesData=get(handles.series,'UserData');
[2]1778     filename=SeriesData.CurrentInputFile_1;
1779     if exist(filename,'file')
1780        hget_field=get_field(filename);
1781        set(hget_field,'name','get_field_1')
1782     end
1783elseif isequal(field,'more...')
1784    str=calc_field;
1785    [ind_answer,v] = listdlg('PromptString','Select a file:',...
1786                'SelectionMode','single',...
1787                'ListString',str);
[446]1788       % edit the choice in the fields and actionname menu
[2]1789     scalar=cell2mat(str(ind_answer));
[446]1790     update_menu(handles.FieldName_1,scalar)
[2]1791end   
[29]1792
[244]1793
[2]1794%%%%%%%%%%%%%
1795function [ind_remove]=find_pairs(dirpair,ind_i,last_i)
[339]1796indsel=ind_i;
1797indiff=diff(ind_i); %test index increment to detect multiplets (several pairs with the same index ind_i) and holes in the series
1798indiff=[1 indiff last_i-ind_i(end)+1];%for testing gaps with the imposed bounds
1799if ~isempty(indiff)
1800    indiff2=diff(indiff);
1801    indiffp=[indiff2 1];
1802    indiffm=[1 indiff2];
1803    ind_multi_m=find((indiff==0)&(indiffm<0))-1;%indices of first members of multiplets
1804    ind_multi_p=find((indiff==0)&(indiffp>0));%indices of last members of multiplets
1805    %for each multiplet, select the most recent file
1806    ind_remove=[];
1807    for i=1:length(ind_multi_m)
1808        ind_pairs=ind_multi_m(i):ind_multi_p(i);
1809        for imulti=1:length(ind_pairs)
1810            datepair(imulti)=datenum(dirpair(ind_pairs(imulti)).date);%dates of creation
[2]1811        end
[339]1812        [datenew,indsort2]=sort(datepair); %sort the multiplet by creation date
1813        ind_s=indsort2(1:end-1);%
1814        ind_remove=[ind_remove ind_pairs(ind_s)];%remove these indices, leave the last one
1815    end
1816end
[2]1817
[89]1818%------------------------------------------------------------------------
[408]1819% --- determine the list of index pairstring of processing file
[32]1820function [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)
[89]1821%------------------------------------------------------------------------
[32]1822num_i1=num_i;% set of first image numbers by default
1823num_i2=num_i;
1824num_j1=num_j;
1825num_j2=num_j;
1826num_i_out=num_i;
1827num_j_out=num_j;
[339]1828% if isequal (NomType,'_1-2_1') || isequal (NomType,'_1-2')
1829if isequal(mode,'series(Di)')
[32]1830    num_i1_line=num_i+ind_shift(3);% set of first image numbers
1831    num_i2_line=num_i+ind_shift(4);
1832    % adjust the first and last field number
1833        indsel=find(num_i1_line >= 1);
1834    num_i_out=num_i(indsel);
1835    num_i1_line=num_i1_line(indsel);
1836    num_i2_line=num_i2_line(indsel);
1837    num_j1=meshgrid(num_j,ones(size(num_i1_line)));
1838    num_j2=meshgrid(num_j,ones(size(num_i1_line)));
1839    [xx,num_i1]=meshgrid(num_j,num_i1_line);
1840    [xx,num_i2]=meshgrid(num_j,num_i2_line);
[339]1841elseif isequal (mode,'series(Dj)')||isequal (mode,'bursts')
[32]1842    if isequal(mode,'bursts') %case of bursts (png_old or png_2D)
1843        num_j1=ind_shift(1)*ones(size(num_i));
1844        num_j2=ind_shift(2)*ones(size(num_i));
1845    else
1846        num_j1_col=num_j+ind_shift(1);% set of first image numbers
1847        num_j2_col=num_j+ind_shift(2);
1848        % adjust the first field number
1849        indsel=find((num_j1_col >= 1));   
1850        num_j_out=num_j(indsel);
1851        num_j1_col=num_j1_col(indsel);
1852        num_j2_col=num_j2_col(indsel);
1853        [num_i1,num_j1]=meshgrid(num_i,num_j1_col);
1854        [num_i2,num_j2]=meshgrid(num_i,num_j2_col);
1855    end   
1856end
[2]1857
[41]1858%------------------------------------------------------------------------
[446]1859% --- Executes on button press in CheckObject.
1860function CheckObject_Callback(hObject, eventdata, handles)
[41]1861%------------------------------------------------------------------------
[446]1862% SeriesData=get(handles.series,'UserData');
1863value=get(handles.CheckObject,'Value');
[2]1864if value
[446]1865     set(handles.CheckObject,'BackgroundColor',[1 1 0])%put unactivated buttons to yellow
[76]1866     hset_object=findobj(allchild(0),'tag','set_object');%find the set_object interface handle
[2]1867     if ishandle(hset_object)
[421]1868         uistack(hset_object,'top')% show the GUI set_object if opened
[2]1869     else
[41]1870         %get the object file
[376]1871         InputTable=get(handles.InputTable,'Data');
1872         defaultname=InputTable{1,1};
[106]1873         if isempty(defaultname)
1874            defaultname={''};
1875         end
[41]1876        [FileName, PathName, filterindex] = uigetfile( ...
1877       {'*.xml;*.mat', ' (*.xml,*.mat)';
1878       '*.xml',  '.xml files '; ...
1879        '*.mat',  '.mat matlab files '}, ...
[427]1880        'Pick an xml object file (or use uvmat to create it)',defaultname);
[41]1881        fileinput=[PathName FileName];%complete file name
1882        sizf=size(fileinput);
1883        if (~ischar(fileinput)||~isequal(sizf(1),1)),return;end
1884        %read the file
[427]1885        data=xml2struct(fileinput);
[446]1886        if ~isfield(data,'Type')
1887             msgbox_uvmat('ERROR',[fileinput ' is not an object xml file'])
1888             return
[41]1889        end
1890        if ~isfield(data,'ProjMode')
[446]1891             data.ProjMode='none';
[41]1892        end
[446]1893        hset_object=set_object(data);% call the set_object interface
[2]1894     end
[446]1895     Object=read_GUI(hset_object);
1896     set(handles.ProjObject,'String',Object.Name);%display the object name
[2]1897else
[446]1898    set(handles.CheckObject,'BackgroundColor',[0.7 0.7 0.7])%put activated buttons to green
[2]1899end
[446]1900%set(handles.series,'UserData',SeriesData)
[2]1901
1902%--------------------------------------------------------------
[446]1903function CheckMask_Callback(hObject, eventdata, handles)
1904value=get(handles.CheckMask,'Value');
[2]1905if value
[41]1906    msgbox_uvmat('ERROR','not implemented yet')
[2]1907end
1908%--------------------------------------------------------------
1909
[41]1910%-------------------------------------------------------------------
[2]1911%'uv_ncbrowser': interactively calls the netcdf file browser 'get_field.m'
1912function ncbrowser_uvmat(hObject, eventdata)
[41]1913%-------------------------------------------------------------------
[2]1914     bla=get(gcbo,'String');
1915     ind=get(gcbo,'Value');
1916     filename=cell2mat(bla(ind));
1917      blank=find(filename==' ');
1918      filename=filename(1:blank-1);
1919     get_field(filename)
1920
[41]1921% ------------------------------------------------------------------
[2]1922function MenuHelp_Callback(hObject, eventdata, handles)
[41]1923%-------------------------------------------------------------------
[2]1924path_to_uvmat=which ('uvmat');% check the path of uvmat
1925pathelp=fileparts(path_to_uvmat);
[36]1926helpfile=fullfile(pathelp,'uvmat_doc','uvmat_doc.html');
1927if isempty(dir(helpfile)), msgbox_uvmat('ERROR','Please put the help file uvmat_doc.html in the sub-directory /uvmat_doc of the UVMAT package')
[2]1928else
[36]1929    addpath (fullfile(pathelp,'uvmat_doc'))
1930    web([helpfile '#series'])
[2]1931end
1932
[41]1933%-------------------------------------------------------------------
[446]1934% --- Executes on selection change in TransformName.
1935function TransformName_Callback(hObject, eventdata, handles)
[41]1936%-------------------------------------------------------------------
[39]1937global nb_transform
[2]1938
[446]1939menu=get(handles.TransformName,'String');
1940ind_coord=get(handles.TransformName,'Value');
[39]1941coord_option=menu{ind_coord};
[446]1942list_transform=get(handles.TransformName,'UserData');
[39]1943ff=functions(list_transform{end});
1944if isequal(coord_option,'more...');
1945    coord_fct='';
1946    prompt = {'Enter the name of the transform function'};
1947    dlg_title = 'user defined transform';
1948    num_lines= 1;
1949    [FileName, PathName, filterindex] = uigetfile( ...
1950       {'*.m', ' (*.m)';
1951        '*.m',  '.m files '; ...
1952        '*.*', 'All Files (*.*)'}, ...
1953        'Pick a file', ff.file);
1954    if isequal(PathName(end),'/')||isequal(PathName(end),'\')
1955        PathName(end)=[];
1956    end
1957    transform_selected =fullfile(PathName,FileName);
1958    if ~exist(transform_selected,'file')
1959          return
1960    end
1961    [ppp,transform,xt_fct]=fileparts(FileName);% removes extension .m
1962    if ~isequal(ext_fct,'.m')
1963        msgbox_uvmat('ERROR','a Matlab function .m must be introduced');
1964        return
1965    end
[446]1966   menu=update_menu(handles.TransformName,transform);%add the selected fct to the menu
1967   ind_coord=get(handles.TransformName,'Value');
[39]1968   addpath(PathName)
1969   list_transform{ind_coord}=str2func(transform);% create the function handle corresponding to the newly seleced function
[446]1970   set(handles.TransformName,'UserData',list_transform)
[39]1971   rmpath(PathName)
1972   % save the new menu in the personal file 'uvmat_perso.mat'
1973   dir_perso=prefdir;%personal Matalb directory
1974   profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
1975   if exist(profil_perso,'file')
1976       for ilist=nb_transform+1:numel(list_transform)
[55]1977           ff=functions(list_transform{ilist});
[39]1978           transform_fct{ilist-nb_transform}=ff.file;
1979       end
1980        save (profil_perso,'transform_fct','-append'); %store the root name for future opening of uvmat
1981   end
1982end
[2]1983
[446]1984%check the current ActionPath to the selected function
[248]1985if ~isempty(list_transform{ind_coord})
[494]1986    func=functions(list_transform{ind_coord});
1987    set(handles.TransformPath,'String',fileparts(func.file)); %show the path to the senlected function
[248]1988else
[494]1989    set(handles.TransformPath,'String',''); %show the path to the senlected function
[248]1990end
[350]1991
1992
1993
[446]1994% --------------------------------------------------------------------
1995function MenuExportConfig_Callback(hObject, eventdata, handles)
1996global Series
[461]1997[tild,Series,errormsg]=prepare_jobs(handles,0);
[446]1998% Series=read_GUI(handles.series);
[358]1999
[446]2000evalin('base','global Series')%make CurData global in the workspace
2001display('current series config :')
2002evalin('base','Series') %display CurData in the workspace
2003commandwindow; %brings the Matlab command window to the front
[472]2004
2005
2006% --- Executes on selection change in RunMode.
2007function RunMode_Callback(hObject, eventdata, handles)
[525]2008
[526]2009% --- Executes on selection change in Coord_x.
2010function Coord_x_Callback(hObject, eventdata, handles)
[525]2011
2012
[526]2013% --- Executes on selection change in Coord_y.
2014function Coord_y_Callback(hObject, eventdata, handles)
[525]2015
2016
2017
[526]2018% --- Executes when series is resized.
2019function series_ResizeFcn(hObject, eventdata, handles)
2020%% input table
2021set(handles.InputTable,'Unit','pixel')
2022Pos=get(handles.InputTable,'Position');
2023set(handles.InputTable,'Unit','normalized')
2024ColumnWidth=round([0.5 0.14 0.14 0.14 0.08]*(Pos(3)-52));
2025ColumnWidth=num2cell(ColumnWidth);
2026set(handles.InputTable,'ColumnWidth',ColumnWidth)
2027
2028%% MinIndex and MaxIndex
2029set(handles.MinIndex,'Unit','pixel')
2030Pos=get(handles.MinIndex,'Position');
2031set(handles.MinIndex,'Unit','normalized')
2032ColumnWidth=get(handles.MinIndex,'ColumnWidth');
2033if numel(ColumnWidth)==2
2034    ColumnWidth=num2cell(floor([0.5 0.5]*(Pos(3)-20)));
2035else
2036    ColumnWidth={Pos(3)-5};
2037end   
2038set(handles.MinIndex,'ColumnWidth',ColumnWidth)
2039set(handles.MaxIndex,'ColumnWidth',ColumnWidth)
2040
2041%% TimeTable
2042set(handles.TimeTable,'Unit','pixel')
2043Pos=get(handles.TimeTable,'Position');
2044set(handles.TimeTable,'Unit','normalized')
2045ColumnWidth=get(handles.TimeTable,'ColumnWidth');
2046ColumnWidth=num2cell(floor([0.25 0.25 0.25 0.25]*(Pos(3)-20)));
2047set(handles.TimeTable,'ColumnWidth',ColumnWidth)
2048
2049
2050%% PairString
2051set(handles.PairString,'Unit','pixel')
2052Pos=get(handles.PairString,'Position');
2053set(handles.PairString,'Unit','normalized')
2054set(handles.PairString,'ColumnWidth',{Pos(3)-5})
Note: See TracBrowser for help on using the repository browser.