-
Notifications
You must be signed in to change notification settings - Fork 1
/
loris5.m
532 lines (487 loc) · 17.9 KB
/
loris5.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
function varargout=loris5(wav,N,J,precon,depkm,xver,gnorjr,panel)
% [vw,depkm,vstats]=LORIS5(wav,N,J,precon,depkm,xver,gnorjr,panel)
%
% Study of the sparsity in the models of Montelli and Ritsema
% Learn from the depth-dependence of scales in a seismic model.
%
% INPUT:
%
% wav The chosen wavelet construction used, 'D2', 'D4' or 'D6'
% N The power of the dyadic subdivision for the cubed sphere
% J Maximum scale in both directions for the wavelet analysis
% precon [1|0 1|0] toggles preconditioning in either dimension
% depkm The single depth in km where the model is read and the results of the
% calculations are saved - must match exactly. If a vector or
% empty then you work on the result and get a plot
% xver For extra verification showing some intermediate results
% gnorjr 1 For the model by Montelli et al. (2006)
% 2 For the model by Ritsema et al. (2010)
% panel 0 Does all panels [default]
% 1-6 Picks a specific panel
%
% OUTPUT:
%
% vw The wavelet-transformed single-depth cubed-sphere for all chunks
% or: the panel number if you're in all-depths output mode
% depkm The depth in km, if you didn't already know it
% vstats A cell structure with the statistics per scale and depth
%
% EXAMPLE:
%
% panel=0;
% loris5('D4',7,4,[1 1],[],0,1,panel) % Paper figure A
% loris5('D4',7,4,[1 1],[],0,2) % Paper figure B
%
% Tested on 8.3.0.532 (R2014a) and 9.0.0.341360 (R2016a)
% Reviewed by gyin-at-princeton.edu, 07/22/2016
% Last modified by fjsimons-at-alum.mit.edu, 07/22/2016
% Identify defaults
defval('wav','D4')
defval('N',7)
defval('J',N-3-strcmp(wav,'D6'))
defval('precon',[1 1]);
% d=readGNmodel(NaN);
% This should hold both for Montelli and Ritsema
d=load('/u/fjsimons/IFILES/EARTHMODELS/MONTELLI/GNdepths');
defval('depkm',d/1000);
defval('xver',0);
defval('fs',11);
defval('panel',0);
% If 1, GN model, if 2, JR model
defval('gnorjr',1)
% Hardwired Earth radius, not ideal, see readGNmodel
rearthkm=6371;
% How many depth layers?
ndeps=length(depkm);
% The default is to do all depths and save the transform calculations if
% they don't exist for the next time you run the program
if gnorjr==1
% And now define what will come out of the analysis at the end
fname2=fullfile(getenv('IFILES'),'EARTHMODELS','MONTELLI','LORIS',...
sprintf('loris5_GN_%i_%i_%s_%i_%i_%i.mat',...
N,J,wav,precon(1),precon(2),panel));
elseif gnorjr==2
% And now define what will come out of the analysis at the end
fname2=fullfile(getenv('IFILES'),'EARTHMODELS','RITSEMA','LORIS',...
sprintf('loris5_JR_%i_%i_%s_%i_%i_%i.mat',...
N,J,wav,precon(1),precon(2),panel));
end
% If all of the depths are to be revisited
if ndeps>1
if exist(fname2,'file')==2
load(fname2)
else
% The percentiles that will be CALCULATED
percs=[85 100];
% Study the properties of this one thresholding percentage
tperc=85;
% Title for the x axis
xlstring1=sprintf('%s wavelet | scaling coefficients',wav);
% Identify the scales in the mr=1 wavelet transform
% Do one more than J so the last one is the scaling coefficients
[vwlev,vwlevs]=cube2scale(N,[J J]+1,1);
% Potential check at a random depth
deptsj=max(1,randi(ndeps));
% Initialize the structure array for good measure
fields={'deptkm','percts','mjuvar','totnum','tcount','normsq'};
% And how many here will populate this?
nmflds={1, length(percs),2, 1, 1, 1 };
nmcols=[1 J+1 J+1 J+1 J+1 J+1 ];
nmrows=[ndeps ndeps ndeps 1 ndeps ndeps];
% Note that being this specific saves memory but increases speed
vwstats=structempty(fields);
for index=1:length(fields)
vwstats.(fields{index})=...
cellnan([nmrows(index) nmcols(index)],1,nmflds{index});
end
% End initialization of the structure array with the results
% Then we call ourselves once per depth layer, still for the straight J
for index=1:ndeps
% Remember that this function calls itself
[vw,depchk,vstats]=...
loris5(wav,N,J,precon,depkm(index),xver,gnorjr,panel);
difer(depchk-depkm(index),[],[],NaN)
% Here we do the panel nulling, or should we do picking
if ~~panel
vw(:,:,skip(1:6,panel))=0;
% Let's see what picking does instead
vw=vw(:,:,panel);
% Remember the vwlevs was just copies in 3D
vwlevs=vwlev;
end
% Quick plot?
if xver==1 && index==deptsj
for jndex=1:J+1
vwnul=vw;
vwnul(vwlevs==jndex)=100;
title(sprintf('Check at depth %i for scale %i',index,jndex))
% This subfunction makes a quick wavelet coefficient plot
clf
[cb,xcb]=quickplot(N,J,vwnul,depkm(index));
pause(1)
end
end
% Remember, we work with the absolute values! But save the originals
vworg=vw;
vw=abs(vw);
% Prepare for the study of the effects of their thresholding which is
% here carried out per individual depth
kilme=vw<prctile(vw(:),tperc);
nkept=sum(~kilme(:));
% Take a look at what is being killed
if xver==1
for lndex=1:min(6,size(vw,3))
clf
spy(kilme(:,:,lndex)); hold on; fridplotw(N,J); axis off
title(num2str(lndex))
pause(1)
end
end
% The overall norm upon inverse transformation is recovered as can be
% checked, but we'll go straight on to identifying the
% scale-dependent information and its inverse transformation
normscsq=0;
for jndex=1:J+1
% Identify where the scales are located over ALL chunks (vwlevs!)
itshere=[vwlevs==jndex];
vwthere=vw(itshere);
% Perform the reconstruction of the model using just this scale
vwnul=vworg;
vwnul(~itshere)=0;
% Now calculate the inverse wavelet transforms, still for straight J
switch wav
case 'D2'
% The 2-tap Haar/Daubechies wavelet transform
vwrec=angularD2WT(vwnul,[J J],'inverse',1);
case 'D4'
% The 4-tap Daubechies wavelet transform
vwrec=angularD4WT(vwnul,[J J],precon,'inverse',1);
case 'D6'
% The 6-tap Daubechies wavelet transform
vwrec=angularD6WT(vwnul,[J J],precon,'inverse',1);
end
% Let us not forget that the norm of the preconditioned transforms
% changes, but when they are subjected to the inverse, the total
% norm aligns itself with the original data, i.e. vstats.normv.
% However, if there was no preconditioning, we can do better:
vwrecnorm=norm(vwrec(:));
if prod(precon)==0
difer(vwrecnorm-norm(vwnul(:)),[],[],NaN)
normscsq=normscsq+vwrecnorm^2;
end
% What is the scale-dependent percentage of the model mean square
% signal strength that is being explained by the wavelet
% coefficients at that scale? Note that the sum of the rms never
% adds up to one hundred percent, and that the mean squared values
% per scale only add to 100 if the transform is NOT preconditioned,
% which provides the most insight. So we deal with the norm squared.
vwstats.normsq{index,jndex}=100*vwrecnorm^2/vstats.normv^2;
% Quick plot?
if xver==1
dax=[];
clf; ah=gca;
if ~~panel
% If it was only one panel, refake 3D
fak3=zeros([size(vwrec) 6]);
fak3(:,:,panel)=vwrec;
vwrec=fak3;
end
[cb,xcb,pgw]=quickplot(N,J,vwrec,depkm(index),dax);
for ons=1:6; delete(cat(1,pgw{ons}{:})); end
axes(ah); plotcont([],[],9)
% Also try this and make sure that it looks nice:
% plotoncube(vwrec,'2D',1,[],[],[],dax,[],0);
% plotcont([],[],9)
% Also try this and make sure that it looks nice:
% plotoncube(vwrec,'3D',1,[],[],[],dax,[],0);
% shading flat; axis image; hold on; plotcont([],[],3)
end
% Make the diagnostics vector, row depth column scale
vwstats.percts{index,jndex}=prctile(vwthere,percs);
vwstats.mjuvar{index,jndex}=[mean(vwthere) var(vwthere)];
% Keep the information in the array for good measure
if jndex==1
vwstats.deptkm{index} =depkm(index);
end
if index==1
vwstats.totnum{ jndex}=sum(itshere(:));
end
% If you threshold globally, what is the scale-dependent percentage
% make up as a function of depth, out of the global number retained
vwstats.tcount{index,jndex}=100*sum(~kilme(itshere))/nkept;
end % End loop over the scales
% If not preconditioned, the individual scales are norm-preserving
if prod(precon)==0
difer(normscsq-vstats.normv^2,7,[],NaN)
% Should perhaps report on how bad it gets - it's slight
% But sure, this check gets done in the main body
end
% Also give the summary statistics for all of the levels
vwstats.totnum{ J+1+1}=prod(size(vw));
vwstats.percts{index,J+1+1}=prctile(vw(:),percs);
vwstats.mjuvar{index,J+1+1}=[mean(vw(:)) var(vw(:))];
vwstats.tcount{index,J+1+1}=100;
% End of the extraction of scale-dependent information
disp(sprintf('Finished layer %3.3i of %3.3i',index,ndeps))
end
% End of the loop over the layers, now save the results
save(fname2,'vwstats','depkm','ndeps','percs','gnorjr','J','fs',...
'xlstring1','panel','wav','vw')
end
% End of the if that questions if calculations are needed
% Check the size of the decomposition which shouldn't have budged
difer(sum([vwstats.totnum{1:J+1}])-vwstats.totnum{J+2},[],[],NaN)
% Check that the depths are the same; keep them in the struct though
difer([vwstats.deptkm{:}]-depkm(:)',[],[],NaN)
% Check that the proportions of the unthresholded coefficients adds up
difer(sum(reshape([vwstats.tcount{:,1:J+1}],ndeps,[]),2)...
-[vwstats.tcount{:,J+1+1}]',[],[],NaN)
% What do the model norms add up to, which isn't one hundred?
% This is NOT the partial correlation coefficient, which would remove
% the effect of the other variables...
% http://faculty.vassar.edu/lowry/ch3a.html
addup=sum(reshape([vwstats.normsq{:,1:J+1}],ndeps,[]),2);
% This should be ABOUT hundred when ALL panels are considered as we are
% comparing with the norm of ALL panels. If it's just ONE panel this is
% the much more variable percentage of the contribution of that panel
% to the overal structure
if panel==0
disp(sprintf('Norm squared percentages add up to %6.2f',...
mean(addup)))
else
disp(sprintf('Panel %i norm squared percentages add up to %6.2f',...
panel,mean(addup)))
end
% Only make the figure if there is no output
if ~nargout
% And now make the figure
% The scale colors
cols={'r','g','b','k','y',grey};
% Which percentages will be PLOTTED
percp=[85 100];
[~,perci]=intersect(percs,percp);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clf ; clear p
ytix=[0 410 660 1000 2000 2899];
ytil={'0' '410' '660' '1000' '2000' 'CMB'};
[ah,ha]=krijetem(subnum(1,2));
set(ah,'FontSize',fs)
axes(ah(1))
% Shade the region which is the [variable] 85th to 100th percentile of
% the entire set considered to provide a background for the percentiles
% within the scales
allpercs=cat(1,vwstats.percts{:,J+1+1});
lft=allpercs(:,1);
rgt=allpercs(:,end);
% Make sure it goes beyond the visible panel
xtra=0.1;
patchdep=[ytix(1)-xtra ; depkm ; ytix(end)+xtra];
patchlft=[lft(1) ; lft ; lft(end)];
patchrgt=[rgt(1) ; rgt ; rgt(end)];
pp=patch([patchlft ; flipud(patchrgt)],...
[patchdep ; flipud(patchdep)],grey);
delete(pp)
hold on
% Now plot the curves for the individual scales
for jndex=1:J+1
% The various percentiles
allpercs=cat(1,vwstats.percts{:,jndex});
for pndex=1:length(percp)
p(pndex,jndex)=plot(allpercs(:,perci(pndex)),depkm,...
'Color',cols{jndex});
end
legs{jndex}=sprintf('wavs %i',jndex);
end
% xl=xlim; xlim([-1 xl(2)]); xlim([-1 25]);
xl=xlim; xlim([-1 xl(2)]);
if gnorjr==1
xlim([-1 40]);
elseif gnorjr==2
xlim([-1 80]);
end
g{1}=plot(xlim,[ytix(2:end-1)' ytix(2:end-1)'],'k:');
% Delete all but the 100th percentiles of the scales but keep all
% percentiles of the total set
set(p,'linew',1)
hold off; delete(p(1:end-1,1:end))
xl(1)=xlabel(xlstring1);
yl(1)=ylabel('depth (km)');
box on
leg(1)=legend(p(2,:),legs,'Location','SouthEast');
axes(ah(2))
for jndex=1:J+1
% The various percentiles
alltcount=cat(1,vwstats.tcount{:,jndex});
% Nope - the various rms proportions
alltcount=cat(1,vwstats.normsq{:,jndex});
p(pndex+1,jndex)=plot(alltcount,depkm,'Color',cols{jndex});
hold on
legs{jndex}=sprintf('scale %i',jndex);
end
% xl=xlim; xlim([0 xl(2)]); xlim([-2 50])
xl=xlim; xlim([0 xl(2)]); xlim([-2 100])
if ~~panel
xlim([-2 30])
end
set(p(pndex+1,:),'linew',1)
g{2}=plot(xlim,[ytix(2:end-1)' ytix(2:end-1)'],'k:');
hold off
% delete(p(end,end))
% xlstring2=sprintf('%s contribution after %i%s thresholding',...
% '%',tperc,'%');
xlstring2=sprintf('%s contribution to l2 model norm','\%');
xlstring2='\textsf{contribution to $\ell_2$ model norm}';
xl(2)=xlabel(xlstring2);
set(xl(2),'Interpreter','LaTeX','FontSize',fs+1)
if ~~panel
% Remember the reordering by the others
pv=[5 4 6 2 3 1];
legs=sprintf('chunk %i',pv(panel));
end
leg(2)=legend(legs,'Location','SouthEast');
set(ah,'ydir','rev')
set(ah,'ytick',ytix,'yticklabel',ytil,'ylim',minmax(ytix))
if ~~panel
set(ah(2),'xtick',[0:10:30])
else
set(ah(2),'xtick',[0:25:100])
end
% Put on the letter labels
[bh,th]=label(ha,'ur',10,2*[gnorjr==2]);
nolabels(ah(2),2)
longticks(ah,2)
fig2print(gcf,'portrait')
shrink(ah,1.25,1)
serre(ah,0.75,'across')
movev(bh,2)
movev(leg(1),.1)
% Next line only for last modification
movev(leg(1),.1)
% Next line only for last modification
movev(leg(2),.15)
% Last minute
if ~panel
delete(leg(2))
end
set(findobj('string',sprintf('wavs %i',J+1)),...
'string',sprintf('scals %i',J))
% Identify panel
if ~~panel
wav=sprintf('%s_%i',wav,panel);
end
actprint=1;
if gnorjr==1
figna=figdisp([],sprintf('GN_%s',wav),[],actprint);
elseif gnorjr==2
figna=figdisp([],sprintf('JR_%s',wav),[],actprint);
end
if actprint==1
system(sprintf('epstopdf %s.eps',figna));
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Making sense? Check again
if xver==1
watdepth=ceil(randi(ndeps));
watscale=J+1;
allpercs=cat(1,vwstats.percts{:,watscale});
al=log10(vw(:));
hist(al(~isinf(al)),100)
lk=log10(allpercs(watdepth,perci));
xlim([-10 5])
set(gca,'xtick',lk(~isinf(lk))); longticks
grid on; rottick; shrink(gca,1.35,1.35)
end
% Potential output (it's vWstats!)
% Let the first output be the panel number
varns={panel,depkm,vwstats};
else
% We're doing a single depth in this section and saving the wavelet
% transforms for the next time. Don't forget that this is a recursive
% portion of the algorithm.
if gnorjr==1
% And now define what will come out of the results at the end
fname=fullfile(getenv('IFILES'),'EARTHMODELS','MONTELLI','LORIS',...
sprintf('loris5_GN_%4.4i_%i_%i_%s_%i_%i.mat',...
round(depkm),N,J,wav,precon(1),precon(2)));
elseif gnorjr==2
% And now define what will come out of the results at the end
fname=fullfile(getenv('IFILES'),'EARTHMODELS','RITSEMA','LORIS',...
sprintf('loris5_JR_%4.4i_%i_%i_%s_%i_%i.mat',...
round(depkm),N,J,wav,precon(1),precon(2)));
end
if exist(fname,'file')==2
% Loading the wavelet transformed seismic models
load(fname)
if xver==1
disp(sprintf('Loading %s',fname))
end
else
if gnorjr==1
disp('Reading Montelli model')
% Load the model at a particular depth, faces rearranged and all
v=readGNmodel(depkm);
elseif gnorjr==2
disp('Reading RITSEMA model')
% Load the model at the requested, faces rearranged and all
v=plm2cube(interpJRmodel(depkm));
end
% This should be on pixel centered, non-overlapping, completely covering,
% registration with an even number of points. Right now we have this on
% grid node registration, with an odd number of points. Later we will
% change this, here we will fake this for the moment, to be quick
disp('Temporary faking of the pixel center registration')
v=v(1:2^N,1:2^N,:);
% Save the norm etc, as when preconditioned, it changes
% But remember this is taking ALL panels
vstats.normv=norm(v(:));
vstats.minmx=minmax(v(:));
vstats.meanz=mean(v(:));
vstats.variz=var(v(:));
% Now calculate the wavelet transforms
switch wav
case 'D2'
% The 2-tap Daubechies wavelet transform
vw=angularD2WT(v,[J J],'forward',1);
case 'D4'
% The 4-tap Daubechies wavelet transform
vw=angularD4WT(v,[J J],precon,'forward',1);
case 'D6'
% The 6-tap Daubechies wavelet transform
vw=angularD6WT(v,[J J],precon,'forward',1);
end
% Quick plot?
if xver==1
clf
[cb,xcb]=quickplot(N,J,vw,depkm);
end
% When you're done, save the results
save(fname,'vw','depkm','wav','N','J','precon','vstats')
end
% Potential output (it's vstats!)
varns={vw,depkm,vstats};
end
% Make output
varargout=varns(1:nargout);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [cb,xcb,pgw]=quickplot(N,J,vw,depkm,dax)
% Font size of the label
defval('fs',8)
% Color map and saturation as percentiles
defval('colmap','kelicol');
% Grid information
wg.N=N; wg.J=J;
% Not at ALL the same as using HALVERANGE
colperc=[1 99];
% May go with HALVERANGE after all
defval('dax',round(halverange(vw,75,NaN)));
% Explicit and absolute color limits of the VALUE of the coeffs
defval('dax',prctile(vw(:),colperc));
% The actual plotting
[~,~,~,pgw]=plotoncube(vw,'2D',1,[],[],[],dax,[],0,100,wg);
% Color bar etc
colpos=[0.5616 0.1714+0.025 0.3143 0.0298];
[cb,xcb]=addcb(colpos,dax,dax,colmap,range(dax)/4);
set(cb,'FontSize',fs)
set(xcb,'string',sprintf(...
'wavelet coefficients at %i km',round(depkm)),'FontSize',fs)