#!/usr/local/bin/perl5.6.1

package pt2_direct;

use strict;
use sql_engine;
use Carp;
use Data::Dumper;
use BarcodeRevised_V2_0;
use Checkbarcode;
use Time::HiRes qw(gettimeofday);
use Mail::Mailer;

#################
# See POD at end
#################
# yarg DONT WANT GLOBALS HERE !!!
# Database interaction 
my $STATEMENTS;
my $SNP_STATEMENTS;




sub new {

    my ($class, $cas_db, $snp_db, $id_role, $printer, $benchmark) = @_;
    croak "pt2_direct.pm new method ERROR No CAS WrapDBI user id supplied !" unless (defined $cas_db);
    croak "pt2_direct.pm new method ERROR No SNP WrapDBI user id supplied !" unless (defined $snp_db);
    croak "pt2_direct.pm new method ERROR No id_role supplied !" unless (defined $id_role);
    croak "pt2_direct.pm new method ERROR No printer supplied !" unless (defined $printer);

    unless ($benchmark eq 'BM' || $benchmark eq 'BMS'){
	$benchmark = 0;
    } elsif ($benchmark eq 'BM') {
	$benchmark = 1;
	print STDOUT "Benchmarking activated.\n";
    } else {
	$benchmark = 2;
    }



    #############################################################
    # Limit dev release to the appropriate development databases
    #############################################################
    # yarg need to allow live connects here !
    #
    #if ($cas_db ne 'canplatetrack'){
    #	croak "cas_db WrapDBI user should be canplatetrack !\n";
    #}
    #if ($snp_db ne 'csnp'){
    #	croak "snp_db WrapDBI user should be csnp !\n";
    #}


    my $self = {};

    bless $self, $class;

    $self->{program} = 'pt2_direct.pm_23-10-2003';


    ################################################
    # Datastructures to set up; copied from pt2_seq
    ################################################
    $self->{valid_oligoplates} = {}; # As we check PCR plates; retrieve valid oligoplates and store
    $self->{TOT} = 0;
    $self->{SECT} = 1;
    $self->{lastSECT} = 1;
    $self->{GRID_ROWS} = 10;
    $self->{DATA};


    if ($benchmark == 1){ 
	$self->start_timer("connection to DB and preparing pt2_seq.sql_lib::all");
    };
    $self->{cas_database} = statements->new("$cas_db") || die;
    #$self->{cas_database}->default_sql_lib_path('/nfs/team71/psg/dn1/badger-bin/platetrack/');
    $self->{cas_database}->load_sql_lib(["pt2_seq.sql_lib::all"]);
    $STATEMENTS = $self->{cas_database};
    if ($benchmark == 1){ 
	$self->stop_timer;
    };
    


    
    if ($benchmark == 1){ 
	$self->start_timer("connection to DB and preparing pt2_snp.sql_lib::all");
    };
    $self->{snp_database} = statements->new("$snp_db") || die;

    #$self->{snp_database}->default_sql_lib_path('/nfs/team71/psg/dn1/badger-bin/platetrack/');
    $self->{snp_database}->load_sql_lib(["pt2_snp.sql_lib::all"]);
    $SNP_STATEMENTS = $self->{snp_database};
    if ($benchmark == 1){
	$self->stop_timer;
    };
    
    
    ##############################
    # Check that id_role is valid
    ##############################
    if ($benchmark == 1){ 
	$self->start_timer("pt2_seq.sql_lib::team_from_id_role $id_role, 'Shotgun'");
    }
    my ($team) =  $self->{cas_database}->get('pt2_seq.sql_lib::team_from_id_role', [$id_role, 'Shotgun']);
    my $who_team = $team->[0]->[0];
    croak "pt2_direct.pm new method ERROR supplied id_role $id_role is not appropriate" unless (defined $who_team);
    $self->{id_role} = $id_role;
    $self->{who_team} = $who_team;
    if ($benchmark == 1){ 
	$self->stop_timer;
    };


    ###################################
    # We need 'email' given an id_role
    ###################################
    #email_from_id_role
    if ($benchmark == 1){ 
	$self->start_timer("pt2_seq.sql_lib::email_from_id_role $id_role");
    }
    my $who = $STATEMENTS->get('pt2_seq.sql_lib::email_from_id_role', [$id_role]);
    $who = $who->[0][0];
    croak "pt2_direct.pm new method ERROR supplied id_role $id_role does not return an email id" unless (defined $who);
    $self->{who} = $who;
    if ($benchmark == 1){ 
	$self->stop_timer;
    }

    
    ####################################################
    # Check that printer is valid and set up the object
    # yarg
    ####################################################
    # TO_DO
    $self->{printer} = Barcode->new($self->{cas_database}->{DBH});
    $self->{printer}->Type("LP");
    $self->{printer}->{'Printer'} = $printer;
    #$self->{printer}->Printer($printer);
    $self->{printer}->User($who);
    

    #############################################################
    # A list of available seqcategories for the team in question
    #############################################################
    if ($benchmark == 1){ 
	$self->start_timer("pt2_seq.sql_lib::available_categories $who_team");
    }

    $self->{seqcats} = {};
    my $seqcats = $STATEMENTS->get('pt2_seq.sql_lib::available_categories', [$who_team]);
    foreach my $scat (@$seqcats){
	$self->{seqcats}->{$scat->[0]} = $scat->[1];
    }
    if ($benchmark == 1){ 
	$self->stop_timer;
    }

    #warn "available_categories ...\n";
    #warn Data::Dumper::Dumper($self->{seqcats});


    ########################################
    # A list of all available seqcategories
    ########################################
    if ($benchmark == 1){ 
	$self->start_timer("pt2_seq.sql_lib::all_available_categories");
    }
    $self->{catsseq} = {};
    my $catsseqs = $STATEMENTS->get('pt2_seq.sql_lib::all_available_categories');
    foreach my $scat (@$catsseqs){
	$self->{catsseq}->{$scat->[0]} = $scat->[1];
    }
    if ($benchmark == 1){ 
	$self->stop_timer;
    }

    #warn "all_available_categories ...\n";
    #warn Data::Dumper::Dumper($self->{catsseq});


    #######################################################
    # A session value for updates made for this plate list
    #######################################################
    if ($benchmark == 1){ 
	$self->start_timer("pt2_seq.sql_lib::new_session");
    }
    my $session = $STATEMENTS->get('pt2_seq.sql_lib::new_session');
    $session = $session->[0][0];
    #warn "session returned = $session\n";
    $self->{session} = $session;
    if ($benchmark == 1){ 
	$self->stop_timer;
    }

    $self->{benchmark} = $benchmark;

    

    return $self;
}



sub add_plate {
    my ($self, $category, $id_scsp, $PCRplate1, $PCRplate2, $Oligoplate1, $Oligoplate2) = @_;

    my $old_seqchem;
    
    croak "pt2_direct.pm add_plate method ERROR No category supplied !" unless (defined $category);
    croak "pt2_direct.pm add_plate method ERROR No id_scsp supplied !" unless (defined $id_scsp);
    croak "pt2_direct.pm add_plate method ERROR No PCRplate1 supplied !" unless (defined $PCRplate1);
    croak "pt2_direct.pm add_plate method ERROR No PCRplate2 supplied !" unless (defined $PCRplate2);
    croak "pt2_direct.pm add_plate method ERROR No Oligoplate1 supplied !" unless (defined $Oligoplate1);
    croak "pt2_direct.pm add_plate method ERROR No Oligoplate2 supplied !" unless (defined $Oligoplate2);

    ###################################
    # Limit the category types for now
    ###################################
    unless ($category == 12){
	croak "pt2_direct.pm add_plate method ERROR only ExoCan category plates are currently handled !";
    }

    #####################################################################
    # Check that the team in question can process this category of plate
    #####################################################################
    unless (defined $self->{seqcats}->{$category}){
	croak "pt2_direct.pm add_plate method ERROR team $self->{who_team} cannot process category $category plates !";
    }
    
    #####################################################################
    # Check that the supplied category does not differ from a previously 
    # defined category for the plate stack
    #####################################################################
    if ( ($self->{category} ne '') && ($category ne $self->{category}) ){
	croak "pt2_direct.pm add_plate method ERROR Supplied category $category does not match list category $self->{category}";
    } else {
	$self->{category} = $category;
    }



    ######################################
    # Sanity check the id_scsp
    # Is it valid for the category type ?
    ######################################
    if ($category == 12){
	unless ($id_scsp == 197){
	    croak "pt2_direct.pm add_plate method ERROR ExoCan category plates can only be submitted with id_scsp 197";
	}
    }
    
    
    #################################################################
    # Need to check that our $chem_var value is a true id_scsp value
    #################################################################
    if ($self->{benchmark} == 1){ 
	$self->start_timer("pt2_seq.sql_lib::seq_info_from_id_scsp $id_scsp");
    }
    my ($chemistry_info) = $self->{cas_database}->get('pt2_seq.sql_lib::seq_info_from_id_scsp', [$id_scsp]);
    if ($self->{benchmark} == 1){
	$self->stop_timer;
    }

    #warn "*******************************************************\n";
    #warn Data::Dumper::Dumper($chemistry_info);
    #warn "*******************************************************\n";

    my ($protocol) = $chemistry_info->[0]->[0];
    my ($seqchem) = $chemistry_info->[0]->[1];
    my ($dir) = $chemistry_info->[0]->[2];
    my ($primer) = $chemistry_info->[0]->[3];
    my ($suffix) = $chemistry_info->[0]->[4];
    my ($primername) = $chemistry_info->[0]->[5];
    my ($vectorname) = $chemistry_info->[0]->[6];
    my ($dyeset) = $chemistry_info->[0]->[7];
    my ($wp) = $chemistry_info->[0]->[8];
    my ($pcr_r) = $chemistry_info->[0]->[9];
    
    
    $protocol =~ /^(\w+)-/;
    my $p_test;
    if ($1) { $p_test = $1; } else {
	croak "pt2_direct.pm add_plate method ERROR Problems parsing $protocol";
    }

    ######################
    # Old style seqchem
    ######################

    if ( (($seqchem eq '') && ($p_test ne 'MB') && ($id_scsp < 98)) ){
	croak "pt2_direct.pm add_plate method ERROR ID_SCSP $id_scsp did not return a valid (old-style) id_seqchem.";
    } else {
	
#	$protocol_var = $protocol;
#	$dye_var = $dyeset;
#	$dir_var = $dir;
#	$term_var = $primer;
#	$vector_var = $vectorname;
#	$primer_var = $primername;
#	$pcr_var = $pcr_r;
#	$suffix_var = $suffix;
#
#	$ID_SCSP = $chem_var;
#	
	
	if ($seqchem eq ''){ 
	    $old_seqchem = 'NULL';
	} else {
	    $old_seqchem = $seqchem;
	}
	
    }

    ##############################
    # Sanity check the PCR_PLATES
    ##############################
    #warn "\t\tFIRST PC plate check on $PCRplate1\n";
    my $PCRplate1_var = $self->pc_check($PCRplate1);
    #warn "\t\tSECOND PC plate check on $PCRplate2\n";
    my $PCRplate2_var = $self->pc_check($PCRplate2);

    #warn "PCRplate1_var $PCRplate1_var\n";
    #warn "PCRplate2_var $PCRplate2_var\n";
    #die "FORCED QUIT !!!\n";

    ################################
    # Sanity check the OLIGO_PLATES
    ################################
    #warn "\t\tFIRST EP plate check on $Oligoplate1\n";
    my $Oligoplate1_var = $self->ep_check($Oligoplate1);
    #warn "\t\tSECOND EP plate check on $Oligoplate2\n";
    my $Oligoplate2_var = $self->ep_check($Oligoplate2);

    #warn "Oligoplate1_var $Oligoplate1_var\n";
    #warn "Oligoplate2_var $Oligoplate2_var\n";
    #die "FORCED QUIT !!!\n";

    ############################################################################
    # We need to clear 'valid_oligoplates' ready for the next plate of the set
    ############################################################################
    $self->{valid_oligoplates} = {};

    #############################################################
    # pt2_seq_can code integrated for speed of implementation
    #############################################################
    $self->make_exocan_batch
	($category, $id_scsp, $PCRplate1_var, $PCRplate2_var, $Oligoplate1_var, $Oligoplate2_var, $suffix, $old_seqchem);
}


sub review_plates {
    my ($self) = @_;
#    warn Data::Dumper::Dumper($self);

    print STDOUT "******************************************* !!!\n";
    print STDOUT "LOOKING AT PT2 interface structures created !!!\n";
    print STDOUT "******************************************* !!!\n";
    print STDOUT "SECT\n";
    print STDOUT Data::Dumper::Dumper($self->{SECT});
    print STDOUT "lastSECT\n";
    print STDOUT Data::Dumper::Dumper($self->{lastSECT});
    print STDOUT "GRID_ROWS\n";
    print STDOUT Data::Dumper::Dumper($self->{GRID_ROWS});
    print STDOUT "DATA\n";
    print STDOUT Data::Dumper::Dumper($self->{DATA});

}



sub clear_plates {

    # yarg; untested

    my ($self) = @_;
    $self->{plates} = [];
    $self->{TOT} = 0;

    $self->{valid_oligoplates} = {}; # As we check PCR plates; retrieve valid oligoplates and store
    $self->{TOT} = 0;
    $self->{SECT} = 1;
    $self->{lastSECT} = 1;
    $self->{GRID_ROWS} = 10;
    undef $self->{DATA};

#    warn "-----------------------------------------------------------------------------\n";
#    warn "Clearing plate list ...\n";
#    warn "-----------------------------------------------------------------------------\n";

}


sub submit_plates {
    my ($self) = @_;
#    warn "Submitting plate list ...\n";

    ######################################################################################
    # Depending on the category type of the stack, call an appropriate submission routine
    ######################################################################################
    
#    warn "NOW SUBMITTING $self->{TOT} PLATE(S) ...\n";
#    warn "FOR LIST CATEGORY = $self->{category}\n";

    if ($self->{category} = 12){
	$self->submit_ExoCan_plates;
    }
    

}



# --------------------------------------------------------------------------------
# Routines for internal calls only
# --------------------------------------------------------------------------------




sub submit_ExoCan_plates {

    my ($self) = @_;
    
    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::make_exocan_batch method ERROR Invalid access to subroutine from $pack";
    }
    
    #warn "Inside submit_ExoCan_plates ...\n";
    

    my $mailer; ###################### All error messages to mail in one report
    
    unless ($self->{TOT} > 0) {
	croak "pt2_direct.pm  submit_ExoCan_plates method ERROR Nothing to submit";
    }
    
    my @new_plates;
    my @db_problems;
    my @to_print_LP;
    my $summary_barf = 0;

    #warn "********************* Submitting ExoCan Loadingplates ************************\n";
    
    # Get the current date from Oracle
    if ($self->{benchmark} == 1){ 
	$self->start_timer("pt2_seq.sql_lib::today");
    }
    my ($today) = $STATEMENTS->get('pt2_seq.sql_lib::today');
    $today = $today->[0]->[0];
    if ($self->{benchmark} == 1){ 
	$self->stop_timer;
    }

    
    foreach my $s (1 .. $self->{lastSECT}){
	foreach my $r (0 .. 9){
	    if ($self->{DATA}->[$s]->[$r]->[0] eq ''){ next; }
	    
	    my $iteration = '';
	    $self->{DATA}->[$s]->[$r]->[3] =~ /^(.\w+)\snew(\d+)\sold(\w+)/;
	    my $suffix = $1;
	    my $cid = $2;
	    my $old_id_seqchem = $3;
	    
	    #warn "-----> suffix $suffix cid $cid old_id_seqchem $old_id_seqchem\n";

	    # Get the protocol too !
	    my ($p_type) = $STATEMENTS->get('pt2_seq.sql_lib::seq_info_from_id_scsp', [$cid]);
	    
	    $p_type =~ /^(\w+)-/;
	    if ($1) { $p_type = $1; }
	    
	    my $format = '384';
	    my $team = $self->{DATA}->[$s]->[$r]->[6];

	    #warn "-----> p_type $p_type format $format team $team\n";
	    
	    
	    # Make the plate first
	    my ($plate) = $STATEMENTS->get('pt2_seq.sql_lib::new_id_loadingplate');
	    $plate = $plate->[0]->[0];
	    
	    my $name = "ExoCan" . "$plate";
	    
	    #warn "-----> plate $plate name $name\n";
	    
	    ###########################################################
	    # Useful data for the sticker
	    # We are not going to fit all of this info on the sticker
	    ###########################################################
	    #my $pcrol = $DATA->[$s]->[$r]->[1];
	    #my ($pcrol_pcr, $pcrol_ol) = split /\//, $pcrol;
	    #$pcrol = "PCR$pcrol_pcr" . "/OL$pcrol_ol";
	    
	    #warn "-------------------------------------\n";
	    #warn "---> $self->{DATA}->[$s]->[$r]->[1]\n";
	    #warn "-------------------------------------\n";
	    
	    # 1PC1/EP1S  2PC1/EP2A  3PC2/EP1S  4PC2/EP2A
	    # 8534/10501 8534/10503 8546/10501 8546/10503
	    my $PCEP = $self->{DATA}->[$s]->[$r]->[1];

	    #warn "--->PCEP $PCEP\n";
	    
	    my ($PC1, $PC2, $EP1, $EP2);
	    ($PC1, $EP1, $PC1, $EP2, $PC2, $EP1, $PC2, $EP2) = $PCEP =~ /^(\d+)-(\d+)\s+(\d+)-(\d+)\s+(\d+)-(\d+)\s+(\d+)-(\d+)/;
	    #warn "PC1 $PC1, EP1 $EP1, PC1 $PC1, EP2 $EP2, PC2 $PC2, EP1 $EP1, PC2 $PC2, EP2 $EP2\n";
	    
	    #warn "PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
	    
	    #warn "Now entering Plate $self->{DATA}->[$s]->[$r]->[0]. ID_LOADINGPLATE $plate NAME $name. Format $format.\n";

	    push @new_plates, $plate;
	    
	    my $cat = $self->{catsseq}{$self->{DATA}->[$s]->[$r]->[7]};
	    #warn "-----> cat $cat\n";
	    
	    ########################################################
	    # Cancer; 2x 96 well PCR_PLATES (1individual per plate)
	    #         2x 96 well OLIGO_PLATES (1 sense 1 antisense)
	    ########################################################
	    #warn "pt2_seq.sql_lib::make_loadingplate\n";
	    #warn "plate $plate name $name team $team cat $cat format $format suffix $suffix iteration $iteration\n";

	    if ($self->{benchmark} == 2){
		print STDOUT "Processing plate $plate\n";
	    }

	    if ($self->{benchmark} == 1){

		$self->start_timer("pt2_seq.sql_lib::make_loadingplate $plate, $name, $team, $cat, $format, $suffix, $iteration");
	    }

	    eval {
		$STATEMENTS->do('pt2_seq.sql_lib::make_loadingplate', [
								       $plate,
								       $name,
								       $team,
								       $cat,
								       $format,
								       $suffix,
								       $iteration
								       ]);		    
	    };
	    if ($@ ne ''){
		push @db_problems, $@;
	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    };

	    
	    #warn "pt2_seq.sql_lib::make_loadingplate_status\n";
	    #warn "plate $plate session $self->{session} prog $self->{program} who $self->{who}\n";

	    
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_seq.sql_lib::make_loadingplate_status $plate, $self->{session}, $self->{program}, $self->{who}");
	    }
		
	    eval {
		$STATEMENTS->do('pt2_seq.sql_lib::make_loadingplate_status', [
									      $plate,
									      $self->{session},
									      $self->{program},
									      $self->{who},
									      ]);		    
	    };
	    if ($@ ne ''){
		push @db_problems, $@;
	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    };
	    
	    
	    ###########################################################################
	    # Need to update a SNP loadingplate status for in-cancer-lab tracking
	    ###########################################################################
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_seq.sql_lib::make_snp_loadingplate $plate");
	    }

	    eval {
		$SNP_STATEMENTS->do('pt2_snp.sql_lib::make_snp_loadingplate', [
									       $plate 
									       ]);		    
	    };
	    if ($@ ne ''){
		push @db_problems, $@;
	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }


	    if ($self->{benchmark} == 1){
		$self->start_timer("pt2_snp.sql_lib::make_snp_loadingplate_status $plate, 1, 1, $self->{program}");
	    }

	    eval {
		$SNP_STATEMENTS->do('pt2_snp.sql_lib::make_snp_loadingplate_status', [
										      $plate, 
										      1, 
										      1,
										      $self->{session},
										      $self->{program},
										      $self->{id_role}
										      ]);		    
	    };
	    if ($@ ne ''){
		push @db_problems, $@;
	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }


	    my %to_go = (
			 "Barcode" => "$plate",
			 "Owner" => "$team",
			 
##			 "Name" => "$pcrol",
			 "Name" => "HumanR",
			 
			 # we can use this field for chem identifier
			 "Project" => "ExoCan-$cid-$p_type",
			 "Suffix" => "$suffix$iteration",
			 "Format" => "384",
			 );
	    push @to_print_LP, \%to_go;
	    
	    
	    #################################
	    # Make 384 loadingsample entries
	    #################################

	    if ($self->{benchmark} == 1){ 
		$self->start_timer("384x pt2_seq.sql_lib::make_loadingsample");
	    }

	    #                          1 to 384
	    foreach my $this_id_map ( 97 .. 480){
		
#		warn "pt2_seq.sql_lib::make_loadingsample\n";
#		warn "plate $plate this_id_map $this_id_map cid $cid\n";

		eval {
		    $STATEMENTS->do('pt2_seq.sql_lib::make_loadingsample', [
									    $plate,
									    $this_id_map,
									    $cid
									    ]);		    
		}
	    };
	    if ($@ ne ''){
		push @db_problems, $@;
	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    ##############################################################
	    # Update SNP db
	    # Summary lookup information in exoseq_loadingsample
	    ##############################################################
	    
	    #####################################
	    # Determine id_map::id_loadingsample
	    #####################################
	    
	    #print STDOUT "-----------------------\n";
	    #print STDOUT "LP$plate\n";
	    #print STDOUT "-----------------------\n";
	    
	    my %exo_id_loadingsample;

	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_seq.sql_lib::loadingplate_vs_loadingsample_info $plate");
	    }

	                                                         # id_map    id_loadingsample
	    my ($lp_info) = $STATEMENTS->get('pt2_seq.sql_lib::loadingplate_vs_loadingsample_info', [$plate]);
	    
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }

	    # check we have 384
	    my $count = 0;
	    foreach my $n (@$lp_info){
		$count++;
		$exo_id_loadingsample{$n->[1]} = $n->[0];
	    }
	    unless ($count == 384){
		$summary_barf++;

		print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		print STDOUT "pt2_seq.sql_lib::loadingplate_vs_loadingsample_info called with LP $plate\n";
		print STDOUT "Exoseq_summary; could not determine 384 loadingsample entries !";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_seq.sql_lib::loadingplate_vs_loadingsample_info called with LP $plate\n";
		$mailer .= "Exoseq_summary; could not determine 384 loadingsample entries !\n";
	    }


	    #############################################
	    # For 2x PCR_PLATES determine id_map::id_ind
	    #############################################
	    #######
	    # $PC1 
	    #######
	    my %PC1_exo_id_pcrwell;
	    my %PC1_exo_id_ind;
	    
	    #############################################
	    # Need a new array_pattern for cancer plates
	    #############################################
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_seq.sql_lib::pp_loadingplate_2_idind_ap10 $PC1");
	    }
	                                             # id_map   id_pcrwell   id_ind   target_idmap
	    my ($PC1_ind_info) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::pp_loadingplate_2_idind_ap10', [$PC1]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    #warn Data::Dumper::Dumper($PC1_ind_info);
	    
	    #print STDOUT "-----------------------\n";
	    #print STDOUT "PC$PC1\n";
	    #print STDOUT "-----------------------\n";
	    
	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$PC1_ind_info){
		$count++;
		$PC1_exo_id_pcrwell{$n->[3]} = $n->[1];
		
		#print STDOUT "new map $n->[3] gets id_pcrwell $n->[1]\n";
		
		$PC1_exo_id_ind{$n->[3]} = $n->[2];
		
		#print STDOUT "new map $n->[3] gets id_ind $n->[2]\n";

	    }
	    unless ($count == 192){
		$summary_barf++;

		print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		print STDOUT "pt2_snp.sql_lib::pp_loadingplate_2_idind_ap10 called with PC $PC1";
		print STDOUT "Exoseq_summary; could not determine 192 id_pcrwell/id_ind entries !";
		
		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::pp_loadingplate_2_idind_ap10 called with PC $PC1\n";
		$mailer .= "Exoseq_summary; could not determine 192 id_pcrwell/id_ind entries\n";
	    }

	    
	    
	    #######
	    # $PC2
	    #######
	    #my %PC2_exo_id_pcrwell;
	    #my %PC2_exo_id_ind;
	    
	    #############################################
	    # Need a new array_pattern for cancer plates
	    #############################################
	    if ($self->{benchmark} == 1){
		$self->start_timer("pt2_seq.sql_lib::pp_loadingplate_2_idind_ap11 $PC2");
	    }
	                                             # id_map   id_pcrwell   id_ind   target_idmap
	    my ($PC2_ind_info) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::pp_loadingplate_2_idind_ap11', [$PC2]);
	    #warn Data::Dumper::Dumper($PC1_ind_info);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    #print STDOUT "-----------------------\n";
	    #print STDOUT "PC$PC2\n";
	    #print STDOUT "-----------------------\n";

	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$PC2_ind_info){
		$count++;
		$PC1_exo_id_pcrwell{$n->[3]} = $n->[1];
		
		#print STDOUT "new map $n->[3] gets id_pcrwell $n->[1]\n";
		
		$PC1_exo_id_ind{$n->[3]} = $n->[2];

		#print STDOUT "new map $n->[3] gets id_ind $n->[2]\n";
		
	    }
	    unless ($count == 192){
		$summary_barf++;

		print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		print STDOUT "pt2_snp.sql_lib::pp_loadingplate_2_idind_ap11 called with PC $PC2";
		print STDOUT "Exoseq_summary; could not determine 192 id_pcrwell/id_ind entries !";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::pp_loadingplate_2_idind_ap11 called with PC $PC2";
		$mailer .= "Exoseq_summary; could not determine 192 id_pcrwell/id_ind entries\n";
	    }

	    
	    #############################################################################################
	    # Determine id_map::id_oligoprimer; ie. the primer used to actually sequence the PCR product
	    #############################################################################################
	    # Note that 2 EPs are used for 1 ExoCan loadingplate
	    my %EP1_exo_id_well;
	    my %EP1_exo_id_oligoprimer;
	    
	    #############################################
	    # Need a new array_pattern for cancer plates
	    #############################################
	    
	    #print STDOUT "-----------------------\n";
	    #print STDOUT "EP$EP1\n";
	    #print STDOUT "-----------------------\n";
	    

	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap12 $EP1");
	    }

	    #warn "Calling ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE with EP $EP1\n";
	                                            # opw.id_map, opw.id_well, oo.id_oligoprimer, ap.target_idmap
	    my ($oligoprimer_info1) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap12', [$EP1]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$oligoprimer_info1){
		$count++;
		$EP1_exo_id_well{$n->[3]} = $n->[1];
		
		#print STDOUT "new map $n->[3] gets id_well $n->[1]\n";
		
		$EP1_exo_id_oligoprimer{$n->[3]} = $n->[2];
		
		#print STDOUT "new map $n->[3] gets id_oligoprimer $n->[2]\n";
		
	    }
	    unless ($count == 192){
		$summary_barf++;
		
		print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		print STDOUT "pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap12 called with EP $EP1";
		print STDOUT "Exoseq_summary; could not determine 192 id_oligoprimer/id_well entries !";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap12 called with EP $EP1\n";
		$mailer .= "Exoseq_summary; could not determine 192 id_oligoprimer/id_well entries\n";
	    }

	    
	    #my %EP2_exo_id_well;
	    #my %EP2_exo_id_oligoprimer;
	    
	    #############################################
	    # Need a new array_pattern for cancer plates
	    #############################################

	    #print STDOUT "-----------------------\n";
	    #print STDOUT "EP$EP2\n";
	    #print STDOUT "-----------------------\n";
	    
	    #warn "Calling ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE with EP $EP2\n";
	    
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap13 $EP2");
	    }
	                                                 # opw.id_map, opw.id_well, oo.id_oligoprimer, ap.target_idmap
	    my ($oligoprimer_info1) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap13', [$EP2]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    
	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$oligoprimer_info1){
		$count++;


		$EP1_exo_id_well{$n->[3]} = $n->[1];
		#print STDOUT "new map $n->[3] gets id_well $n->[1]\n";
		
		$EP1_exo_id_oligoprimer{$n->[3]} = $n->[2];
		#print STDOUT "new map $n->[3] gets id_oligoprimer $n->[2]\n";

	    }
	    unless ($count == 192){
		$summary_barf++;

		print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		print STDOUT "pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap13 called with EP $EP2";
		print STDOUT "Exoseq_summary; could not determine 192 id_oligoprimer/id_well entries !";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::ID_OLIGOPRIMER_ID_WELL_from_ID_OLIGOPLATE_ap13 called with EP $EP2\n";
		$mailer .= "Exoseq_summary; could not determine 192 id_oligoprimer/id_well entries\n";
	    }

	    
	    ####################################################
	    # Need id_gene/id_sts info for exoseq_loadingsample
	    ####################################################
	    
	    my %PC1_exo_gene;
	    my %PC1_exo_design;
	    my %PC1_exo_idsts;
	    
	    #print STDOUT "-----------------------\n";
	    #print STDOUT "PC$PC1\n";
	    #print STDOUT "-----------------------\n";
	    
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP10 $PC1");
	    }
	                           # pw.id_pcrplate, pw.id_map, ed.id_design, cs.id_gene, st1.id_sts, st1.amplimer, ap.target_idmap
	    my ($gene_info1) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP10', [$PC1]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }

	    ################################################################################################
	    #warn Data::Dumper::Dumper($gene_info1);
	    ################################################################################################
	    
	    
	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$gene_info1){
		$count++;

		# We cannot get this until we make a new call to gene_expt_project
#		$PC1_exo_projectname{$n->[6]} = $n->[];
#		print STDOUT "new map $n->[6] gets projectname $n->[1]\n";
		
		$PC1_exo_gene{$n->[6]} = $n->[3];
		#print STDOUT "new map $n->[6] gets id_gene $n->[3]\n";

		$PC1_exo_idsts{$n->[6]} = $n->[4];
		#print STDOUT "new map $n->[6] gets id_sts $n->[4]\n";
		
		$PC1_exo_design{$n->[6]} = $n->[2];
		#print STDOUT "new map $n->[6] gets id_design $n->[2]\n";




		################################
		# Amplimer check missing - yarg
		################################
		#print STDOUT "--------------------------------->AMPLIMER ... $n->[5]\n";



	    }
	    

	    unless ($count == 192){
		$summary_barf++;

		print STDOUT "LP $plate PC1 $PC1";
		print STDOUT "pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP10 called with PC $PC1";
		print STDOUT "Exoseq_summary; could not determine 192 id_gene, id_design, id_sts /id_well entries";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP10 called with PC $PC1";
		$mailer .= "Exoseq_summary; could not determine 192 id_gene, id_design, id_sts /id_well entries\n";
	    }


	    #print STDOUT "-----------------------\n";
	    #print STDOUT "PC$PC2\n";
	    #print STDOUT "-----------------------\n";


	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP11 $PC2");
	    }
	                           # pw.id_pcrplate, pw.id_map, ed.id_design, cs.id_gene, st1.id_sts, st1.amplimer, ap.target_idmap
	    my ($gene_info2) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP11', [$PC2]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }

	    ################################################################################################
	    #warn Data::Dumper::Dumper($gene_info2);
	    ################################################################################################
	    
	    # Check we have 192
	    my $count = 0;
	    foreach my $n (@$gene_info2){
		$count++;
		
		# We cannot get this until we make a new call to gene_expt_project
#		$PC1_exo_projectname{$n->[6]} = $n->[];
#		print STDOUT "new map $n->[6] gets projectname $n->[1]\n";
		
		$PC1_exo_gene{$n->[6]} = $n->[3];
		#print STDOUT "new map $n->[6] gets id_gene $n->[3]\n";

		$PC1_exo_idsts{$n->[6]} = $n->[4];
		#print STDOUT "new map $n->[6] gets id_sts $n->[4]\n";

		$PC1_exo_design{$n->[6]} = $n->[2];
		#print STDOUT "new map $n->[6] gets id_design $n->[2]\n";
		
		#########################
		# Amplimer check missing
		#########################

	    }
	    
	    unless ($count == 192){
		$summary_barf++;

		print STDOUT "LP $plate PC2 $PC2";
		print STDOUT "pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP11 called with PC $PC2";
		print STDOUT "Exoseq_summary; could not determine 192 id_gene/id_sts entries !";

		$mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		$mailer .= "pt2_snp.sql_lib::v2_loadingplate_2_gene_and_design_and_sts_PC_AP11 called with PC $PC2\n";
		$mailer .= "Exoseq_summary; could not determine 192 id_gene, id_design, id_sts /id_well entries\n";
	    }



#############################################################################################################################
#############################################################################################################################
##		#############################################
##		# Process and sanity check the returned data
##		#############################################
##		 if (defined $seen_well{$n->[1]}){
##
##		    # $n->[0]         $n->[1]    $n->[2]       $n->[3]    $n->[4]    $n->[5]
##		    # pw.id_pcrplate, pw.id_map, ed.id_design, g.id_gene, st.id_sts, st.amplimer
##		   
##		    ##############################################################################
##		    # Note that some well duplicates are ok; eg. if it is just the id_gene which
##		    # differs between the sets
##		    #
##		    # Anything other than this ... potential problem hence inform and don't allow
##		    # futher processing
##		    ##############################################################################
##		    if (
##			($seen_well{$n->[1]}->[0] ne $n->[0]) ||
##			($seen_well{$n->[1]}->[1] ne $n->[1]) ||
##			#($seen_well{$n->[1]}->[2] ne $n->[2]) || # We must handle multiple designs (GOMI designs
##			                                          # may be an already processed exon
##			#($seen_well{$n->[1]}->[3] ne $n->[3]) || # We must handle multiple genes
##			($seen_well{$n->[1]}->[4] ne $n->[4]) ||  
##			($seen_well{$n->[1]}->[5] ne $n->[5])
##			) {
##			
##			########################
##			# We have hit a problem
##			########################
##			&update("Exoseq_summary ; data problem for id_pcrplate $n->[0] well $n->[1]");
##			&update("Exoseq_summary ; Check output in terminal (a debugging mail will also be sent)");
##			$update_screen->update('idletasks');
##
##			warn "-------------------------------------------------------------------------------------\n";
##			warn "WELL $n->[1] ON PCR_PLATE RETURNED MULTIPLE DATA SETS (PC$pcrol_pcr EP$pcrol_ol) !!!\n";
##			warn "-------------------------------------------------------------------------------------\n";
##
##			warn "*last hit*\n";
##			warn "pcr_well.id_pcrplate  ... $seen_well{$n->[1]}->[0]\n";
##			warn "pcr_well.id_map       ... $seen_well{$n->[1]}->[1]\n";
##			warn "expt_design.id_design ... $seen_well{$n->[1]}->[2]\n";
##			warn "gene.id_gene          ... $seen_well{$n->[1]}->[3]\n";
##			warn "sts.id_sts            ... $seen_well{$n->[1]}->[4]\n";
##			warn "sts.id_amplimer       ... $seen_well{$n->[1]}->[5]\n";
##			warn "\n\n";
##			#warn Data::Dumper::Dumper($seen_well{$n->[1]});
##			
##			warn "*this hit*\n";
##			warn "pcr_well.id_pcrplate  ... $n->[0]\n";
##			warn "pcr_well.id_map       ... $n->[1]\n";
##			warn "expt_design.id_design ... $n->[2]\n";
##			warn "gene.id_gene          ... $n->[3]\n";
##			warn "sts.id_sts            ... $n->[4]\n";
##			warn "sts.id_amplimer       ... $n->[5]\n";
##			warn "\n\n";
##			#warn Data::Dumper::Dumper($n);
##
##			########################
##			# APPEND TO MAIL REPORT
##			########################
##
##			 
##			    $mailer .= "-------------------------------------------------------------------------------------\n";
##			    $mailer .= "WELL $n->[1] ON PCR_PLATE RETURNED MULTIPLE DATA SETS (PC$pcrol_pcr EP$pcrol_ol) !!!\n";
##			    $mailer .= "-------------------------------------------------------------------------------------\n";
##			    
##			    $mailer .= "*last hit*\n";
##			    $mailer .= "pcr_well.id_pcrplate  ... $seen_well{$n->[1]}->[0]\n";
##			    $mailer .= "pcr_well.id_map       ... $seen_well{$n->[1]}->[1]\n";
##			    $mailer .= "expt_design.id_design ... $seen_well{$n->[1]}->[2]\n";
##			    $mailer .= "gene.id_gene          ... $seen_well{$n->[1]}->[3]\n";
##			    $mailer .= "sts.id_sts            ... $seen_well{$n->[1]}->[4]\n";
##			    $mailer .= "sts.id_amplimer       ... $seen_well{$n->[1]}->[5]\n";
##			    $mailer .= "\n\n";
##			    
##			    $mailer .= "*this hit*\n";
##			    $mailer .= "pcr_well.id_pcrplate  ... $n->[0]\n";
##			    $mailer .= "pcr_well.id_map       ... $n->[1]\n";
##			    $mailer .= "expt_design.id_design ... $n->[2]\n";
##			    $mailer .= "gene.id_gene          ... $n->[3]\n";
##			    $mailer .= "sts.id_sts            ... $n->[4]\n";
##			    $mailer .= "sts.id_amplimer       ... $n->[5]\n";
##			    $mailer .= "\n\n";
##				
##			   
##			
##			
##
##			$summary_barf++;
##			next;
##
##		    }
##		    
##		    ################################################################################################
##		    # If multiple genes ... need to select 1 (seh suggested taking the lowest id_gene of the two)
##		    ################################################################################################
##		    if ($seen_well{$n->[1]}->[3] ne $n->[3]) {
##
##			&update("Exoseq_summary ; Well $n->[1] on PCR_PLATE $n->[0] Multiple id_gene seen  $seen_well{$n->[1]}->[3] ... $n->[3]");
##			$update_screen->update('idletasks');
##
##			warn "---------------------------------------------------------\n";
##			warn "WELL $n->[1] ON PCR_PLATE RETURNED MULTIPLE GENES\n";
##			warn "---------------------------------------------------------\n";
##
##			warn "*last hit*\n";
##			warn "gene.id_gene          ... $seen_well{$n->[1]}->[3]\n";
##			warn "\n";
##			warn "*this hit*\n";
##			warn "gene.id_gene          ... $n->[3]\n";
##			warn "\n";
##
##		    }
##
##		 
##		    ################################################################################################
##		    # If multiple designs ... check multiple designs are attached to the same project
##		    # ; mail if not.... take the last one if they agree
##		    #  ***** Need to check this by gene, incase 2 different
##		    #  ***** genes with two different designs are returned  seh 200302
##		    ################################################################################################
##		    if ($seen_well{$n->[1]}->[2] ne $n->[2]) {
##
##			&update("Exoseq_summary ; Well $n->[1] on PCR_PLATE $n->[0] Multiple id_design seen  $seen_well{$n->[1]}->[2] ... $n->[2]");
##			$update_screen->update('idletasks');
##
##			warn "---------------------------------------------------------\n";
##			warn "WELL $n->[2] ON PCR_PLATE RETURNED MULTIPLE DESIGNS\n";
##			warn "---------------------------------------------------------\n";
##
##			warn "*last hit*\n";
##			warn "design.id_design          ... $seen_well{$n->[1]}->[2]\n";
##			warn "\n";
##			warn "*this hit*\n";
##			warn "design.id_design          ... $n->[2]\n";
##			warn "\n";
##
##			&update("Now checking multiple designs point to the same project...");
##			$update_screen->update('idletasks');
##			# gene in $n->[3]
##			######seh 200302
##			my ($project_info2) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::gene_design_2_project', [$n->[3], $n->[2]]);
##			
##			if ($project_info2->[0]->[0] eq ''){
##			    $summary_barf++;
##			    warn "WELL $n->[1] (PC$pcrol_pcr EP$pcrol_ol) !!!\n";
##			    warn "No project returned for gene $n->[3] design $n->[2]\n\n";
##			    $mailer .= "-------------------------------------------------------------------------------------\n";
##			    $mailer .= "WELL $n->[1] (PC$pcrol_pcr EP$pcrol_ol) !!!\n";
##			    $mailer .= "-------------------------------------------------------------------------------------\n";
##			    $mailer .= "No project returned for gene $n->[3] design $n->[2]  \n\n";
##			    next;
##			} 
##
##			elsif (defined  $exo_projectname{$n->[3]} && ($exo_projectname{$n->[3]} ne $project_info2->[0]->[0]) ){
##
##			    warn "first design => project  $exo_projectname{$n->[3]}  $n->[3], $seen_well{$n->[1]}->[2]]\n";
##			    warn "second design => project  $project_info2->[0]->[0] $n->[3], $n->[2]]\n";
##			    #################################################################
##			    # PROJECTS FOR SAME GENE  DO NOT MATCH ! Mail out problem
##			    #################################################################
##			    
##			    $mailer .= "first design $seen_well{$n->[1]}->[2], gene $n->[3] => project $exo_projectname{$n->[3]}\n";
##			    $mailer .= "second design $n->[2], gene $n->[3]=> project $project_info2->[0]->[0] \n";
##			    $mailer .= "\n\n";
##			    
##			    $summary_barf++;
##			    next;
##   			} else {
##			    ########### store project for gene
##			    $exo_projectname{$n->[3]} =  $project_info2->[0]->[0];
##			} 
##
##		    } # end of if ($seen_well{$n->[1]}->[2] ne $n->[2]) {
##		    
##
##
##
##		} else { # If the well IS NOT a duplicate
##		    
##		    $seen_well{$n->[1]} = $n;
##
##		    ############### We only chose a gene at the end of this loop
##		    ############### There may be multiple genes with disctinct designs
##		    ############### => store and check valid Project names by gene  seh 200302
##		    
##		    my ($project_info) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::gene_design_2_project', [$n->[3], $n->[2]]);
##		    $exo_projectname{$n->[3]} = $project_info->[0]->[0];
##		
##		}
##		###############################################################################################
##
##
##
##		#############################################################
##		# Did we see an amplimer sequence ? seh needs to know *mail*
##		#############################################################
##		 if ($n->[5] eq ''){
##		     $summary_barf++;
##		     &update("Exoseq_summary PC$pcrol_pcr; no amplimer seen for STS $n->[4] !");
##		     $update_screen->update('idletasks');
##		    
##		    
##		     $mailer .= "-------------------------------------------------------------------------------------\n";
##		     $mailer .= "No amplimer seen for STS $n->[4] (PC$pcrol_pcr EP$pcrol_ol) !!!\n";
##		     $mailer .= "-------------------------------------------------------------------------------------\n";
##		     $mailer .= "\n\n";
##		    
##		    
##		 }
##
##
##		 ############################################################################################################
##		 ## For each returned sample, take the first occurance of an id_well
##		 ## and determine the relevant project from gene_expt_project
##		 #Now done above (seh)                                                                 id_gene  id_design
##		 #my ($project_info) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::gene_design_2_project', [$n->[3], $n->[2]]);
##		 #$exo_projectname{$n->[1]} = $project_info->[0]->[0];
##		 ############################################################################################################
##
##
##
##
##		# If this is a 'multiple gene hit' we only want to re-enter
##		# $exo_gene{$n->[1]} if the new id_gene is lower
##		if (defined $exo_gene{$n->[1]}) {
##		    if ($n->[3] < $exo_gene{$n->[1]}){
##			
##			warn "Resetting id_gene from $exo_gene{$n->[1]} to $n->[3] ...\n";
##			$exo_gene{$n->[1]} = $n->[3];
##		    }
##		} else {
##		    $exo_gene{$n->[1]} = $n->[3];
##		}
##			
##		$exo_id_sts{$n->[1]} = $n->[4];
##		    
##
#
##	    }
#	    # end of foreach my $n (@$gene_info){
#############################################################################################################################
##############################################################################################################################

	    
	    #################################################
	    # Isolate projectname from id_gene and id_design
	    #################################################
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("384x pt2_snp.sql_lib::gene_design_2_project");
	    }
	    
	    my %PC1_exo_projectname;
	    foreach my $map_loc(97 .. 480){
		my $id_gene = $PC1_exo_gene{$map_loc};
		my $id_design =  $PC1_exo_design{$map_loc};

		
		my ($project_info) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::gene_design_2_project', [$id_gene, $id_design]);

		$PC1_exo_projectname{$map_loc} = $project_info->[0]->[0];
		
		if ($PC1_exo_projectname{$map_loc} eq ''){
		    $summary_barf++;

		    print STDOUT "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2";
		    print STDOUT "pt2_snp.sql_lib::gene_design_2_project called with id_gene $id_gene and id_design $id_design";
		    print STDOUT "Exoseq_summary; Gene $id_gene Design $id_design ; No project in GENE_EXPT_PROJECT";

		    $mailer .= "LP $plate PC1 $PC1 --- PC2 $PC2 --- EP1 $EP1 --- EP2 $EP2\n";
		    $mailer .= "pt2_snp.sql_lib::gene_design_2_project called with id_gene $id_gene and id_design $id_design\n";
		    $mailer .= "Exoseq_summary; Gene $id_gene Design $id_design ; No project in GENE_EXPT_PROJECT";
		}


	    }
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    

	    if ($summary_barf == 0){
		
#############################################################################
# We should now have enough information to populate snp.exoseq_loadingsample
#############################################################################
# ID_LOADINGSAMPLE   NOT NULL NUMBER(38)      %exo_id_loadingsample
# ID_LOADINGPLATE    NOT NULL NUMBER(38)      $plate
# ID_MAP 	     NOT NULL NUMBER(3)       97 - 480
# ID_IND 	     NOT NULL NUMBER(38)      %PC1_exo_id_ind
# ID_STS 	     NOT NULL NUMBER(38)      %PC1_exo_idsts
# ID_OLIGOPRIMER     NOT NULL NUMBER(38)      %EP1_exo_id_oligoprimer
# PROJECTNAME	     NOT NULL VARCHAR2(30)    %PC1_exo_projectname
# ID_GENE	     NOT NULL NUMBER          %PC1_exo_gene
# ID_PCRWELL	  	    NUMBER(38)        %PC1_exo_id_pcrwell
# ID_WELL	  	    NUMBER(38)        %EP1_exo_id_well

		if ($self->{benchmark} == 1){ 
		    $self->start_timer("384x pt2_snp.sql_lib::make_exoseq_loadingsample");
		}

		foreach my $map_loc(97 .. 480){

		    #print STDOUT "id_loadingsample $exo_id_loadingsample{$map_loc} id_loadingplate $plate id_map $map_loc id_ind $PC1_exo_id_ind{$map_loc} id_sts $PC1_exo_idsts{$map_loc} id_oligoprimer $EP1_exo_id_oligoprimer{$map_loc} projectname $PC1_exo_projectname{$map_loc} id_gene $PC1_exo_gene{$map_loc} id_pcrwell $PC1_exo_id_pcrwell{$map_loc} id_well $EP1_exo_id_well{$map_loc}\n";
		
#>make_exoseq_loadingsample<
#insert into exoseq_loadingsample (
#id_loadingsample,
#id_loadingplate,
#id_map,
#id_ind,
#id_sts,
#id_oligoprimer,
#projectname,
#id_gene,
#id_pcrwell,
#id_well)
#values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)


		    #warn "exo_id_loadingsample{$map_loc} $exo_id_loadingsample{$map_loc} ";
		    #warn "plate $plate map_loc $map_loc ";
		    #warn "PC1_exo_id_ind{$map_loc} $PC1_exo_id_ind{$map_loc} ";
		    #warn "PC1_exo_idsts{$map_loc} $PC1_exo_idsts{$map_loc} ";
		    #warn "EP1_exo_id_oligoprimer{$map_loc} $EP1_exo_id_oligoprimer{$map_loc} ";
		    #warn "PC1_exo_projectname{$map_loc} $PC1_exo_projectname{$map_loc} ";
		    #warn "PC1_exo_gene{$map_loc} $PC1_exo_gene{$map_loc} ";
		    #warn "PC1_exo_id_pcrwell{$map_loc} $PC1_exo_id_pcrwell{$map_loc} ";
		    #warn "EP1_exo_id_well{$map_loc} $EP1_exo_id_well{$map_loc} ";

		    eval {

			$SNP_STATEMENTS->do('pt2_snp.sql_lib::make_exoseq_loadingsample', [
											   $exo_id_loadingsample{$map_loc},
											   $plate, 
											   $map_loc,
											   $PC1_exo_id_ind{$map_loc},
											   $PC1_exo_idsts{$map_loc},
											   $EP1_exo_id_oligoprimer{$map_loc},
											   $PC1_exo_projectname{$map_loc},
											   $PC1_exo_gene{$map_loc},
											   $PC1_exo_id_pcrwell{$map_loc},
											   $EP1_exo_id_well{$map_loc}
											   ]);
			
		    };
		    
		    
		    if ($@ ne ''){
			push @db_problems, $@;
			
		    }

		}
		if ($self->{benchmark} == 1){ 
		    $self->stop_timer;
		}
		
	    }    
	}
	push @db_problems, 'End';
    }
    
    
    #############################
    # Need to test @db_problems
    #############################
    if ( ($db_problems[0] eq 'End') && ($summary_barf == 0) ){
	
	undef $self->{printer}->{"Label"};
	
	$self->{printer}->Type("LP");
	foreach my $p (@to_print_LP){
	    $self->{printer}->Date("$today");
	    $self->{printer}->Barcode("$p->{Barcode}");
	    $self->{printer}->Owner("$p->{Owner}");
	    $self->{printer}->Name("$p->{Name}");
	    $self->{printer}->Project("$p->{Project}");
	    $self->{printer}->Suffix("$p->{Suffix}");
	    $self->{printer}->Labellist();
	}
	
	eval {
	    $self->{printer}->Printlabel();
	};
	
	if ($@ ne ''){
	    print STDOUT "$@";
	    print STDOUT "Problems printing labels ! Rolling back entries.";

	    $STATEMENTS->{DBH}->rollback;
	    $SNP_STATEMENTS->{DBH}->rollback;
	    
	} else {

	    ###################################################################################
	    ############################################
	    # TURN ON ROLLBACK HERE FOR LIVE DB TESTING
	    ############################################
#	    warn "Rolling back for testing...\n";
#	    $STATEMENTS->{DBH}->rollback;
#	    $SNP_STATEMENTS ->{DBH}->rollback;
#	    warn "********************* Rolling back test entries *********************\n";
#	    warn "@new_plates";

	    $STATEMENTS->{DBH}->commit;
	    $SNP_STATEMENTS->{DBH}->commit;
	    print STDOUT "********************* New loadingplate entries made *********************\n";
	    print STDOUT "@new_plates\n";
	    ###################################################################################
	    
	}

	# If there were db problems
    } else {

	print STDOUT "********************* Errors occured ! Rolling back entries. *********************\n";

	foreach my $t (@db_problems){
	    print STDOUT "$t";
	    $mailer .= "$t\n";
	}
	$STATEMENTS->{DBH}->rollback;
	$SNP_STATEMENTS->{DBH}->rollback;
	
	eval {
	    ################ send only 1 mail per submit
	    my $mail_send = Mail::Mailer->new("sendmail");
	    $mail_send->open({ From => "$self->{who}",
			       To   => "dn1, exocan",
			       Subject => "pt2_direct.pm ExoCan LP creation problem"
			       })
		or die "Can't open: $!\n";
	    
	    
	    print $mail_send $mailer ;
	    close($mail_send);
	};
	
	if ($@){
	    print STDOUT "Problems sending email: ". "$@";
	}
	
    }
    
}




sub make_exocan_batch {
    my ($self, $category, $id_scsp, $PCRplate1, $PCRplate2, $Oligoplate1, $Oligoplate2, $suffix_var, $old_seqchem) 
	= @_;
    
    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::make_exocan_batch method ERROR Invalid access to subroutine from $pack";
    }

#    warn "Inside make_exocan_batch ... \n";
#    warn "category $category\n";
#    warn "id_scsp $id_scsp\n";
#    warn "PCRplate1 $PCRplate1\n";
#    warn "PCRplate2 $PCRplate2\n";
#    warn "Oligoplate1 $Oligoplate1\n";
#    warn "Oligoplate2 $Oligoplate2\n";

    my @new;
    $self->{TOT}++;

    ###########################################
    # Conversion of category id to description
    ###########################################
    my $category_var = $self->{seqcats}->{$category};
    

    push(@new,[
	       "$self->{TOT}", 
	       "$PCRplate1-$Oligoplate1 $PCRplate1-$Oligoplate2 $PCRplate2-$Oligoplate1 $PCRplate2-$Oligoplate2", 
	       "ExoCan[next id_loadingplate]", 
	       "$suffix_var new$id_scsp old$old_seqchem", 
	       "", 
	       "384", 
	       "$self->{who_team}", 
	       "$category_var"
	       ]);

    $self->fill_table(\@new);

}


sub fill_table {

    my ($self, $new) = @_;

    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::fill_table method ERROR Invalid access to subroutine from $pack";
    }

    #warn "Inside fill_table ... \n";
    #warn Data::Dumper::Dumper($new);
    
    $self->{SECT} = $self->{lastSECT};
    my ($quickContents) = $self->quickCheck;

    #warn "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
    #warn "quickContents ... $quickContents\n";
    #warn "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";

    if ($quickContents == 0 && $self->{lastSECT} != 1){	# lastSECT maybe the first SECT as well, and be empty
	$self->{SECT} = $self->{lastSECT} -1;
    }
    
    my $r = 0;
    my $sam_r = 0;
    for ($r=$self->{GRID_ROWS}-1;$r>=0;$r--) {
	
	if ($self->{DATA}->[$self->{SECT}]->[$r]->[0] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[1] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[2] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[3] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[4] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[5] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[6] ne '' || $self->{DATA}->[$self->{SECT}]->[$r]->[7] ne '') {

	    # We have found the last sample of a view
	    $sam_r = $r+1;
	    last;
	}
    }

    if ($sam_r == $self->{GRID_ROWS}){
	$self->{lastSECT}++;
	$self->{SECT} = $self->{lastSECT};
	$sam_r = 0;
    }

    
    foreach my $newt (@$new) {
	
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[0] = $newt->[0];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[1] = $newt->[1];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[2] = $newt->[2];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[3] = $newt->[3];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[4] = $newt->[4];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[5] = $newt->[5];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[6] = $newt->[6];
	$self->{DATA}->[$self->{SECT}]->[$sam_r]->[7] = $newt->[7];
	
	$sam_r++;
	if ($sam_r == $self->{GRID_ROWS}) {	###### There is a view max-row limit ######
	    $self->{SECT}++;
	    $self->{lastSECT}++;
	    $sam_r = 0;
	}
    }


    
    $self->{SECT} = $self->{lastSECT};
    $quickContents = 0;
    ($quickContents) = $self->quickCheck;
    if ($quickContents == 0){
	$self->{SECT} = $self->{lastSECT} -1;
	$self->{lastSECT}--;
    }
    
}


####################################
# A check to see if a view is empty
####################################
sub quickCheck {
    my ($self) = @_;

    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::quickCheck method ERROR Invalid access to subroutine from $pack";
    }
    my $r;
    my $c;
    my $quickContents = 0;
    
    for ($r=0;$r<$self->{GRID_ROWS};$r++) {
	foreach $c (0 .. 7){
	    if ($self->{DATA}->[$self->{SECT}]->[$r]->[$c] ne ''){
		$quickContents++;
	    }
	}
    }
    return($quickContents);
}





#########################################################
# Do we care about seeing a PC multiple times in a 'set'
#########################################################
sub pc_check {
    my ($self, $PCRplate) = @_;
    
    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::pc_check method ERROR Invalid access to subroutine from $pack";
    }

    my $PCRplate_var;

    my $hash_return = Verifynumber("$PCRplate", "PC");
    if ($hash_return->{Process} eq 'Good'){
	$PCRplate_var = $hash_return->{Number};
	
	###################################################
	# For now limit the pipeline to 96 well PCR_PLATES
	###################################################
	if ($self->{benchmark} == 1){ 
	    $self->start_timer("pt2_snp.sql_lib::pcr_plate_format $PCRplate_var");
	}

	my ($format) =  $SNP_STATEMENTS->get('pt2_snp.sql_lib::pcr_plate_format', [$PCRplate_var]);
	if ($self->{benchmark} == 1){ 
	    $self->stop_timer;
	}

	if ($format->[0]->[0] ne '96'){
	    croak "pt2_direct.pm add_plate::pc_check method ERROR PCR plate $PCRplate is not in 96 well format";

	# Good scan
	} else {
	    
	    ######################################
	    # Is the status of the pcr_plate ok ?
	    ######################################
	    if ($self->{benchmark} == 1){ 
		$self->start_timer("pt2_snp.sql_lib::current_pcr_plate_status $PCRplate_var");
	    }

	    my ($status) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::current_pcr_plate_status', [$PCRplate_var]);
	    if ($self->{benchmark} == 1){ 
		$self->stop_timer;
	    }
	    
	    
	    if (@$status > 1) {
		croak "pt2_direct.pm add_plate::pc_check method ERROR PCR plate $PCRplate_var has multiple current status entries";
	    } elsif (@$status == 0) {
		croak "pt2_direct.pm add_plate::pc_check method ERROR PCR plate $PCRplate_var does not have a current status entry";
		
	    } elsif ($status->[0]->[0] != 6){
		croak "pt2_direct.pm add_plate::pc_check method ERROR PCR plate $PCRplate_var does not have a current status of Cleaned up. Cannot process";

		# Passed status checks
	    } else {
		
		###################################################################
		# Find out which oligoplates are suitable for sequencing the plate
		###################################################################
		#warn "Oligoplates suitable for sequencing PC $PCRplate_var are...\n";
		
		if ($self->{benchmark} == 1){ 
		    $self->start_timer("pt2_snp.sql_lib::which_oligoplates_can_sequence_pcrplate_96 $PCRplate_var");
		}
		
		my ($seq_plates) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::which_oligoplates_can_sequence_pcrplate_96', [$PCRplate_var]);
		if ($self->{benchmark} == 1){ 
		    $self->stop_timer;
		}

		#warn "these are the oligo plates to use ...\n";
		#warn Data::Dumper::Dumper($seq_plates);
		
		if (@$seq_plates == 0) {
		    croak "pt2_direct.pm add_plate::pc_check method ERROR PCR There are no oligoplates suitable for PCR plate $PCRplate_var";
		} else {
		    # Display the suitable plates
		    foreach my $e_s (@$seq_plates){
			$self->{valid_oligoplates}->{$e_s->[0]}++;
			#$valid_oligoplates{$e_s->[0]}++;
			#warn "Oligoplate $e_s->[0] Type $e_s->[1]\n";
		    }
		    #warn Data::Dumper::Dumper($self->{valid_oligoplates});

		}
	    }
	}
    
	# Bad scan
    } else {
	croak "pt2_direct.pm add_plate::pc_check method ERROR Bad scan on $PCRplate";
    }

    return ($PCRplate_var);

}



sub ep_check {
    my ($self, $EPplate) = @_;

    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm add_plate::ep_check method ERROR Invalid access to subroutine from $pack";
    }
    
    my $EPplate_var;
    my $hash_return = Verifynumber("$EPplate", "EP");
    if ($hash_return->{Process} eq 'Good'){
	$EPplate_var = $hash_return->{Number};
	
	#warn "Good scan ---> decoded to $EPplate_var\n";

	######################################
	# Check the format of the OLIGO_PLATE
	######################################
	# TO_DO


	#############################################
	# Check the current status of the oligoplate
	#############################################
	if ($self->{benchmark} == 1){ 
	    $self->start_timer("pt2_snp.sql_lib::current_oligo_plate_status $EPplate_var");
	}
	
	my ($status) = $SNP_STATEMENTS->get('pt2_snp.sql_lib::current_oligo_plate_status', [$EPplate_var]);
	if ($self->{benchmark} == 1){ 
	    $self->stop_timer;
	}

	#warn "----------------------------------\n";
	#warn "Status returned on EP $EPplate_var\n";
	#warn Data::Dumper::Dumper($status);
	#warn "----------------------------------\n";


	#############################################################################
	# Is the oligoplate suitable for sequencing with this PCR plate ?
	# - We have already worked out valid oligoplates; check against this list
	# - We should have seen the oligoplate in question twice (once per PC plate)
	#############################################################################
	unless ( ($self->{valid_oligoplates}->{$EPplate_var}) == 2 ){
	    my $valid_oligoplates = Data::Dumper::Dumper($self->{valid_oligoplates});
	    croak "pt2_direct.pm add_plate::ep_check method ERROR Could not find EP $EPplate_var x2 in ... $valid_oligoplates\n";
	    
	} else {

	    #warn "Found EP $EPplate_var x2 in ... \n";
	    #warn Data::Dumper::Dumper($self->{valid_oligoplates});


	    ###################################
	    # Sanity check the returned status
	    ###################################

	    if (@$status > 1) {
		croak "pt2_direct.pm add_plate::ep_check method ERROR EP $EPplate_var has multiple current status entries\n";
	    } elsif (@$status == 0) {
		croak "pt2_direct.pm add_plate::ep_check method ERROR EP $EPplate_var does not have a current status entry\n";
	    } elsif ($status->[0]->[0] != 4){
		croak "pt2_direct.pm add_plate::ep_check method ERROR EP $EPplate_var does not have a current status of Created. Cannot process\n";
	    } 

	}    
	
    } else {
	# Bad scan
	croak "pt2_direct.pm add_plate::ep_check method ERROR Bad scan on $EPplate";
    }

    return ($EPplate_var);
}



sub start_timer {
    my ($self, $phrase) = @_;

    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm start_timer method ERROR Invalid access to subroutine from $pack";
    }

    print STDERR "Started $phrase\n";
    $self->{start_timer} = gettimeofday;
    return;
}

sub stop_timer {
    my ($self) = @_;

    my ($pack, $file, $line) = caller;
    unless ($pack eq __PACKAGE__ && $file eq __FILE__){
	croak "pt2_direct.pm stop_timer method ERROR Invalid access to subroutine from $pack";
    }

    $self->{stop_timer} = gettimeofday;

    my $total = ( ($self->{stop_timer}) - ($self->{start_timer}) );
    print STDERR "Finished $total\n";

    return;
}



END {
    ################################################
    # Clear up any remaining sql_engine connections
    ################################################
    if ($STATEMENTS){
	$STATEMENTS->end;
    }

    if ($SNP_STATEMENTS){
	$SNP_STATEMENTS->end;
    }

};

1;

__END__


=head1 NAME

pt2_direct - Class to allow programmatic access to loadingplate creation.
!NOTE! Only currently active for 'ExoCan' category plates.

=head1 SYNOPSIS
    
    use pt2_direct;
    
    #
    # Create an object to represent a loadingplate order
    #
    

    my $pt2_direct = pt2_direct->new('canplatetrack', 'csnp', 25201, 'd318bc');


    #
    # Populate the order with plate requests
    #

    $pt2_direct->add_plate(12, 197, 'PC8714U', 'PC8715V', 'EP16158I', 'EP16159J');
    $pt2_direct->add_plate(12, 197, 'PC8716W', 'PC8717A', 'EP16158I', 'EP16159J');
    $pt2_direct->add_plate(12, 197, 'PC8716W', 'PC8717A', 'EP16158I', 'EP16159J');

    #
    # Submit the list. Relevant database updates are made and loadingplate (LP)
    # stickers are produced
    #

    $pt2_direct->submit_plates;


=head1 DESCRIPTION


This class allows programmers to create loadingplates for entry into the sequencing
pipeline (ie. category/team specific processing strategies under Capminder control). 
Plates can be made without using platetrack2 (TK GUI previously used for loadingplate creation) 
hence allowing more flexible integration of non PSG LIMs.


=head1 VARIABLES

<>

=head1 CONSTRUCTORS

=over 4

=item pt2_direct->new('$cas_db', '$snp_db', $id_role, '$printer', '$bm');

=over 4

=item $cas_db

WrapDBI user    The cas database connection to use

=item $snp_db

WrapDBI user    The snp database connection to use

=item $id_role

From team_person_role.id_role
(who is submitting the plates in question ? Used to determine a team and operator)

=item $printer

Supply a valid barcode printer name

=item $bm

Supply 'BM' to activate sql statement benchmarking (STDERR)
Supply 'BMS' to activate per plate processing feedback (STDOUT)

=back
=back


=head1 METHODS

=over 4

=item pt2_direct->add_plate($category, $id_scsp, $PCRplate1, $PCRplate2, $Oligoplate1, $Oligoplate2)

=over 4

=item $category        

The category of the plate (determines processing along with team)

=item $id_scsp         

The chemistry to use

=item $PCRplate1       

quadrant1  quadrant2 (of 384 well loadingplate)

=item $PCRplate2       

quadrant3  quadrant4 (of 384 well loadingplate)

=item $Oligoplate1     

quadrant1  quadrant3 (of 384 well loadingplate)

=item $Oligoplate2     

quadrant2  quadrant4 (of 384 well loadingplate)

=back

=back

=over 4

=item pt2_direct->submit_plates

=over 4

Check and submit the list of plates. Relevant database entries are made. Note that some plate
categories require database updates in multiple instances.

=back

=back


=over 4

=item pt2_direct->review_plates     

=over 4

Dumps the pt2_direct.pm object to STDERR

=back

=back

=over 4

=item pt2_direct->clear_plates     

=over 4

Clears the plate list

=back

=back

=head1 AUTHOR

Dave Niblett

=head1 BUGS

<>

=head1 SEE ALSO

<>

=head1 COPYRIGHT

This software has been created by Genome Research Limited (GRL).  GRL
hereby grants permission to use, copy, modify and distribute this
software and its documentation for non-commercial purposes without fee
at the user's own risk on the basis set out below.  GRL neither
undertakes nor accepts any duty whether contractual or otherwise in
connection with the software, its use or the use of any derivative,
and makes no representations or warranties, express or implied,
concerning the software, its suitability, fitness for a particular
purpose or non-infringement.

In no event shall the authors of the software or GRL be responsible or
liable for any loss or damage whatsoever arising in any way directly
or indirectly out of the use of this software or its derivatives, even
if advised of the possibility of such damage.

Our software can be freely distributed under the conditions set out
above, and must contain this copyright notice.

=cut
