#! /usr/bin/perl # A script to query for LAADS DAAC data resources by temporal and geographic region, # and download the resulting list of files (if any found) use warnings; use strict; use JSON; use Time::Piece; use Getopt::Long; my $VERSION = '1.2'; use Data::Dumper; # File scope variables: my $NAMESPACE = 'api/v2/content/details'; my @IN_FORMATS = ( # supported input date/time formats '%F %T', '%FT%T', '%F', '%Y-%j %T', '%Y-%j', '%Y%j %T', '%Y%j', ); # do not change... my $DATE_FORMAT = '%FT%T'; # default values for command line switches... my $help = 0; my $print_only = 0; my %options = ( 'host' => 'https://ladsweb.modaps.eosdis.nasa.gov', 'archiveSet' => 61, 'start_time' => date_format('today'), 'end_time' => date_format('today'), 'collection' => 61, # search the whole globe... 'north' => 90.0, 'south' => -90.0, 'east' => 180.0, 'west' => -180.0, 'token' => 0, ); # read in command line switches... GetOptions( \%options, 'domain|d=s' => \$options{host}, 'key|k=s' => \$options{token}, 'start_time|t=s' => \$options{start_time}, 'end_time|u=s' => \$options{end_time}, 'archiveSet|a=s' => \$options{archiveSet}, 'north_bound|n=f' => \$options{north}, 'south_bound|s=f' => \$options{south}, 'east_bound|e=f' => \$options{east}, 'west_bound|w=f' => \$options{west}, 'help|h' => \$help, 'print|P' => \$print_only, ); usage() if $help; # format date/times... my $start_time = date_format($options{start_time}); my $end_time = date_format($options{end_time}); # and the rest of the command line... my @products = @ARGV; usage("ERROR: No products specified") unless scalar @products; usage("ERROR: No token specified") unless $options{token} or $print_only; foreach my $product (@products) { # construct the request my $req_str = "$options{host}/$NAMESPACE?"; $req_str .= join('&', "products=$product", "archiveSets=$options{archiveSet}", "temporalRanges=$start_time..$end_time", "regions=[BBOX]W$options{west}%20N$options{north}%20E$options{east}%20S$options{south}", ); # query the Web Service for a list of files matching the specified command line parameters. # the "-g" option turns off the curl globbing parser, which allows the [] characters, # used in the regions parameter, to function correctly. # the -s option turns off curl's stderr output, making the script's output easier to read and follow # or if the SSL version is not up to date # the -b option turns on the cookie processor, which allows curl to # forward session cookies during redirects # the -L option allows curl to follow redirects. This is necessary if using an # Earthdata Login token # the -C - option allows curl to continue where it left off if the connection # is lost, then regained my $json_str = qx{curl -L -b session -s -g --header 'Authorization: Bearer $options{token} -C - ' '$req_str'}; if ($json_str) { # convert JSON output to perl variable my $listing = decode_json($json_str); # download the files. if ($listing && ref $listing->{content} eq 'ARRAY') { foreach my $entry (@{$listing->{content}}) { my $url = "$entry->{downloadsLink}"; next unless $url; # skip files not available if ($print_only) { warn "would download file : $url\n"; } else { my $cmd = "curl -L -b session -s -g --header 'Authorization: Bearer $options{token} -C - ' '$url' > $entry->{name}"; my $result = system($cmd); if ($result == 0) { warn "downloaded '$url'\n"; } else { warn "FAIL : $cmd\n"; } } } # end foreach entry in listing } else { warn "\nno files found for product=$product from $start_time..$end_time\n", " in region [BBOX]W$options{west} N$options{north} E$options{east} S$options{south}\n\n"; } } else { warn "no json from endpoint\n"; } warn "\n"; } # end foreach product # all done warn "\nDone\n"; exit(0); #------------------------------------------------------------ # usage -- print usage message. #------------------------------------------------------------ sub usage { if (scalar @_) { print join("\n", @_), "\n"; } print <<"USAGE_END"; VERSION = $VERSION; USAGE: stage_MODIS.pl product WHERE: options are... -d 'domain' --domain 'domain' service domain (e.g. https://ladsweb.modaps.eosdis.nasa.gov or for near real time data https://nrt3.modaps.eosdis.nasa.gov https://nrt4.modaps.eosdis.nasa.gov ) -k 'download key' --key 'download key' download key (token) obtained from service -a N --archiveSet N number indicating the MODAPS ArchiveSet to search -t 'date time' --start_time 'date time' data start date time (time should be 24 hr) -u 'date time' --end_time 'date time' data end date time (time should be 24 hr) -n F --north_bound F north bound of area of interest, decimal degrees -s F --south_bound F south bound of area of interest, decimal degrees -w F --west_bound F west bound of area of interest, decimal degrees -n F --east_bound F east bound of area of interest, decimal degrees -P --print print file download URLs in the terminal, but don't download them NOTE: We recommend using GNU "wget" for downloads, since it has more complete error handling. - see https://www.gnu.org/software/wget/ - for Windows, try https://gnuwin32.sourceforge.net/packages/wget.htm USAGE_END exit(0); } #------------------------------------------------------------ # date_format -- return time string in date/time format # that the web service understands if the input time # string is valid, else today's date. #------------------------------------------------------------ sub date_format { my ($in_time_str) = @_; return undef unless $in_time_str; my $now_str = Time::Piece->localtime->strftime('%F %T'); $in_time_str = $now_str if $in_time_str =~ /today/i; $in_time_str = $now_str unless $in_time_str; warn "\nparsing $in_time_str\n"; my $tt = undef; foreach my $in_format (@IN_FORMATS) { eval { warn " trying $in_format\n"; $tt = Time::Piece->strptime($in_time_str, $in_format); }; if ($tt) { warn "matched $in_format\n\n"; last; } } return $tt->strftime($DATE_FORMAT) if $tt; warn "don't understand $in_time_str\nusing now for time\n"; return $now_str; } __END__ # some test cases. # for the following, the file does not exist stage_MODIS.pl -a 2 --start_time '2001-05-21' --end_time '2001-05-25' -P MOD15A2GFS # for the following, expect one file stage_MODIS.pl -a 61 -w -100 -n 30 -s 25 -e -90 -t '2002-123 00:00:00' -u '2002-123 23:59:59' -P MOD03 MOD04_L2 MOD07_L2