source: trunk/src/series/merge_proj.m @ 478

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

series fcts updated to fit with new waitbar fct and background run mode, and various bug repairs

File size: 16.8 KB
Line 
1%'merge_proj': project and concatene fields
2% can be used as a template for applying an operation (here projection and concatenation) on each field of an input series
3%------------------------------------------------------------------------
4% function ParamOut=merge_proj(Param)
5%------------------------------------------------------------------------
6
7%%%%%%%%%%% GENERAL TO ALL SERIES ACTION FCTS %%%%%%%%%%%%%%%%%%%%%%%%%%%
8%
9% This function is used in four modes by the GUI series:
10%           1) config GUI: with no input argument, the function determine the suitable GUI configuration
11%           2) interactive input: the function is used to interactively introduce input parameters, and then stops
12%           3) RUN: the function itself runs, when an appropriate input  structure Param has been introduced.
13%           4) BATCH: the function itself proceeds in BATCH mode, using an xml file 'Param' as input.
14%
15% This function is used in four modes by the GUI series:
16%           1) config GUI: with no input argument, the function determine the suitable GUI configuration
17%           2) interactive input: the function is used to interactively introduce input parameters, and then stops
18%           3) RUN: the function itself runs, when an appropriate input  structure Param has been introduced.
19%           4) BATCH: the function itself proceeds in BATCH mode, using an xml file 'Param' as input.
20%
21%OUTPUT
22% GUI_input=list of options in the GUI series.fig needed for the function
23%
24%INPUT:
25% In run mode, the input parameters are given as a Matlab structure Param copied from the GUI series.
26% In batch mode, Param is the name of the corresponding xml file containing the same information
27% In the absence of input (as activated when the current Action is selected
28% in series), the function ouput GUI_input set the activation of the needed GUI elements
29%
30% Param contains the elements:(use the menu bar command 'export/GUI config' in series to see the current structure Param)
31%    .InputTable: cell of input file names, (several lines for multiple input)
32%                      each line decomposed as {RootPath,SubDir,Rootfile,NomType,Extension}
33%    .OutputSubDir: name of the subdirectory for data outputs
34%    .OutputDirExt: directory extension for data outputs
35%    .Action: .ActionName: name of the current activated function
36%             .ActionPath:   path of the current activated function
37%    .IndexRange: set the file or frame indices on which the action must be performed
38%    .FieldTransform: .TransformName: name of the selected transform function
39%                     .TransformPath:   path  of the selected transform function
40%                     .TransformHandle: corresponding function handle
41%    .InputFields: sub structure describing the input fields withfields
42%              .FieldName: name of the field
43%              .VelType: velocity type
44%              .FieldName_1: name of the second field in case of two input series
45%              .VelType_1: velocity type of the second field in case of two input series
46%    .ProjObject: %sub structure describing a projection object (read from ancillary GUI set_object)
47%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48
49function ParamOut=merge_proj(Param)
50
51%% set the input elements needed on the GUI series when the action is selected in the menu ActionName
52if ~exist('Param','var') % case with no input parameter
53    ParamOut={'AllowInputSort';'off';...% allow alphabetic sorting of the list of input files (options 'off'/'on', 'off' by default)
54        'WholeIndexRange';'off';...% prescribes the file index ranges from min to max (options 'off'/'on', 'off' by default)
55        'NbSlice';'on'; ...%nbre of slices ('off' by default)
56        'VelType';'one';...% menu for selecting the velocity type (options 'off'/'one'/'two',  'off' by default)
57        'FieldName';'one';...% menu for selecting the field (s) in the input file(options 'off'/'one'/'two', 'off' by default)
58        'FieldTransform'; 'on';...%can use a transform function
59        'ProjObject';'on';...%can use projection object(option 'off'/'on',
60        'Mask';'off';...%can use mask option   (option 'off'/'on', 'off' by default)
61        'OutputDirExt';'.mproj';...%set the output dir extension
62               ''};
63        return
64end
65
66%%%%%%%%%%%% STANDARD PART (DO NOT EDIT) %%%%%%%%%%%%
67%% select different modes,  RUN, parameter input, BATCH
68% BATCH  case: read the xml file for batch case
69if ischar(Param)
70        Param=xml2struct(Param);
71        checkrun=0;
72% RUN case: parameters introduced as the input structure Param
73else
74    hseries=guidata(Param.hseries);%handles of the GUI series
75    if isfield(Param,'Specific')&& strcmp(Param.Specific,'?')
76        checkrun=1;% will only search interactive input parameters (preparation of BATCH mode)
77    else
78        checkrun=2; % indicate the RUN option is used
79    end
80end
81ParamOut=Param; %default output
82OutputSubDir=[Param.OutputSubDir Param.OutputDirExt];
83
84%% root input file(s) and type
85RootPath=Param.InputTable(:,1);
86RootFile=Param.InputTable(:,3);
87SubDir=Param.InputTable(:,2);
88NomType=Param.InputTable(:,4);
89FileExt=Param.InputTable(:,5);
90[filecell,i1_series,i2_series,j1_series,j2_series]=get_file_series(Param);
91%%%%%%%%%%%%
92% The cell array filecell is the list of input file names, while
93% filecell{iview,fileindex}:
94%        iview: line in the table corresponding to a given file series
95%        fileindex: file index within  the file series,
96% i1_series(iview,ref_j,ref_i)... are the corresponding arrays of indices i1,i2,j1,j2, depending on the input line iview and the two reference indices ref_i,ref_j
97% i1_series(iview,fileindex) expresses the same indices as a 1D array in file indices
98%%%%%%%%%%%%
99NbSlice=1;%default
100if isfield(Param.IndexRange,'NbSlice')&&~isempty(Param.IndexRange.NbSlice)
101    NbSlice=Param.IndexRange.NbSlice;
102end
103nbview=numel(i1_series);%number of input file series (lines in InputTable)
104nbfield_j=size(i1_series{1},1); %nb of fields for the j index (bursts or volume slices)
105nbfield_i=size(i1_series{1},2); %nb of fields for the i index
106nbfield=nbfield_j*nbfield_i; %total number of fields
107nbfield_i=floor(nbfield/NbSlice);%total number of  indexes in a slice (adjusted to an integer number of slices)
108nbfield=nbfield_i*NbSlice; %total number of fields after adjustement
109
110%determine the file type on each line from the first input file
111ImageTypeOptions={'image','multimage','mmreader','video'};
112NcTypeOptions={'netcdf','civx','civdata'};
113for iview=1:nbview
114    if ~exist(filecell{iview,1}','file')
115        displ_uvmat('ERROR',['the first input file ' filecell{iview,1} ' does not exist'],checkrun)
116        return
117    end
118    [FileType{iview},FileInfo{iview},MovieObject{iview}]=get_file_type(filecell{iview,1});
119    CheckImage{iview}=~isempty(find(strcmp(FileType{iview},ImageTypeOptions)));% =1 for images
120    CheckNc{iview}=~isempty(find(strcmp(FileType{iview},NcTypeOptions)));% =1 for netcdf files
121    if ~isempty(j1_series{iview})
122        frame_index{iview}=j1_series{iview};
123    else
124        frame_index{iview}=i1_series{iview};
125    end
126end
127
128
129%% calibration data and timing: read the ImaDoc files
130[XmlData,NbSlice_calib,time,errormsg]=read_multimadoc(RootPath,SubDir,RootFile,FileExt,i1_series,i2_series,j1_series,j2_series);
131if size(time,1)>1
132    diff_time=max(max(diff(time)));
133    if diff_time>0
134        displ_uvmat('WARNING',['times of series differ by (max) ' num2str(diff_time)],checkrun)
135    end   
136end
137
138%% coordinate transform or other user defined transform
139transform_fct='';%default
140if isfield(Param,'FieldTransform')&&~isempty(Param.FieldTransform.TransformName)
141    addpath(Param.FieldTransform.TransformPath)
142    transform_fct=str2func(Param.FieldTransform.TransformName);
143    rmpath(Param.FieldTransform.TransformPath)
144end
145
146%%%%%%%%%%%% END STANDARD PART  %%%%%%%%%%%%
147 % EDIT FROM HERE
148
149%% check the validity of  input file types
150if CheckImage{1}
151    FileExtOut='.png'; % write result as .png images for image inputs
152elseif CheckNc{1}
153    FileExtOut='.nc';% write result as .nc files for netcdf inputs
154else
155    displ_uvmat('ERROR',['invalid file type input ' FileType{1}],checkrun)
156    return
157end
158for iview=1:nbview
159        if ~isequal(CheckImage{iview},CheckImage{1})||~isequal(CheckNc{iview},CheckNc{1})
160        displ_uvmat('ERROR','input set of input series: need  either netcdf either image series',checkrun)
161    return
162    end
163end
164NomTypeOut=NomType;% output file index will indicate the first and last ref index in the series
165if checkrun==1
166    ParamOut.Specific=[];%no specific parameter
167    return %stop here for interactive input (option Param.Specific='?')
168end
169
170%% Set field names and velocity types
171%use Param.InputFields for all views
172
173%% MAIN LOOP ON SLICES
174%%%%%%%%%%%%% STANDARD PART (DO NOT EDIT) %%%%%%%%%%%%
175for i_slice=1:NbSlice
176    index_slice=i_slice:NbSlice:nbfield;% select file indices of the slice
177    nbfiles=0;
178    nbmissing=0;
179
180    %%%%%%%%%%%%%%%% loop on field indices %%%%%%%%%%%%%%%%
181    for index=index_slice
182 
183        if checkrun
184            update_waitbar(hseries.Waitbar,index/(nbfield))
185            stopstate=get(hseries.RUN,'BusyAction');
186        else
187            stopstate='queue';
188        end
189       
190        %%%%%%%%%%%%%%%% loop on views (input lines) %%%%%%%%%%%%%%%%
191        Data=cell(1,nbview);%initiate the set Data
192        nbtime=0;
193        for iview=1:nbview
194            % reading input file(s)
195            [Data{iview},tild,errormsg] = read_field(filecell{iview,index},FileType{iview},Param.InputFields,frame_index{iview}(index));
196            if ~isempty(errormsg)
197                errormsg=['merge_proj/read_field/' errormsg];
198                display(errormsg)
199                break
200            end
201            timeread(iview)=0;
202            if isfield(Data{iview},'Time')
203                    timeread(iview)=Data{iview}.Time;
204                    nbtime=nbtime+1;
205                end
206            if ~isempty(NbSlice_calib)
207                Data{iview}.ZIndex=mod(i1_series{iview}(index)-1,NbSlice_calib{iview})+1;%Zindex for phys transform
208            end
209            %transform the input field (e.g; phys) if requested
210            if ~isempty(transform_fct)
211                Data{iview}=transform_fct(Data{iview},XmlData{iview});  %transform to phys if requested
212            end
213            % field calculation (vort, div...)
214            if strcmp(FileType{iview},'civx')||strcmp(FileType{iview},'civdata')
215                Data{iview}=calc_field(Param.InputFields.FieldName,Data{iview});%calculate field (vort..)
216            end
217           
218            %projection on object (gridded plane)
219            if Param.CheckObject
220                [Data{iview},errormsg]=proj_field(Data{iview},Param.ProjObject);
221                if ~isempty(errormsg)
222                    displ_uvmat('ERROR',['error in merge_proge/proj_field: ' errormsg],checkrun)
223                    return
224                end
225            end
226        end
227        %----------END LOOP ON VIEWS----------------------
228       
229        %% merge the nbview fields
230        MergeData=merge_field(Data);
231        if isfield(MergeData,'Txt')
232            displ_uvmat('ERROR',MergeData.Txt,checkrun)
233            return
234        end
235       
236        % time of the merged field:
237        if ~isempty(time)% time defined from ImaDoc
238            timeread=time(:,index);
239        end
240        timeread=mean(timeread);
241       
242        % generating the name of the merged field
243        i1=i1_series{iview}(index);
244        if ~isempty(i2_series{iview})
245            i2=i2_series{iview}(index);
246        else
247            i2=i1;
248        end
249        j1=1;
250        j2=1;
251        if ~isempty(j1_series{iview})
252            j1=j1_series{iview}(index);
253            if ~isempty(j2_series{iview})
254                j2=j2_series{iview}(index);
255            else
256                j2=j1;
257            end
258        end
259        OutputFile=fullfile_uvmat(RootPath{1},OutputSubDir,RootFile{1},FileExtOut,NomType{1},i1,i2,j1,j2);
260       
261        % recording the merged field
262        if CheckImage{1}    %in case of input images an image is produced
263            if isa(MergeData.A,'uint8')
264                bitdepth=8;
265            elseif isa(MergeData.A,'uint16')
266                bitdepth=16;
267            end
268            imwrite(MergeData.A,OutputFile,'BitDepth',bitdepth);
269            %write xml calibration file
270            siz=size(MergeData.A);
271            npy=siz(1);
272            npx=siz(2);
273            if isfield(MergeData,'VarAttribute')&&isfield(MergeData.VarAttribute{1},'Coord_2')&&isfield(MergeData.VarAttribute{1},'Coord_1')
274                Rangx=MergeData.VarAttribute{1}.Coord_2;
275                Rangy=MergeData.VarAttribute{1}.Coord_1;
276            elseif isfield(MergeData,'AX')&& isfield(MergeData,'AY')
277                Rangx=[MergeData.AX(1) MergeData.AX(end)];
278                Rangy=[MergeData.AY(1) MergeData.AY(end)];
279            else
280                Rangx=[0.5 npx-0.5];
281                Rangy=[npy-0.5 0.5];%default
282            end
283            pxcmx=(npx-1)/(Rangx(2)-Rangx(1));
284            pxcmy=(npy-1)/(Rangy(1)-Rangy(2));
285            T_x=-pxcmx*Rangx(1)+0.5;
286            T_y=-pxcmy*Rangy(2)+0.5;
287            GeometryCal.focal=1;
288            GeometryCal.R=[pxcmx,0,0;0,pxcmy,0;0,0,1];
289            GeometryCal.Tx_Ty_Tz=[T_x T_y 1];
290            ImaDoc.GeometryCalib=GeometryCal;
291            t=struct2xml(ImaDoc);
292            t=set(t,1,'name','ImaDoc');
293            save(t,[filebase_merge '.xml'])
294            display([filebase_merge '.xml saved'])
295        else
296            MergeData.ListGlobalAttribute={'Conventions','Project','InputFile_1','InputFile_end','nb_coord','nb_dim','dt','Time','civ'};
297            MergeData.Conventions='uvmat';
298            MergeData.nb_coord=2;
299            MergeData.nb_dim=2;
300            dt=[];
301            if isfield(Data{1},'dt')&& isnumeric(Data{1}.dt)
302                dt=Data{1}.dt;
303            end
304            for iview =2:numel(Data)
305                if ~(isfield(Data{iview},'dt')&& isequal(Data{iview}.dt,dt))
306                    dt=[];%dt not the same for all fields
307                end
308            end
309            if isempty(dt)
310                MergeData.ListGlobalAttribute(6)=[];
311            else
312                MergeData.dt=dt;
313            end
314            MergeData.Time=timeread;
315            error=struct2nc(OutputFile,MergeData);%save result file
316            if isempty(error)
317                display(['output file ' OutputFile ' written'])
318            else
319                display(error)
320            end
321        end
322    end
323end
324
325%'merge_field': concatene fields
326%------------------------------------------------------------------------
327function MergeData=merge_field(Data)
328%% default output
329if isempty(Data)||~iscell(Data)
330    MergeData=[];
331    return
332end
333MergeData=Data{1};%default
334error=0;
335nbview=length(Data);
336if nbview==1
337    return
338end
339
340%% group the variables (fields of 'FieldData') in cells of variables with the same dimensions
341[CellVarIndex,NbDim,VarTypeCell]=find_field_indices(Data{1});
342%LOOP ON GROUPS OF VARIABLES SHARING THE SAME DIMENSIONS
343% CellVarIndex=cells of variable index arrays
344ivar_new=0; % index of the current variable in the projected field
345for icell=1:length(CellVarIndex)
346    if NbDim(icell)==1
347        continue
348    end
349    VarIndex=CellVarIndex{icell};%  indices of the selected variables in the list FieldData.ListVarName
350    VarType=VarTypeCell{icell};
351    ivar_X=VarType.coord_x;
352    ivar_Y=VarType.coord_y;
353    ivar_FF=VarType.errorflag;
354    if isempty(ivar_X)
355        test_grid=1;%test for input data on regular grid (e.g. image)coordinates
356    else
357        if length(ivar_Y)~=1
358                displ_uvmat('ERROR','y coordinate missing in proj_field.m',checkrun)
359                return
360        end
361        test_grid=0;
362    end
363    %case of input fields with unstructured coordinates
364    if ~test_grid
365        for ivar=VarIndex
366            VarName=MergeData.ListVarName{ivar};
367            for iview=1:nbview
368                eval(['MergeData.' VarName '=[MergeData.' VarName '; Data{iview}.' VarName '];'])
369            end
370        end
371    %case of fields defined on a structured  grid
372    else 
373        testFF=0;
374        for iview=2:nbview
375            for ivar=VarIndex
376                VarName=MergeData.ListVarName{ivar};
377                if isfield(MergeData,'VarAttribute')
378                    if length(MergeData.VarAttribute)>=ivar && isfield(MergeData.VarAttribute{ivar},'Role') && isequal(MergeData.VarAttribute{ivar}.Role,'errorflag')
379                        testFF=1;
380                    end
381                end
382                eval(['MergeData.' VarName '=MergeData.' VarName '+ Data{iview}.' VarName ';'])
383            end
384        end
385        if testFF
386            nbaver=nbview-MergeData.FF;
387            indgood=find(nbaver>0);
388            for ivar=VarIndex
389                VarName=MergeData.ListVarName{ivar};
390                eval(['MergeData.' VarName '(indgood)=double(MergeData.' VarName '(indgood))./nbaver(indgood);'])
391            end
392        else
393            for ivar=VarIndex
394                VarName=MergeData.ListVarName{ivar};
395                eval(['MergeData.' VarName '=double(MergeData.' VarName ')./nbview;'])
396            end   
397        end
398    end
399end
400
401   
Note: See TracBrowser for help on using the repository browser.