head 1.2; access; symbols; locks wmc:1.2; strict; comment @% @; 1.2 date 2003.10.28.22.27.56; author wmc; state Exp; branches; next 1.1; 1.1 date 2003.10.28.22.27.19; author wmc; state Exp; branches; next ; desc @Version sitting there, 2003/10/28 @ 1.2 log @Better version. I hope. @ text @#!/bin/perl -w # wunconv - re-insert modified pp-fields into unified model ancillary fields # # use: - wunconv.pl ancil-file pp-file output-ancil-file # # diags to: stdout # # method: # 1. read in all of ancillary file (first argument) # 2. read in pp-field(s) (second arg) # 3. diagnostic info to wunconv.info # 4. interpret header (mostly for info + to make sure we know what we're doing) # 5. write pp-headers into lookup tables and data into data block # (check that the headers are the same; warn if not) # 6. write out result to stdout # # reference: # UMDP f3 (format of files), R. S. Bell, v 22 27/1/95 $N_ins=0; $MAX_warn=5; $Verbose=1; $FIXHD10=-1; %FIXHD10=qw(0 single 1 timeseries 2 repeating); $DATE=-1; $ENDDATE=-1; $MakeAncilOcean=0; # Set H[1] to 2 # Command-line setup eval "\$$1=\$2" while $ARGV[0] =~ /^(\w+)=(.*)/ && shift; if (scalar @@ARGV != 3) { die "use: wunconv.pl ancil-file pp-file output-ancil-file" }; # 1. readin ancil # undef $/; $ANCIL=shift; open(IN,$ANCIL) or die "Failed to open ancillary file <$ANCIL> (first arg)\n"; $IN=; close(IN); $NL=length($IN); # 2. readin pp(s) # $PPF=shift; open(IN,$PPF) or die "Failed to open pp file <$PPF> (second arg)\n"; $PIN=; close(IN); $NLP=length($PIN); # 3. Output # $OUTFILE=shift; if (!$OUTFILE) { die "No output file specified" }; open(OUT,"> $OUTFILE") or die "Can't open output to $OUTFILE"; # 4. Info # @@H=unpack("i256",substr($IN,0,256*4)); if ($Verbose) { if ($H[1] == 1) { $m="Atmos" } elsif ($H[1] == 2) { $m="Ocean" } else { $m="Unknown" }; print "Ancil model type: $m\n"; print "\n\n"; }; if ($Verbose > 1) { for ($I=0; $I<256; $I++) { if ($H[$I] == -32768) { print sprintf("%4d%7s",$I+1,"null") } else { print sprintf("%4d%7d",$I+1,$H[$I]) }; if (($I+1) % 8 == 0) { print "\n" }; } }; if (($H[0] == -32768) or ($H[0] == 15)) { if ($Verbose > 3) { print "H0=15 or null; OK\n" } } else { wwarn("H0 <> 15: $H[0]\n") }; if ($MakeAncilOcean) { $H[1]=2 }; @@INTS=unpack("i*",substr($IN,$H[99]*4-4,$H[100]*4)); $NX=$INTS[5]; $NY=$INTS[6]; # Ancil specific $NF=$INTS[14]*$H[151]; # Ancil specific if ($Verbose > 0) { print "Ty: ",$H[1],"\n"; print "Vn: ",$H[11]/100.,"\n"; print "t0 (start) Y/M/D:H/M/S:D $H[20]/$H[21]/$H[22]:$H[23]/$H[24]/$H[25]:$H[26]\n"; print "t1 (end) Y/M/D:H/M/S:D $H[27]/$H[28]/$H[29]:$H[30]/$H[31]/$H[32]:$H[33]\n"; print "t2 (skip) Y/M/D:H/M/S:D $H[34]/$H[35]/$H[36]:$H[37]/$H[38]/$H[39]:$H[40]\n"; print "Global (0): $H[3], Type (4=ancil): $H[4]\n"; print "Start, len of ints: $H[99],$H[100]\n"; print "We seem to have ${NX}x${NY}x$NF\n"; print "Start (StartI+LenI), len of real: $H[104] (",$H[99]+$H[100],"),$H[105]\n"; print "Start (StartR+lenR), len of Lookup: $H[149] (",$H[104]+$H[105],"), \[$H[150],$H[151]\]\n"; }; if ($Verbose > 1) { print " ints: ",join(",",@@INTS),"\n" }; # Check out various constants... if ($Verbose > 1) { print "Constants: start d1 (d2)\n"; print " Integer: $H[99] $H[100]\n"; print " Real : $H[104] $H[105]\n"; print " LevDepC: $H[109] $H[110] ($H[111])\n"; print " RowDepC: $H[114] $H[115] ($H[116])\n"; print " ColDepC: $H[119] $H[120] ($H[121])\n"; print " FieldsC: $H[124] $H[125] ($H[126])\n"; print " Extra : $H[129] $H[130]\n\n"; }; if ($NF == $H[151]) { if ($Verbose > 2) { print "N Field types matches 2nd dim of lookup; good ($NF)\n" } } else { wwarn("N Field types ($NF) does not match 2nd dim of lookup ($H[151])\n"); }; # Start of data is officially item 160, with dimension 161 # But there may be a connection to start_of_lookup+length_of_lookup (150+151*152) if ($Verbose > 0) { print "Start (StartLookup+lenL), len of data: $H[159] (",$H[149]+$H[150]*$H[151],"),$H[160]\n" }; if ($H[149]+$H[151]*$H[150] < $H[159]) { if ($Verbose > 2) { print "Data starts ($H[159]) after end of lookup ($H[149]+$H[151]*$H[150]=",$H[149]+$H[151]*$H[150],") ... good!\n" } } else { wwarn("Data starts before end of lookup... bad! (probably fatal)\n") }; if ($H[160] == $NX*$NY*$NF) { if ($Verbose > 2) { print "Length of data matches NX*NY*NF; good\n" } } else { warn "Length of data ($H[160]) != NX*NY*NF (",$NX*$NY*$NF,")\n" }; # Grid info (PP) $pbdx=unpack("f",substr($PIN,(46+16)*4,4)); $pbzx=unpack("f",substr($PIN,(46+15)*4,4)); $pbdy=unpack("f",substr($PIN,(46+14)*4,4)); $pbzy=unpack("f",substr($PIN,(46+13)*4,4)); if ($Verbose > 1) { print "PP bdx,y: [$pbdx,$pbdy] bzx,y: [$pbzx,$pbzy]\n" }; # Grid info (ancil) # Check expected pp-length $LREC=$NX*$NY; $PPL=4*(4+64+$LREC); $LREC1=unpack("i",substr($PIN,15*4,4)); $NY1=unpack("i",substr($PIN,18*4,4)); $NX1=unpack("i",substr($PIN,19*4,4)); $PPL1=($LREC1 +64 +4)*4; if ($PPL != $PPL1) { print " these PP-fields are not the same as the ancil. Ah well. $PPL. $PPL1\n" } else { if ($Verbose > 3) { print " these PP-fields are the same as the ancil: good: $PPL\n" } }; $PPL=$PPL1; $LREC=$LREC1; $NX=$NX1; $NY=$NY1; $NPP=$NLP/$PPL; if ($Verbose > 1) { print "Expected pp-field length is: $PPL; that would mean we read in ",$NPP," fields\n" }; # 5. Insert fields # if ($N_ins) { $N=$N_ins } else { $N=$H[151] }; if ($H[151] != $NPP or $H[151] != $N_ins) { if ($Verbose > 1) { print " H151,2: $H[150],$H[151] NPP: $NPP N_ins: $N_ins \n" }; wwarn("I think I read in $NPP fields but I'm inserting $N and the original ancil had $H[151]\n"); if ($Verbose > 0) { print "I'm going to change H[152(151)] (currently $H[151]) to $N (or try to...)\n" }; substr($IN,151*4,4)=pack "i",$N; if ($Verbose > 0) { print "I think I'll change NX ($NX1) and NY ($NY1) too... (to ${NX}x${NY})\n" }; substr($IN,$H[99]*4-4+5*4,4)=pack "i",$NX; substr($IN,$H[99]*4-4+6*4,4)=pack "i",$NY; # Start-of-data seems to pad from end-of-lookup so its at 16385 (and 2^14=16384, by chance). # So rather than just putting our stuff immeadiately after lookup, lets pad too. $OurDataStart=(int(($H[149]+$N*$H[150])/16384)+1)*16384+1; if ($Verbose > 0) { print "I think I'll change 160 (Start of data: $H[159]) and 161 (Dim of data: $H[160]) too... (to: ".($OurDataStart).", ".($N*$LREC).")\n" }; substr($IN,159*4,4)=pack "i",$OurDataStart; substr($IN,160*4,4)=pack "i",$N*$LREC; # Redo this with the new values. @@H=unpack("i256",substr($IN,0,256*4)); }; if ($FIXHD10 != -1) { print "Changing Fixhd(10 (ftn indexing)) from $H[9] ($FIXHD10{$H[9]}) to $FIXHD10 ($FIXHD10{$FIXHD10})\n"; substr($IN,9*4,4)=pack "i",$FIXHD10; # Redo this with the new values. @@H=unpack("i256",substr($IN,0,256*4)); }; if ($DATE != -1) { print "changing Fixhd(21 (ftn indexing)) from $H[20] to $DATE \n"; substr($IN,20*4,4)=pack "i",$DATE; # Redo this with the new values. @@H=unpack("i256",substr($IN,0,256*4)); }; if ($ENDDATE != -1) { print "change Fixhd(28 (ftn indexing)) from $H[27] to $ENDDATE \n"; substr($IN,27*4,4)=pack "i",$ENDDATE; # Redo this with the new values. @@H=unpack("i256",substr($IN,0,256*4)); }; for ($F=0; $F<$N; $F++) { if ($F >= $NPP) { print "Run out of pp-fields to insert; stopping\n"; last }; if ($Verbose > 1 ) { print "Inserting field number $F / Header from: ",$H[149]+$F*$H[150]," to ",$H[149]+(1+$F)*$H[150]-1, " / Data from : ",$H[159]+$F*$LREC," to ",$H[159]+(1+$F)*$LREC-1,"\n" }; $PP=substr($PIN,$PPL*$F,$PPL); $PPH=substr($PP,4,64*4); $PPD=substr($PP,4*(3+64),4*$LREC); if ($PPH ne substr($IN,($H[149]+$F*$H[150]-1)*4,$H[150]*4)) { wwarn("header inserting for field $F does not match the one in the ancil\n") } else { if ($Verbose > 2) { print " header to insert matches that in ancil; good\n" }; }; # Insert pp header into lookup # Remembering to change LBEGIN substr($IN,($H[149]+$F*$H[150]-1)*4,$H[150]*4)=$PPH; substr($IN,($H[149]+$F*$H[150]-1+29-1)*4,4)=pack("i",($H[159]+$F*$LREC-1)); # Insert data into data substr($IN,($H[159]+$F*$LREC-1)*4,$LREC*4)=$PPD; @@data=unpack "f*",$PPD; if ($Verbose > 3) { print "data range: ".makerange(\@@data,unpack("f",substr($PPH,(46+16)*4,4))).", [0,0]: $data[0]\n" }; }; if ($Verbose > 1) { print "(Length (words) of file read in: $NL (",$NL/4,"))\n" }; # 6. Write out result print OUT $IN; sub wwarn { $MAX_warn--; if ($MAX_warn >= 0) { print " *** Warning: @@_" }; if ($MAX_warn == 0) { print " ... and this is the last warning! (set MAX_warn=nn on the command line if you want more)\n" }; }; sub makerange { ($rdata,$bmdi)=@@_; $begun=0; for (@@$rdata) { if (abs($_-$bmdi) > abs($bmdi)/100) { if (!$begun) { $begun=1; $mn=$_; $mx=$_ }; if ($_>$mx) { $mx=$_ }; if ($_<$mn) { $mn=$_ } } }; return "[".sprintf("%.2f",$mn).",".sprintf("%.2f",$mx)."] (mdi: $bmdi)"; } @ 1.1 log @Initial revision @ text @d27 1 d58 12 d78 6 a83 7 if (($H[0] == -32768) or ($H[0] == 15)) { print "H0=15 or null; OK\n" } else { warn "H0 <> 15: $H[0]\n" }; print "Vn: ",$H[11]/100.,"\n"; print "t0 (start) Y/M/D:H/M/S:D $H[20]/$H[21]/$H[22]:$H[23]/$H[24]/$H[25]:$H[26]\n"; print "t1 (end) Y/M/D:H/M/S:D $H[27]/$H[28]/$H[29]:$H[30]/$H[31]/$H[32]:$H[33]\n"; print "t2 (skip) Y/M/D:H/M/S:D $H[34]/$H[35]/$H[36]:$H[37]/$H[38]/$H[39]:$H[40]\n"; print "Global (0): $H[3], Type (4=ancil): $H[4]\n"; print "Start, len of ints: $H[99],$H[100]\n"; a84 1 if ($Verbose > 1) { print " ints: ",join(",",@@INTS),"\n" }; d87 17 a103 8 print "We seem to have ${NX}x${NY}x$NF\n"; print "Start (StartI+LenI), len of real: $H[104] (",$H[99]+$H[100],"),$H[105]\n"; print "Start (StartR+lenR), len of Lookup: $H[149] (",$H[104]+$H[105],"), \[$H[150],$H[151]\]\n"; if ($NF == $H[151]) { print "N Field types matches 2nd dim of lookup; good ($NF)\n" } else { warn "N Field types ($NF) does not match 2nd dim of lookup ($H[151])\n" } print "Start (StartR+lenR), len of data: $H[159] (",$H[149]+$H[150]*$H[151],"),$H[160]\n"; if ($H[160] == $NX*$NY*$NF) { print "Length of data matches NX*NY*NF; good\n" } else { warn "Length of data ($H[160]) != NX*NY*NF (",$NX*$NY*$NF,")\n" }; d105 45 d157 5 a161 1 if ($PPL != $PPL1) { print " these PP-fields are not the same as the ancil. Ah well. $PPL. $PPL1\n" }; d165 1 a165 1 print "Expected pp-field length is: $PPL; that would mean we read in ",$NPP," fields\n"; d171 4 a174 2 print "***Warning: I think I read in $NPP fields but I'm inserting $N and the original ancil had $H[151]\n"; print "***I'm going to change H[152(151)] to $N (or try to...)\n"; d176 1 a176 1 print "I think I'll change NX and NY too... (to ${NX}x${NY})\n"; d179 5 a183 2 print "I think I'll change 160,161 too... (to: ".($H[149]+$N*$H[150]).", ".($N*$LREC).")\n"; substr($IN,159*4,4)=pack "i",$H[149]+$N*$H[150]; d210 1 a210 1 print "Inserting field number $F / Header from: ",$H[149]+$F*$H[150]," to ",$H[149]+(1+$F)*$H[150]-1, " / Data from : ",$H[159]+$F*$LREC," to ",$H[159]+(1+$F)*$LREC-1,"\n"; d214 1 a214 1 wwarn("*** Warning: header inserting for field $F does not match the one in the ancil\n ") d216 1 a216 1 print " header to insert matches that in ancil; good\n" d218 2 d221 2 d225 1 a225 1 print "data range: ".makerange(\@@data,unpack("f",substr($PPH,(46+16)*4,4))).", [0,0]: $data[0]\n"; d228 1 a228 1 print "(Length (words) of file read in: $NL (",$NL/4,"))\n"; d239 1 a239 1 print @@_ d241 1 a241 1 if ($MAX_warn == 0) { print "...and this is the last warning! (set MAX_warn=nn on the command line if you wnat more)\n" }; d258 1 a258 1 return "[".sprintf("%.2f",$mn).",".sprintf("%.2f",$mx)."] ($bmdi)"; @