bufr.pm:bufrdump.pl_source

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
bufr.pm:bufrdump.pl_source [2012-02-15 13:42:25]
pals
bufr.pm:bufrdump.pl_source [2022-05-31 09:29:31] (current)
Line 1: Line 1:
-<code perl>+<code perl bufrdump.pl>
 #!/usr/bin/perl -w #!/usr/bin/perl -w
  
Line 35: Line 35:
            'help',            'help',
            'tablepath=s', # Set BUFR table path            'tablepath=s', # Set BUFR table path
-           'filter=s',    # Decode observations meeting criteria in <filter file> only+           'filter=s',    # Decode observations meeting the filter criteria specified only
            'param=s',     # Decode/print specified parameters only            'param=s',     # Decode/print specified parameters only
            'csv',         # Use CSV format for printing            'csv',         # Use CSV format for printing
-           'sort',        # Sort on stationid (wmonr/nationalnr/call_sign/buoy_id/aircraft)+           'delimiter=s', # Choose the delimiter for the CSV format 
 +           'sort',        # Sort on stationid (wmonr/nationalnr/call_sign/buoy_id/aircraft/icao_id/wigosid)
            'sort_on=s',   # Sort on specified parameter            'sort_on=s',   # Sort on specified parameter
            'station=s',   # Filter on list of stations            'station=s',   # Filter on list of stations
Line 75: Line 76:
  
 my $obstype = $option{obstype} ? "--obstype $option{obstype}" : ''; my $obstype = $option{obstype} ? "--obstype $option{obstype}" : '';
-my $filter = $option{filter} ? "--filter $option{filter}" : '';+my $filt = $option{filter} ? "$option{filter}" : '';
 my $lon1 = $option{lon1} ? "--lon1 $option{lon1}" : ''; my $lon1 = $option{lon1} ? "--lon1 $option{lon1}" : '';
 my $lat1 = $option{lat1} ? "--lat1 $option{lat1}" : ''; my $lat1 = $option{lat1} ? "--lat1 $option{lat1}" : '';
 my $lon2 = $option{lon2} ? "--lon2 $option{lon2}" : ''; my $lon2 = $option{lon2} ? "--lon2 $option{lon2}" : '';
 my $lat2 = $option{lat2} ? "--lat2 $option{lat2}" : ''; my $lat2 = $option{lat2} ? "--lat2 $option{lat2}" : '';
 +my $del = $option{delimiter} ? "$option{delimiter}" : ';';
 +my $delimiter = $option{delimiter} ? "--delimiter $del" : '';
  
 # Any filter criteria provided? # Any filter criteria provided?
-my ($criteria_ref, $num_alt_ref) = read_filter_file($option{filter});+my ($filter, $criteria_ref, $num_alt_ref) = get_filter_conditions($filt);
  
 # Any specific stations requested? # Any specific stations requested?
Line 92: Line 95:
 my $csv = $option{csv} ? 1 : 0; my $csv = $option{csv} ? 1 : 0;
 # First line in CSV should be the parameters # First line in CSV should be the parameters
-print join(',', @$params_ref) . "\n" if $csv;+print join($del, @$params_ref) . "\n" if $csv;
  
 # Any transformations of units specified? # Any transformations of units specified?
Line 110: Line 113:
  
     # Dump the content of the BUFR file using the Fortran program $BUFRDUMP     # Dump the content of the BUFR file using the Fortran program $BUFRDUMP
-    my $dump `$BUFRDUMP $obstype $filter $lon1 $lat1 $lon2 $lat2 $inputfname`;+    my $fortran_options "$obstype $filter $lon1 $lat1 $lon2 $lat2"; 
 +    my $dump = `$BUFRDUMP $fortran_options $inputfname`;
     die if $?; # Reason for bufrdump failing should have been printed to STDERR     die if $?; # Reason for bufrdump failing should have been printed to STDERR
  
Line 133: Line 137:
             # Build up the message to be (possibly) printed             # Build up the message to be (possibly) printed
             my ($param, $value) = ($line =~ /^(.+)=\s*(.*?)\s*$/);             my ($param, $value) = ($line =~ /^(.+)=\s*(.*?)\s*$/);
 +            # 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->{$param}) {             if ($transform_file && $transform_ref->{$param}) {
                 # Replace value with transformed value                 # Replace value with transformed value
Line 148: Line 155:
         if ($line =~ /^\s*$/ or @lines == 0) {         if ($line =~ /^\s*$/ or @lines == 0) {
             # A full message has been completed. Should it be printed?             # A full message has been completed. Should it be printed?
-            if ($filter && filter_obs(\%msg, $criteria_ref, $num_alt_ref)) {+            if ($filt && filter_obs(\%msg, $criteria_ref, $num_alt_ref)) {
                 # Skip this message                 # Skip this message
             } elsif ($req_id && filter_station(\%msg, $req_id, $req_stn_ref)) {             } elsif ($req_id && filter_station(\%msg, $req_id, $req_stn_ref)) {
Line 160: Line 167:
                     foreach my $name (@$params_ref) {                     foreach my $name (@$params_ref) {
                         if (exists $msg{$name}) {                         if (exists $msg{$name}) {
-                            $txt .= $csv ? $msg{$name} . ',' : "$name=$msg{$name}\n";+                            $txt .= $csv ? $msg{$name} . $del : "$name=$msg{$name}\n";
                         } elsif ($forced_params_ref->{$name}) {                         } elsif ($forced_params_ref->{$name}) {
-                            $txt .= $csv ? '-32767,' : "$name=-32767\n";+                            $txt .= $csv ? '-32767' . $del : "$name=-32767\n";
                         } elsif ($csv) {                         } elsif ($csv) {
-                            $txt .= ',';+                            $txt .= $del;
                         }                         }
                     }                     }
Line 173: Line 180:
                     }                     }
                 }                 }
-                chop $txt if $csvremoves last ','+                if ($csv) { 
 +                    Remove last $del 
 +                    for (1 .. length($del)) { 
 +                        chop $txt; 
 +                    } 
 +                }
                 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+                        # buoy_id before aircraft before icaoid before wigosid
                         if ($msg{wmonr}) {                         if ($msg{wmonr}) {
                             $stnid = '00_' . $msg{wmonr};                             $stnid = '00_' . $msg{wmonr};
Line 188: Line 200:
                         } elsif ($msg{aircraft}) {                         } elsif ($msg{aircraft}) {
                             $stnid = '40_' . $msg{aircraft};                             $stnid = '40_' . $msg{aircraft};
 +                        } elsif ($msg{icao_id}) {
 +                            $stnid = '50_' . $msg{icao_id};
 +                        } elsif ($msg{wigosid}) {
 +                            $stnid = '60_' . $msg{wigosid};
                         } else {                         } else {
                             # Skip observation if no station identification found                             # Skip observation if no station identification found
Line 196: Line 212:
                             my $key = $stnid . '|' . $val;                             my $key = $stnid . '|' . $val;
                             $data_of{$key} = exists $data_of{$key}                             $data_of{$key} = exists $data_of{$key}
-                                ? $data_of{$key} . "$txt \n" : "$txt \n";+                            ? $data_of{$key} . "$txt\n" : "$txt\n";
                         } else {                         } else {
                             $data_of{$stnid} = exists $data_of{$stnid}                             $data_of{$stnid} = exists $data_of{$stnid}
-                                ? $data_of{$stnid} . "$txt \n" : "$txt \n";+                            ? $data_of{$stnid} . "$txt\n" : "$txt\n";
                         }                         }
                     } 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}
-                            ? $data_of{$val} . "$txt \n" : "$txt \n";+                        ? $data_of{$val} . "$txt\n" : "$txt\n";
                     } else {                     } else {
                         # No sorting. We can print the line immediately                         # No sorting. We can print the line immediately
Line 235: Line 251:
     }     }
     print $data_of_missing_value if $data_of_missing_value;     print $data_of_missing_value if $data_of_missing_value;
 +}
 +
 +
 +# Read the filter conditions (if any). Return the filter option to be
 +# used by bufrdump, the found criteria (if any) as well as the number
 +# of succeeding alternatives for each criterium
 +sub get_filter_conditions {
 +    my $filt = shift;
 +    return ('') if ! $filt;
 +
 +    my $fortran_filter = '';
 +    my @f;
 +    if ($filt =~ /,/) {
 +        # Argument to --filter is a comma separated list
 +        @f = split /,/, $filt;
 +    } else {
 +        # Argument to --filter is a file
 +        $fortran_filter = "--filter $filt";
 +        open my $FILTER, '<', $filt
 +            or die "Cannot open $filt: $!";
 +        # Skip the criteria meant for Fortran parsing, i.e. proceed to
 +        # first line following a blank line
 +        while (<$FILTER>) {
 +            last if $_ =~ /^\s*$/;
 +        }
 +        @f = <$FILTER>;
 +        close $FILTER or die "Cannot close $filt: $!";;
 +    }
 +    return ($fortran_filter) if !@f; # BUFR descriptor criteria only
 +
 +    my @allowed_operators =
 +        ('=',
 +         '<',
 +         '<=',
 +         '>',
 +         '>=',
 +         '!=',
 +         '=~',
 +         '!~',
 +        );
 +    my @criteria;
 +    my @num_alt; # Number of alternative criteria following this,
 +                 # i.e. if line is '<cr1> | <cr2> | <cr3>' then
 +                 # corresponding values in @num_alt will be 2,1,0
 +
 +    # Read the filter criteria meant for Perl parsing, skipping blank
 +    # lines and comment lines
 +  FILTERLINE:
 +    foreach my $line (@f) {
 +        $line =~ s/^\s+//;
 +        $line =~ s/\s+$//;
 +        next FILTERLINE if !$line || $line =~ /^#/;
 +        my @crit = split /\|/, $line;
 +        my $num = scalar @crit;
 +        foreach my $criterium (@crit) {
 +            $criterium =~ s/^\s+//;
 +            $criterium =~ s/\s+$//;
 +            if ($criterium ne '') {
 +                push @criteria, $criterium;
 +                push @num_alt, --$num;
 +            }
 +        }
 +    }
 +    return ($fortran_filter) if !@criteria;
 +
 +    # Check that the criteria are properly formatted
 +    foreach my $criterium (@criteria) {
 +        # Naked parameter possibly preceded by '!' is ok
 +        next if $criterium =~ /^!?\w+$/;
 +
 +        my $op = (split / +/, $criterium)[1];
 +        if (!defined($op) or grep(/[+*?\\]/, $op)
 +            or !grep(/^$op$/, @allowed_operators) ) {
 +            print "Error in $filt:\ncriterium is badly formatted"
 +                . " or operator not supported:\n$criterium";
 +            exit 1;
 +        }
 +    }
 +    return ($fortran_filter, \@criteria, \@num_alt);
 } }
  
Line 251: 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 291: Line 388:
         $line =~ s/^\s+//;         $line =~ s/^\s+//;
         $line =~ s/\s+$//;         $line =~ s/\s+$//;
-         next if !$line || $line =~ /^#/;+        next if !$line || $line =~ /^#/;
         my ($param, $transform) = split /=/, $line, 2;         my ($param, $transform) = split /=/, $line, 2;
         die "Invalid transformation in $transform_file:\n$line\n"         die "Invalid transformation in $transform_file:\n$line\n"
Line 299: Line 396:
         $transform_of{$param} = $transform;         $transform_of{$param} = $transform;
     }     }
 +    close $TRANSFORM or die "Cannot close $transform_file: $!";
     return \%transform_of;     return \%transform_of;
-} 
- 
-# Read the filter file and return the criteria as well as the number 
-# of succeeding alternatives for each criterium 
-sub read_filter_file { 
-    my $filter_file = shift; 
-    return if !$filter_file; 
- 
-    my @allowed_operators = 
-        ('=', 
-         '<', 
-         '<=', 
-         '>', 
-         '>=', 
-         '!=', 
-     ); 
-    my @criteria; 
-    my @num_alt; # Number of alternative criteria following this, 
-                 # i.e. if line is '<cr1> | <cr2> | <cr3>' then 
-                 # corresponding values in @num_alt will be 2,1,0 
- 
-    open my $FILTER, '<', $filter_file 
-        or die "Cannot open $filter_file: $!"; 
-    # Skip the criteria meant for Fortran parsing, i.e. proceed to 
-    # first line following a blank line 
-    while (<$FILTER>) { 
-        last if $_ =~ /^\s*$/; 
-    } 
- 
-    # Read the filter criteria meant for Perl parsing, skipping blank 
-    # lines and comment lines 
-  FILTERLINE: 
-    while (my $line = <$FILTER>) { 
-        $line =~ s/^\s+//; 
-        $line =~ s/\s+$//; 
-        next FILTERLINE if !$line || $line =~ /^#/; 
-        my @crit = split /\|/, $line; 
-        my $num = scalar @crit; 
-        foreach my $criterium (@crit) { 
-            $criterium =~ s/^\s+//; 
-            $criterium =~ s/\s+$//; 
-            push @criteria, $criterium; 
-            push @num_alt, --$num; 
-        } 
-    } 
- 
-    # Check that the criteria are properly formatted 
-    foreach my $criterium (@criteria) { 
-        # Naked parameter is ok 
-        next if $criterium =~ /^\w+$/; 
- 
-        my $op = (split / +/, $criterium)[1]; 
-        if (!defined($op) or grep(/[+*?\\]/, $op) 
-            or !grep(/^$op$/, @allowed_operators) ) { 
-            print "Error in $filter_file, line $. is badly formatted" 
-                . " or operator not supported:\n$criterium"; 
-            exit 1; 
-        } 
-    } 
-    return (\@criteria, \@num_alt); 
 } }
  
Line 370: Line 408:
     my $num_alt_ref = shift; # gives the number of alternative     my $num_alt_ref = shift; # gives the number of alternative
                              # criteria still to be checked                              # criteria still to be checked
 +    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 378: Line 417:
         my $criterium = $criteria_ref->[$i];         my $criterium = $criteria_ref->[$i];
         my ($f_param, $f_operator, $f_value) = split / +/, $criterium, 3;         my ($f_param, $f_operator, $f_value) = split / +/, $criterium, 3;
-        # If parameter not present, criterium is obviously not fullfilled + 
-        if (not exists $msg_ref->{$f_param}) { +        # First check for !$par, meaning $par should not be in the observation 
-            if ($num_alt) { +        if (substr($f_param,0,1) eq '!') { 
-                Criterium not fullfilled, but more alternatives to check +            $f_param = substr($f_param,1); 
-                next; +            # If parameter is present, criterium is not fullfilled 
-            } else {+            if (exists $msg_ref->{$f_param}) { 
 +                next if $num_altMore alternatives to check 
                 # 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;
             }             }
         }         }
  
- my $msg_value = $msg_ref->{$f_param};+        # If parameter not present, criterium is obviously not fullfilled 
 +        if (not exists $msg_ref->{$f_param}) { 
 +            next if $num_alt; 
 +            return 1; 
 +        } 
 + 
 +        my $msg_value = $msg_ref->{$f_param};
         # If a naked parameter criterium, we already know parameter is         # If a naked parameter criterium, we already know parameter is
         # present (as found in previous check), so criterium is fulfilled         # present (as found in previous check), so criterium is fulfilled
Line 404: 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 '>=') {+            || $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 420: Line 473:
         }         }
  
- if ($f_param eq 'wmonr' || $f_param eq 'buoy_id') { + # Some parameters might need special massaging 
-     # Make non octal by removing leading 0 +        if ($f_operator !~ /~/) { 
-     $msg_value =~ s/^0+//; +            if ($f_param eq 'wmonr' || $f_param eq 'buoy_id') { 
-     $f_value =~ s/^0+//; +                # Make non octal by removing leading 0 
- } elsif ($f_param eq 'nationalnr') { +                $msg_value =~ s/^0+//; 
-     # Convert to a pure numerical value (float). For 001101 +                $f_value =~ s/^0+// if $f_value != 0
-     # State id only numbers between 100 and 699 are operational +            } elsif ($f_param eq 'nationalnr') { 
-     $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 'obstime') { +                $msg_value =~ s/_0*/./; 
-     # Convert to a pure numerical value (float) +                $f_value =~ s/_0*/./; 
-     $msg_value =~ s/[-:]//g; +            } elsif ($f_param eq 'obstime') { 
-     $msg_value =~ s/ /./; +                # Convert to a pure numerical value (float) 
-     $f_value =~ s/[-:']//g; +                $msg_value =~ s/[-:]//g; 
-     $f_value =~ s/^ +//; +                $msg_value =~ s/ /./; 
-     $f_value =~ s/ +$//; +                $f_value =~ s/[-:']//g; 
-     $f_value =~ s/ /./;+                $f_value =~ s/^ +//; 
 +                $f_value =~ s/ +$//; 
 +                $f_value =~ s/ /./
 +            } elsif ($f_param eq 'name') { 
 +                # Add or correct quoting to "" and ignore casing 
 +                $msg_value = '"' . lc $msg_value . '"'; 
 +                $f_value = lc $f_value; 
 +                if ($f_value =~ /^'.*'$/) { 
 +                    $f_value =~ s/^'//; 
 +                    $f_value =~ s/'$//; 
 +                } 
 +                if ($f_value !~ /^".*"$/) { 
 +                    $f_value = '"' . $f_value . '"'; 
 +                } 
 +            } 
 +        } 
 + 
 + my $condition = "$msg_value $op $f_value"; 
 + # Some values should be string values 
 + if ($f_operator =~ /~/) { 
 +     $condition = "q{$msg_value} $op $f_value"; 
 + } elsif (grep {$_ eq $f_param} @ascii_params) { 
 +     $condition = "q{$msg_value} $op q{$f_value}";
  }  }
  
- # Finally, do the criterium check +        # Finally, do the criterium check 
-        if (eval "$msg_value $op $f_value") {+ if (eval $condition) {
      # No need to check the remaining alternative criteria      # No need to check the remaining alternative criteria
-            $i += $num_alt if $num_alt; +     $i += $num_alt if $num_alt; 
-            next; +     next; 
-        } else { + } else { 
-            next if $num_alt; +     next if $num_alt; 
-            return 1; +     return 1; 
-        }+ }
     }     }
  
Line 461: Line 536:
     return if !$req_stations;     return if !$req_stations;
     die "Station list must start with 'wmonr=', 'nationalnr=', "     die "Station list must start with 'wmonr=', 'nationalnr=', "
-        . "'call_sign=', 'buoy_id=' or aircraft='" +        . "'call_sign=', 'buoy_id=', 'aircraft=', 'icao_id' or 'wigosid='" 
-        unless $req_stations  +        unless $req_stations 
- =~ /^(wmonr=|nationalnr=|call_sign=|buoy_id=|aircraft=)/;+        =~ /^(wmonr=|nationalnr=|call_sign=|buoy_id=|aircraft=|icao_id=|wigosid=)/;
  
     my ($id, $rest) = split /=/, $req_stations;     my ($id, $rest) = split /=/, $req_stations;
Line 480: Line 555:
         my @req_stn;         my @req_stn;
         foreach my $station (@stations) {         foreach my $station (@stations) {
-     # Turn national station number into 10 digits +            # Turn national station number into 10 digits 
-     my ($state_id, $national_id) = split /_/, $station; +            my ($state_id, $national_id) = split /_/, $station; 
-     die "Uncorrected formatted station: '$station' in station list" +            die "Uncorrected formatted station: '$station' in station list" 
- if !defined $national_id or $national_id eq ''; +                if !defined $national_id or $national_id eq ''; 
-     $station = $state_id . '_' . sprintf("%010d", $national_id);+            $station = $state_id . '_' . sprintf("%010d", $national_id);
             push @req_stn, $station;             push @req_stn, $station;
         }         }
Line 524: 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 582: Line 657:
  
   bufrdump.pl <bufr file(s)>   bufrdump.pl <bufr file(s)>
-      [--filter <filter file>] +      [--filter <filter file | filter list>] 
-      [--param <parameter file | parameter list> [--csv]]+      [--param <parameter file | parameter list> [--csv [--delimiter <del>]]
       [--sort]       [--sort]
       [--sort_on <parameter>[-]]       [--sort_on <parameter>[-]]
       [--station <station list>]       [--station <station list>]
       [--transform <transformation file>]       [--transform <transformation file>]
-      [--lon1 x1] +      [--lon1 <x1>
-      [--lat1 y1] +      [--lat1 <y1>
-      [--lon2 x2] +      [--lon2 <x2>
-      [--lat2 x2]+      [--lat2 <y2>]
       [--obstype <amdar|ocea|surface|sounding|sounding->]       [--obstype <amdar|ocea|surface|sounding|sounding->]
       [--tablepath <path to BUFR tables>]       [--tablepath <path to BUFR tables>]
Line 611: Line 686:
  
  
-  --filter <filter file> +  --filter <filter file | filter list
-                  Decode observations meeting criteria in <filter fileonly +                  Decode observations meeting criteria in filter file or 
-  --param <parameter file | parameter list> [--csv] +                  filter list only 
-                  Print parameters in parameter file or comma separated +  --param <parameter file | parameter list> [--csv [--delimiter <del>]
-                  list (e.g. wmonr,TA) only, in same order as they occur +                  Print parameters in parameter file or comma 
-                  there. If --csv, the parameters vill be printed using +                  separated list (e.g. wmonr,TA) only, in same order 
-                  the CSV (comma separated values) format+                  as they occur there. If using --csv possibly 
 +                  followed by --delimiter <del>, the parameters vill 
 +                  be printed using the CSV (comma-separated values) 
 +                  format, with the delimiter del (default is ';')
   --sort          Sort the decoded observations on station identification;   --sort          Sort the decoded observations on station identification;
                   first stations with wmonr, then stations with nationalnr,                   first stations with wmonr, then stations with nationalnr,
-                  call sign, buoy_id or aircraft (others left out)+                  call_sign, buoy_idaircraft, icao_id or wigosid 
 +                  (others left out)
   --sort_on <parameter>[-] Sort the decoded observations on increasing   --sort_on <parameter>[-] Sort the decoded observations on increasing
-                  values of <parameter>, or decreasing values if a '-'+                  values of parameter, or decreasing values if a '-'
                   follows the parameter name. E.g. --sort_on TA- will                   follows the parameter name. E.g. --sort_on TA- will
                   sort on decreasing temperatures. Observations not                   sort on decreasing temperatures. Observations not
Line 628: Line 707:
                   except when --sort_on is combined with --sort (in which                   except when --sort_on is combined with --sort (in which
                   case sorting is done firstly on station identification,                   case sorting is done firstly on station identification,
-                  secondly on <parameterwith missing values printed first)+                  secondly on parameter with missing values printed first)
   --station <station list>   --station <station list>
                   Print observations for stations in station list only,                   Print observations for stations in station list only,
Line 634: Line 713:
   --transform <transformation file>   --transform <transformation file>
                   Do the transformations of parameter values listed in                   Do the transformations of parameter values listed in
-                  <transformation file> +                  transformation file 
-  --lon1 x1       Decode observations with longitude >= x1 only +  --lon1 <x1>     Decode observations with longitude >= x1 only 
-  --lat1 y1       Decode observations with latitude >= y1 only +  --lat1 <y1>     Decode observations with latitude >= y1 only 
-  --lon2 x2       Decode observations with longitude <= x2 only +  --lon2 <x2>     Decode observations with longitude <= x2 only 
-  --lat2 y2       Decode observations with latitude <= y2 only+  --lat2 <y2>     Decode observations with latitude <= y2 only
                   x1,y1,x2,y2 should be decimal degrees                   x1,y1,x2,y2 should be decimal degrees
   --obstype <amdar|ocea|surface|sounding|sounding->]   --obstype <amdar|ocea|surface|sounding|sounding->]
                   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
-                  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 653: Line 731:
  
 To avoid having to use the C<--tablepath> option, you are adviced to To avoid having to use the C<--tablepath> option, you are adviced to
-set the invironment variable BUFR_TABLES to the directory where your+set the environment variable BUFR_TABLES to the directory where your
 BUFR tables are located (unless the default path provided by BUFR tables are located (unless the default path provided by
 bufrdump.pl works for you). bufrdump.pl works for you).
Line 662: 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,call_sign,TA+  wmonr,nationalnr,call_sign,TA
  
 as argument to --params, or supply a <parameter file> which should as argument to --params, or supply a <parameter file> which should
Line 668: Line 746:
  
   wmonr   wmonr
 +  nationalnr
   call_sign   call_sign
   TA   TA
Line 688: Line 767:
 listing may for example start like listing may for example start like
  
-  wmonr,call_sign,TA +  wmonr;nationalnr;call_sign;TA 
-  01001,,-1.5 +  01001;;;-1.5 
-  ,LF5U,9.0+  ;;LF5U;9.0 
 + 
 +You can choose another delimiter than semicolon by use of option 
 +--delimiter <del>, e.g. --csv --delimiter ','
  
 Using --filter will decode only those observations that meet at least Using --filter will decode only those observations that meet at least
Line 696: 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 <param> or <param> <operator> <value> +criteria which should match <param> or !<param> or <param> <operator> 
-where operator is one of =, !=, <, <=, > and >=. The parameter+<value> where operator is one of =, !=, =~, !~, <, <=, > and >=. What 
 +follows =~ and !~ should be a Perl match regular expression. The parameter
 criteria may be phrased as alternatives by separating them with '|' on criteria may be phrased as alternatives by separating them with '|' on
 a single line. An example filter file is a single line. An example filter file is
Line 716: 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 stations and +specific wmo stations and one specific ship, where stations should be 
-having cloud cover different from 8 (but NN must be part of the +manned and have cloud cover with a value different from 8and have 
-message) and temperature between 5 and 9.5 degrees Celsius and +temperature between 5 and 9.5 degrees Celsiusand contain 
-containing precipitation for last 24 hours. Comment lines starting +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!)
  
  
-  wmonr+  call_sign =~ /^L[A-N]..$/
   obstime >= '2012-02-10 06:00:00'   obstime >= '2012-02-10 06:00:00'
-  RR_1 RR_12 RR_24 +  HW HWA PW | PWA 
-  TA < -30 | TA > 30+  FF > 10 FG_010 > 10 
 + 
 +will print only those ship observations for which the 4 character 
 +call_sign starts with 2 letters in the interval LA-LN, and having 
 +obstime larger or equal to the datetime given, and containing wave 
 +data (specifically: height or period of waves, manually or 
 +automatically measured), and with wind or 10 minutes gust more than 10 
 +m/s. 
 + 
 +For convenience, when there are no BUFR descriptor criteria, you might 
 +provide the filter criteria on the command line. Example: 
 + 
 +--filter 'wmonr,TA > 0,RR_12 | RR_24, !FF'
  
-will print only those observations containing a wmonr (skipping ships+will decode only observations with wmonr, having positive temperature 
-and having obstime larger or equal to the datetime given, and +and containing precipitation for 12 or 24 hours and not reporting 
-containing precipitation for 1, 12 or 24 hoursand having temperature +wind. If (like for --param) the filter list consists of one criterium 
-below minus 30 or above plus 30 degrees Celsius.+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 744: Line 839:
   --station buoyid=64607,64609   --station buoyid=64607,64609
   --station aircraft=EU3421,JHCWUURA   --station aircraft=EU3421,JHCWUURA
 +  --station icao_id=ENGM,ENBO
 +  --station wigosid=0-376-0-511,0-20000-0-01492
  
 You cannot mix different kinds of stations this way (before '=' you You cannot mix different kinds of stations this way (before '=' you
-must choose either wmonr, nationalnr, call_sign, buoy_id or +must choose either wmonr, nationalnr, call_sign, buoy_idaircraft
-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, compared to using option --station. It is execution time considerably, compared to using option --station. It is
  • bufr.pm/bufrdump.pl_source.1329313345.txt.gz
  • Last modified: 2022-05-31 09:23:11
  • (external edit)