-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathold.html
1671 lines (1659 loc) · 81.5 KB
/
old.html
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
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.23">
<meta name="author" content="2024-09-12">
<title>DMR++ - OPeNDAP</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
</head>
<body class="article">
<div id="header">
<h1>DMR++ - OPeNDAP</h1>
<div class="details">
<span id="author" class="author">2024-09-12</span><br>
</div>
<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_introduction">1. Introduction</a></li>
<li><a href="#_how_does_it_work">2. How Does It Work?</a></li>
<li><a href="#_supported_data_formats">3. Supported Data Formats</a>
<ul class="sectlevel2">
<li><a href="#_hdf5">3.1. hdf5</a></li>
<li><a href="#_hdf4hdf4_eos2">3.2. <em>HDF4</em>/<em>HDF4-EOS2</em></a></li>
</ul>
</li>
<li><a href="#_building_dmr_files_for_hdf4_and_hdf4_eos2_experimental">4. Building DMR++ files for HDF4 and HDF4-EOS2 (experimental)</a>
<ul class="sectlevel2">
<li><a href="#_using_get_dmrpp_h4">4.1. Using get_dmrpp_h4</a></li>
</ul>
</li>
<li><a href="#_building_dmr_files_for_hdf5netcdf4_with_get_dmrpp">5. Building DMR++ files for HDF5/NetCDF4 with <em>get_dmrpp</em></a>
<ul class="sectlevel2">
<li><a href="#_using_get_dmrpp">5.1. Using <em>get_dmrpp</em></a></li>
<li><a href="#_command_line_options">5.2. Command line options</a></li>
<li><a href="#_hdf5_handler_configuration">5.3. <em>hdf5_handler</em> Configuration</a></li>
<li><a href="#_the_h5_enablecf_option">5.4. The <em>H5.EnableCF</em> option</a></li>
<li><a href="#_missing_data_the_cf_conventions_and_hdf5">5.5. Missing data, the CF conventions and <em>hdf5</em></a></li>
</ul>
</li>
<li><a href="#_hyrax_serving_data_using_dmr_files">6. Hyrax - Serving data using DMR++ files</a>
<ul class="sectlevel2">
<li><a href="#_using_dmr_with_https_urls">6.1. Using DMR++ with http(s) URLs</a></li>
<li><a href="#_using_dmr_with_file_urls">6.2. Using DMR++ with file URLs</a></li>
<li><a href="#_using_dmr_with_the_template_string_nasa">6.3. Using DMR++ with the template string (NASA).</a></li>
</ul>
</li>
<li><a href="#_recipe_building_and_testing_dmr_files">7. Recipe: Building and testing DMR++ files</a>
<ul class="sectlevel2">
<li><a href="#_recipe_building_dmr_files_using_a_hyrax_docker_container">7.1. Recipe: Building DMR++ files using a Hyrax docker container</a></li>
<li><a href="#_testing_and_qualifying_dmr_files">7.2. Testing and qualifying DMR++ files</a></li>
<li><a href="#_flattening_groups">7.3. Flattening Groups</a></li>
<li><a href="#_dap_representations">7.4. DAP representations</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="_introduction">1. Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The DMR++ is a fast and flexible way to serve data stored in S3.
The DMR++ encodes the location of the data content residing in a binary data file/object (e.g., an <a href="https://docs.hdfgroup.org/hdf5/v1_14/_intro_h_d_f5.html">hdf5</a> file) so that it can be directly accessed, without the need for an intermediate library API, by using the file with the location information. The binary data objects may be on a local filesystem, or they may reside across the web in something like an S3 bucket.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_how_does_it_work">2. How Does It Work?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The DMR++ ingest software reads a data file (see <a href="#note1">this note</a>) and builds a document that holds all of the file’s metadata (the names and types of all of the variables along with any other information bound to those variables). This information is stored in a document we call the Dataset Metadata Response (DMR). The DMR++ adds some extra information to this (that’s the ++ part) about where each variable can be found and how to decode those values. The DMR++ is simply an special annotated DMR document.</p>
</div>
<div class="paragraph">
<p>This effectively decouples the annotated DMR ( DMR++ ) from the location of the granule file itself. Since DMR++ files are typically significantly smaller than the source data granules they represent, they can be stored and moved for less expense. They also enable reading all of the file’s metadata in one operation instead of the iterative process that many APIs require.</p>
</div>
<div class="paragraph">
<p>If the DMR++ contains references to the source granules location on the web, the location of the the DMR++ file itself does not matter.</p>
</div>
<div class="paragraph">
<p>Software that understands the DMR++ content can directly access the data values held in the source granule file, and it can do so without having to retrieve the entire file and work on it locally, even when the file is stored in a Web Object Store like S3.</p>
</div>
<div class="paragraph">
<p>If the granule file contains multiple variables and only a subset of them are needed, the DMR++ enabled software can retrieve just the bytes associated with the desired variables parts.</p>
</div>
<div id="note1" class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The OPeNDAP software currently supports HDF5 and NetCDF4. Other formats can be supported, such as zarr.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_supported_data_formats">3. Supported Data Formats</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The DMR++ software currently works with 'hdf5', 'netcdf-4', and (experimental as of 8/29/24) ''HDF4''/''HDF4-EOS2'' files. (The 'netcdf-4' format is a subset of ''hdf5'' so ''hdf5'' tools are utilized for both.) Other formats like ''zarr'', ''netcdf-3'' are not currently supported by the DMR++ software, but support could be added if requested. However, an external group working on the Python Kerchunk software has developed <a href="https://virtualizarr.readthedocs.io/en/latest/">VirtualiZarr</a> which can parse either Kerchunk or DMR++ documents and read from data those describe using the Zarr API.</p>
</div>
<div class="sect2">
<h3 id="_hdf5">3.1. hdf5</h3>
<div class="paragraph">
<p>The 'hdf5' data format is quite complex and many of the options and edge cases are not currently supported by the DMR++ software.</p>
</div>
<div class="paragraph">
<p>These limitations and how to quickly evaluate an ''hdf5'' or ''netcdf-4'' file for use with the DMR++ software are explained below.</p>
</div>
<div class="sect3">
<h4 id="_hdf5_filters">3.1.1. ''hdf5'' filters</h4>
<div class="paragraph">
<p>The ''hdf5'' format has several filter/compression options used for storing data values.
The DMR++ software currently supports data that utilize the H5Z_FILTER_DEFLATE, H5Z_FILTER_SHUFFLE, and H5Z_FILTER_FLETCHER32 filters.
<a href="https://support.hdfgroup.org/HDF5/doc/RM/RM_H5Z.html">You can find more on hdf5 filters here.</a></p>
</div>
</div>
<div class="sect3">
<h4 id="_hdf5_storage_layouts">3.1.2. ''hdf5'' storage layouts</h4>
<div class="paragraph">
<p>The ''hdf5'' format also uses a number of "storage layouts" that describe various structural organizations of the data values associated with a variable in the granule file.
The DMR++ software currently supports data that utilize the H5D_COMPACT, H5D_CHUNKED, and H5D_CONTIGUOUS storage layouts. These are all of the storage layouts defined by the ''hdf5'' library, but others can be added.
<a href="https://support.hdfgroup.org/HDF5/doc1.6/Datasets.html">You can find more on hdf5 storage layouts here.</a></p>
</div>
</div>
<div class="sect3">
<h4 id="_is_my_hdf5_or_netcdf_4_file_suitable_for_dmr">3.1.3. Is my ''hdf5'' or ''netcdf-4'' file suitable for DMR++ ?</h4>
<div class="paragraph">
<p>To determine the ''hdf5'' filters, storage layouts, and chunking scheme used in an ''hdf5'' or ''netcdf-4'' file you can use the command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>h5dump -H -p <filename></pre>
</div>
</div>
<div class="paragraph">
<p>To get a human readable assessment of the file that will show the storage layouts, chunking structure, and the filters needed for each variable (aka DATASET in the <em>hdf5</em> vocabulary) <a href="https://support.hdfgroup.org/HDF5/doc/RM/Tools.html#Tools-Dump">h5dump info can be found here.</a></p>
</div>
<div class="paragraph">
<p><em>h5dump example output</em>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ h5dump -H -p chunked_gzipped_fourD.h5
HDF5 "chunked_gzipped_fourD.h5" {
GROUP "/" {
DATASET "d_16_gzipped_chunks" {
DATATYPE H5T_IEEE_F32LE
DATASPACE SIMPLE { ( 40, 40, 40, 40 ) / ( 40, 40, 40, 40 ) }
STORAGE_LAYOUT {
CHUNKED ( 20, 20, 20, 20 )
SIZE 2863311 (3.576:1 COMPRESSION)
}
FILTERS {
COMPRESSION DEFLATE { LEVEL 6 }
}
FILLVALUE {
FILL_TIME H5D_FILL_TIME_ALLOC
VALUE H5D_FILL_VALUE_DEFAULT
}
ALLOCATION_TIME {
H5D_ALLOC_TIME_INCR
}
}
}
}</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_is_my_netcdf_file_netcdf_3_or_netcdf_4">3.1.4. Is my netcdf file <em>netcdf-3</em> or <em>netcdf-4</em>?</h4>
<div class="paragraph">
<p>A file with the suffix <em>.nc4</em> is recognized as a <em>netcdf-4</em> file. However, the file suffix <em>.nc</em> can be the commonly used naming convention for both <em>netcdf-3</em> and <em>netcdf-4</em> files. You can use the command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>ncdump -k <filename></pre>
</div>
</div>
<div class="paragraph">
<p>to determine if a <em>netcdf</em> file is either classic <em>netcdf-3</em> (classic) or <em>netcdf-4</em> (netCDF-4). <a href="http://www.bic.mni.mcgill.ca/users/sean/Docs/netcdf/guide.txn_79.html">You can learn more in the NetCDF documentation here.</a></p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The <em>netcdf</em> library must be installed on the system upon which the command is issued.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_hdf4hdf4_eos2">3.2. <em>HDF4</em>/<em>HDF4-EOS2</em></h3>
<div class="paragraph">
<p>This is a complicated case, and its support as of 8/29/24 is still considered experimental. The HDF4 data model is quite complex, more so than the HDF5 model, and we focusing on complete support for those features used by NASA. To this end, we are also working on support for HDF4-EOS2, data files that can only be read correctly with the HDF4-EOS2 library. The main distinction of that API is the treatment of values for the Domain variables for Latitude and Longitude. Our support handles the HDF4-EOS Grid data type and using DMR++ the Latitude and Longitude values appear as users expect, although some aspects of this are ongoing. We do not yet support the HDF4-EOS2 Swath data type.</p>
</div>
<div class="paragraph">
<p>Se the section below for information on the tool for building DMR++ files for HDF4 and HDF4-EOS2 data files.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_building_dmr_files_for_hdf4_and_hdf4_eos2_experimental">4. Building DMR++ files for HDF4 and HDF4-EOS2 (experimental)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The HDF4 and HDF4-EOS2 (hereafter just HDF4) DMR++ document builder is currently available in the docker container we build for <a href="https://opendap.github.io/hyrax_guide/Master_Hyrax_Guide.html">hyrax</a> server/service. You can get this container from the public Docker Hub repository. You can also get and build the ''Hyrax'' source code, and use the client that way (as part of a source code build) but it’s much more complex than getting the Docker container. In addition, the Docker container includes a server that can test the DMR++ documents that are built and can even show you how the files would look when served without using the DMR++ .</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The followingg commands should be consider still experimental and subject to some change. Modify it to suit your own needs.
</td>
</tr>
</table>
</div>
<div class="sect2">
<h3 id="_using_get_dmrpp_h4">4.1. Using get_dmrpp_h4</h3>
<div class="paragraph">
<p>Make a new directory in a convenient place and copy the HDF4 and/or HDF4-EOS2 files in that directory. Once you have the files in that directory, make an environment variable so it can be referred to easily. From inside the directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>export HDF4_DIR=$(pwd)</pre>
</div>
</div>
<div class="paragraph">
<p>Get the Docker container from Docker Hub using this command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker run -d -h hyrax -p 8080:8080 -v $HDF4_DIR:/usr/share/hyrax --name=hyrax opendap/hyrax:snapshot</pre>
</div>
</div>
<div class="paragraph">
<p>What the options mean:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>-d, --detach Run container in background and print container ID
-h, --hostname Container host name
-p, --publish Publish a container's port(s) to the host
-v, --volume Bind mount a volume
--name Assign a name to the container</pre>
</div>
</div>
<div class="paragraph">
<p>This command will fetch the container <strong>opendap/hyrax:snapshot</strong> from Docker Hub. Thw <em>snapshot</em> is the latest build of the container. It will then <em>run</em> the container and return the container ID. The <em>hyrax</em> server is now running on you computer and can be accessed with a web browser, curl, et cetera. More on that in a bit.</p>
</div>
<div class="paragraph">
<p>The volume mount, from <code>$HDF4_DIR</code> to <code>'/usr/share/hyrax'</code> mounts the current directory of the host computer running the container to the directory <em>/usr/share/hyrax</em> inside the container. That directory is the root of the server’s data tree. This means that the HDF4 files you copied into the <code>HDF4_DIR</code> directory will be accessible by the server running in the container. That will be useful for testing later on.</p>
</div>
<div class="paragraph">
<p>Note: If you want to use a specific container version, just substitute the version info for <em>snapshot.</em></p>
</div>
<div class="paragraph">
<p>Check that the container is running using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre> docker ps</pre>
</div>
</div>
<div class="paragraph">
<p>This will show a somewhat hard-to-read bit of information about all the running Docker container on you host:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2949d4101df4 opendap/hyrax:snapshot "/entrypoint.sh -" 15 seconds ago Up 14 seconds 8009/tcp, 8443/tcp,
10022/tcp, 11002/tcp, 0.0.0.0:8080->8080/tcp hyrax</pre>
</div>
</div>
<div class="paragraph">
<p>If you want to stop the containers, use</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker rm -f <CONTAINER ID></pre>
</div>
</div>
<div class="paragraph">
<p>where the <code><CONTAINER ID></code> for the one we just started and shown in the output of <em>docker ps -a</em> above is <em>2949d4101df4</em>. No need to stop the container now, I’m just pointing out how to do it because it’s often useful.</p>
</div>
<div class="sect3">
<h4 id="_lets_run_the_dmr_builder">4.1.1. Lets run the DMR++ builder</h4>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
At the end of this, I’ll include a shell script that takes away many of these steps, but the script obscures some aspects of the command that you might want to tweak, so the following shows you all the details. Skip to <strong>Simple shell command</strong> to skip over these details.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Make sure you are in the directory with the HDF4 files for these steps.</p>
</div>
<div class="paragraph">
<p>Get the command to return its help information:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker exec -it hyrax get_dmrpp_h4 -h</pre>
</div>
</div>
<div class="paragraph">
<p>will return:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>usage: get_dmrpp_h4 [-h] -i I [-c CONF] [-s] [-u DATA_URL] [-D] [-v]
Build a dmrpp file for an HDF4 file. get_dmrpp_h4 -i h4_file_name. A dmrpp
file that uses the HDF4 file name will be generated.
optional arguments:
...</pre>
</div>
</div>
<div class="paragraph">
<p>Lets build a DMR++ now, by explicitly using the container:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker exec -it hyrax bash</pre>
</div>
</div>
<div class="paragraph">
<p>starts the <em>bash</em> shell in the container, with the current directory as root (/)</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[root@hyrax /]#</pre>
</div>
</div>
<div class="paragraph">
<p>Change to the directory that is the root of the data (you’ll see your HDF4 files in here):</p>
</div>
<div class="listingblock">
<div class="content">
<pre> cd /usr/share/hyrax</pre>
</div>
</div>
<div class="paragraph">
<p>You will see, roughly:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[root@hyrax /]# cd /usr/share/hyrax
[root@hyrax hyrax]# ls
3B42.19980101.00.7.HDF
3B42.19980101.03.7.HDF
3B42.19980101.06.7.HDF
...</pre>
</div>
</div>
<div class="paragraph">
<p>In that directory, use the <em>get_dmrpp_h4</em> command to build a DMR++ document for one of the files:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[root@hyrax hyrax]# get_dmrpp_h4 -i 3B42.20130111.09.7.HDF -u 'file:///usr/share/hyrax/3B42.20130111.09.7.HDF'</pre>
</div>
</div>
<div class="paragraph">
<p>Copy that pattern for whatever file you use. From the <code>/usr/share/hyrax</code> directory, you pass <em>get_dmrpp_h4</em> the name of the file (because it’s local to the current directory) using the <strong>-i</strong> option. The <strong>-u</strong> option tells the command to embed the URL that follows it in the DMR++ . I’ve used a <em>file://</em> URL to the file <em>/usr/share/hyrax/3B42.19980101.00.7.HDF</em>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
In the URL above, three slashes following the colon: two from the way a URL names a protocol and one because the pathname starts at the root directory.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Building the DMR++ and embedding a <em>file://</em> URL will enable testing the DMR++ .</p>
</div>
</div>
<div class="sect3">
<h4 id="_using_the_server_to_examine_data_returned_by_the_dmr">4.1.2. Using the server to examine data returned by the DMR++ </h4>
<div class="paragraph">
<p>Lets look at how the <em>hyrax</em> service will treat that data file using the DMR++ . In a browser, go to <a href="http://localhost:8080/opendap/">http://localhost:8080/opendap/</a></p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/Hyrax-including-new-DMRpp.png" alt="Hyrax including new DMRpp" width="650" height="400">
</div>
<div class="title">Figure 1. Hyrax Catalog view of all files available.</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<em>The server caches data catalog information for 5 minutes (although this can be configured) so new items (e..g., DMR++ documents) may not show up right away. To force the display of a DMR++ that you just created, click on the source data file name and edit the URL so that the suffix <strong>.dmr.html</strong> is replaced by <strong>.dmrpp/dmr</strong> .</em>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Click on the your equivalent of the <strong>3B42.20130111.09.7.HDF</strong> link, subset, download and open in Panoply or the equivalent.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/Hyrax-subsetting.png" alt="Hyrax subsetting" width="650" height="400">
</div>
<div class="title">Figure 2. Page view of the DAP <em>Data Request Form</em> for subsetting the dataset.</div>
</div>
<div class="paragraph">
<p>You can run batch tests in lots of files by building many DMR documents and then asking the server for various responses (_nc4_, _dap_) from the + DMR + and the original file. Those could be compared using various schemes, although in its entirety that is beyond this section’s scope, the command <em>getdap4</em> is also included in the container and could be used to compare <em>dap</em> responses from the data file and the DMR++ document.</p>
</div>
<div class="paragraph">
<p>Below is a comparison of the same underlying data, the left window shows the data returned using the DMR++ , the right shows the data read directly from the file using the server’s builtin HDF4 reader.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/Data-comparison.png" alt="Data comparison" width="650" height="400">
</div>
<div class="title">Figure 3. Comparison of responses from a DMR++ and the native file handler.</div>
</div>
</div>
<div class="sect3">
<h4 id="_simple_shell_command">4.1.3. Simple shell command</h4>
<div class="paragraph">
<p>Here is a simple shell command that you can run on the host computer that will eliminate most of the above.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
''In the spirit of a recipe, I’ll restate the earlier command for starting the docker container with the <strong>get_dmrpp_h4</strong> command and the <strong>hyrax</strong> server.''
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Start the container:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker run -d -h hyrax -p 8080:8080 -v $HDF4_DIR:/usr/share/hyrax --name=hyrax opendap/hyrax:snapshot</pre>
</div>
</div>
<div class="paragraph">
<p>Check if it is running:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>docker ps</pre>
</div>
</div>
<div class="paragraph">
<p>The command, written for the Bourne Shell, is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>#!/bin/sh
#
# usage get_dmrpp_h4.sh <file>
data_root=/usr/share/hyrax
cat <<EOF | docker exec --interactive hyrax sh
cd $data_root
get_dmrpp_h4 -i $1 -u "file://$data_root/$1"
EOF</pre>
</div>
</div>
<div class="paragraph">
<p>Copy that, save it in a file (I named the file <em>get_dmrpp_h4.sh</em>).</p>
</div>
<div class="paragraph">
<p>Run the command on the host (not the docker container) and in the directory with the HDF4 files (you don’t have to do that, but sorting out the details is left as an exercise for the reader. Run the command like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre> ./get_dmrpp_h4.sh AMSR_E_L3_SeaIce25km_V15_20020601.hdf</pre>
</div>
</div>
<div class="paragraph">
<p>The DMR++ will appear when the command completes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>(hyrax500) hyrax_git/HDF4-dir % ls -l
total 1251240
-rw-r--r--@ 1 jimg staff 1250778 Aug 22 22:31 AMSR_E_L2_Land_V09_200206191112_A.hdf
-rw-r--r--@ 1 jimg staff 20746207 Aug 22 22:32 AMSR_E_L3_SeaIce25km_V15_20020601.hdf
-rw-r--r-- 1 jimg staff 3378674 Aug 28 17:37 AMSR_E_L3_SeaIce25km_V15_20020601.hdf.dmrpp</pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_building_dmr_files_for_hdf5netcdf4_with_get_dmrpp">5. Building DMR++ files for HDF5/NetCDF4 with <em>get_dmrpp</em></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The application that builds the DMR++ files is a command line tool called <em>get_dmrpp</em>. It in turn utilizes other executables such as <em>build_dmrpp</em>, <em>reduce_mdf</em>, <em>merge_dmrpp</em> (which rely in turn on the <em>hdf5_handler</em> and the ''hdf5'' library), along with a number of UNIX shell commands.</p>
</div>
<div class="paragraph">
<p>All of these components are install with each recent version of the Hyrax Data Server</p>
</div>
<div class="paragraph">
<p>You can see the <em>get_dmrpp</em> usage statement with the command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>get_dmrpp -h</pre>
</div>
</div>
<div class="sect2">
<h3 id="_using_get_dmrpp">5.1. Using <em>get_dmrpp</em></h3>
<div class="paragraph">
<p>The way that <em>get_dmrpp</em> is invoked controls the way that the data are ultimately represented in the resulting DMR++ file(s).</p>
</div>
<div class="paragraph">
<p>The <em>get_dmrpp</em> application utilizes software from the Hyrax data server to produce the base DMR document which is used to construct the DMR++ file.</p>
</div>
<div class="paragraph">
<p>The Hyrax server has a long list of configuration options, several of which can substantially alter the the structural and semantic representation of the dataset as seen in the DMR++ files generated using these options.</p>
</div>
</div>
<div class="sect2">
<h3 id="_command_line_options">5.2. Command line options</h3>
<div class="paragraph">
<p>The command line switches provide a way to control the output of the tool. In addition to common options like verbose output or testing modes, the tool provides options to build extra (aka 'sidecar') data files that hold information needed for CF compliance if the original HDF5 data files lack that information (see the ''missing data'' section ). In addition, it is often desirable to build DMR++ files before the source data files are uploaded to a cloud store like S3. In this case, the URL to the data may not be known when the DMR++ is built. We support this by using placeholder/template strings in the ''dmr'' and which can then be replaced with the URL at runtime, when the + DMR + file is evaluated. See the '-u' and '-p' options below.</p>
</div>
<div class="sect3">
<h4 id="_inputs">5.2.1. Inputs</h4>
<div class="dlist">
<dl>
<dt class="hdlist1"><strong>-b</strong> </dt>
<dd>
<p>The fully qualified path to the top level data directory. Data files read by <em>get_dmrpp</em> must be in the directory tree rooted at this location and their names expressed as a path relative to this location. The value may not be set to <code>/</code> , or <code>/etc</code>. The default value is <code>/tmp</code> if a value is not provided. All the data files to be processed must be in this directory or one of its subdirectories. If <em>get_dmrpp</em> is being executed from same directory as the data then <code>-b `pwd`</code> or <code>-b .</code> works as well.</p>
</dd>
<dt class="hdlist1"><strong>-u</strong> </dt>
<dd>
<p>This option is used to specify the location of the binary data object. It’s value must be an http, https, or file (file://) URL. This URL will be injected into the DMR++ when it is constructed. If option <code>-u</code> is not used; then the template string <code>OPeNDAP_DMRpp_DATA_ACCESS_URL</code> will be used and the DMR++ will substitute a value at runtime.</p>
</dd>
<dt class="hdlist1"><strong>-c</strong> </dt>