Documentation/UserGuide/restartability: nccmp_obelix.m

File nccmp_obelix.m, 13.9 KB (added by lathiere, 4 years ago)

Modified Matlab nccmp function

Line 
1function nccmp(ncfile1,ncfile2,varargin)
2%NCCMP  compares two NetCDF files and prints the differences.
3% This function is useful for testing mathematical forecasting or prediction models.
4%
5% USAGE:
6%          NCCMP(ncfile1,ncfile2)
7%          NCCMP(ncfile1,ncfile2,tolerance,forceCompare)
8%
9% INPUT:
10%    ncfile1      - name of the NetCDF file to compare
11%    ncfile2      - name of the NetCDF file to compare
12%    tolerance    - compare numeric data using a tolerance threshold
13%    forceCompare - if false, exit when first difference is found
14%                      true:  coninues to process all variables
15% OUTPUT:
16%
17% EXAMPLES:
18%    nccmp('old.nc','new.nc',0.000001)
19%    nccmp('old.nc','new.nc',[],true)
20%    ...
21% FEATURES:
22% 1. Print the differences and their locations
23% 2. Exits when first difference is found or optionally continues to process all variables
24% 3. User defined tolerance threshold to compare the variables
25% TO DO:
26% 1. Specific variable inclusion or exclusion
27% 2. Specific attribute inclusion or exclusion
28% 3. Option to ignore the history attribute
29% 4. Ignore difference between values that have different missing values etc
30% See also:
31%
32% HISTORY:
33% 1.0.0 (21-07-2014): Initial release
34% 1.1.0 (21-07-2014): Option to forceCompare true or false
35% 1.2.0 (16-09-2014): Input checking and clean up
36% 1.3.0 (16-09-2014): Adding internal function IND2SUB1 to return single
37%                     variable IJ rather than returning I,J (length(siz))
38% Author: Durga Lal Shrestha
39% CSIRO Land & Water, Highett, Australia
40% eMail: durgalal.shrestha@gmail.com
41% Website: www.durgalal.co.cc
42% Copyright 2014 Durga Lal Shrestha
43% $First created: 21-Jul-2014
44% $Revision: 1.3.0 $ $Date: 16-Sep-2014 10:06:03 $
45% ***********************************************************************
46%% INPUT ARGUMENTS CHECK
47narginchk(2, 4)
48tolerance = 0;
49filesAreIdentical = true;
50forceCompare = false;
51if nargin>2 && ~isempty(varargin{1})
52    tolerance = varargin{1};
53    if ~isscalar(tolerance)
54        error('NCCMP:WrongDataType','Tolerance input should be scalar')
55    end
56end
57if nargin>3
58    forceCompare = varargin{2};
59    if ~isscalar(forceCompare)
60        error('NCCMP:WrongDataType','Fourth argumnet should be boolean')
61    end
62end
63% Check if files exist
64if exist(ncfile1,'file')~=2 && exist(ncfile2,'file')~=2
65    error('NCCMP:FileNotFound','Input files %s and %s do not exist...',ncfile1,ncfile2)
66end
67if exist(ncfile1,'file')~=2
68    error('NCCMP:FileNotFound','Input file %s does not exist...',ncfile1)
69end
70if exist(ncfile2,'file')~=2
71    error('NCCMP:FileNotFound','Input file %s does not exist...',ncfile2)
72end
73fprintf('COMPARING netcdf files: %s <> %s\n',ncfile1,ncfile2)
74fprintf('...With tolerance: %1.1E\n',tolerance)
75fprintf('\n')
76ncid1 = netcdf.open(ncfile1,'NC_NOWRITE');
77ncid2 = netcdf.open(ncfile2,'NC_NOWRITE');
78% Check if output files exit, if yes delete it. Otherwise we can end up
79% with huge files, in particular the savefile_all
80if forceCompare
81   if exist('all_diff.txt')
82       fprintf('The all_diff.txt exist, we delete it before we run the script \n')
83       delete('all_diff.txt')
84   end
85else
86   if exist('first_diff.txt')
87       fprintf('The first_diff.txt exist, we delete it before we run the script \n')
88       delete('first_diff.txt')
89   end
90end
91%% % Get information about the contents of the file.
92[numdims1, numvars1, numglobalatts1, unlimdimID1] = netcdf.inq(ncid1);
93[numdims2, numvars2, numglobalatts2, unlimdimID2] = netcdf.inq(ncid2);
94%ncfile2(ncid1)
95%ncfile2(ncid2)
96%% Get Global attributes Information
97if numglobalatts1~=numglobalatts2
98    fprintf('DIFFER: NUMBER OF GLOBAL ATTRIBUTES : %d <> %d\n',numglobalatts1,numglobalatts2)
99    filesAreIdentical = false;
100end
101finfo1 = ncinfo(ncfile1);
102finfo2 = ncinfo(ncfile2);
103attrName1 = {finfo1.Attributes.Name};
104attrName2 = {finfo2.Attributes.Name};
105% Check common attribute names
106comName = intersect(attrName1,attrName2);
107% Check value of common attributes
108for i=1:length(comName)
109    attvalue1 = ncreadatt(ncfile1,'/',comName{i});
110    attvalue2 = ncreadatt(ncfile2,'/',comName{i});
111    if ischar(attvalue1) && ischar(attvalue1)
112        if ~strcmp(attvalue1,attvalue2)
113            fprintf('DIFFER: LENGTH OF GLOBAL ATTRIBUTE: %s : %d <> %d : VALUES :%s <> %s\n' ,comName{i},length(attvalue1),length(attvalue2),attvalue1,attvalue2)
114            filesAreIdentical = false;
115        end
116    else
117        if ~isequal(attvalue1,attvalue2)
118            fprintf('DIFFER: LENGTH OF GLOBAL ATTRIBUTE: %s : %d <> %d : VALUES :%12.5f <> %12.5f\n' ,comName{i},length(attvalue1),length(attvalue2),attvalue1,attvalue2)
119            filesAreIdentical = false;
120        end
121    end
122end
123% Check name of attributes which exist in ncfile1 but not in ncfile2
124attrName1Only  = setdiff(attrName1,attrName2);
125for i=1:length(attrName1Only)
126    fprintf('DIFFER: NAME OF GLOBAL ATTRIBUTE: %s : GLOBAL ATTRIBUTE DOES NOT EXIST in %s\n' ,attrName1Only{i},ncfile2)
127end
128% Check name of attributes which exist in ncfile2 but not in ncfile1
129attrName2Only  = setdiff(attrName2,attrName1);
130for i=1:length(attrName2Only)
131    fprintf('DIFFER: NAME OF GLOBAL ATTRIBUTE: %s : GLOBAL ATTRIBUTE DOES NOT EXIST in %s\n' ,attrName2Only{i},ncfile1)
132end
133fprintf('\n')
134%% Get Dimension Information
135if numdims1~=numdims2
136    fprintf('DIFFER: NUMBER OF DIMENSION IN FILES: %d <> %d\n',numdims1,numdims2)
137    filesAreIdentical = false;
138end
139% if ~isequal(finfo1.Dimensions,finfo2.Dimensions)
140%     fprintf('Dimesnions are not same\n')
141% end
142dimName1 = {finfo1.Dimensions.Name};
143dimName2 = {finfo2.Dimensions.Name};
144% Check common attribute names
145comName = intersect(dimName1,dimName2);
146% Check value of common attributes
147for i=1:length(comName)
148    dimid1 = netcdf.inqDimID(ncid1,comName{i});
149    dimid2 = netcdf.inqDimID(ncid2,comName{i});
150    [dimname1, dimlen1] = netcdf.inqDim(ncid1,dimid1);
151    [dimname2, dimlen2] = netcdf.inqDim(ncid2,dimid2);
152    if  dimlen1 ~= dimlen2
153        fprintf('DIFFER: LENGTH OF DIMENSION: %s : %d <> %d\n' ,comName{i},dimlen1,dimlen2)
154    end
155end
156netcdf.close(ncid1);
157netcdf.close(ncid2);
158% Check name of attributes which exist in ncfile1 but not in ncfile2
159dimName1Only  = setdiff(dimName1,dimName2);
160for i=1:length(dimName1Only)
161    fprintf('DIFFER: NAME OF DIMENSION: %s : DIMENSION DOES NOT EXIST in %s\n' ,dimName1Only{i},ncfile2)
162end
163% Check name of attributes which exist in ncfile2 but not in ncfile1
164dimName2Only  = setdiff(dimName2,dimName1);
165for i=1:length(dimName2Only)
166    fprintf('DIFFER: NAME OF DIMENSION: %s : DIMESNION DOES NOT EXIST in %s\n' ,dimName2Only{i},ncfile1)
167end
168fprintf('\n')
169%% Get Variable Information
170if numvars1~=numvars2
171    fprintf('DIFFER: NUMBER OF VARIABLE IN FILES: %d <> %d\n',numvars1,numvars2)
172    filesAreIdentical = false;
173end
174% if ~isequal(finfo1.Variables,finfo2.Variables)
175%     fprintf('Variables are not same\n')
176% end
177varName1 = {finfo1.Variables.Name};
178varName2 = {finfo2.Variables.Name};
179% Check common attribute names
180[comName,ia,ib] =  intersect(varName1,varName2);
181% Check value of common attributes
182for i=1:length(comName)
183    %     dimensions1 = finfo1.Variables(ia(i)).Dimensions;
184    %     dimensions2 = finfo2.Variables(ib(i)).Dimensions;
185    %     if ~isequal(dimensions1,dimensions2)
186    %         %fprintf('DIFFER: DIMENSIONS: %s : %d <> %d\n' ,comName{i},dimensions1,dimensions1)
187    %         fprintf('TO DO: CHECK dimension Name and Length\n')
188    %     end
189    size1  = finfo1.Variables(ia(i)).Size;
190    size2 = finfo2.Variables(ib(i)).Size;
191    if ~isequal(size1,size2)
192        fprintf('DIFFER: SIZE, VARIABLE: %s : %s <> %s\n' ,comName{i},num2str(size1),num2str(size2))
193    else
194        DataType1  = finfo1.Variables(ia(i)).Datatype;
195        DataType2  =  finfo2.Variables(ib(i)).Datatype;
196        if ~strcmp(DataType1,DataType2)
197            fprintf('DIFFER: TYPES, VARIABLE: %s : %s <> %s\n' ,comName{i},DataType1,DataType2)
198        end
199        data1=ncread(ncfile1,comName{i});
200        data2=ncread(ncfile2,comName{i});
201        if ~ischar(data1) && ~ischar(data2)
202            dff = abs(double(data1)-double(data2));
203            %             [row,col] = find(dff > tolerance);
204            ind = find(dff > tolerance);
205            if ~isempty(ind)
206                filesAreIdentical = false;
207                if forceCompare
208                    for j=1:length(ind)
209                        %[I1,I2,I3] = ind2sub(size1,ind(j));                       
210                        X = ind2sub1(size1,ind(j));
211                        all_diff{j} = sprintf('DIFFER: VARIABLE, %s : POSITION %s: VALUES: %12.20G <> %12.20G \n' ,comName{i},num2str(X),data1(ind(j)),data2(ind(j)));
212                        dlmwrite('all_diff.txt',all_diff{j},'-append','delimiter','')
213                    end
214                else
215                    % Just report the first occurrence
216                    first_diff = sprintf('DIFFER: VARIABLE, %s : NUMBER OF LOCATION %d, Reporting the first location only...\n' ,comName{i},length(ind));                   
217                    dlmwrite('first_diff.txt',first_diff,'-append','delimiter','')
218                    X = ind2sub1(size1,ind(1));
219                    first_diff = sprintf('DIFFER: VARIABLE, %s : POSITION %s: VALUES: %12.20G <> %12.20G \n' ,comName{i},num2str(X),data1(ind(1)),data2(ind(1)));
220                    dlmwrite('first_diff.txt',first_diff,'-append','delimiter','')
221                end
222            end
223        else
224            % character data
225            ind = find(data1~=data2);
226            if ~isempty(ind)
227                filesAreIdentical = false;
228                if forceCompare
229                    for j=1:length(ind)
230                        %[I1,I2,I3] = ind2sub(size1,ind(j));                       
231                        X = ind2sub1(size1,ind(j));
232                        savefile = fprintf('DIFFER: VARIABLE, %s : POSITION %s: VALUES: %12.20G <> %12.20G \n' ,comName{i},num2str(X),data1(ind(j)),data2(ind(j)));
233                        dlmwrite('Savefile.txt',savefile)
234                    end
235                else
236                    % Just report the first occurance
237                    fprintf('DIFFER: VARIABLE, %s : NUMBER OF LOCATION %d, Reporting the first location only...\n' ,comName{i},length(ind))                   
238                    X = ind2sub1(size1,ind(1));
239                    fprintf('DIFFER: VARIABLE, %s : POSITION %s: VALUES: %12.20G <> %12.20G \n' ,comName{i},num2str(X),data1(ind(1)),data2(ind(1)))
240                end
241            end
242        end
243    end
244    att = '';
245    att = '';
246    if isempty(finfo1.Variables(ia(i)).Attributes)
247        fname = ncfile1;
248    elseif isempty(finfo2.Variables(ib(i)).Attributes)
249        fname = ncfile2;
250    end
251   
252    if isempty(finfo1.Variables(ia(i)).Attributes) || isempty(finfo2.Variables(ib(i)).Attributes)
253        if ~(isempty(finfo1.Variables(ia(i)).Attributes) && isempty(finfo2.Variables(ib(i)).Attributes))
254            fprintf('DIFFER: ATTRIBUTE: VARIABLE: %s : No attributes in %s\n' ,finfo1.Variables(ia(i)).Name,fname)
255        end
256    else
257        att1 = {finfo1.Variables(ia(i)).Attributes.Name};
258        att2 = {finfo2.Variables(ib(i)).Attributes.Name};
259        if length(att1)~=length(att2)
260            fprintf('DIFFER: NUMBER OF ATTRIBUTE: VARIABLE: %s :  %d <> %d\n' ,finfo1.Variables(ia(i)).Name,length(att1),length(att2))
261        end
262       
263        [comAtt,ind1,ind2] =  intersect(att1,att2);
264        % Check if values are same in common attributes
265        for j=1:length(comAtt)
266            attvalue1 = '';
267            attvalue2 = '';
268            if isfield(finfo1.Variables(ia(i)),'Attributes')
269                Att1= finfo1.Variables(ia(i)).Attributes;
270                attvalue1  = Att1(ind1(j)).Value;
271            end
272            if isfield(finfo2.Variables(ib(i)),'Attributes')
273                Att2= finfo2.Variables(ib(i)).Attributes;
274                attvalue2  = Att2(ind2(j)).Value;
275            end
276            if ischar(attvalue1) && ischar(attvalue2)
277                if ~strcmp(attvalue1,attvalue2)
278                    fprintf('DIFFER: LENGTH, ATTRIBUTE: %s, VARIABLE: %s :%d <> %d , VALUES: %s <> %s\n' ,comAtt{j},comName{i},length(attvalue1),length(attvalue2),attvalue1,attvalue2)
279                    filesAreIdentical = false;
280                end
281            else
282                if ~isequal(attvalue1,attvalue2)
283                    fprintf('DIFFER: LENGTH, ATTRIBUTE: %s, VARIABLE : %s :%d <> %d : VALUES: %12.5f <> %12.5f\n' ,comAtt{j},comName{i},length(attvalue1),length(attvalue2),attvalue1,attvalue2)
284                    filesAreIdentical = false;
285                end
286            end
287        end
288       
289        % Check name of attributes which exist in ncfile1 but not in ncfile2
290        attrName1Only  = setdiff(att1,att2);
291        for j=1:length(attrName1Only)
292            fprintf('DIFFER: NAME OF ATTRIBUTE: %s : ATTRIBUTE DOES NOT EXIST in VARIABLE: %s in %s\n' ,attrName1Only{j},comName{i},ncfile2)
293        end
294       
295        % Check name of attributes which exist in ncfile2 but not in ncfile1
296        attrName2Only  = setdiff(att1,att2);
297        for j=1:length(attrName2Only)
298            fprintf('DIFFER: NAME OF ATTRIBUTE: %s : ATTRIBUTE DOES NOT EXIST in VARIABLE: %s in %s\n' ,attrName2Only{j},comName{i},ncfile1)
299        end
300    end
301end
302% Check name of attributes which exist in ncfile1 but not in ncfile2
303varName1Only  = setdiff(varName1,varName2);
304for i=1:length(varName1Only)
305    fprintf('DIFFER: NAME OF VARIABLE: %s : VARIABLE DOES NOT EXIST in %s\n' ,varName1Only{i},ncfile2)
306end
307% Check name of attributes which exist in ncfile2 but not in ncfile1
308varName2Only  = setdiff(varName2,varName1);
309for i=1:length(varName2Only)
310    fprintf('DIFFER: NAME OF VARIABLE: %s : VARIABLE DOES NOT EXIST in %s\n' ,varName2Only{i},ncfile1)
311end
312fprintf('\n')
313%%
314if filesAreIdentical
315    % fprintf('FILES: %s and %s are identical\n' ,ncfile1,ncfile2)
316    fprintf('FILES are identical\n')
317end
318%% Internal function ind2sub1
319function IJ = ind2sub1(siz,IND)
320% IND2SUB1 returns single variable IJ rather than returning I,J (length(siz))
321% variables
322if ~isvector(IND)
323    error('IND2SUB1:WrongInputFormat','ind2sub1 only works with scalar and vector')     
324end
325IND = IND(:);
326[out{1:length(siz)}] = ind2sub(siz,IND);
327IJ = cell2mat(out);