#! /usr/bin/perl
# /usr/bin/perl -w -d

# Add path to soglobec.pl to the perl include envar
# soglobecV1.pl includes NBP0202 cruise, moc, and net info
# soglobecV2.pl does NOT include NBP0202 info
push @INC, '/eos-serv2/d2/home/scotty/Sci/Globec/Copley/soglobec_processing';
require('soglobecV1.pl');

###################################################################
#############                Definitions         ##################
###################################################################

$TRUE='1'; 
$FALSE='0';

# $DEBUG and $FULLPRINTOUT should be mutually exclusive, but rather
# than code them that way and reduce flexibility the user should
# explicitely make the change(s).

#$DEBUG=$TRUE; $DEBUG_ANNOT="Mismatches"; $FULLPRINTOUT=$FALSE;
#$DEBUG=$FALSE; $DEBUG_ANNOT="Problem DEBUG boolean"; $FULLPRINTOUT=$TRUE;
$DEBUG=$FALSE; $DEBUG_ANNOT=""; $FULLPRINTOUT=$TRUE;

# Someday there might be weight formulae and weight values to accompany
# length values- weights are calculated from length. But for now there
# are no legitimate weight values and calculations haven't been properly
# invoked. Therefore, blank out weight formulae-related stuff through
# use of a variable FALLBACKWEIGHTFORMULATRUEVAL.

$FALLBACKWEIGHTFORMULATRUEVAL = $TRUE;

# Name of file containing info about times and location of cruises/nets
$moctimefile = "moc_time_pos_table.txt";

# Name of the file that provides length to weight formulas by specie
$lenwgtformulafile = "default.wgt.list.csv";

# Name of file containing specie count per volume data 
# UNUSED CURRENTLY.
#$countfile = "total_counts_orgs.csv";

#####################################################################
# Use the following as a template for processing a subset of cruises,
# mocs, or nets. Definitions here will override cruise list that's in
# soglobecVx.pl

# Edit and uncomment to override definitions from the soglobec.pl
# definition file "required" above.
 @cruises=("NBP0103", "NBP0104");
#@cruises=("NBP0103");
#
#%mocsbycruise = (
#NBP0103 => [1],
#		 );
#
#%netsbymocandcruise= (
#NBP0103 => {
#              1 => [1],
#           },
#);
#####################################################################

%nh = ();

##### Read in metadata hash from file ##############################
open MOCF, "<$moctimefile" or die "Couldnt open $moctimefile\n";
# Read in cruise pseudo meta data
while (<MOCF>) {
  if (/^[^#]/) {

    ($cid,$moc,$date,$time,$lat,$lon,$maxd,$bottomd,$region1,$region2) = split(' ');

         my $region = $region1.$region2;

         $nh{$cid}{$moc}{date} = $date;
         $nh{$cid}{$moc}{time} = $time;
         $nh{$cid}{$moc}{lon} = $lon;
         $nh{$cid}{$moc}{lat} = $lat;
         $nh{$cid}{$moc}{md} = $maxd;
         $nh{$cid}{$moc}{bd} = $bottomd;
         $nh{$cid}{$moc}{reg} = $region;
   }
}

close(MOCF);

##### Length->weight boolean lookup table ###########################
# Create a lookup table of "length -> weight formula exists" booleans for the species

%lenwgtsbool = ();
@lenwgts = ();
open FORMF, "<$lenwgtformulafile" or die "Didnt find $lenweightformulafile\n";
@lenwgts = <FORMF>;
close FORMF;

  foreach $spid (keys %spname2numh) {
      $exp = '@sp_line = grep  /'.$spid.'/, @lenwgts';
      eval $exp;
      if (!defined($sp_line[0])) { $lenwgtsbool{$spid} = $FALSE; }
      elsif ($sp_line[0] =~ m/no formula/) { $lenwgtsbool{$spid} = $FALSE; }
      else { $lenwgtsbool{$spid} = $FALLBACKWEIGHTFORMULATRUEVAL; }
  }


# cruise and moc-number-by-cruise comes from the include file. All
# mocs have net numbers 1 through 8.

##### Print output header ###########################################
  printf STDOUT "cruiseid\tdate_local\ttime_local\tlon\tlat\tcast\tnet\tdepth_median\tdepth_w\tregion\tnet_upper_depth\tnet_lower_depth\tdepth_int\tvol_tot\tvol_liquid\tvol_displ\tvol_filt\tbiomass\tinteg_biomass\tspecies_index\tspecies_code\tspecies\tspecies_biom\tnum_species_count_len\tlen_mean\tlen_max\tlen_min\tnum_species_count_weight\tweight_mean\tweight_max\tweight_min\n";


##### Begin processing csv files -> flat file ######################
foreach $cruise (@cruises) {
  foreach $mocthiscruise (@{$mocsbycruise{$cruise}}) {
    foreach $thisnet (@{$netsbymocandcruise{$cruise}{$mocthiscruise}}) {
        $rbm = getmocnetbiomass($cruise,$mocthiscruise);
        $rdvol = getmocnetdvol($cruise,$mocthiscruise,$thisnet);
        $rlen = getmocnetlen($cruise,$mocthiscruise,$thisnet);

        $rwgt = getmocnetwgt($cruise,$mocthiscruise,$thisnet);


     # 7/1 With mods to the merge_arrays subroutine we now have two keys per specie ID. One is an index value,
     # the other is a species ID string (the desired one). Figure out how to use the one desired and toss the
     # undesired one.
        foreach $splen (sort numerically keys (%{$rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}})) {
          # Confirm that the key is a species ID string and not an indexing number
         if ($lenwgtsbool{$splen}) {$rwgt = getmocnetwgt($cruise,$mocthiscruise,$thisnet);}
         else {$rwgt = makefakehash($cruise,$mocthiscruise,$thisnet);}


          if ( $splen =~ m/\W/ ) {
            $lenpositionindex = $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$splen}->{index};
            $lenhashindex = $spname2numh{$splen};
            $spwgt = $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$lenpositionindex};
            $splencount = $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$splen}->{data};
            $spwgtcount = $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$splen}->{data};

             printf STDOUT "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
               $cruise,
	       $nh{$cruise}{$mocthiscruise}{date},
	       $nh{$cruise}{$mocthiscruise}{time},
	       $nh{$cruise}{$mocthiscruise}{lon},
	       $nh{$cruise}{$mocthiscruise}{lat},
	       $mocthiscruise,
	       $thisnet,
	       $nh{$cruise}{$mocthiscruise}{md},
	       $nh{$cruise}{$mocthiscruise}{bd},
	       $nh{$cruise}{$mocthiscruise}{reg},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{highdepth},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{lowdepth},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{depthinterval},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{totvol},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{liqvol},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{dispvol},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{filtvol},
 	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{ccpermcubed},
	       $rdvol->{$cruise}->{$mocthiscruise}->{$thisnet}->{integdvol},
 	       $lenpositionindex,
               $splen,
	       $spnum2nameh{$lenpositionindex}{sn},
 	       $rbm->{$cruise}->{$mocthiscruise}->{$thisnet}->{datapairs}->{$splen}->{data},
 	       $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$splen}->{data},
 	       $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{meanpairs}->{$splen}->{data},
 	       $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{maxpairs}->{$splen}->{data},
 	       $rlen->{$cruise}->{$mocthiscruise}->{$thisnet}->{minpairs}->{$splen}->{data},
 	       $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{countpairs}->{$spwgt}->{data},
 	       $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{meanpairs}->{$spwgt}->{data},
 	       $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{maxpairs}->{$spwgt}->{data},
 	       $rwgt->{$cruise}->{$mocthiscruise}->{$thisnet}->{minpairs}->{$spwgt}->{data};

	} # if $splen =~ m/\W/
                
                 
      } # each splen
    } # each thisnet
  } # each moc
} # each cruise




############################################################################
############################# Subroutines ##################################
############################################################################

sub getmocnetdvol {

# arguments: getmocnetdvol(cruise, moc, net)

# Accepts arguments for target moc and net and takes the
# following actions:
#
# 1. assembles the name of the file that contains moc/net-specific data.
# 2. opens, reads, and loses that file. Assumes relative path.
# 3. parses the file to throw away all but moc/net-specific data.
# 4. assembles a suitable structure for the data.
# 5. passes a reference for the structure back to main script.

    my $targetcruise = $_[0];
    my $targetmoc = $_[1];
    my $targetnet = $_[2];
    my $debugctr = 0;

    my($net,$depthrange,$depthinterval,$totvol,$liqvol);
    my($dispvol,$filtvol,$ccpermcubed,$integdvol);

    my $targetdvolfile = sprintf("%sm%2.2d/m%2.2ddvols.csv",
                    $cruise,$targetmoc,$targetmoc);
 #  print STDERR "$targetdvolfile\n";
    open INDV, "<$targetdvolfile" or warn "Couldnt open $targetdvolfile\n";
    my @dvols = <INDV>; close INDV;

    foreach (@dvols) {
    # Typical pattern is for target data lines to begin with net number
    # while non-data lines begin with characters.

        $debugctr++;
	chomp();
       
      DVOLCASE: {

        /^\d/ && do {
	    ($net,$depthrange,$depthinterval,$totvol,$liqvol,
              $dispvol,$filtvol,$ccpermcubed,$integdvol) = split(/,/);

	    ($highdepth,$lowdepth) = split_depthrange($depthrange);

            # Use a numeric comparison for net number
            if ($net != $targetnet) {
                last DVOLCASE;
            } else {
                my %dvh = ();
		$dvh{$targetcruise}{$targetmoc}{$targetnet}{highdepth} = $highdepth;
		$dvh{$targetcruise}{$targetmoc}{$targetnet}{lowdepth} = $lowdepth;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{depthinterval} = $depthinterval;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{totvol} = $totvol;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{liqvol} = $liqvol;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{dispvol} = $dispvol;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{filtvol} = $filtvol;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{ccpermcubed} = $ccpermcubed;
                $dvh{$targetcruise}{$targetmoc}{$targetnet}{integdvol} = $integdvol;

                 # For debugging
		if ($TRUE == $FALSE) {
		 printf STDERR "%d\n", $debugctr;
                 foreach $cruise (%dvh) {
                  foreach $moc (%{$dvh{$cruise}}) {
                   foreach $mnet (%{$dvh{$cruise}{$moc}}) {
                     printf STDERR "dvol:%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
                    $cruise,
                    $moc,
                    $mnet,
                    $dvh{$cruise}{$moc}{$mnet}{depthrange},
                    $dvh{$cruise}{$moc}{$mnet}{depthinterval},
                    $dvh{$cruise}{$moc}{$mnet}{totvol},
	            $dvh{$cruise}{$moc}{$mnet}{integdvol};
                 }
                }
               }
	       } # true == false


                return(\%dvh);             
	    }
          }; # data line case
        };   # DVOLCASE
    } # foreach line

} # sub dvol

############################################################################

sub getmocnetbiomass {

  my $targetcruise = $_[0];
  my $targetmoc = $_[1];

  my($moc,$net,$mocnet,$depth,$idepth,$fdepth);
  my($depthint,$depthavg,$allsp,$allspi);

  my %pr = ();           # pr for parseresult
  my(@headers) = ();
  my(@spvals) = ();
  my($a,$b,$c,$d,$e,$f,$g,$h);


  my $bminfile = sprintf("%sm%2.2d/m%2.2dbiomass.csv",$targetcruise,$targetmoc,$targetmoc);
#   print "$bminfile\n";
  open INBM, "<$bminfile" or warn "Warning:Couldnt open $bminfile\n";
  my @biomassdata = <INBM>; close INBM;

foreach (@biomassdata) {

  my $line = $_;

  LINETYPECASE: {

      # If it's the header line
      /1-copsml/ and /2-coplrg/ and /3-copnau/ && do {
	  ($a,$b,$c,$d,$e,$f,$g,$h,@headers) = split(/,/);
          @headers = despaceify_array(\@headers);
          last LINETYPECASE;
      };

      # One form of a net line- in this one the data author has labelled each
      # net with form m (for moc), moc number, n (for net), net number.

         /m(\d*)n(\d*)/ && do {
            ($mocnet,$depth,$idepth,$fdepth,$depthint,$depthavg,$allsp,$allspi,@spvals) = split(/,/);
            # $mocnet is in form mXnX. Parse them out.
            ($moc, $net) = split_mocnet($mocnet);
            if ($#spvals != $#headers) {printf STDERR "getmocnetbiomass: header-values mismatch moc:%2.2d net:%2.2d header:%d vals: %d\n",$moc,$net, $#headers, $#spvals;}
            else {$pr{$targetcruise}{$targetmoc}{$net}{datapairs} = merge_arrays(\@headers, \@spvals);}
            last LINETYPECASE;
         };
      # Other form of a net line.
         /^\s*(\d*)\.(\d*)\s*,/ && do {
            ($mocnet,$depth,$idepth,$fdepth,$depthint,$depthavg,$allsp,$allspi,@spvals) = split(/,/);
            $moc = $1;          # from regexp at start of block.
            $net = $2;
            if ($#spvals != $#headers) {printf STDERR "getmocnetbiomass: Header-values mismatch moc:%2.2d net:%2.2d header:%d vals: %d\n",$moc,$net, $#headers, $#spvals;}
            else {$pr{$targetcruise}{$targetmoc}{$net}{datapairs} = merge_arrays(\@headers, \@spvals);}
            last LINETYPECASE;
         };
  }; # LINETYPECASE
}  # foreach

#  foreach $key (%{$pr{$targetcruise}{$targetmoc}{$net}{datapairs}}) {
#      print "$key\t$pr{$targetcruise}{$targetmoc}{$net}{datapairs}{$key}\n";
#  }

return \%pr;

} # sub getmocnetbiomass

############################################################################

sub getmocnetlen {

  my $targetcruise = $_[0];
  my $targetmoc = $_[1];
  my $targetnet = $_[2];

  my %lh = ();
  my @headers = ();
  my @spvals = ();
  my ($arref, $s, $stat_type);

  my $linfile = sprintf("%sm%2.2d/m%2.2dn%2.2dlen.csv",$targetcruise,$targetmoc,$targetmoc,$targetnet);
#  print "$targetcruise\t$targetmoc\t$targetnet\t$linfile\n";
  open INL, "<$linfile" or die "Couldnt open $linfile\n";
  my @lengthstats = <INL>; close INL;

foreach (@lengthstats) {

#  printf STDERR "$_";

  LINETYPECASE: {

      # If it's the header line
      /.tatistic./ and /1-copsml/ and /2-coplrg/ and /3-copnau/ && do {
	  ($s,@headers) = split(/,/);
          @headers = despaceify_array(\@headers);
          last LINETYPECASE;
      };

         /count/  && do {
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "len count::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d head: %d vals: %d\n",$targetcruise,$targetmoc,$targetnet,$#headers,$#spvals;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $lh{$targetcruise}{$targetmoc}{$targetnet}{countpairs} = {%$arref};
#               $lh{$targetcruise}{$targetmoc}{$targetnet}{countpairs} = merge_arrays(\@headers, \@spvals);
            }

            last LINETYPECASE;
         };

         /mean/ && do {
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "len mean::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d head: %d vals: %d\n",$targetcruise,$targetmoc,$targetnet,$#headers,$#spvals;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $lh{$targetcruise}{$targetmoc}{$targetnet}{meanpairs} = {%$arref};
#              $lh{$targetcruise}{$targetmoc}{$targetnet}{meanpairs} = merge_arrays(\@headers, \@spvals);
	    }

            last LINETYPECASE;
         };

         /max/ && do {
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "len max::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d head: %d vals: %d\n",$targetcruise,$targetmoc,$targetnet,$#headers,$#spvals;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $lh{$targetcruise}{$targetmoc}{$targetnet}{maxpairs} = {%$arref};  
#              $lh{$targetcruise}{$targetmoc}{$targetnet}{maxpairs} = merge_arrays(\@headers, \@spvals);
            }

            last LINETYPECASE;
         };

         /min/ && do {
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "len min::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d head: %d vals: %d\n",$targetcruise,$targetmoc,$targetnet,$#headers,$#spvals;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $lh{$targetcruise}{$targetmoc}{$targetnet}{minpairs} = {%$arref};
 #            $lh{$targetcruise}{$targetmoc}{$targetnet}{minpairs} = merge_arrays(\@headers, \@spvals);
            }

            last LINETYPECASE;
         };

         /squares/ && do {
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "len sq::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d head: %d vals: %d\n",$targetcruise,$targetmoc,$targetnet,$#headers,$#spvals;}
            else {
               my $arref = merge_arrays(\@headers, \@spvals);
               $lh{$targetcruise}{$targetmoc}{$targetnet}{squarepairs} = {%$arref};
#              $lh{$targetcruise}{$targetmoc}{$targetnet}{squarepairs} = merge_arrays(\@headers, \@spvals);
            }

            last LINETYPECASE;
         };

  }; # LINETYPECASE
}  # foreach


return \%lh;
} # sub getmocnetlen

############################################################################

sub getmocnetwgt {

  my $targetcruise = $_[0];
  my $targetmoc = $_[1];
  my $targetnet = $_[2];

  my %wh = ();
  my @headers = ();
  my @spvals = ();
  my ($arref, $s, $stat_type);

  my $countflg = $FALSE;
  my $meanflg = $FALSE;
  my $maxflg = $FALSE;
  my $minflg = $FALSE;

  my $winfile = sprintf("%sm%2.2d/m%2.2dn%2.2dwgt.csv",$targetcruise,$targetmoc,$targetmoc,$targetnet);
#  print "$targetcruise\t$targetmoc\t$targetnet\t$linfile\n";
  open WNL, "<$winfile" or die "Couldnt open $winfile\n";
  my @weightstats = <WNL>; close WNL;


foreach (@weightstats) {

#  print "$_";

  LINETYPECASE: {

      # If it's the header line
      /.tatistic./ and /1-copsml/ and /2-coplrg/ and /3-copnau/ && do {
	  ($s,@headers) = split(/,/);
          @headers = despaceify_array(\@headers);
          last LINETYPECASE;
      };

         /count/  && do {
	    $countflg=$TRUE;
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "wgt::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d\n",$targetcruise,$targetmoc,$targetnet;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $wh{$targetcruise}{$targetmoc}{$targetnet}{countpairs} = {%$arref};
            }

            last LINETYPECASE;
         };

         /mean/ && do {
            $meanflg=$TRUE;
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "wgt::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d\n",$targetcruise,$targetmoc,$targetnet;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $wh{$targetcruise}{$targetmoc}{$targetnet}{meanpairs} = {%$arref};
	    }

            last LINETYPECASE;
         };

         /max/ && do {
            $maxflg=$TRUE;
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "wgt::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d\n",$targetcruise,$targetmoc,$targetnet;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $wh{$targetcruise}{$targetmoc}{$targetnet}{maxpairs} = {%$arref};  
            }

            last LINETYPECASE;
         };

         /min/ && do {
            $minflg=$TRUE;
            ($stat_type,@spvals) = split(/,/);
            if ($#spvals != $#headers) {printf STDERR "wgt::Header-values mismatch cruise: %s moc:%2.2d net:%2.2d\n",$targetcruise,$targetmoc,$targetnet;}
            else {
              my $arref = merge_arrays(\@headers, \@spvals);
              $wh{$targetcruise}{$targetmoc}{$targetnet}{minpairs} = {%$arref};
            }
            last LINETYPECASE;
         };


  }; # LINETYPECASE
}  # foreach

# Some (NBP0103 moc 16) weight files have no summary stats, i.e., no count,
# mean, max, and min. If they're not all set, then return a null hash.

unless ($countflg == $TRUE and
        $meanflg  == $TRUE and
        $minflg   == $TRUE and
        $maxflg   == $TRUE) { 
          $rwh = makefakehash($targetcruise, $targetmoc, $targetnet);
          return $rwh;
      } else {
          return \%wh;
      }

} # sub getmocnetwgt
############################################################################

sub split_mocnet {

    my $mocnet = $_[0];  # Form mXnX

    $mocnet =~ m/m(\d*)n(\d*)/;

    my $moc = $1;
    my $net = $2;

    return($moc, $net);

}

############################################################################

sub despaceify_array {

    my $inarray = $_[0];
    my @outarray = ();
    my $el;

    foreach $el (@$inarray) {
	$el =~ tr/ //d;
        push @outarray, $el;
    }

    return @outarray;

}

############################################################################

sub merge_arrays {

    my $labels = $_[0];
    my $data = $_[1];

    my %rh = ();
    my $i;

    for ($i=0; $i<$#$labels; $i++) {
	$rh{@$labels[$i]}{data} = @$data[$i];
        # Make the index one-based like species hash rather than zero-based like perl arrays.
        $index = $i+1;
	$rh{@$labels[$i]}{index} = $index;
        $rh{$index} = @$labels[$i];
    }

    return \%rh;
}

############################################################################

sub makefakehash {

# 7/11/2005 Create dummy count/mean/max/min hashs


  my $targetcruise = $_[0];
  my $targetmoc = $_[1];
  my $targetnet = $_[2];

  my %fh = ();
  my %th = ();
  my @headers = ();
  my ($arref, $s, $stat_type, $i);


  # Create headers from the reference hashes

  @headers = sort keys %spname2numh;

  for ($i=0; $i<$#headers; $i++) {

      $th{$headers[$i]}{data} = "nd";
      # Make the index one-based like species hash rather than zero-based like perl arrays.
      $index = $i+1;
      $th{$headers[$i]}{index} = $index;
      $th{$index} = $headers[$i];
  }

  $arref = \%th;
  $fh{$targetcruise}{$targetmoc}{$targetnet}{countpairs} = {%$arref};
  $fh{$targetcruise}{$targetmoc}{$targetnet}{meanpairs} = {%$arref};
  $fh{$targetcruise}{$targetmoc}{$targetnet}{maxpairs} = {%$arref};
  $fh{$targetcruise}{$targetmoc}{$targetnet}{minpairs} = {%$arref};


return \%fh;

} # sub makefakehash


############################################################################

sub numerically {$a <=> $b;}

############################################################################

sub split_cruisemoc {

    my $infield = $_[0];  # form NBP010?_Moc??

    $infield =~ m/(NBP010\d)_(Moc\d{1,2})/;

    $cid = $1;
    $mid = $2;

    return($cid,$mid);

}  # sub split_cruisemoc

############################################################################

sub split_depthrange {

    my $rangestring = $_[0];

    ($highd,$lowd) = split(/-/, $rangestring);

    return($highd,$lowd);

} # sub split_range
