--- a/antsnc.pl
+++ b/antsnc.pl
@@ -1,9 +1,9 @@
#======================================================================
# A N T S N C . P L
# doc: Mon Jul 17 11:59:37 2006
-# dlm: Fri Jan 15 10:17:51 2016
+# dlm: Mon Apr 12 06:32:43 2021
# (c) 2006 A.M. Thurnherr
-# uE-Info: 25 56 NIL 0 0 72 2 2 4 NIL ofnI
+# uE-Info: 199 0 NIL 0 0 72 2 2 4 NIL ofnI
#======================================================================
# ANTS netcdf library
@@ -48,12 +48,12 @@
{
my($tp) = @_;
- return 'byte' if ($tp == NetCDF::BYTE);
- return 'char' if ($tp == NetCDF::CHAR);
- return 'short' if ($tp == NetCDF::SHORT);
- return 'long' if ($tp == NetCDF::LONG);
- return 'float' if ($tp == NetCDF::FLOAT);
- return 'double' if ($tp == NetCDF::DOUBLE);
+ return 'byte' if ($tp == NetCDF::constant(BYTE,0));
+ return 'char' if ($tp == NetCDF::constant(CHAR,0));
+ return 'short' if ($tp == NetCDF::constant(SHORT,0));
+ return 'long' if ($tp == NetCDF::constant(LONG,0));
+ return 'float' if ($tp == NetCDF::constant(FLOAT,0));
+ return 'double' if ($tp == NetCDF::constant(DOUBLE,0));
croak("$0: unknown NetCDF type #$tp\n");
}
@@ -61,12 +61,12 @@
{
my($tn) = lc($_[0]);
- return NetCDF::BYTE if ($tn eq 'byte');
- return NetCDF::CHAR if ($tn eq 'char');
- return NetCDF::SHORT if ($tn eq 'short');
- return NetCDF::LONG if ($tn eq 'long');
- return NetCDF::FLOAT if ($tn eq 'float');
- return NetCDF::DOUBLE if ($tn eq 'double');
+ return NetCDF::constant(BYTE,0) if ($tn eq 'byte');
+ return NetCDF::constant(CHAR,0) if ($tn eq 'char');
+ return NetCDF::constant(SHORT,0) if ($tn eq 'short');
+ return NetCDF::constant(LONG,0) if ($tn eq 'long');
+ return NetCDF::constant(FLOAT,0) if ($tn eq 'float');
+ return NetCDF::constant(DOUBLE,0) if ($tn eq 'double');
croak("$0: unknown NetCDF type <$tn>\n");
}
@@ -78,11 +78,11 @@
{
my($tp) = @_;
- return 1 if ($tp == NetCDF::BYTE);
- return 1 if ($tp == NetCDF::SHORT);
- return 1 if ($tp == NetCDF::LONG);
- return 1 if ($tp == NetCDF::FLOAT);
- return 1 if ($tp == NetCDF::DOUBLE);
+ return 1 if ($tp == NetCDF::constant(BYTE,0));
+ return 1 if ($tp == NetCDF::constant(SHORT,0));
+ return 1 if ($tp == NetCDF::constant(LONG,0));
+ return 1 if ($tp == NetCDF::constant(FLOAT,0));
+ return 1 if ($tp == NetCDF::constant(DOUBLE,0));
return 0;
}
@@ -92,7 +92,7 @@
sub NC_isChar($)
{
- return $_[0] == NetCDF::CHAR;
+ return $_[0] == NetCDF::constant(CHAR,0);
}
#-----------------------------------
@@ -154,15 +154,15 @@
my($fn) = @_;
my(%NC);
- $NC{id} = NetCDF::open($ARGV[0],NetCDF::NOWRITE); # open
+ $NC{id} = NetCDF::ncopen($ARGV[0],NetCDF::constant(NOWRITE,0)); # open
my($nd,$nv,$nga,$udi); # get nelts
- NetCDF::inquire($NC{id},$nd,$nv,$nga,$udi);
+ NetCDF::ncinquire($NC{id},$nd,$nv,$nga,$udi);
$NC{unlim_dimId} = $udi;
for (my($d)=0; $d<$nd; $d++) { # dimensions
my($dnm,$ln);
- NetCDF::diminq($NC{id},$d,$dnm,$ln);
+ NetCDF::ncdiminq($NC{id},$d,$dnm,$ln);
$NC{dimName}[$d] = $dnm;
$NC{dimId}{$dnm} = $d;
$NC{dimLen}{$dnm} = $ln;
@@ -171,7 +171,7 @@
for (my($v)=0; $v<$nv; $v++) { # vars & var-attribs
my($vnm,$vtp,$nvd,$nva);
my(@dids) = ();
- NetCDF::varinq($NC{id},$v,$vnm,$vtp,$nvd,\@dids,$nva);
+ NetCDF::ncvarinq($NC{id},$v,$vnm,$vtp,$nvd,\@dids,$nva);
$NC{varName}[$v] = $vnm;
$NC{varId}{$vnm} = $v;
$NC{varType}{$vnm} = $vtp;
@@ -179,15 +179,15 @@
for (my($a)=0; $a<$nva; $a++) { # var-attribs
my($anm,$atp,$aln);
- NetCDF::attname($NC{id},$v,$a,$anm);
+ NetCDF::ncattname($NC{id},$v,$a,$anm);
$NC{varAttrName}{$vnm}[$a] = $anm;
- NetCDF::attinq($NC{id},$v,$anm,$atp,$aln);
+ NetCDF::ncattinq($NC{id},$v,$anm,$atp,$aln);
$NC{varAttrType}{$vnm}{$anm} = $atp;
$NC{varAttrLen}{$vnm}{$anm} = $aln;
- if ($atp == NetCDF::BYTE || $atp == NetCDF::CHAR || $aln == 1) {
+ if ($atp == NetCDF::constant(BYTE,0) || $atp == NetCDF::constant(CHAR,0) || $aln == 1) {
my($val) = "";
- NetCDF::attget($NC{id},$v,$anm,\$val);
- $val =~ s{\0+$}{} if ($atp == NetCDF::CHAR); # trailing \0
+ NetCDF::ncattget($NC{id},$v,$anm,\$val);
+ $val =~ s{\0+$}{} if ($atp == NetCDF::constant(CHAR,0)); # trailing \0
$NC{varAttr}{$vnm}{$anm} = $val;
}
}
@@ -195,15 +195,15 @@
for (my($a)=0; $a<$nga; $a++) { # global attribs
my($anm,$atp,$aln);
- NetCDF::attname($NC{id},NetCDF::GLOBAL,$a,$anm);
+ NetCDF::ncattname($NC{id},NetCDF::constant(GLOBAL,0),$a,$anm);
$NC{attrName}[$a] = $anm;
- NetCDF::attinq($NC{id},NetCDF::GLOBAL,$anm,$atp,$aln);
+ NetCDF::ncattinq($NC{id},NetCDF::constant(GLOBAL,0),$anm,$atp,$aln);
$NC{attrType}{$anm} = $atp;
$NC{attrLen}{$anm} = $aln;
- if ($atp == NetCDF::BYTE || $atp == NetCDF::CHAR || $aln == 1) {
+ if ($atp == NetCDF::constant(BYTE,0) || $atp == NetCDF::constant(CHAR,0) || $aln == 1) {
my($val) = "";
- NetCDF::attget($NC{id},NetCDF::GLOBAL,$anm,\$val);
- $val =~ s{\0+$}{} if ($atp == NetCDF::CHAR);
+ NetCDF::ncattget($NC{id},NetCDF::constant(GLOBAL,0),$anm,\$val);
+ $val =~ s{\0+$}{} if ($atp == NetCDF::constant(CHAR,0));
$NC{attr}{$anm} = $val;
}
}
@@ -235,22 +235,22 @@
my($fn,$abscissa,$suppress_params) = @_;
my(%attrDone,@slDim,@NCtype);
- my($ncId) = NetCDF::create($fn,NetCDF::CLOBBER);
- NetCDF::setfill($ncId,NetCDF::NOFILL); # NetCDF library bug
+ my($ncId) = NetCDF::nccreate($fn,NetCDF::constant(CLOBBER,0));
+ NetCDF::ncsetfill($ncId,NetCDF::constant(NOFILL,0)); # NetCDF library bug
# DIMENSIONS
- my($aid) = NetCDF::dimdef($ncId,$abscissa,NetCDF::UNLIMITED);
+ my($aid) = NetCDF::ncdimdef($ncId,$abscissa,NetCDF::constant(UNLIMITED,0));
for (my($f)=0; $f<=$#antsLayout; $f++) { # types
my($tpa) = $antsLayout[$f] . ':NC_type';
my($sl) = ($P{$tpa} =~ m{^string(\d+)$});
if ($sl > 0) { # string
- $slDim[$f] = NetCDF::dimdef($ncId,"$antsLayout[$f]:strlen",$sl);
- $NCtype[$f] = NetCDF::CHAR;
+ $slDim[$f] = NetCDF::ncdimdef($ncId,"$antsLayout[$f]:strlen",$sl);
+ $NCtype[$f] = NetCDF::constant(CHAR,0);
} elsif (defined($P{$tpa})) { # custom
$NCtype[$f] = NC_type($P{$tpa});
} else { # default
- $NCtype[$f] = NetCDF::DOUBLE;
+ $NCtype[$f] = NetCDF::constant(DOUBLE,0);
}
# printf(STDERR "type %s set to %s\n",$antsLayout[$f],NC_typeName($NCtype[$f]));
undef($P{$tpa}); # do not add to ATTRIBs
@@ -259,9 +259,9 @@
for (my($f)=0; $f<=$#antsLayout; $f++) { # VARIABLES
my($vid);
if (defined($slDim[$f])) {
- $vid = NetCDF::vardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid,$slDim[$f]]);
+ $vid = NetCDF::ncvardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid,$slDim[$f]]);
} else {
- $vid = NetCDF::vardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid]);
+ $vid = NetCDF::ncvardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid]);
}
croak("$0: varid != fnr (implementation restriction)")
unless ($vid == $f);
@@ -271,9 +271,9 @@
next unless ($var eq $antsLayout[$f]);
$attrDone{$anm} = 1; # mark
if (numberp($P{$anm}) || lc($P{$anm}) eq nan) {
- NetCDF::attput($ncId,$f,$attr,NetCDF::DOUBLE,$P{$anm});
+ NetCDF::ncattput($ncId,$f,$attr,NetCDF::constant(DOUBLE,0),$P{$anm});
} else {
- NetCDF::attput($ncId,$f,$attr,NetCDF::CHAR,$P{$anm});
+ NetCDF::ncattput($ncId,$f,$attr,NetCDF::constant(CHAR,0),$P{$anm});
}
}
}
@@ -287,14 +287,14 @@
$anm eq 'RECNO' || $anm eq 'LINENO');
next if $attrDone{$anm};
if (numberp($P{$anm}) || lc($P{$anm}) eq nan) {
- NetCDF::attput($ncId,NetCDF::GLOBAL,$anm,NetCDF::DOUBLE,$P{$anm});
+ NetCDF::ncattput($ncId,NetCDF::constant(GLOBAL,0),$anm,NetCDF::constant(DOUBLE,0),$P{$anm});
} else {
- NetCDF::attput($ncId,NetCDF::GLOBAL,$anm,NetCDF::CHAR,$P{$anm});
+ NetCDF::ncattput($ncId,NetCDF::constant(GLOBAL,0),$anm,NetCDF::constant(CHAR,0),$P{$anm});
}
}
}
- NetCDF::endef($ncId);
+ NetCDF::ncendef($ncId);
return $ncId;
}
new file mode 100644
--- /dev/null
+++ b/antsnc.pl.old
@@ -0,0 +1,302 @@
+#======================================================================
+# A N T S N C . P L
+# doc: Mon Jul 17 11:59:37 2006
+# dlm: Fri Jan 15 10:17:51 2016
+# (c) 2006 A.M. Thurnherr
+# uE-Info: 25 56 NIL 0 0 72 2 2 4 NIL ofnI
+#======================================================================
+
+# ANTS netcdf library
+
+# HISTORY:
+# Jul 17, 2006: - created
+# Jul 21, 2006: - documented
+# - added NC-encoding routines
+# Jul 22: 2006: - BUG: pseudo %PARAMs were written as well
+# - BUG: var ATTRs were not enconded correctly
+# - added type support
+# Jul 23, 2006: - improved type magic
+# Sep 1, 2006: - BUG: removing trainling 0s had not worked
+# Sep 23, 2006: - fiddled
+# Jul 11, 2008: - adapted to new pseudo %PARAMs
+# Jul 16, 2008: - remove \0s from strings in NC_stringify
+# Mar 20, 2008: - added progress output to NC_stringify
+# Jul 21, 2009: - allowed for suppression of %PARAMs
+# Jan 15, 2016: - BUG: %DEPS pseudo-%PARAM was encoded
+
+# NOTES:
+# - multi-valued attribs are not loaded by getInfo()
+# - spaces in NC strings are replaced by underscores
+# - data filling is disabled, because of a bug in the NetCDF library
+
+# NetCDF Library Bug:
+# The library appears to have incorrect default _FillValue types for
+# integer data types. The error appears if the "setfill" line is commented
+# out and the following command is run:
+# listNC -ct dbk100.nc | NCode -o TEMP.nc time
+# NB: The error occurs when the 1st variable value is written, NOT when
+# the first Q_time value is written. However, when all the Q_ fields
+# are ommitted, the error disappears.
+
+use NetCDF;
+
+#----------------------------------
+# string representation of NC types
+#----------------------------------
+
+sub NC_typeName($)
+{
+ my($tp) = @_;
+
+ return 'byte' if ($tp == NetCDF::BYTE);
+ return 'char' if ($tp == NetCDF::CHAR);
+ return 'short' if ($tp == NetCDF::SHORT);
+ return 'long' if ($tp == NetCDF::LONG);
+ return 'float' if ($tp == NetCDF::FLOAT);
+ return 'double' if ($tp == NetCDF::DOUBLE);
+ croak("$0: unknown NetCDF type #$tp\n");
+}
+
+sub NC_type($)
+{
+ my($tn) = lc($_[0]);
+
+ return NetCDF::BYTE if ($tn eq 'byte');
+ return NetCDF::CHAR if ($tn eq 'char');
+ return NetCDF::SHORT if ($tn eq 'short');
+ return NetCDF::LONG if ($tn eq 'long');
+ return NetCDF::FLOAT if ($tn eq 'float');
+ return NetCDF::DOUBLE if ($tn eq 'double');
+ croak("$0: unknown NetCDF type <$tn>\n");
+}
+
+#--------------------------------------
+# test whether given NC type is numeric
+#--------------------------------------
+
+sub NC_isNumeric($)
+{
+ my($tp) = @_;
+
+ return 1 if ($tp == NetCDF::BYTE);
+ return 1 if ($tp == NetCDF::SHORT);
+ return 1 if ($tp == NetCDF::LONG);
+ return 1 if ($tp == NetCDF::FLOAT);
+ return 1 if ($tp == NetCDF::DOUBLE);
+ return 0;
+}
+
+#----------------------------------------
+# test whether given NC type is character
+#----------------------------------------
+
+sub NC_isChar($)
+{
+ return $_[0] == NetCDF::CHAR;
+}
+
+#-----------------------------------
+# convert character- to string array
+#-----------------------------------
+
+sub NC_stringify($@)
+{
+ my($len,@chars) = @_;
+ my(@strings);
+ my($nStrings) = @chars/$len;
+
+ print(STDERR "$0: extracting $nStrings strings")
+ if ($nStrings > 1000);
+
+ while (@chars) {
+ print(STDERR ".") if ($nStrings>1000 && $n++%1000 == 0);
+ push(@strings,pack("c$len",@chars));
+ $strings[$#strings] =~ s/ /_/g;
+ $strings[$#strings] =~ s/\0//g;
+ splice(@chars,0,$len);
+ }
+ print(STDERR "\n") if ($nStrings > 1000);
+ return @strings;
+}
+
+#----------------------------------------------------------------------
+# open netcdf file and read (most) metadata into hash
+#
+# INPUT:
+# <filename>
+#
+# OUTPUT:
+# $NC{id} netcdf id
+#
+# @NC{attrName}[] names of global attrs
+# %NC{AttrType}{$aName} types of global attrs
+# %NC{AttrLen}{$aName} # of elts in global attrs
+# %NC{Attr}{$aName} vals of scalar global attrs
+#
+# $NC{unlim_dimId} dim id of unlimited dim
+# @NC{dimName}[$dimId] dim names
+# %NC{dimID}{$dName} dim ids
+# %NC{dimLen}{$dName} # elts in dim
+#
+# @NC{varName}[$varId] var names
+# %NC{varType}{$vName} var types
+# %NC{varId}{$vName} var ids
+# @%NC{varDimIDs}{$vName}[] dims of vars, e.g. u(lon,lat)
+# @%NC{varAttrName}{$vName}[] names of var attrs
+# %%NC{varAttrType}{$vName}{$aName} types of var attrs
+# %%NC{varAttrLen}{$vName}{$aName} # of elts in var attrs
+# %%NC{varAttr}{$vName}{$aName} vals of scalar var attrs
+#
+#----------------------------------------------------------------------
+
+sub NC_readMData($)
+{
+ my($fn) = @_;
+ my(%NC);
+
+ $NC{id} = NetCDF::open($ARGV[0],NetCDF::NOWRITE); # open
+
+ my($nd,$nv,$nga,$udi); # get nelts
+ NetCDF::inquire($NC{id},$nd,$nv,$nga,$udi);
+ $NC{unlim_dimId} = $udi;
+
+ for (my($d)=0; $d<$nd; $d++) { # dimensions
+ my($dnm,$ln);
+ NetCDF::diminq($NC{id},$d,$dnm,$ln);
+ $NC{dimName}[$d] = $dnm;
+ $NC{dimId}{$dnm} = $d;
+ $NC{dimLen}{$dnm} = $ln;
+ }
+
+ for (my($v)=0; $v<$nv; $v++) { # vars & var-attribs
+ my($vnm,$vtp,$nvd,$nva);
+ my(@dids) = ();
+ NetCDF::varinq($NC{id},$v,$vnm,$vtp,$nvd,\@dids,$nva);
+ $NC{varName}[$v] = $vnm;
+ $NC{varId}{$vnm} = $v;
+ $NC{varType}{$vnm} = $vtp;
+ @{$NC{varDimIds}{$vnm}} = @dids[0..$nvd-1];
+
+ for (my($a)=0; $a<$nva; $a++) { # var-attribs
+ my($anm,$atp,$aln);
+ NetCDF::attname($NC{id},$v,$a,$anm);
+ $NC{varAttrName}{$vnm}[$a] = $anm;
+ NetCDF::attinq($NC{id},$v,$anm,$atp,$aln);
+ $NC{varAttrType}{$vnm}{$anm} = $atp;
+ $NC{varAttrLen}{$vnm}{$anm} = $aln;
+ if ($atp == NetCDF::BYTE || $atp == NetCDF::CHAR || $aln == 1) {
+ my($val) = "";
+ NetCDF::attget($NC{id},$v,$anm,\$val);
+ $val =~ s{\0+$}{} if ($atp == NetCDF::CHAR); # trailing \0
+ $NC{varAttr}{$vnm}{$anm} = $val;
+ }
+ }
+ }
+
+ for (my($a)=0; $a<$nga; $a++) { # global attribs
+ my($anm,$atp,$aln);
+ NetCDF::attname($NC{id},NetCDF::GLOBAL,$a,$anm);
+ $NC{attrName}[$a] = $anm;
+ NetCDF::attinq($NC{id},NetCDF::GLOBAL,$anm,$atp,$aln);
+ $NC{attrType}{$anm} = $atp;
+ $NC{attrLen}{$anm} = $aln;
+ if ($atp == NetCDF::BYTE || $atp == NetCDF::CHAR || $aln == 1) {
+ my($val) = "";
+ NetCDF::attget($NC{id},NetCDF::GLOBAL,$anm,\$val);
+ $val =~ s{\0+$}{} if ($atp == NetCDF::CHAR);
+ $NC{attr}{$anm} = $val;
+ }
+ }
+
+ return %NC;
+}
+
+#----------------------------------------------------------------------
+# create new nc file and write metadata
+#
+# INPUT:
+# <filename>
+# <abscissa> name of unlimited dimension
+# <suppress-params> if true, don't write %PARAMs
+#
+# OUTPUT:
+# <netcdf id>
+#
+# NOTES:
+# - netcdf types can be set with %<var>:NC_type to
+# byte, long, short, double
+# - string types are as in old PASCAL convention (e.g. string80)
+# - default type is NetCDF::DOUBLE
+# - %<var>:NC_type are not added to ATTRIBs
+#----------------------------------------------------------------------
+
+sub NC_writeMData($$$)
+{
+ my($fn,$abscissa,$suppress_params) = @_;
+ my(%attrDone,@slDim,@NCtype);
+
+ my($ncId) = NetCDF::create($fn,NetCDF::CLOBBER);
+ NetCDF::setfill($ncId,NetCDF::NOFILL); # NetCDF library bug
+
+ # DIMENSIONS
+ my($aid) = NetCDF::dimdef($ncId,$abscissa,NetCDF::UNLIMITED);
+
+ for (my($f)=0; $f<=$#antsLayout; $f++) { # types
+ my($tpa) = $antsLayout[$f] . ':NC_type';
+ my($sl) = ($P{$tpa} =~ m{^string(\d+)$});
+ if ($sl > 0) { # string
+ $slDim[$f] = NetCDF::dimdef($ncId,"$antsLayout[$f]:strlen",$sl);
+ $NCtype[$f] = NetCDF::CHAR;
+ } elsif (defined($P{$tpa})) { # custom
+ $NCtype[$f] = NC_type($P{$tpa});
+ } else { # default
+ $NCtype[$f] = NetCDF::DOUBLE;
+ }
+# printf(STDERR "type %s set to %s\n",$antsLayout[$f],NC_typeName($NCtype[$f]));
+ undef($P{$tpa}); # do not add to ATTRIBs
+ }
+
+ for (my($f)=0; $f<=$#antsLayout; $f++) { # VARIABLES
+ my($vid);
+ if (defined($slDim[$f])) {
+ $vid = NetCDF::vardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid,$slDim[$f]]);
+ } else {
+ $vid = NetCDF::vardef($ncId,$antsLayout[$f],$NCtype[$f],[$aid]);
+ }
+ croak("$0: varid != fnr (implementation restriction)")
+ unless ($vid == $f);
+ foreach my $anm (keys(%P)) { # variable attributes
+ next unless defined($P{$anm});
+ my($var,$attr) = ($anm =~ m{([^:]+):(.*)});
+ next unless ($var eq $antsLayout[$f]);
+ $attrDone{$anm} = 1; # mark
+ if (numberp($P{$anm}) || lc($P{$anm}) eq nan) {
+ NetCDF::attput($ncId,$f,$attr,NetCDF::DOUBLE,$P{$anm});
+ } else {
+ NetCDF::attput($ncId,$f,$attr,NetCDF::CHAR,$P{$anm});
+ }
+ }
+ }
+
+ unless ($suppress_params) {
+ foreach my $anm (keys(%P)) { # GLOBAL ATTRIBUTES
+ next unless defined($P{$anm});
+ next if ($anm eq 'FILENAME' || $anm eq 'DIRNAME' || # skip pseudo
+ $anm eq 'BASENAME' || $anm eq 'EXTN' ||
+ $anm eq 'PATHNAME' || $anm eq 'DEPS' ||
+ $anm eq 'RECNO' || $anm eq 'LINENO');
+ next if $attrDone{$anm};
+ if (numberp($P{$anm}) || lc($P{$anm}) eq nan) {
+ NetCDF::attput($ncId,NetCDF::GLOBAL,$anm,NetCDF::DOUBLE,$P{$anm});
+ } else {
+ NetCDF::attput($ncId,NetCDF::GLOBAL,$anm,NetCDF::CHAR,$P{$anm});
+ }
+ }
+ }
+
+ NetCDF::endef($ncId);
+
+ return $ncId;
+}
+
+1;