#!/bin/perl sub grid_jpl () { # some JPL exceptions $missing_value_value = 'nan'; $Fill_value_value = 'nan'; $institution_code_value = $institution_value; $institution_code_value =~ s/ /_/g; $platform_code_value = 'quikscat'; $package_code_value = 'quikscat'; # Assume this data is on a normal grid, and assume that the variable # names are fixed and agreed upon, i.e. no :standard_name attrs. # # Loop through variables my $this_var_name = ''; my $this_var_type = ''; my $this_var_dims = ''; my @this_var_dimid = ''; for ($i = 0; $i < $nvars; $i++) { my $varinq = NetCDF::varinq($ncid, $i, \$this_var_name, \$this_var_type, \$this_var_dims, \@this_var_dimid, \$this_var_natts); if ($varinq < 0) {die "ABORT! Cannot get to variables.\n";} if ($this_var_name =~ /^lon_range$/) { if ($this_var_dims != 1) {die "ABORT! lon_range has incorrect number of dimensions.\n";} %lon_range_var = ( var_name => $this_var_name, var_id => $i, dim_id => $this_var_dimid[0] ); } elsif ($this_var_name =~ /^lat_range$/) { if ($this_var_dims != 1) {die "ABORT! lat_range has incorrect number of dimensions.\n";} %lat_range_var = ( var_name => $this_var_name, var_id => $i, dim_id => $this_var_dimid[0] ); } elsif ($this_var_name =~ /^grid_spacing$/) { if ($this_var_dims != 1) {die "ABORT! grid_spacing has incorrect number of dimensions.\n";} %grid_spacing_var = ( var_name => $this_var_name, var_id => $i, dim_id => $this_var_dimid[0] ); } elsif ($this_var_name =~ /^grid_dimensions$/) { if ($this_var_dims != 1) {die "ABORT! grid_dimensions has incorrect number of dimensions.\n";} %grid_dimensions_var = ( var_name => $this_var_name, var_id => $i, dim_id => $this_var_dimid[0] ); } elsif ($this_var_name =~ /^epoch_time_range$/) { if ($this_var_dims != 1) {die "ABORT! epoch_time_range has incorrect number of dimensions.\n";} %epoch_time_range_var = ( var_name => $this_var_name, var_id => $i, dim_id => $this_var_dimid[0] ); } # push all wind_speed's onto a stack elsif ($this_var_name =~ /^wind_speed$/) { %this_wind_speed = ( var_name => $this_var_name, var_id => $i, dim_id_npnts => $this_var_dimid[0], height => '', can_be_normalized => '' ); push @wind_speed, {%this_wind_speed}; } # push all wind_from_direction's onto a stack elsif ($this_var_name =~ /^wind_direction$/) { %this_wind_from_direction = ( var_name => $this_var_name, var_id => $i, dim_id_npnts => $this_var_dimid[0], height => '', can_be_normalized => '' ); push @wind_from_direction, {%this_wind_from_direction}; } } # # Get the dimensions and their sizes. # side { my $this_dim_size = ''; my $this_dim_name = ''; my $this_dim_id = NetCDF::dimid($ncid,'side'); my $diminq = NetCDF::diminq($ncid,$this_dim_id,\$this_dim_name,\$this_dim_size); if ($diminq >= 0) { $side_dim{'dim_id'} = $this_dim_id; $side_dim{'dim_name'} = $this_dim_name; $side_dim{'dim_size'} = $this_dim_size; } else { die "ABORT! Error $diminq getting side dimension.\n"; } # print "side dim_name [$side_dim{'dim_name'}] dim_size [$side_dim{'dim_size'}]\n"; } # npnts { my $this_dim_size = ''; my $this_dim_name = ''; my $this_dim_id = NetCDF::dimid($ncid,'npnts'); my $diminq = NetCDF::diminq($ncid,$this_dim_id,\$this_dim_name,\$this_dim_size); if ($diminq >= 0) { $npnts_dim{'dim_id'} = $this_dim_id; $npnts_dim{'dim_name'} = $this_dim_name; $npnts_dim{'dim_size'} = $this_dim_size; } else { die "ABORT! Error $diminq getting npnts dimension.\n"; } # print "npnts dim_name [$npnts_dim{'dim_name'}] dim_size [$npnts_dim{'dim_size'}]\n"; } # # Check to make sure that the required variables have # the correct dimensions listed, e.g. latitude(latitude), longitude(longitude), etc. # lon_range if ($lon_range_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! lon_range variable does not have correct side dimension.\n"; } # lat_range if ($lat_range_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! lat_range variable does not have correct side dimension.\n"; } # grid_spacing if ($grid_spacing_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! grid_spacing variable does not have correct side dimension.\n"; } # grid_dimensions if ($grid_dimensions_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! grid_dimensions variable does not have correct side dimension.\n"; } # epoch_time_range if ($epoch_time_range_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! epoch_time_range variable does not have correct side dimension.\n"; } # # Get the data of the required elements. @lon_range_values = ''; @lat_range_values = ''; @grid_spacing_values = ''; @grid_dimensions_values = ''; @epoch_time_range_values = ''; my $positive_value = ''; # lon_range (vector) $varget = NetCDF::varget($ncid, $lon_range_var{'var_id'}, (0), $side_dim{'dim_size'}, \@lon_range_values); if ($varget < 0) {die "ABORT! Cannot get lon_range values.\n";} # lat_range (vector) $varget = NetCDF::varget($ncid, $lat_range_var{'var_id'}, (0), $side_dim{'dim_size'}, \@lat_range_values); if ($varget < 0) {die "ABORT! Cannot get lat_range values.\n";} # grid_spacing (vector) $varget = NetCDF::varget($ncid, $grid_spacing_var{'var_id'}, (0), $side_dim{'dim_size'}, \@grid_spacing_values); if ($varget < 0) {die "ABORT! Cannot get grid_spacing values.\n";} # grid_dimensions (vector) $varget = NetCDF::varget($ncid, $grid_dimensions_var{'var_id'}, (0), $side_dim{'dim_size'}, \@grid_dimensions_values); if ($varget < 0) {die "ABORT! Cannot get grid_dimensions values.\n";} # epoch_time_range (vector) $varget = NetCDF::varget($ncid, $epoch_time_range_var{'var_id'}, (0), $side_dim{'dim_size'}, \@epoch_time_range_values); if ($varget < 0) {die "ABORT! Cannot get epoch_time_range values.\n";} # time's @this_time_data = (); @this_time_formatted_value = ''; # this variable's dimension better be (side) if ($epoch_time_range_var{'dim_id'} != $side_dim{'dim_id'}) { die "ABORT! $epoch_time_range_var{'var_name'} has wrong dimension. Should be side.\n"; } else { # get all the variable goodies @this_time_slice = $side_dim{'dim_size'}; @zero_offset = (0); $varget = NetCDF::varget($ncid, $epoch_time_range_var{'var_id'}, \@zero_offset, \@this_time_slice, \@this_time_data); if ($varget < 0) {die "ABORT! Cannot get $epoch_time_range_var{'var_name'} data.\n";} # get time units my $units_value = ''; my $attget = NetCDF::attget($ncid, $epoch_time_range_var{'var_id'}, 'units', \$units_value); if ($attget < 0) {die "ABORT! $epoch_time_range_var{'var_name'} has no units.\n";} if (substr($units_value,length($units_value)-1) eq chr(0)) {chop($units_value);} my $base_time = UDUNITS::scan('secs since 1970-1-1 (UTC)') || die "ABORT! Error with $epoch_time_range_var{'var_name'} units.\n"; $base_time->istime() || die "ABORT! Invalid units for $epoch_time_range_var{'var_name'}.\n"; # going to average the times for one time value $total_time = 0; for my $i (0..$#this_time_data) { $total_time += $this_time_data[$i]; } $averaged_time = $total_time / ($#this_time_data+1); # convert the time value to new value based on the time units my $this_time_value = $base_time->valtocal($averaged_time, $base_year, $base_month, $base_day, $base_hour, $base_minute, $base_second) == 0 || die "ABORT! Invalid units for $time_var{'var_name'}.\n"; # format the time values for database insertion (no timezone right now) $this_time_formatted_value = $base_year.'-' .sprintf("%02d",$base_month).'-' .sprintf("%02d",$base_day).' ' .sprintf("%02d",$base_hour).':' .sprintf("%02d",$base_minute).':' .sprintf("%02d",$base_second); # this is overkill (since there is only 1 time) but in keeping w/ the rest of the CDL .pl push @{$epoch_time_range_var{'data'}}, $this_time_formatted_value; } # wind_speed's @this_wind_speed_data = (); for $i (0..$#wind_speed) { # this variable's dimensions better be (npnts) if ($wind_speed[$i]{'dim_id_npnts'} != $npnts_dim{'dim_id'}) { die "ABORT! $wind_speed[$i]{'var_name'} has wrong dimension.\n"; } else { # get all the variable goodies @this_wind_speed_slice = ($npnts_dim{'dim_size'}); @zero_offset = (0); $varget = NetCDF::varget($ncid, $wind_speed[$i]{'var_id'}, \@zero_offset, \@this_wind_speed_slice, \@this_wind_speed_data); if ($varget < 0) {die "ABORT! Cannot get $wind_speed[$i]{'var_name'} data.\n";} # get all the attributes for this variable my $name = ''; my $nc_type = ''; my $ndims = ''; my @dimids = ''; my $natts = ''; # we need to loop through the attributes, so find out how many there are my $varinq = NetCDF::varinq($ncid, $wind_speed[$i]{'var_id'}, \$name, \$nc_type, $ndims, \@dimids, \$natts); if ($varinq < 0) {die "ABORT! Cannot get $wind_speed[$i]{'var_name'} attributes.\n";} for my $k (0..$natts-1) { # find out about each attribute my $this_attname = ''; my $attname = NetCDF::attname($ncid, $wind_speed[$i]{'var_id'}, $k, \$this_attname); if ($attname < 0) {die "ABORT! Cannot get $wind_speed[$i]{'var_name'} $k attribute.\n";} # is this a height? if ($this_attname eq $height_var{'var_name'}) { my $attval = ''; my $attget = NetCDF::attget($ncid, $wind_speed[$i]{'var_id'}, $this_attname, \$attval); if ($attget < 0) {die "ABORT! Cannot get $wind_speed[$i]{'var_name'} $k attribute.\n";} if (substr($attval,length($attval)-1) eq chr(0)) {chop($attval);} $wind_speed[$i]{'height'} = $attval; } elsif ($this_attname eq 'can_be_normalized') { my $attval = ''; my $attget = NetCDF::attget($ncid, $wind_speed[$i]{'var_id'}, $this_attname, \$attval); if ($attget < 0) {die "ABORT! Cannot get $wind_speed[$i]{'var_name'} $k attribute.\n";} if (substr($attval,length($attval)-1) eq chr(0)) {chop($attval);} $wind_speed[$i]{'can_be_normalized'} = $attval; } } # abort if we didn't have an height attribute # cpurvis temp fix # if ($wind_speed[$i]{'height'} == '') { # die "ABORT! $wind_speed[$i]{'var_name'} has no height.\n"; # } # add a NULL where missing value for my $j (0..$#this_wind_speed_data) { push @{$wind_speed[$i]{'data'}}, $this_wind_speed_data[$j]; } } } # wind_from_direction's @this_wind_from_direction_data = (); for $i (0..$#wind_from_direction) { # this variable's dimensions better be (npnts) if ($wind_from_direction[$i]{'dim_id_npnts'} != $npnts_dim{'dim_id'}) { die "ABORT! $wind_from_direction[$i]{'var_name'} has wrong dimension.\n"; } else { # get all the variable goodies @this_wind_from_direction_slice = ($npnts_dim{'dim_size'}); @zero_offset = (0); $varget = NetCDF::varget($ncid, $wind_from_direction[$i]{'var_id'}, \@zero_offset, \@this_wind_from_direction_slice, \@this_wind_from_direction_data); if ($varget < 0) {die "ABORT! Cannot get $wind_from_direction[$i]{'var_name'} data.\n";} # get all the attributes for this variable my $name = ''; my $nc_type = ''; my $ndims = ''; my @dimids = ''; my $natts = ''; # we need to loop through the attributes, so find out how many there are my $varinq = NetCDF::varinq($ncid, $wind_from_direction[$i]{'var_id'}, \$name, \$nc_type, $ndims, \@dimids, \$natts); if ($varinq < 0) {die "ABORT! Cannot get $wind_from_direction[$i]{'var_name'} attributes.\n";} for my $k (0..$natts-1) { # find out about each attribute my $this_attname = ''; my $attname = NetCDF::attname($ncid, $wind_from_direction[$i]{'var_id'}, $k, \$this_attname); if ($attname < 0) {die "ABORT! Cannot get $wind_from_direction[$i]{'var_name'} $k attribute.\n";} # is this a height? if ($this_attname eq $height_var{'var_name'}) { my $attval = ''; my $attget = NetCDF::attget($ncid, $wind_from_direction[$i]{'var_id'}, $this_attname, \$attval); if ($attget < 0) {die "ABORT! Cannot get $wind_from_direction[$i]{'var_name'} $k attribute.\n";} if (substr($attval,length($attval)-1) eq chr(0)) {chop($attval);} $wind_from_direction[$i]{'height'} = $attval; } elsif ($this_attname eq 'can_be_normalized') { my $attval = ''; my $attget = NetCDF::attget($ncid, $wind_from_direction[$i]{'var_id'}, $this_attname, \$attval); if ($attget < 0) {die "ABORT! Cannot get $wind_from_direction[$i]{'var_name'} $k attribute.\n";} if (substr($attval,length($attval)-1) eq chr(0)) {chop($attval);} $wind_from_direction[$i]{'can_be_normalized'} = $attval; } } # abort if we didn't have an height attribute # cpurvis temp fix # if ($wind_from_direction[$i]{'height'} == '') { # die "ABORT! $wind_from_direction[$i]{'var_name'} has no height.\n"; # } # add a NULL where missing value for my $j (0..$#this_wind_from_direction_data) { $this_dir = $this_wind_from_direction_data[$j] - 180; if ($this_dir < 0) { $this_dir += 360; } elsif ($this_dir > 360) { $this_dir -= 360; } # push @{$wind_from_direction[$i]{'data'}}, (180.0 - $this_wind_from_direction_data[$j]); push @{$wind_from_direction[$i]{'data'}}, $this_dir; } } } # # write data to file(s) # wind_speed and wind_from_direction # assume that wind_speed and wind_from_direction have an ordered, 1:1 relationship if ($#wind_speed > -1) { # need time and rand as part of filename since PO.DAAC isn't using *latest convention open(WIND_SQLFILE,'>../sql_grid_jpl/quickscat_wind_stage_'.$institution_code_value.'_' .$platform_code_value.'_'.$package_code_value.'_' .time.'_'.rand() .'.sql'); print WIND_SQLFILE "-- format_category = $format_category_value\n"; print WIND_SQLFILE "-- institution_code = $institution_code_value\n"; print WIND_SQLFILE "-- platform_code = $platform_code_value\n"; print WIND_SQLFILE "-- package_code = $package_code_value\n"; print WIND_SQLFILE "-- title = $title_value\n"; print WIND_SQLFILE "-- institution = $institution_value\n"; print WIND_SQLFILE "-- institution_url = $institution_url_value\n"; print WIND_SQLFILE "-- institution_dods_url = $institution_dods_url_value\n"; print WIND_SQLFILE "-- source = $source_value\n"; print WIND_SQLFILE "-- references = $references_value\n"; print WIND_SQLFILE "-- contact = $contact_value\n"; print WIND_SQLFILE "-- missing_value = $missing_value_value\n"; print WIND_SQLFILE "-- _FillValue = $Fill_value_value\n"; for my $wind_index (0..$#wind_speed) { $i = 0; $j = 0; for my $k (0..$#this_wind_speed_data) { if ($i == $grid_dimensions_values[0]) { $i = 0; $j++; } # $lon = $min_lon + $i * $grid_size_lon $longitude = $lon_range_values[0] + $i * $grid_spacing_values[0]; # $lat = $max_lat - $j * $grid_size_lat $latitude = $lat_range_values[1] - $j * $grid_spacing_values[1]; if (!($wind_speed[$wind_index]{'data'}[$k] =~ /$missing_value_value/ && $wind_speed[$wind_index]{'data'}[$k] =~ /$Fill_value_value/ && $wind_from_direction[$wind_index]{'data'}[$k] =~ /$missing_value_value/ && $wind_from_direction[$wind_index]{'data'}[$k] =~ /$Fill_value_value/)) { print WIND_SQLFILE "INSERT INTO quickscat_wind_stage ("; print WIND_SQLFILE "station_id,"; print WIND_SQLFILE "time_stamp,"; # print WIND_SQLFILE "orbit,"; print WIND_SQLFILE "z,"; print WIND_SQLFILE "positive,"; print WIND_SQLFILE "wind_speed,"; print WIND_SQLFILE "wind_from_direction,"; print WIND_SQLFILE "can_be_normalized,"; print WIND_SQLFILE "title,"; print WIND_SQLFILE "institution,"; print WIND_SQLFILE "institution_url,"; print WIND_SQLFILE "institution_dods_url,"; print WIND_SQLFILE "source,"; print WIND_SQLFILE "refs,"; print WIND_SQLFILE "contact,"; print WIND_SQLFILE "the_geom"; print WIND_SQLFILE ") "; print WIND_SQLFILE "VALUES ("; print WIND_SQLFILE '\''.$institution_code_value.'_'.$platform_code_value.'_'.$package_code_value.'\''; print WIND_SQLFILE ','.'timestamp without time zone \''.$epoch_time_range_var{'data'}[0].'\''; # print WIND_SQLFILE ',\'\''; # temp fix cpurvis $wind_speed[$wind_index]{'height'} = 15.0; if ($wind_speed[$wind_index]{'height'} == $missing_value_value || $wind_speed[$wind_index]{'height'} == $Fill_value_value) { print WIND_SQLFILE ','.'\'\''; } else { $this_val = sprintf("%.2f",$wind_speed[$wind_index]{'height'}); print WIND_SQLFILE ','.$this_val; } print WIND_SQLFILE ','.'\''.$height_var{'positive'}.'\''; $this_val = sprintf("%.2f",$wind_speed[$wind_index]{'data'}[$k]); print WIND_SQLFILE ','.$this_val; $this_val = sprintf("%.2f",$wind_from_direction[$wind_index]{'data'}[$k]); print WIND_SQLFILE ','.$this_val; print WIND_SQLFILE ','.'\''.$wind_speed[$wind_index]{'can_be_normalized'}.'\''; print WIND_SQLFILE ','.'\''.$title_value.'\''; print WIND_SQLFILE ','.'\''.$institution_value.'\''; print WIND_SQLFILE ','.'\''.''.$institution_url_value.''.'\''; print WIND_SQLFILE ','.'\''.''.$institution_dods_url_value.''.'\''; print WIND_SQLFILE ','.'\''.$source_value.'\''; print WIND_SQLFILE ','.'\''.$references_value.'\''; print WIND_SQLFILE ','.'\''.$contact_value.'\''; print WIND_SQLFILE ",GeometryFromText('POINT("; print WIND_SQLFILE "$longitude $latitude"; print WIND_SQLFILE ")',-1));\n"; } $i++; } print WIND_SQLFILE "\n"; } close(WIND_SQLFILE); } }