Wednesday, June 21, 2000

Perl P190 Navigation Merge script (code nostalgia)

Continuing my explorations of the newly found old backup hard disk I found this small gem :). The code and structure could arguably be improved on a lot but considering this stared out as a small utility script that was immensely useful and it just worked back in 1997-1999 it never got rewritten.

When you are doing marine seismic exploration you are  gathering navigation data (where have the boat been and where have the recording equipment been located) when recording the seismic data. Quite a lot of the time a "seismic line" cannot be completed due to equipment failure, noise on the hydrophones ... If this happens you circle the boat and try again with an Alpha, Beta ... part of the line.
 
The navigation data is recorded in P2/91 & P2/94 (P2/94 EXCHANGE FORMAT FOR RAW MARINE POSITIONING DATA) format and the processed navigational data can be in P1/90 format (U.K.O.O.A. P1/90 POST PLOT DATA EXCHANGE TAPE).

Anyway this perl script processes and combines any Alpha, Beta ... lines into one file.

#!/opt/perl5/bin/perl

# Script : Navigation Merging v1.52

# Description 

# This script takes any number of P190 files and merges them 
# file1, file2,file3. It can deal with incrementing SP as well
# as decrementing SP. It also searches Alpha, Bravo, Charlie 
# linename prefixes in the final .cmb file. and changes this to
# the basic linename. Corrects LSP in the header if Streamer Model
# comment is exported to file.

# Linename P98-030
# Alphaname P98-030A

# The script looks for
# VP98-030A       1    3141145154.97S12115 5.23E...

# and changes this to
# VP98-030        1    3141145154.97S12115 5.23E...

# Author :     Kenneth Thorman
# Date      :     27/12/1998




# MAJOR SUBROUTINES
sub CheckCommandLineSyntax;
sub CreateOutputFile;
sub WriteFirstFile;
sub WriteMiddleFiles;
sub GetSPRangeForAllFiles;
sub CreateSPRangeHeaderRemark;



# MINOR SUBROUTINES
sub Author;
sub GetFileBaseName;
sub MakeReadmeFile;
sub Presentation1;
sub HeadFileInfo;
sub BodyFileInfo;
sub Finish;
sub HeaderStatus;



################################### MAIN SCRIPT ################################

    # Check that the user has entered the right amount of command line arguments
    CheckCommandLineSyntax;
    
    # Open the "cmb" file for writing
    CreateOutputFile;

    # In order to put a remark in the header about the streamer shaping we need
    # to know the SP range for the files we are combining
    GetSPRangeForAllFiles;

    # Create the header remark
    CreateSPRangeHeaderRemark;

    # Since we have to process the first file different than the remaining files
    # we do it here in a seperate procedure
    WriteFirstFile;

    # Since we have processed the first file above lets set the pointer to the 
    # second supplied file
    $counter = 1;

    # Run through the files one by one as long as there files left to process
    while ($counter < ($arg_cnt))
    {
         WriteMiddleFiles ($ARGV[$counter]);

         # Move to the next file
         $counter++;
    }

    # Make a README file in the current directory explaining the "cmb" file
    MakeReadmeFile;

    # Before finishing of time for a little bit of narcisim from my side
    # Print the author information
    Finish;



################################### SUB ROUTINES ###############################

sub CheckCommandLineSyntax
{
  $arg_cnt = @ARGV;   # GET NUMBER OF CMD LINE ARGUMENTS
  if ($arg_cnt < 2)   # IF 0 CMD ARGUMENTS THEN ERROR!
  {
    print ($info);
    print ("\nYou need at least 2 command line arguments!\n");
    die ("SYNTAX: nav_merge file1 file2 file3 file4 ...\n\n");
    Author;
  }
}



sub GetSPRangeForAllFiles{
  
  $arg_cnt = @ARGV;
  $file_cnt = 0;
  
  foreach $file (@ARGV){
    open (P190FILE, "$file") or die ("Could not open $file.\n");
    #print ("Checking SP range for file: $file...\n");
    $filebasename = GetFileBaseName($file);
    $vessel_record = "V" . $filebasename;
    $count = 1;
     
    $line = <P190FILE>;
    while ($line !~ /EOF/g){
      if ($line =~ /^V/) {
         $last_sp = substr($line,20,5);    
      }
      $line = <P190FILE>;
      if (($line =~ /$vessel_record/) and ($count != 0)){
        $first_sp = substr($line,20,5); 
        $count--;
      }
    }
    
    if ($file_cnt == 0){
      $final_FSP = $first_sp;
      #print ("Final FSP is: $final_FSP\n");
      $FSP = 1;
    }
    if ($file_cnt == $arg_cnt-1){
      $final_LSP = $last_sp;
      #print ("Final LSP is: $final_LSP\n");
    }
    $file_cnt++;
    close (P190FILE);
  }
  #print ("FSP: $final_FSP   LSP: $final_LSP\n");
}



sub CreateOutputFile
{
  $output_filename = $ARGV[0] . ".cmb";
  open (OUTFILE,">$output_filename") or die ("Cannot create file $output_filename");
}



sub CreateSPRangeHeaderRemark
{
  $cmb_line_name = GetFileBaseName ($ARGV[0]);
  $temp_str1 = sprintf("H2600 Streamer_001 Model Line %s shots %d to %d: Arc                                          ",
                        $cmb_line_name, $final_FSP, $final_LSP);  
  $temp_str2 = substr($temp_str1,0,80);
  $str_to_add = $temp_str2 . "\n";
}



sub WriteFirstFile
{
  open (HEADFILE, "$ARGV[0]") or die ("Could not open file $ARGV[0].\n");
  $filebasename = GetFileBaseName($ARGV[0]);
  $count = 1;
     
  $line = <HEADFILE>;
  $file_card = substr($line,0,1);
  $SPrangeheader = "no";
  $vessel_record = "V" . $filebasename;

  while ($line !~ /EOF/g){
    if ($file_card eq "H"){
      if (($line =~ /H2600/) and ($line =~ /$final_FSP/) and ($line !~ /$final_LSP/)){ 
        print OUTFILE ($str_to_add);
 $error =  "LSP in the header was incorrect.\n";
        $status = "Corrected. Now reflecting actual SP range in .cmb file";
        HeaderStatus;
        $SPrangeheader = "yes";
      }
      else{
        print OUTFILE ($line);
      }
    }
    elsif ($SPrangeheader eq "no"){
      print OUTFILE ($str_to_add);
      print OUTFILE ($line);
      $error =  "No SP range comment found in header";
      $status = "Corrected. Comment inserted: $str_to_add";
      HeaderStatus;
      $SPrangeheader = "yes";
    }
    else{ 
      print OUTFILE ($line);
    }   
    if ($line =~ /^V/) {
       $headfile_lsp = substr($line,20,5);
    }
    if (($line =~ /$vessel_record/) and ($count != 0)){
      $headfile_fsp = substr($line,20,5); 
      $count--;
    }
    $line = <HEADFILE>;
    $file_card = substr($line,0,1);
    
  }
  Presentation1;
  HeadFileInfo;
  close (HEADFILE);
}   



sub WriteMiddleFiles
{
  my ($file_name) = @_;    #  ASSIGN PASSED PARA. TO $file_name
  
  open (BODYFILE, $file_name) or die ("Could not open file $file_name.\n");
   
  $line = <BODYFILE>;
  $count = 1;
  
  if ($headfile_fsp < $headfile_lsp)             # INCREMENTING SP NUMBER
  { 
    while ($line ne "")
    {
      
      if  ($line =~ /^V/) {
        $temp = substr($line,20,5);
      }
             
      if (((~ /$filebasename/) and ($temp > $headfile_lsp) and ($line !~ /H2600/)) or ($line =~ /EOF/)) {
        if ($line =~ /$filebasename[A-Z]/)
        {
          $line =~ s/$filebasename[A-Z]/$filebasename /;
          print OUTFILE ($line);
        }
        elsif ($counter == ($arg_cnt-1))
        { 
          print OUTFILE ($line);
        }
        if (($line =~ /$vessel_record/) and ($count != 0)) #  GET FIRST EXPORTED SP
        {
          $tailfile_fsp = substr($line,20,5); 
          $count = 0;
        }
      }

      if (($line =~ /^R/) and ($temp < $headfile_lsp)){
       print OUTFILE ($line);
      }

      if ($line =~ /^V/) {
        $tailfile_lsp = substr($line,20,5);
      } 

      $line = <BODYFILE>;
    }
  }
  
  
  elsif ($headfile_fsp > $headfile_ls)
  {
    while ($line ne "")    # DECREMENTING SP NUMBER
    {
      
      
      if  ($line =~ /^V/) {
        $temp = substr($line,20,5);
      }
      
      
      if ((($line =~ /$filebasename/) and ($temp < $headfile_lsp) and ($line !~ /H2600/)) or ($line =~ /EOF/))      {      
        if ($line =~ /$filebasename[A-Z]/) {
          $line =~ s/$filebasename[A-Z]/$filebasename /;
          print OUTFILE ($line);
        }
        elsif ($counter == ($arg_cnt-1)) { 
          print OUTFILE ($line);
        }
        if (($line =~ /$vessel_record/) and ($count != 0)) {
          $tailfile_fsp = substr($line,20,5); 
          $count = 0;
        }
      }

      if (($line =~ /^R/) and ($temp < $headfile_lsp)){
       print OUTFILE ($line);
      }

      
      if ($line =~ /^V/) {
        $tailfile_lsp = substr($line,20,5);
      } 

      $line = <BODYFILE>;
    }
  }
  BodyFileInfo;
  $headfile_fsp = $tailfile_fsp;
  $headfile_lsp = $tailfile_lsp;  
  close (BODYFILE);
}



sub MakeReadmeFile
{ 
  open (READMEFILE,"> README");
  print READMEFILE ("Note: All \"cmb\" files are combined from multiple line segments\n");
  print READMEFILE ("      as per the seismic merge.\n");
  close (READMEFILE);
}



sub Author
{
  print ("\n\nNavigation Merge v1.5\n\n");
  print ("Author: Kenneth Thorman\n");
  print ("Date  : 27 dec 1998\n");
}



sub HeaderStatus{
$~ = "HEADERSTATUS";
write;
}



sub Presentation1{
$~ = "MYFORMAT1";
write;
}



sub HeadFileInfo{
$~ = "HEADFILEINFO";
write;
}



sub BodyFileInfo{
$~ = "BODYFILEINFO";
write;
}



sub Finish{
$~ = "FINISH";
write;
}



format HEADERSTATUS =



Header Check                                  
------------
Output File : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
$output_filename
Error       : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
$error
Status      : @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
$status
.



format MYFORMAT1 =


Combining Files
---------------
.

format HEADFILEINFO =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<       @<<<<<              @<<<<<      
 $ARGV[0]                    $headfile_fsp        $headfile_lsp   
.

format BODYFILEINFO =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<        @<<<<<              @<<<<<      
 $ARGV[$counter]                   $tailfile_fsp        $tailfile_lsp   
.  



format FINISH =





                                    
27-Dec-1998, Kenneth Thorman 

.



sub GetFileBaseName
{
  my ($input_str) = @_;
  my ($end_pos, $temp);
      
 if ($input_str =~/_/g){
    $start_pos = pos ($input_str);
  }    
  if ($input_str =~ /\./g){
    $end_pos = pos ($input_str) - $start_pos ;
  }
  
  $temp = substr ($input_str, $start_pos, $end_pos-1);
  return ($temp);
}


#Script   : navigation_merge
#Version  : 1.5
#Author   : Kenneth Thorman
Post a Comment