Differences
This shows you the differences between two versions of the page.
bufr.pm:mergebufrtemp.pl [2015-02-05 07:58:08] pals |
bufr.pm:mergebufrtemp.pl [2022-05-31 09:29:31] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | <code perl> | ||
- | # | ||
- | # (C) Copyright 2015, met.no | ||
- | # | ||
- | # This program is free software; you can redistribute it and/or modify | ||
- | # it under the terms of the GNU General Public License as published by | ||
- | # the Free Software Foundation; either version 2 of the License, or | ||
- | # (at your option) any later version. | ||
- | # | ||
- | # This program is distributed in the hope that it will be useful, but | ||
- | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
- | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
- | # General Public License for more details. | ||
- | # | ||
- | # You should have received a copy of the GNU General Public License | ||
- | # along with this program; if not, write to the Free Software | ||
- | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
- | # 02110-1301, USA. | ||
- | |||
- | # pod included at end of file | ||
- | |||
- | use strict; | ||
- | use Getopt:: | ||
- | use Pod::Usage qw(pod2usage); | ||
- | use File::Slurp qw(write_file); | ||
- | use Geo::BUFR; | ||
- | |||
- | # Will be used if neither --tablepath nor $ENV{BUFR_TABLES} is set | ||
- | use constant DEFAULT_TABLE_PATH => '/ | ||
- | |||
- | # Parse command line options | ||
- | our %option = (); | ||
- | GetOptions( | ||
- | | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ) or pod2usage(-verbose => 0); | ||
- | |||
- | # User asked for help | ||
- | pod2usage(-verbose => 1) if $option{help}; | ||
- | |||
- | # Make sure there are 2 input files | ||
- | pod2usage(-verbose => 0) unless @ARGV == 2; | ||
- | |||
- | my $infile1 = $ARGV[0]; | ||
- | my $infile2 = $ARGV[1]; | ||
- | |||
- | # Set BUFR table path | ||
- | if ($option{tablepath}) { | ||
- | # Command line option --tablepath overrides all | ||
- | Geo:: | ||
- | } elsif ($ENV{BUFR_TABLES}) { | ||
- | # If no --tablepath option, use the BUFR_TABLES environment variable | ||
- | Geo:: | ||
- | } else { | ||
- | # If all else fails, use the libbufr bufrtables | ||
- | Geo:: | ||
- | } | ||
- | |||
- | my $bufr1 = Geo:: | ||
- | $bufr1-> | ||
- | my $bufr2 = Geo:: | ||
- | $bufr2-> | ||
- | |||
- | my ($data1, $desc1) = $bufr1-> | ||
- | my ($data2, $desc2) = $bufr2-> | ||
- | |||
- | die " | ||
- | . $bufr1-> | ||
- | if $bufr1-> | ||
- | die " | ||
- | . $bufr2-> | ||
- | if $bufr2-> | ||
- | die "Can only handle single subset BUFR messages, but $infile1 contains " | ||
- | . $bufr1-> | ||
- | if $bufr1-> | ||
- | die "Can only handle single subset BUFR messages, but $infile2 contains " | ||
- | . $bufr2-> | ||
- | if $bufr2-> | ||
- | |||
- | my $bufr3 = Geo:: | ||
- | $bufr3-> | ||
- | |||
- | my @pressure_level_desc = ( | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ); | ||
- | my @windshear_level_desc = ( | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ' | ||
- | ); | ||
- | |||
- | my ($data, $desc); | ||
- | |||
- | # First handle section 4 up to where pressure level data starts | ||
- | for my $ii (0 .. 27) { | ||
- | $desc-> | ||
- | if (defined($data1-> | ||
- | $data-> | ||
- | } else { | ||
- | $data-> | ||
- | } | ||
- | } | ||
- | |||
- | # Then handle pressure levels (and eddrf) | ||
- | $desc-> | ||
- | $data-> | ||
- | my $eddrf = 0; # extended delayed descriptor replication factor | ||
- | my ($ii, | ||
- | while ($desc1-> | ||
- | splice(@$desc, | ||
- | if ($desc1-> | ||
- | # No more pressure levels in message 1, so fetch from message 2 | ||
- | splice(@$data, | ||
- | $i2 += 10; | ||
- | } elsif ($desc2-> | ||
- | # No more pressure levels in message 2, so fetch from message 1 | ||
- | splice(@$data, | ||
- | $i1 += 10; | ||
- | } elsif ($data1-> | ||
- | # Same pressure level, should be merged into one | ||
- | # evss = extended vertical sounding significance | ||
- | my $evss1 = $data1-> | ||
- | my $evss2 = $data2-> | ||
- | my $evss = combine_evss($evss1, | ||
- | push(@$data, | ||
- | push(@$data, | ||
- | for (2 .. 9) { | ||
- | push(@$data, | ||
- | : $data2-> | ||
- | } | ||
- | $i1 += 10; | ||
- | $i2 += 10; | ||
- | } elsif ($data1-> | ||
- | # pick the highest pressure, i.e. data1 | ||
- | splice(@$data, | ||
- | $i1 += 10; | ||
- | } else { | ||
- | # pick the highest pressure, i.e. data2 | ||
- | splice(@$data, | ||
- | $i2 += 10; | ||
- | } | ||
- | $eddrf++; | ||
- | $ii += 10; | ||
- | } | ||
- | $data-> | ||
- | |||
- | # Handle windshear levels | ||
- | my $iws = $ii; | ||
- | $desc-> | ||
- | $data-> | ||
- | if ($data1-> | ||
- | $data-> | ||
- | } else { | ||
- | my $nws = 0; # Number of wind shear levels, to be calculated | ||
- | my $nws1 = $data1-> | ||
- | my $nws2 = $data2-> | ||
- | $data-> | ||
- | while ($nws1 > 0 || $nws2 > 0) { | ||
- | splice(@$desc, | ||
- | if ($nws1 == 0) { | ||
- | # Fetch from message 2 | ||
- | splice(@$data, | ||
- | $i2 += 7; | ||
- | $nws2--; | ||
- | } elsif ($nws2 == 0) { | ||
- | # Fetch from message 1 | ||
- | splice(@$data, | ||
- | $i1 += 7; | ||
- | $nws1--; | ||
- | } elsif ($data1-> | ||
- | # see no reason why data1 should differ from data2 here, | ||
- | # so we use data1 | ||
- | splice(@$data, | ||
- | $i1 += 7; | ||
- | $i2 += 7; | ||
- | $nws2--; | ||
- | } elsif ($data1-> | ||
- | # pick the highest pressure, i.e. data1 | ||
- | splice(@$data, | ||
- | $i1 += 7; | ||
- | $nws1--; | ||
- | } else { | ||
- | # pick the highest pressure, i.e. data2 | ||
- | splice(@$data, | ||
- | $i2 += 7; | ||
- | $nws2--; | ||
- | } | ||
- | $nws++; | ||
- | $ii += 7; | ||
- | } | ||
- | $data-> | ||
- | } | ||
- | |||
- | my ($data_refs, | ||
- | # One subset only | ||
- | $data_refs-> | ||
- | $desc_refs-> | ||
- | |||
- | # Print the encoded BUFR message | ||
- | my $msg = $bufr3-> | ||
- | if ($option{outfile}) { | ||
- | write_file($option{outfile}, | ||
- | } else { | ||
- | print $msg; | ||
- | } | ||
- | |||
- | |||
- | ## Combine two extended vertical sounding significance (evss) into one | ||
- | sub combine_evss { | ||
- | my ($evss1, | ||
- | my $binary1 = pack " | ||
- | my $binary2 = pack " | ||
- | my $binary = $binary1 | $binary2; # bitwise or | ||
- | return unpack " | ||
- | } | ||
- | |||
- | =pod | ||
- | |||
- | =head1 SYNOPSIS | ||
- | |||
- | mergebufrtemp.pl <bufr file 1> <bufr file 2> | ||
- | [--outfile < | ||
- | [--tablepath <path to BUFR tables>] | ||
- | [--help] | ||
- | |||
- | =head1 DESCRIPTION | ||
- | |||
- | Will merge (the first) BUFR message in <bufr file 1> with (the first) | ||
- | BUFR message in <bufr file 2> into one single BUFR message, printing | ||
- | to STDOUT unless C< | ||
- | assumed to be single subset BUFR TEMPs utilizing TM305092 (this is | ||
- | checked) containing data for the same station and termin (this is not | ||
- | checked). Metadata are fetched from input file 1, the same applies for | ||
- | conflicting data in section 4 (e.g. if BUFR launch time differs) | ||
- | except that input file 2 is used for data missing in input file 1. | ||
- | |||
- | Execute without arguments for Usage, with option C< | ||
- | additional info. | ||
- | |||
- | =head1 OPTIONS | ||
- | |||
- | |||
- | | ||
- | Will print to < | ||
- | | ||
- | Set path to BUFR tables (overrides $ENV{BUFR_TABLES}) | ||
- | | ||
- | the same as consulting perldoc mergebufrtemp.pl | ||
- | |||
- | Options may be abbreviated, | ||
- | |||
- | To avoid having to use the C< | ||
- | set the environment variable BUFR_TABLES to the directory where your | ||
- | BUFR tables are located (unless the default path provided by | ||
- | mergebufrtemp.pl works for you). | ||
- | |||
- | =head1 AUTHOR | ||
- | |||
- | Pål Sannes E< | ||
- | |||
- | =head1 COPYRIGHT | ||
- | |||
- | Copyright (C) 2015 met.no | ||
- | |||
- | =cut | ||
- | </ |