Data-SeaBASS
view release on metacpan or search on metacpan
lib/Data/SeaBASS.pm view on Meta::CPAN
}
if (wantarray) {
return %{$data_row};
} else {
return $data_row;
}
} ## end if ($line)
} ## end while (my $line = <$handle>)
} ## end elsif ($self->{'handle'})
return;
} ## end sub next
=head2 rewind()
C<rewind> seeks to the start of the data. The next C<next> will return the
very first row (or C<data(0)>). If caching is enabled, it will not actually
perform a seek, it will merely reset the index interator. If caching is
disabled, a seek is performed on the file handle to return to the start of the
data.
=cut
sub rewind {
my ($self) = @_;
if ( $self->{'dataidx'} != -1 ) {
if ( !$self->{'options'}{'cache'} ) {
seek( $self->{'handle'}, $self->{'data_start_position'}, SEEK_SET );
}
$self->{'line_number'} = $self->{'data_start_line'};
$self->{'dataidx'} = -1;
} ## end if ($self->{'dataidx'}...)
} ## end sub rewind
=head2 update(\%data_row | \@data_row | $data_row | %data_row)
while (my %row = $sb_file->next()){
if ($row{'depth'} == -999){
$row{'depth'} = 0;
}
$sb_file->update(\%row);
}
# Less useful for update():
print join(',',@{$sb_file->actual_fields()}); #lat,lon,depth,chl
while (my %row = $sb_file->next()){
if ($row{'depth'} == -999){
$row{'depth'} = 0;
}
$sb_file->update(@row{'lat','lon','depth','chl'});
# or
$sb_file->update([@row{'lat','lon','depth','chl'}]);
}
C<update> replaces the last row read (using C<next()>) with the input.
Caching must be enabled to use C<update>, C<set>, or C<insert>.
=cut
sub update {
my $self = shift;
if ( !$self->{'options'}{'cache'} ) {
croak("Caching must be enabled to write.");
} elsif ( $self->{'dataidx'} == -1 ) {
croak("No rows read yet.");
}
my $new_row = $self->ingest_row(@_);
unless ( defined($new_row) ) {
croak("Error parsing inputs");
}
$self->{'data'}[ $self->{'dataidx'} ] = $new_row;
} ## end sub update
=head2 set($index, \%data_row | \@data_row | $data_row | %data_row)
my %row = (lat => 1, lon => 2, chl => 1);
$sb_file->set(0, \%row);
print join(',',@{$sb_file->actual_fields()}); #lat,lon,chl
$sb_file->set(0, [1, 2, 1]);
C<set> replaces the row at the given index with the input. Seeks to the
given index if it has not been read to yet. C<croak>s if the file does not go
up to the index specified.
Caching must be enabled to use C<update>, C<set>, or C<insert>.
=cut
sub set {
my $self = shift;
my $index = shift;
if ( !$self->{'options'}{'cache'} ) {
croak("Caching must be enabled to write");
}
if ( $index < 0 ) {
croak("Index must be positive integer");
}
my $new_row = $self->ingest_row(@_);
unless ( defined($new_row) ) {
croak("Error parsing inputs");
}
if ( $index > $self->{'max_dataidx'} ) {
my $current_idx = $self->{'dataidx'};
$self->data($index);
$self->{'dataidx'} = $current_idx;
if ( $index > $self->{'max_dataidx'} ) {
croak("Index out of bounds.");
}
} ## end if ($index > $self->{'max_dataidx'...})
$self->{'data'}[$index] = $new_row;
} ## end sub set
=head2 insert($index, \%data_row | \@data_row | $data_row | %data_row)
use Data::SeaBASS qw(INSERT_BEGINNING INSERT_END);
...
my %row = (lat => 1, lon => 2, chl => 1);
$sb_file->insert(INSERT_BEGINNING, \%row);
print join(',',@{$sb_file->actual_fields()}); #lat,lon,chl
$sb_file->insert(1, [1, 2, 1]);
$sb_file->insert(INSERT_END, [1, 2, 1]);
Inserts the row into the given position. C<INSERT_BEGINNING> inserts a new row
at the start of the data, C<INSERT_END> inserts one at the end of the data
lib/Data/SeaBASS.pm view on Meta::CPAN
unless ( $self->set_delim( $strict, $v ) ) {
if ($strict) {
$success = 0;
}
}
} elsif ( $k =~ m"^/?missing$" ) {
$self->{'missing'} = ( length($v) ? $v : $DEFAULT_MISSING );
$self->{'missing_is_number'} = looks_like_number( $self->{'missing'} );
} elsif ( $k =~ m"^/?above_detection_limit" ) {
$self->{'above_detection_limit'} = ( length($v) ? $v : $self->{'missing'} );
$self->{'adl_is_number'} = looks_like_number( $self->{'above_detection_limit'} );
} elsif ( $k =~ m"^/?below_detection_limit" ) {
$self->{'below_detection_limit'} = ( length($v) ? $v : $self->{'missing'} );
$self->{'bdl_is_number'} = looks_like_number( $self->{'below_detection_limit'} );
}
$_[1] = $k;
$_[2] = $v;
return $success;
} ## end sub validate_header
=head2 set_delim($strict, $delim)
Takes a string declaring the delim (IE: 'comma', 'space', etc) and updates the
object's internal delimiter regex.
=cut
sub set_delim {
my $self = shift;
my $strict = shift;
my $delim = shift || '';
if ( $delim eq 'comma' ) {
$delim = qr/\s*,\s*/;
} elsif ( $delim eq 'semicolon' ) {
$delim = qr/\s*;\s*/;
} elsif ( $delim eq 'space' ) {
$delim = qr/\s+/;
} elsif ( $delim eq 'tab' ) {
$delim = qr/\t/;
} elsif ($strict) {
carp("delimiter not understood");
} else {
my $slash = ( $self->{'options'}{'keep_slashes'} ? '/' : '' );
$self->{'headers'}{"${slash}delimiter"} = 'comma';
$delim = undef;
}
$self->{'delim'} = $delim;
return ( $delim ? 1 : 0 );
} ## end sub set_delim
=head2 update_fields()
C<update_fields> runs through the currently cached rows and calls
C<add_and_remove_fields> on each row. It then updates the /fields and /units
headers in the header hash.
=cut
sub update_fields {
my ($self) = @_;
if ( $self->{'options'}{'cache'} && $self->{'max_dataidx'} >= 0 ) {
foreach my $hash ( @{ $self->{'data'} } ) {
$self->add_and_remove_fields($hash);
}
}
my $slash = ( $self->{'options'}{'keep_slashes'} ? '/' : '' );
$self->{'headers'}{"${slash}fields"} = join( ',', @{ $self->{'actual_fields'} } );
$self->{'headers'}{"${slash}units"} = join( ',', @{ $self->{'actual_units'} } );
} ## end sub update_fields
=head2 add_and_remove_fields(\%row)
Given a reference to a row, this function deletes any fields removed with
C<remove_field> and adds an undefined or /missing value for each field added
via C<add_field>. If C<missing_data_to_undef> is set, an undefined value is
given, otherwise, it is filled with the /missing value.
If C<fill_ancillary_data> is set, this function adds missing date, time,
date_time, lat, lon, and depth fields to the retrieved row from the header.
Needlessly returns the hash reference passed in.
=cut
sub add_and_remove_fields {
my ( $self, $hash ) = @_;
foreach my $field ( keys(%$hash) ) {
if ( ( firstidx { $_ eq $field } @{ $self->{'actual_fields'} } ) < 0 ) {
unless ( $self->{'options'}{'fill_ancillary_data'} && ( firstidx { $_ eq $field } keys( %{ $self->{'ancillary'} } ) ) >= 0 ) {
delete( $hash->{$field} );
}
}
} ## end foreach my $field (keys(%$hash...))
my $missing = ( $self->{'options'}{'missing_data_to_undef'} ? undef : $self->{'missing'} );
while ( my ( $variable, $pad ) = each(%FIELD_FORMATTING) ) {
my $case_var = $self->{'case_conversion'}{$variable} || $variable;
my $v = $hash->{$case_var};
if ($case_var eq 'second'){
if ( defined($v) && length($v) && (!defined($missing) || $v != $missing)) {
if ($v =~ /\D/){
$hash->{$case_var} = sprintf('%02.3f', $v);
} else {
$hash->{$case_var} = sprintf('%02d', $v);
}
}
} elsif ( defined($v) && length($v) && (!defined($missing) || $v != $missing)) {
$hash->{$case_var} = sprintf($pad, $v);
}
} ## end while (my ($variable, $pad...))
if ( defined($self->{'ancillary'}) ) {
$self->{'ancillary_tmp'} = {};
for my $variable (@FILL_ANCILLARY_DATA) {
if ( defined($self->{'ancillary'}{$variable}) ) {
my $value = $self->extrapolate_variables( $missing, $self->{'ancillary'}{$variable}, $hash );
if ( defined($value) ) {
$hash->{$variable} = $value;
}
} ## end if ($self->{'ancillary'...})
} ## end for my $variable (@FILL_ANCILLARY_DATA)
} ## end if ($self->{'ancillary'...})
foreach my $field ( @{ $self->{'actual_fields'} } ) {
if ( !exists( $hash->{$field} ) ) {
$hash->{$field} = $missing;
}
}
( run in 0.826 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )