Weather-GHCN-Fetch

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

  - for API use, provided an optional parameter to StationTable::load_stations to receive the station text
  - corrected some API POD related to the now defunct user_options and profile_options hashes in set_options
  - eliminated multiple declarations of $PROFILE_FILE
  - moved _get_profile_options and _get_profile_filespec from StationTable to Options
  - renamed _get_profile_options and _get_profile_filespec to get_profile_options and get_profile_filespec
  - moved testing of get_profile_options and get_profile_filespec from 22 to 14_options.t
  - added a cache maintenance utility script (ghcn_cache)
  - removed check for valid cachedir that was preventing ghcn_fetch working without a cache
  - eliminated uninitialized warning in kml report when a station active range has only one value (i.e. end = start)
  - fixed a problem causing ghcn_fetch to croak when both -cachedir and -profile are empty strings
  - fixed 91_ghcn_fetch.t 'output to clipboard' test, which was failing during dzil release


v0.0.010       2022-11-10
  - moved EXAMPLES POD from Fetch.pm to ghch_fetch
  - fixed: user prompt when stations found > 100 
  - fixed: broken URL in exported KML

v0.0.009       2022-10-23
  - fix Options::get_getopt_list so it handles aliases properly
  - require version 1.32 of Time::Piece so truncate is supported

Changes  view on Meta::CPAN

  - still some cleanup needed; apps not included
  - not for public use

v0.22.258      2022-09-15
  - As GHCN (never indexed, scheduled for deletion (2022-09-18)
  - Builds, passes tests, installs and runs ok on Windows and WSL Ubuntu
  - Change dist.in main_module to bin/ghcn_fetch.pl
  - gui works on Windows if Tk is installed
  - gui work on WSL Ubuntu using GWSL
  - Suppress printing the "Hash sizes" header when there are no hash statistics (i.e. when -report "").
  - Add some documentation in Readme.pm about the GUI and Windows clipboard support.
  - Replace Syntax::Keyword::Try with Try::Tiny
  - bug fixes


v0.22.257      2022-09-14
  - As GHCN (never indexed, scheduled for deletion (2022-09-18)
  - Builds, passes tests, installs and runs ok on Windows and WSL Ubuntu
  - Tk not tested
  - PAUSE upload failed (it didn't like main_module as lib/GHCN/StationTable.pm)
  

bin/ghcn_extremes  view on Meta::CPAN

from the x-axis, which not only distorts the picture, it can lead
to inaccurate trend analysis.

When -nogaps is specified, the script will fill in these gaps by
adding rows at the end with the missing years.  It will be necessary
to manually sort the table in Excel, or specify an ascending sort
order for the year axis, in order for charts to look correct.

=item -outclip

Send output to the Windows clipboard.

=item -h | -help

Display this documentation.

=back

=head1 INPUT

The input data is expected to be tab-separated, with columns year,

bin/ghcn_fetch  view on Meta::CPAN

Launch a graphic user interface that can be used to set options.
Not available unless modules Tk and Tk::Getopt are installed.

=item -savegui <filespec>

Designate a file to be used to save load options, or from which to
load options that were previously saved from the GUI.

=item -outclip

Send output to the Windows clipboard.  (Windows only)

=item -readme

Launch the default web browser and display the NOAA Daily Readme.txt
file, providing a description of the Daily data files and station
data.

=item -h | -help

Display this documentation.

bin/ghcn_fetch  view on Meta::CPAN

-location value matches a key defined in this section, the station id 
or id-list is substituted.  Note that keys must be lowercase letter 
only, and may have a leading underscore.

=head1 RELATED SCRIPTS

Additional scripts are provided for data analysis.  These scripts
are designed to take the output ghcn_fetch.

For Windows users, a -outclip option directs the tab-separated output
to the Windows clipboard, so it can be pasted into Excel for analysis
using PivotTable and PivotChart. Alternatively you can use the usual
'>' method to direct the output to a file.

=over 4

=item ghcn_extremes.pl

Report patterns of temperature extremes (heatwaves or coldwaves) by
analyzing daily temperature records and looking for consecutive days
of extreme temperatures; e.g.

bin/ghcn_station_counts  view on Meta::CPAN


Getoptions::Long is used, so either - or -- may be used.  Parameter
names may be abbreviated, so long as they remains unambiguous.  Flag
options may appear after filenames.

=over 4


=item -outclip

Send output to the Windows clipboard.

=item -debug

Enables debug() statements.

=item -h | -help

Display this documentation.

=back

lib/Weather/GHCN/App/CacheUtil.pm  view on Meta::CPAN


    if ($Opt->clean) {
        my @errors = $ghcn->cache_obj->clean_cache();
        if (@errors) {
            say {*STDERR} join "\n", @errors;
            exit 1;
        }
        return;
    }

    # send print output to the Windows clipboard if requested and doable
    outclip() if $Opt->outclip and $USE_WINCLIP;

    my $alias_href = get_alias_stnids($ghcn->profile_href);

    my $files_href = load_cached_files($ghcn, $cache_pto, $alias_href);
    
    if (keys $files_href->%* == 0) {
        say {*STDERR} '*I* cache is empty';
        return;
    }

lib/Weather/GHCN/App/CacheUtil.pm  view on Meta::CPAN

        'state|prov:s',         # filter by state or province
        'location:s',           # filter by localtime
        'remove',               # remove cached daily files (except aliases)
        'clean',                # remove all files from the cache
        'invert|v',             # invert -location selection criteria
        'size|kb:i',            # select files by size in Kb
        'age:i',                # select file if >= age
        'type:s',               # select based on type
        'cachedir:s',           # cache location
        'profile:s',            # profile file
        'outclip',              # output data to the Windows clipboard
        'help','usage|?',       # help
    );

    my %opt;

    # create a list of option key names by stripping the various adornments
    my @keys = map { (split m{ [!+=:|] }xms)[0] } grep { !ref  } @options;
    # initialize all possible options to undef
    @opt{ @keys } = ( undef ) x @keys;

lib/Weather/GHCN/App/CacheUtil.pm  view on Meta::CPAN


Since Windows::Clipboard is platform specific, calls to this subroutine
should conditional.  The following pattern is recommended:

    # modules for Windows only
    use if $OSNAME eq 'MSWin32', 'Win32::Clipboard';

    # is it ok to use Win32::Clipboard?
    our $USE_WINCLIP = $OSNAME eq 'MSWin32';

    # send print output to the Windows clipboard if requested and doable
    outclip() if $Opt->outclip and $USE_WINCLIP;

    ... print stuff
    
    # restore print output to stdout
    outclip() if $Opt->outclip and $USE_WINCLIP;

This subroutine relies on state variables.  It cannot be used in a 
nested fashion.  It is best confined to main:: (or the top-level 
subroutine).

lib/Weather/GHCN/App/Extremes.pm  view on Meta::CPAN


            while ( my ( $from, $to ) = $iter->() ) {
                foreach my $yr ($from .. $to) {
                    say join $TAB, $stnid, $Location{$stnid}, $yr;
                }
            }
        }
    }

WRAP_UP:
    # send output to the Windows clipboard
    if ( $Opt->outclip and $USE_WINCLIP ) {
        Win32::Clipboard->new()->Set( $output );
        select $old_fh; ## no critic [ProhibitOneArgSelect]
    }

    return;
}

########################################################################
# Script-specific Subroutines

lib/Weather/GHCN/App/Extremes.pm  view on Meta::CPAN

=cut

sub get_options ($argv_aref) {

    my @options = (
        'limit=i',              # lower bound of extremes daily temperature
        'ndays=i',              # number of consecutive days needed to be a extremes
        'peryear',              # report number of heatwaves per year
        'cold',                 # report coldwaves instead of heatwaves
        'nogaps',               # generate a line for missing years (for charting)
        'outclip',              # output data to the Windows clipboard
        'help','usage|?',       # help
    );

    my %opt;

    # create a list of option key names by stripping the various adornments
    my @keys = map { (split m{ [!+=:|] }xms)[0] } grep { !ref  } @options;
    # initialize all possible options to undef
    @opt{ @keys } = ( undef ) x @keys;

lib/Weather/GHCN/App/Fetch.pm  view on Meta::CPAN

our $USE_TK      = can_load( modules => $TK_MODULES );

my $Opt;    # options object, with property accessors for each user option

# options that relate to script execution, not GHCN processing and output
my $Opt_savegui;    # file in which to save options from GUI dialog
my $Opt_gui;        # launch the GUI dialog
my $Opt_help;       # display POD documentation
my $Opt_readme;     # print the text of the GHCN readme file
my $Opt_usage;      # display a synopsis of the command line syntax
my $Opt_outclip;    # send report output to the Windows clipboard instead of STDOUT

########################################################################
# Constants
########################################################################

const my $EMPTY  => q();       # empty string
const my $SPACE  => q( );      # space character
const my $DASH   => q(-);      # dash character
const my $TAB    => qq(\t);    # tab character
const my $NL     => qq(\n);    # perl universal newline (any platform)

lib/Weather/GHCN/App/Fetch.pm  view on Meta::CPAN

    if ( $Opt->performance ) {
        say $EMPTY;
        say sprintf 'Timing statistics (ms) and memory [bytes]';
        say $ghcn->get_timing_stats;

        say $EMPTY;
        say $ghcn->get_hash_stats;
    }

WRAP_UP:
    # send output to the Windows clipboard
    if ( $Opt_outclip and $USE_WINCLIP ) {
        Win32::Clipboard->new()->Set( $output );
        select $old_fh;     ## no critic [ProhibitOneArgSelect]
    }

    return;
}

########################################################################
# Subroutines

lib/Weather/GHCN/App/StationCounts.pm  view on Meta::CPAN

    say join "\t", qw(Year Decade Stn_Count);

    foreach my $yr (sort { $a <=> $b } keys %count) {
        my $stn_count = keys %{ $count{$yr} };
        ## no critic [ProhibitMagicNumbers]
        my $decade = (substr $yr, 0, 3) . '0s';
        say sprintf "%3d\t%s\t%d", $yr, $decade, $stn_count;
    }

WRAP_UP:
    # send output to the Windows clipboard
    if ( $Opt->outclip and $USE_WINCLIP ) {
        Win32::Clipboard->new()->Set( $output );
        select $old_fh; ## no critic [ProhibitOneArgSelect]
    }


    return;
}

########################################################################

lib/Weather/GHCN/App/StationCounts.pm  view on Meta::CPAN


By convention, you should set up a file-scoped lexical variable named
$Opt and set it in the mainline using the return value from this function.
Then all options can be accessed used $Opt->option notation.

=cut

sub get_options ($argv_aref) {

    my @options = (
        'outclip',              # output data to the Windows clipboard
        'debug',                # enable debug() statements on stderr
        'help','usage|?',       # help
    );

    my %opt;

    # create a list of option key names by stripping the various adornments
    my @keys = map { (split m{ [!+=:|] }xms)[0] } grep { !ref  } @options;
    # initialize all possible options to undef
    @opt{ @keys } = ( undef ) x @keys;

t/91_ghcn_fetch.t  view on Meta::CPAN

    @opttable = ( Weather::GHCN::Options->get_tk_options_table() );
    my $valid_rt = Weather::GHCN::Options->valid_report_type('detail',\@opttable);
    ok $valid_rt,  'valid_report_type - detail valid';
    ok !Weather::GHCN::Options->valid_report_type('xxx',\@opttable),     'valid_report_type - xxx invalid';

    my $ro = Weather::GHCN::Options->valid_refresh_option('never',\@opttable);
    ok  $ro,'valid_refresh_option - never valid';
    ok !Weather::GHCN::Options->valid_refresh_option('xxx',\@opttable),  'valid_refresh_option - xxx invalid';
};

subtest 'output to clipboard' => sub {
    
    if ( not check_install( module => 'Win32::Clipboard') ) {
        plan skip_all => 'no Win32::Clipboard';
    }

    my $clip = Win32::Clipboard();
    $clip->Empty();
    @args = (
        '-country',     'US',
        '-state',       'NY',

t/91_ghcn_fetch.t  view on Meta::CPAN

        '-refresh',     'never',
        '-profile',     $PROFILE,
        '-cachedir',    $Cachedir,
        '-outclip',
    );
    my $got;
    ($stdout, $stderr) = capture {
        Weather::GHCN::App::Fetch->run( \@args );
        $got = $clip->Get();
    };
    like $got, qr/Year\s+Decade\s+TMAX\s+TMIN.*?\d{4}/ms, 'clipboard output';
};

subtest 'kml and color options' => sub {
    @args = (
        '-report',      'kml',
        '-kmlcolor',    'azure',
        '-location',    'CA006105976,CA006105978',
        '-refresh',     'never',
        '-profile',     $PROFILE,
        '-cachedir',    $Cachedir,

t/94_ghcn_cacheutil.t  view on Meta::CPAN

subtest 'report_daily_files' => sub {
    my $total_kb;
    my ($stdout, $stderr) = capture {
        $total_kb = CU::report_daily_files($Files_href);       
    };
    ok $total_kb > 0, 'report_daily_files returned non-zero kb';
    like $stdout, qr/T StationId/, 'report_daily_files generated output';
};

subtest '-outclip' => sub {
    plan skip_all => 'testing clipboard output seems to fail during dzil -release';
};

done_testing();

######################################################################
# Subroutines
######################################################################

sub syserror {
    if ($? == -1) {



( run in 3.251 seconds using v1.01-cache-2.11-cpan-84e82930d8c )