HMS Investigator (1801-3)

HMS Investigator made a survey voyage to map the Australian coastline, under the command of Matthew Flinders.

Their observations were published in Flinders’ personal journal.

Transcribed observations

Conversion script

#!/usr/bin/perl

# Process digitised logbook data from the Investigator into
#  IMMA records.

use strict;
use warnings;
use IMMA;
use Getopt::Long;
use FindBin;
use Date::Calc qw(Delta_DHMS);

my $Ship_name = 'Investiga';
my ( $Year, $Month, $Day );
my $Last_lon;
my $Lat_flag = 'N';
my $Lon_flag = 'E';

for ( my $i = 0 ; $i < 8 ; $i++ ) { <>; }    # Skip headers

while (<>) {
    my $Ob = new IMMA;
    $Ob->clear();                            # Why is this necessary?
    push @{ $Ob->{attachments} }, 0;
    my @Fields = split /\t/, $_;

    if ( defined( $Fields[0] ) && $Fields[0] =~ /\d/ ) {
        $Year = $Fields[0];
    }
    if ( defined( $Fields[1] ) && $Fields[1] =~ /\d/ ) {
        $Month = $Fields[1];
    }
    if ( defined( $Fields[2] ) && $Fields[2] =~ /\d/ ) {
        $Day = $Fields[2];

        #        printf "%04d/%02d/%02d\n",$Year,$Month,$Day
    }
    $Ob->{YR} = $Year;
    $Ob->{MO} = $Month;
    $Ob->{DY} = $Day;
    if ( defined( $Fields[3] ) && $Fields[3] =~ /\d/ ) {
        $Ob->{HR} = int( $Fields[3] / 100 ) + ( $Fields[3] % 100 ) / 60;
    }

    if ( defined( $Fields[4] ) && $Fields[4] =~ /[a-z]/ ) {    # Port name
        ( $Ob->{LAT}, $Ob->{LON} ) = position_from_port( $Fields[4] );
        $Ob->{LI} = 6;    # Position from metadata
    }
    else {
        if ( defined( $Fields[4] )
            && $Fields[4] =~ /(\d+)\s+(\d+)\s*([NS]*)/ )
        {
            $Ob->{LAT} = $1 + $2 / 60;
            if ( defined($3) && ( $3 eq 'N' || $3 eq 'S' ) ) { $Lat_flag = $3; }
            if ( $Lat_flag eq 'S' ) { $Ob->{LAT} *= -1; }
        }
        if ( defined( $Fields[5] )
            && $Fields[5] =~ /(\d+)\s+(\d+)\s*([EW]*)/ )
        {
            $Ob->{LON} = $1 + $2 / 60;
            if ( defined($3) && ( $3 eq 'E' || $3 eq 'W' ) ) { $Lon_flag = $3; }
            if ( $Lon_flag eq 'W' ) { $Ob->{LON} *= -1; }
        }
        if ( defined( $Ob->{LAT} ) || defined( $Ob->{LON} ) ) {
            $Ob->{LI} = 4;    # Deg+Min position precision
        }
    }
    if ( defined( $Ob->{LON} ) ) { $Last_lon = $Ob->{LON}; }

    correct_hour_for_lon($Ob);

    # Fix a couple of points where Flinders was out in his longitude
    correctLongitude($Ob);

    # Pressure converted from inches
    if ( defined( $Fields[6] ) && $Fields[6] =~ /\d/ ) {
        $Ob->{SLP} = $Fields[6] * 33.86;
    }

    # Temperatures converted from Farenheit
    if ( defined( $Fields[7] ) && $Fields[7] =~ /\d/ ) {
        $Ob->{AT} = ( $Fields[7] - 32 ) * 5 / 9;
    }
    if ( defined( $Fields[8] ) && $Fields[8] =~ /\d/ ) {
        $Ob->{SST} = ( $Fields[8] - 32 ) * 5 / 9;
    }

    # Fill in extra metadata
    $Ob->{IM}   = 0;            # Check with Scott
    $Ob->{ATTC} = 0;            # No attachments
    $Ob->{TI}   = 0;            # Nearest hour time precision
    $Ob->{DS}   = undef;        # Unknown course
    $Ob->{VS}   = undef;        # Unknown speed
    $Ob->{NID}  = undef;        # Check with Scott
    $Ob->{II}   = 10;           # Check with Scott
    $Ob->{ID}   = $Ship_name;
    $Ob->{C1}   = '03';         # UK
    if (   defined( $Ob->{AT} )
        || defined( $Ob->{WBT} )
        || defined( $Ob->{DPT} )
        || defined( $Ob->{SST} ) )
    {
        $Ob->{IT} = 4;          # Temps in degF and 10ths
    }

    $Ob->write( \*STDOUT );

}

# Get a position from a port name
sub position_from_port {
    my $Name = lc(shift);
    if ( $Name =~ /spithead/ ) {
        return ( 50.8, -1.1, );
    }
    if ( $Name =~ /funchal/ ) {
        return ( 32.6, -16.9 );
    }
    if ( $Name =~ /false bay/ ) {
        return ( -34.22, 18.63 );
    }
    if ( $Name =~ /king georges sound/ ) {
        return ( -35.03, 117.95 );
    }
    if ( $Name =~ /princess royal harbour/ ) {
        return ( -35.0, 117.9 );
    }
    if ( $Name =~ /d.entrecasteaux archipelago/ ) {
        return ( undef, undef );

        # At ( -9.65, 150.7 ) - but Flinders used the name for somewhere else
    }
    if ( $Name =~ /memory cove/ ) {
        return ( -34.96, 135.99 );
    }
    if ( $Name =~ /kangaroo island/ ) {
        return ( -35.83, 137.33 );
    }
    if ( $Name =~ /westernport/ ) {
        return ( -38.33, 145.25 );
    }
    if ( $Name =~ /port jackson/ ) {
        return ( -33.9, 151.2 );
    }
    if ( $Name =~ /no. \d port/ ) {
        return ( undef, undef );
    }
    if ( $Name =~ /east coast/ ) {
        return ( undef, undef );
    }
    if ( $Name =~ /keppel bay/ ) {
        return ( -23.38, 150.88 );
    }
    if ( $Name =~ /shoal-water bay/ ) {
        return ( -22.17, 150.22 );
    }
    if ( $Name =~ /thirsty sound/ ) {
        return ( -22.27, 149.90 );
    }
    if ( $Name =~ /broad sound/ ) {
        return ( -22.17, 149.75 );
    }
    if ( $Name =~ /northern northumberland isles/ ) {
        return ( -21.0, 150.0 );
    }
    if ( $Name =~ /between a and b isles/ ) {    # What imaginative names.
        return ( undef, undef );
    }
    if ( $Name =~ /c vanderlin/ ) {
        return ( -15.58, 137 );
    }
    if ( $Name =~ /groote eyland/ ) {
        return ( -14.0, 136.67 );
    }
    if ( $Name =~ /arnhem/ ) {
        return ( -12.35, 136.97 );
    }
    if ( $Name =~ /coupang bay, timor/ ) {
        return ( undef, undef );
    }
    if ( $Name =~ /goose bay/ ) {
        return ( undef, undef );
    }

    die "Unknown port $Name";
    return ( undef, undef );
}

# Correct the date to UTC from local time
sub correct_hour_for_lon {
    my @Days_in_month = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
    my $Ob = shift;
    unless ( defined($Last_lon)
        && defined( $Ob->{HR} )
        && defined( $Ob->{DY} )
        && defined( $Ob->{MO} )
        && defined( $Ob->{YR} ) )
    {
        $Ob->{HR} = undef;
        return;
    }
    if ( $Ob->{YR} % 4 == 0
        && ( $Ob->{YR} % 100 != 0 || $Ob->{YR} % 400 == 0 ) )
    {
        $Days_in_month[1] = 29;
    }
    $Ob->{HR} += $Last_lon * 12 / 180;
    if ( $Ob->{HR} < 0 ) {
        $Ob->{HR} += 24;
        $Ob->{DY}--;
        if ( $Ob->{DY} <= 0 ) {
            $Ob->{MO}--;
            if ( $Ob->{MO} < 1 ) {
                $Ob->{YR}--;
                $Ob->{MO} = 12;
            }
            $Ob->{DY} = $Days_in_month[ $Ob->{MO} - 1 ];
        }
    }
    if ( $Ob->{HR} > 23.99 ) {
        $Ob->{HR} -= 24;
        if ( $Ob->{HR} < 0 ) { $Ob->{HR} = 0; }
        $Ob->{DY}++;
        if ( $Ob->{DY} > $Days_in_month[ $Ob->{MO} - 1 ] ) {
            $Ob->{DY} = 1;
            $Ob->{MO}++;
            if ( $Ob->{MO} > 12 ) {
                $Ob->{YR}++;
                $Ob->{MO} = 1;
            }
        }
    }
    if ( $Ob->{HR} == 23.99 ) { $Ob->{HR} = 23.98; }
    return 1;
}

# Apply arbitrary corrections for longitude
sub correctLongitude {
    my $ob = shift;
    unless ( defined( $ob->{YR} )
        && defined( $ob->{MO} )
        && defined( $ob->{DY} )
        && defined( $ob->{HR} )
        && defined( $ob->{LON} ) )
    {
        return;
    }

    # Going into Sydney in 1803
    if (
        deltaS(
            "1803/06/01:00:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) > 0
        && deltaS(
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            ),
            "1803/06/09:22:00:00"
        ) >= 0
      )
    {
        $ob->{LON} += ( 151.2 - 149.29 ) * deltaS(
            "1803/06/01:00:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) / deltaS( "1803/06/01:00:00:00", "1803/06/09:22:00:00" );

    }

    # Going round Cape York peninsula in 1802
    if (
        deltaS(
            "1802/10/20:00:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) > 0
        && deltaS(
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            ),
            "1802/10/31:22:00:00"
        ) >= 0
      )
    {
        $ob->{LON} += ( 141.5 - 145.27 ) * deltaS(
            "1802/10/20:00:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) / deltaS( "1802/10/20:00:00:00", "1802/10/31:22:00:00" );

    }
    if (
        deltaS(
            "1802/10/31:22:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) > 0
        && deltaS(
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            ),
            "1802/11/30:22:00:00"
        ) >= 0
      )
    {
        my $Fraction = deltaS(
            "1802/10/31:22:00:00",
            sprintf(
                "%04d/%02d/%02d:%02d:%02d:%02d",
                $ob->{YR}, $ob->{MO}, $ob->{DY}, int( $ob->{HR} ),
                0, 0
            )
        ) / deltaS( "1802/10/31:22:00:00", "1802/11/30:22:00:00" );
        $ob->{LON} +=
          ( 140.0 - 142.33 ) * $Fraction +
          ( 141.5 - 145.27 ) * ( 1 - $Fraction );

    }

}

# Calculate difference in s between two dates
sub deltaS {
    my $D1 = shift;
    my $D2 = shift;
    unless ( $D1 =~ /(\d\d\d\d)\/(\d\d)\/(\d\d):(\d\d):(\d\d):(\d\d)/ ) {
        die "Bad date $D1";
    }
    my %Date1 = (
        year   => $1,
        month  => $2,
        day    => $3,
        hour   => $4,
        minute => $5,
        second => $6
    );
    unless ( $D2 =~ /(\d\d\d\d)\/(\d\d)\/(\d\d):(\d\d):(\d\d):(\d\d)/ ) {
        die "Bad date $D2";
    }
    my %Date2 = (
        year   => $1,
        month  => $2,
        day    => $3,
        hour   => $4,
        minute => $5,
        second => $6
    );
    my @Dhms = Delta_DHMS(
        $Date1{year},   $Date1{month},  $Date1{day},    $Date1{hour},
        $Date1{minute}, $Date1{second}, $Date2{year},   $Date2{month},
        $Date2{day},    $Date2{hour},   $Date2{minute}, $Date2{second}
    );
    return $Dhms[3] + $Dhms[2] * 60 + $Dhms[1] * 3600 + $Dhms[0] * 86400;
}

Converted observations