#!/usr/bin/perl use strict; my ($xml_source, $data_source, $return_type) = @ARGV; #call data args into scope from xml document use LWP::Simple; my $content; $content = get $xml_source; die "Couldn't get $xml_source" unless defined $content; use XML::Simple; my $xs1 = XML::Simple->new(); my $doc = $xs1->XMLin($content, forcearray => 1); =comment #to view the contents of the $doc array use Data::Dumper; print Dumper($doc); =cut =comment my $line; my @line_array; =cut my ($filename, $institution_desc, $institution_url, $institution_id, $platform_id, $package_id, $latitude, $longitude, $data_url, $filename_search, $file_row_start, $file_row_comment, $file_field_separator, $file_field_missing_value, $column_time, $dods_url, $comment) ; my $contact_info = $doc->{'global_attributes'}->[0]->{'contact_info'}->[0] ; my $institution_desc = $doc->{'global_attributes'}->[0]->{'institution_desc'}->[0] ; my $institution_url = $doc->{'global_attributes'}->[0]->{'institution_url'}->[0] ; my $institution_id = $doc->{'global_attributes'}->[0]->{'institution_id'}->[0] ; my $platform_id = $doc->{'global_attributes'}->[0]->{'platform_id'}->[0] ; my $package_id = $doc->{'global_attributes'}->[0]->{'package_id'}->[0] ; my $latitude = $doc->{'global_attributes'}->[0]->{'latitude'}->[0] ; my $longitude = $doc->{'global_attributes'}->[0]->{'longitude'}->[0] ; my $data_url = $doc->{'global_attributes'}->[0]->{'data_url'}->[0] ; my $filename_search = $doc->{'global_attributes'}->[0]->{'filename_search'}->[0] ; my $file_row_start = $doc->{'global_attributes'}->[0]->{'file_row_start'}->[0] ; if ($file_row_start =~ /HASH/) { $file_row_start = 1; } #assumes 'none' won't actually be used as a line comment #not testing for escape characters my $file_row_comment = $doc->{'global_attributes'}->[0]->{'file_row_comment'}->[0] ; if ($file_row_comment =~ /HASH/) { $file_row_comment = 'none'; } #not testing for escape characters my $file_field_separator = $doc->{'global_attributes'}->[0]->{'file_field_separator'}->[0] ; #forced filtering to below separator on files my $file_field_separator = '_SEP_' ; #assumes 'none' won't actually be used as a missing value #not testing for escape characters my $file_field_missing_value = $doc->{'global_attributes'}->[0]->{'file_field_missing_value'}->[0] ; if ($file_field_missing_value =~ /HASH/) { $file_field_missing_value = 'none'; } my $column_time = $doc->{'global_attributes'}->[0]->{'column_time'}->[0] ; if ($column_time =~ /HASH/) { $column_time = 1; } my $measurement_time_zone = $doc->{'global_attributes'}->[0]->{'measurement_time_zone'}->[0] ; if ($measurement_time_zone =~ /HASH/) { $measurement_time_zone = '+00'; } my $dods_url = $doc->{'global_attributes'}->[0]->{'dods_url'}->[0] ; if ($dods_url =~ /HASH/) { $dods_url = ''; } my $comment = $doc->{'global_attributes'}->[0]->{'comment'}->[0] ; if ($comment =~ /HASH/) { $comment = ''; } #populate local array from ascii column data using xml file processing args $content = get $data_source; die "Couldn't get $data_source" unless defined $content; #split rows into array elements my @data_content = split (/\n/, $content); my @obs_values; my $number_file_columns; my $line; my @line_array; my $line_count_file = 0; my $line_count_processed = 0; foreach $line (@data_content) { $line_count_file++; #drop lines until first row start if ($line_count_file < $file_row_start) { next; } #skip lines which are commented if ($line =~ /^$file_row_comment/) { next; } #processing row #print "process\n"; $line_count_processed++; #map missing values @line_array = split(/$file_field_separator/,$line); foreach my $element (@line_array) { if ($element eq $file_field_missing_value) { $element = '-99999'; } } foreach my $element (@line_array) { #print "$element\n"; } push (@obs_values, @line_array); } my $number_file_columns = scalar(@line_array); #print "line_count_processed: $line_count_processed\n"; #loop through observations building substitution strings my $obs_declaration = ''; my $z_count = 0; my $z_list = ''; my $obs_list = ''; foreach my $obs_returned ( @{$doc->{'dependent_variables'}->[0]->{'variable'}} ) { my $obs_column_number = $obs_returned->{'column_number'}->[0] ; my $obs_standard_name = $obs_returned->{'standard_name'}->[0] ; my $obs_units = $obs_returned->{'units'}->[0] ; my $obs_z = $obs_returned->{'z'}->[0] ; if (!($obs_column_number =~ /HASH/)) { $obs_declaration .= " \ double $obs_standard_name(time) ; \ $obs_standard_name:standard_name = \"$obs_standard_name\" ; $obs_standard_name:units = \"$obs_units\" ; $obs_standard_name:z = $obs_z ; "; $z_count++; $z_list .= "$obs_z,"; $obs_list .= "$obs_standard_name = ".get_array_column(\@obs_values, $obs_column_number, $number_file_columns, 0)." ;\n\n"; } } $z_list = substr($z_list,0,-1); #strip trailing comma my ($time_list, $start_time, $end_time) = get_array_column(\@obs_values, $column_time, $number_file_columns, 1); #print $time_list."\n"; #print $start_time."\n"; #print $end_time."\n"; my $filename_prefix = $institution_id.'_'.$platform_id.'_'.$package_id; #my $timestamp_prefix = `date +"%Y%m%d%H%M%S"`; #my $timestamp_prefix = `date --date='$end_time' +"%Y%m%d%H%M%S"`; #chomp($timestamp_prefix); my $timestamp_prefix = substr($end_time,0,4).substr($end_time,5,2).substr($end_time,8,2).substr($end_time,11,2).substr($end_time,14,2).substr($end_time,17,2).substr($end_time,19,3); my $filename_text = $filename_prefix."_".$timestamp_prefix."_latest.txt"; my $create_date = `date +"%Y-%m-%d %H:%M:%S"`; chomp($create_date); #substitute args into netcdf template open (NETCDF_FILE, ">/tmp/ms_tmp/$filename_text"); $content = `cat seacoos_xml_netcdf_template.txt`; $content =~ s//$contact_info/g; #platform information $content =~ s//$institution_desc/g; $content =~ s//$institution_url/g; $content =~ s//$institution_id/g; $content =~ s//$platform_id/g; $content =~ s//$package_id/g; $content =~ s//$latitude/g; $content =~ s//$longitude/g; #column information $content =~ s//$obs_declaration/g; $content =~ s//$line_count_processed/g; $content =~ s//$time_list/g; $content =~ s//$start_time/g; $content =~ s//$end_time/g; $content =~ s//$create_date/g; $content =~ s//$create_date/g; $content =~ s//$create_date/g; $content =~ s//$z_count/g; $content =~ s//$z_list/g; $content =~ s//$obs_list/g; #other information $content =~ s//$dods_url/g; $content =~ s//$comment/g; print NETCDF_FILE $content; close (NETCDF_FILE); my $filename_netcdf = $filename_prefix."_".$timestamp_prefix."_latest.nc"; `/usr2/home/jcothran/storm_surge/ncgen -o /tmp/ms_tmp/$filename_netcdf /tmp/ms_tmp/$filename_text`; #the filename handle is passed back to the calling php page for reference if ($return_type eq 'txt') { print $filename_text; } else { print $filename_netcdf; } exit 0; sub get_array_column { #returns a comma separated listing of a vertical sectioning of a flat array based on known number of columns and converts time to netcdf representation if flag set my ($array_line, $get_column, $array_num_columns, $convert_time) = @_; my $column_count = 1; my $array_list = ''; my ($start_time, $end_time); foreach my $element (@{$array_line}) { if ($column_count == $get_column) { if ($convert_time) { my $measurement_date = substr($element,0,19); #my $measurement_time_zone = substr($element,19,3); #only considering hour(not minute) zone differences #if (!($measurement_time_zone)) { $measurement_time_zone = '+00'; } my $full_arg_measurement_date = $measurement_date.$measurement_time_zone.'00'; #print "$full_arg_measurement_date\n"; if (!($start_time)) { $start_time = $full_arg_measurement_date; } $end_time = $full_arg_measurement_date; my $time_sec = `date --date='$full_arg_measurement_date' +%s`; chomp($time_sec); $array_list .= $time_sec.','; } else { $array_list .= $element.','; } } $column_count++; if ($column_count == $array_num_columns+1) { $column_count = 1; } } $array_list = substr($array_list,0,-1); #strip trailing comma if ($convert_time) { my @array_list_more; push (@array_list_more, $array_list); push (@array_list_more, $start_time); push (@array_list_more, $end_time); return @array_list_more; } else { return $array_list; } } #get_array_column