Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
bufr.pm:bufrdump.pl_source [2012-06-04 09:24:05] pals |
bufr.pm:bufrdump.pl_source [2022-05-31 09:29:31] (current) |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | <code perl> | + | <code perl bufrdump.pl> |
| # | # | ||
| Line 38: | Line 38: | ||
| ' | ' | ||
| ' | ' | ||
| - | ' | + | ' |
| - | ' | + | ' |
| ' | ' | ||
| ' | ' | ||
| Line 81: | Line 81: | ||
| my $lon2 = $option{lon2} ? " | my $lon2 = $option{lon2} ? " | ||
| my $lat2 = $option{lat2} ? " | my $lat2 = $option{lat2} ? " | ||
| - | my $del = $option{delimiter} ? " | + | my $del = $option{delimiter} ? " |
| my $delimiter = $option{delimiter} ? " | my $delimiter = $option{delimiter} ? " | ||
| Line 137: | Line 137: | ||
| # Build up the message to be (possibly) printed | # Build up the message to be (possibly) printed | ||
| my ($param, $value) = ($line =~ / | my ($param, $value) = ($line =~ / | ||
| + | # Know only of one case where next check is necessary: if | ||
| + | # a CCITT IA5 value contains new line (\n) | ||
| + | next LINE if !defined $value; | ||
| if ($transform_file && $transform_ref-> | if ($transform_file && $transform_ref-> | ||
| # Replace value with transformed value | # Replace value with transformed value | ||
| Line 185: | Line 188: | ||
| if ($txt) { | if ($txt) { | ||
| if ($sort) { | if ($sort) { | ||
| - | # Sort wmonr before nationalnr before call | + | # Sort wmonr before nationalnr before call sign before |
| - | # sign before | + | # buoy_id before aircraft |
| if ($msg{wmonr}) { | if ($msg{wmonr}) { | ||
| $stnid = ' | $stnid = ' | ||
| Line 197: | Line 200: | ||
| } elsif ($msg{aircraft}) { | } elsif ($msg{aircraft}) { | ||
| $stnid = ' | $stnid = ' | ||
| + | } elsif ($msg{icao_id}) { | ||
| + | $stnid = ' | ||
| + | } elsif ($msg{wigosid}) { | ||
| + | $stnid = ' | ||
| } else { | } else { | ||
| # Skip observation if no station identification found | # Skip observation if no station identification found | ||
| Line 205: | Line 212: | ||
| my $key = $stnid . ' | my $key = $stnid . ' | ||
| $data_of{$key} = exists $data_of{$key} | $data_of{$key} = exists $data_of{$key} | ||
| - | | + | |
| } else { | } else { | ||
| $data_of{$stnid} = exists $data_of{$stnid} | $data_of{$stnid} = exists $data_of{$stnid} | ||
| - | | + | |
| } | } | ||
| } elsif ($sort_on) { | } elsif ($sort_on) { | ||
| my $val = exists $msg{$sort_on} ? $msg{$sort_on} : ''; | my $val = exists $msg{$sort_on} ? $msg{$sort_on} : ''; | ||
| $data_of{$val} = exists $data_of{$val} | $data_of{$val} = exists $data_of{$val} | ||
| - | | + | |
| } else { | } else { | ||
| # No sorting. We can print the line immediately | # No sorting. We can print the line immediately | ||
| Line 281: | Line 288: | ||
| '> | '> | ||
| ' | ' | ||
| - | ); | + | ' |
| + | ' | ||
| + | | ||
| my @criteria; | my @criteria; | ||
| my @num_alt; # Number of alternative criteria following this, | my @num_alt; # Number of alternative criteria following this, | ||
| Line 309: | Line 318: | ||
| # Check that the criteria are properly formatted | # Check that the criteria are properly formatted | ||
| foreach my $criterium (@criteria) { | foreach my $criterium (@criteria) { | ||
| - | # Naked parameter is ok | + | # Naked parameter |
| - | next if $criterium =~ /^\w+$/; | + | next if $criterium =~ /^!?\w+$/; |
| my $op = (split / +/, $criterium)[1]; | my $op = (split / +/, $criterium)[1]; | ||
| Line 337: | Line 346: | ||
| my @p = split /,/, $params; | my @p = split /,/, $params; | ||
| foreach my $name (@p) { | foreach my $name (@p) { | ||
| + | $name =~ s/^\s+//; | ||
| + | $name =~ s/\s+$//; | ||
| if ($name =~ /^!/) { | if ($name =~ /^!/) { | ||
| $name = substr $name, 1; | $name = substr $name, 1; | ||
| Line 377: | Line 388: | ||
| $line =~ s/^\s+//; | $line =~ s/^\s+//; | ||
| $line =~ s/\s+$//; | $line =~ s/\s+$//; | ||
| - | next if !$line || $line =~ /^#/; | + | |
| my ($param, $transform) = split /=/, $line, 2; | my ($param, $transform) = split /=/, $line, 2; | ||
| die " | die " | ||
| Line 399: | Line 410: | ||
| return unless $criteria_ref; | return unless $criteria_ref; | ||
| - | my @ascii_params = qw(aircraft call_sign icao_id name obstime type); | + | my @ascii_params = qw(aircraft call_sign icao_id name obstime type wigosid); |
| # Note that the loop counter $i might be changed in the loop | # Note that the loop counter $i might be changed in the loop | ||
| Line 406: | Line 417: | ||
| my $criterium = $criteria_ref-> | my $criterium = $criteria_ref-> | ||
| my ($f_param, $f_operator, | my ($f_param, $f_operator, | ||
| - | | + | |
| - | if (not exists $msg_ref-> | + | # First check for !$par, meaning $par should not be in the observation |
| - | if ($num_alt) { | + | if (substr($f_param, |
| - | | + | $f_param = substr($f_param, |
| - | | + | |
| - | } else { | + | if (exists $msg_ref-> |
| + | | ||
| # Criterium not fulfilled and no more alternatives to | # Criterium not fulfilled and no more alternatives to | ||
| # check. This observation should be filtered away | # check. This observation should be filtered away | ||
| return 1; | return 1; | ||
| + | } else { | ||
| + | # Criterium fulfilled. No need to check alternative criteria | ||
| + | $i += $num_alt if $num_alt; | ||
| + | next; | ||
| } | } | ||
| + | } | ||
| + | |||
| + | # If parameter not present, criterium is obviously not fullfilled | ||
| + | if (not exists $msg_ref-> | ||
| + | next if $num_alt; | ||
| + | return 1; | ||
| } | } | ||
| Line 432: | Line 455: | ||
| my $op; | my $op; | ||
| if ($f_operator eq '<' | if ($f_operator eq '<' | ||
| - | | $f_operator eq '< | + | |
| - | | $f_operator eq '>' | + | |
| - | | $f_operator eq '> | + | |
| + | || $f_operator eq ' | ||
| + | || $f_operator eq '!~') { | ||
| $op = $f_operator; | $op = $f_operator; | ||
| } elsif ($f_operator eq ' | } elsif ($f_operator eq ' | ||
| - | | $f_operator eq ' | + | || $f_operator eq ' |
| if (grep {$_ eq $f_param} @ascii_params) { | if (grep {$_ eq $f_param} @ascii_params) { | ||
| $msg_value =~ s/\s*$//; | $msg_value =~ s/\s*$//; | ||
| Line 448: | Line 473: | ||
| } | } | ||
| - | | + | # Some parameters might need special massaging |
| - | # Make non octal by removing leading 0 | + | if ($f_operator !~ /~/) { |
| - | $msg_value =~ s/^0+//; | + | |
| - | $f_value =~ s/^0+//; | + | # Make non octal by removing leading 0 |
| - | } elsif ($f_param eq ' | + | $msg_value =~ s/^0+//; |
| - | # Convert to a pure numerical value (float). For 001101 | + | $f_value =~ s/ |
| - | # State id only numbers between 100 and 699 are operational | + | } elsif ($f_param eq ' |
| - | $msg_value =~ s/_0*/./; | + | # Convert to a pure numerical value (float). For 001101 |
| - | $f_value =~ s/_0*/./; | + | # State id only numbers between 100 and 699 are operational |
| - | } elsif ($f_param eq ' | + | $msg_value =~ s/_0*/./; |
| - | # Convert to a pure numerical value (float) | + | $f_value =~ s/_0*/./; |
| - | $msg_value =~ s/ | + | } elsif ($f_param eq ' |
| - | $msg_value =~ s/ /./; | + | # Convert to a pure numerical value (float) |
| - | $f_value =~ s/ | + | $msg_value =~ s/ |
| - | $f_value =~ s/^ +//; | + | $msg_value =~ s/ /./; |
| - | $f_value =~ s/ +$//; | + | $f_value =~ s/ |
| - | $f_value =~ s/ /./; | + | $f_value =~ s/^ +//; |
| + | $f_value =~ s/ +$//; | ||
| + | $f_value =~ s/ /./; | ||
| + | | ||
| + | # Add or correct quoting to "" | ||
| + | $msg_value = '"' | ||
| + | $f_value = lc $f_value; | ||
| + | if ($f_value =~ / | ||
| + | | ||
| + | $f_value =~ s/' | ||
| + | } | ||
| + | if ($f_value !~ /^".*"$/) { | ||
| + | $f_value = '"' | ||
| + | } | ||
| + | } | ||
| } | } | ||
| + | |||
| + | my $condition = " | ||
| + | # Some values should be string values | ||
| + | if ($f_operator =~ /~/) { | ||
| + | $condition = " | ||
| + | } elsif (grep {$_ eq $f_param} @ascii_params) { | ||
| + | $condition = " | ||
| + | } | ||
| # Finally, do the criterium check | # Finally, do the criterium check | ||
| - | | + | if (eval $condition) { |
| - | # No need to check the remaining alternative criteria | + | |
| - | $i += $num_alt if $num_alt; | + | |
| - | next; | + | |
| - | } else { | + | } else { |
| - | next if $num_alt; | + | |
| - | return 1; | + | |
| - | } | + | } |
| } | } | ||
| Line 489: | Line 536: | ||
| return if !$req_stations; | return if !$req_stations; | ||
| die " | die " | ||
| - | . "' | + | . "' |
| unless $req_stations | unless $req_stations | ||
| - | =~ / | + | =~ / |
| my ($id, $rest) = split /=/, $req_stations; | my ($id, $rest) = split /=/, $req_stations; | ||
| Line 552: | Line 599: | ||
| } | } | ||
| - | my @ascii_params = qw(aircraft call_sign icao_id obstime name type); | + | my @ascii_params = qw(aircraft call_sign icao_id obstime name type wigosid); |
| my $lexical_sort = grep {$_ eq $sort_on} @ascii_params; | my $lexical_sort = grep {$_ eq $sort_on} @ascii_params; | ||
| Line 647: | Line 694: | ||
| as they occur there. If using --csv possibly | as they occur there. If using --csv possibly | ||
| followed by --delimiter < | followed by --delimiter < | ||
| - | be printed using the CSV (comma separated values) | + | be printed using the CSV (comma-separated values) |
| - | format, with the delimiter del (default is ',') | + | format, with the delimiter del (default is ';') |
| --sort | --sort | ||
| first stations with wmonr, then stations with nationalnr, | first stations with wmonr, then stations with nationalnr, | ||
| - | | + | |
| + | | ||
| --sort_on < | --sort_on < | ||
| values of parameter, or decreasing values if a ' | values of parameter, or decreasing values if a ' | ||
| Line 674: | Line 722: | ||
| Force observation type. If this option is not set, | Force observation type. If this option is not set, | ||
| will make an educated guess of observation type | will make an educated guess of observation type | ||
| - | based on metadata in section 1 of each BUFR | + | based on metadata in section 1 of each BUFR message |
| - | | + | |
| --tablepath <path to BUFR tables> | --tablepath <path to BUFR tables> | ||
| Set path to BUFR tables (overrides ENV{BUFR_TABLES}) | Set path to BUFR tables (overrides ENV{BUFR_TABLES}) | ||
| Line 693: | Line 740: | ||
| temperature to be printed for a BUFR SYNOP file, either supply | temperature to be printed for a BUFR SYNOP file, either supply | ||
| - | wmonr, | + | wmonr,nationalnr, |
| as argument to --params, or supply a < | as argument to --params, or supply a < | ||
| Line 699: | Line 746: | ||
| wmonr | wmonr | ||
| + | nationalnr | ||
| call_sign | call_sign | ||
| TA | TA | ||
| Line 719: | Line 767: | ||
| listing may for example start like | listing may for example start like | ||
| - | wmonr,call_sign,TA | + | wmonr; |
| - | 01001,,-1.5 | + | 01001;;;-1.5 |
| - | | + | |
| - | You can choose another delimiter than comma by use of option | + | You can choose another delimiter than semicolon |
| - | --delimiter < | + | --delimiter < |
| Using --filter will decode only those observations that meet at least | Using --filter will decode only those observations that meet at least | ||
| Line 730: | Line 778: | ||
| in <filter file>, where the BUFR descriptor criteria should come first | in <filter file>, where the BUFR descriptor criteria should come first | ||
| in filter file followed by a blank line, then comes the parameter | in filter file followed by a blank line, then comes the parameter | ||
| - | criteria which should match < | + | criteria which should match < |
| - | where operator is one of =, !=, <, <=, > and >=. The parameter | + | < |
| + | follows =~ and !~ should be a Perl match regular expression. The parameter | ||
| criteria may be phrased as alternatives by separating them with ' | criteria may be phrased as alternatives by separating them with ' | ||
| a single line. An example filter file is | a single line. An example filter file is | ||
| Line 750: | Line 799: | ||
| which decodes all observations with block number 01, two other | which decodes all observations with block number 01, two other | ||
| - | specific wmo stations and one specific ship, being manned | + | specific wmo stations and one specific ship, where stations |
| - | having | + | manned and have cloud cover with a value different from 8, and have |
| - | message) | + | temperature between 5 and 9.5 degrees Celsius, and contain |
| - | containing | + | precipitation for last 24 hours. Comment lines starting with # will be |
| - | with # will be ignored. | + | ignored. |
| Another example: the filter file (starting with a blank line!) | Another example: the filter file (starting with a blank line!) | ||
| - | | + | |
| obstime >= ' | obstime >= ' | ||
| - | | + | |
| - | | + | |
| - | will print only those observations | + | will print only those ship observations |
| - | and having obstime larger or equal to the datetime given, and | + | call_sign starts with 2 letters in the interval LA-LN, |
| - | containing | + | obstime larger or equal to the datetime given, and containing |
| - | below minus 30 or above plus 30 degrees Celsius. | + | data (specifically: |
| + | automatically measured), and with wind or 10 minutes gust more than 10 | ||
| + | m/s. | ||
| For convenience, | For convenience, | ||
| provide the filter criteria on the command line. Example: | provide the filter criteria on the command line. Example: | ||
| - | --filter wmonr,'TA > 0','RR_12 | RR_24' | + | --filter |
| will decode only observations with wmonr, having positive temperature | will decode only observations with wmonr, having positive temperature | ||
| - | and containing precipitation for 12 or 24 hours. If (like for --param) | + | and containing precipitation for 12 or 24 hours and not reporting |
| - | the filter list consists of one criterium only, a comma must be | + | wind. If (like for --param) the filter list consists of one criterium |
| - | appended. | + | only, a comma must be appended. |
| To avoid the need of creating a filter file when observations for some | To avoid the need of creating a filter file when observations for some | ||
| Line 788: | Line 839: | ||
| --station buoyid=64607, | --station buoyid=64607, | ||
| --station aircraft=EU3421, | --station aircraft=EU3421, | ||
| + | --station icao_id=ENGM, | ||
| + | --station wigosid=0-376-0-511, | ||
| You cannot mix different kinds of stations this way (before ' | You cannot mix different kinds of stations this way (before ' | ||
| - | must choose either wmonr, nationalnr, call_sign, buoy_id | + | must choose either wmonr, nationalnr, call_sign, buoy_id, aircraft, |
| - | aircraft). Note also that providing the stations in the BUFR | + | icao_id or wigosid). Note also that providing the stations in the BUFR |
| descriptor part (first part) of the filter file will speed up | descriptor part (first part) of the filter file will speed up | ||
| execution time considerably, | execution time considerably, | ||