package LIMS::MT_Plate_File; use 5.006; use strict; use warnings; our $VERSION = '1.2'; use Microarray::File; # Access the LIMS::MT_Plate::* packages via imported constants instead of top-level package names sub import { my $pkg = caller; eval "*$pkg\::$_ = sub(){'LIMS::MT_Plate_File::$_'}" for qw(mt_plate_file simple_plate_file rowcol_plate_file); } { package LIMS::MT_Plate_File::mt_plate_file; our @ISA = qw( simple_delimited_file ); # standard format # required fields; well name, sample name, sample type sub sort_data { my $self = shift; my $aaData = shift; my $aCol_Headers = shift @$aaData; my $col_num = @$aCol_Headers; $self->column_num($col_num); $self->set_data_fields($aCol_Headers); $self->import_samples($aaData); } sub import_samples { my $self = shift; my $aaData = shift; my $hhData_Rows = $self->get_data_rows; for my $aData_Row (@$aaData){ $self->set_well($aData_Row->[$self->well_index], $aData_Row->[$self->sample_index], $aData_Row->[$self->sample_type_index]); $self->count_well; } } sub set_well { my $self = shift; my $well = shift; $self->{ "_$well" } = shift; $self->{ "_$well"."_type" } = shift; $self->record_well($well); } sub record_well { my $self = shift; my $aWells = $self->get_all_wells; push (@$aWells,shift); } sub get_all_wells { my $self = shift; unless (defined $self->{ _all_wells }){ $self->{ _all_wells } = [ ]; } $self->{ _all_wells }; } sub get_sample { my $self = shift; my $well = shift; $self->{ "_$well" }; } sub get_sample_type { my $self = shift; my $well = shift; $self->{ "_$well"."_type" }; } sub get_all_samples { my $self = shift; my $aWells = $self->get_all_wells; my $aSamples = []; for my $well (@$aWells){ push (@$aSamples,$self->get_sample($well)); } return $aSamples; } sub get_all_sample_types { my $self = shift; my $aWells = $self->get_all_wells; my $aSample_Types = []; for my $well (@$aWells){ push (@$aSample_Types,$self->get_sample_type($well)); } return $aSample_Types; } sub plate_barcode { my $self = shift; if (@_){ $self->{ _plate_name } = shift; } else { if (defined $self->{ _plate_name }){ return $self->{ _plate_name }; } else { return $self->file_name; } } } sub plate_type { my $self = shift; if (@_){ $self->{ _plate_type } = shift; } else { if (defined $self->{ _plate_type }){ return $self->{ _plate_type }; } else { return $self->guessed_plate_type; } } } sub guessed_plate_type { my $self = shift; unless (defined $self->{ _guessed_plate_type }){ $self->guess_plate_type; } $self->{ _guessed_plate_type }; } sub guess_plate_type { my $self = shift; my $aWells = $self->get_all_wells; my ($aRows,$aCols) = get_well_coords($aWells); my $last_row = uc $aRows->[-1]; my $last_col = $aCols->[-1]; my $plate_type; if (($last_row eq "A")&&($last_col == 1)){ $plate_type = "tube"; } elsif (($last_row le "H")&&($last_col <= 12)) { $plate_type = "mt_96"; } elsif (($last_row le "P")&&($last_col <= 24)) { $plate_type = "mt_384"; } elsif (($last_row le "AF")&&($last_col <= 48)) { $plate_type = "mt_1536"; } else { die "LIMS::MT_Plate_File ERROR: Well name '$last_row$last_col' doesn't match supported plate formats"; } $self->{ _guessed_plate_type } = $plate_type; } #Ęsplits the column number and the row letter sub get_well_coords { my $aWells = shift; my @aRows = (); my @aCols = (); for my $well (@$aWells){ my ($row,$col) = (uc $well, uc $well); $row =~ s/\d//g; $col =~ s/\D//g; push (@aRows,$row); push (@aCols,$col); } my @aSorted_Rows = sort @aRows; my @aSorted_Cols = sort @aCols; return (\@aSorted_Rows,\@aSorted_Cols); } sub wells_imported { my $self = shift; $self->{ _wells_imported }; } sub count_well { my $self = shift; $self->{ _wells_imported }++; } sub well_index { my $self = shift; $self->get_column_id('well'); } sub sample_index { my $self = shift; $self->get_column_id('name'); } sub sample_type_index { my $self = shift; $self->get_column_id('type'); } } { package LIMS::MT_Plate_File::simple_plate_file; our @ISA = qw( mt_plate_file ); } { package LIMS::MT_Plate_File::rowcol_plate_file; our @ISA = qw( mt_plate_file ); sub import_samples { my $self = shift; my $aaData = shift; my $hhData_Rows = $self->get_data_rows; for my $aData_Row (@$aaData){ my $well = $aData_Row->[$self->row_index].$aData_Row->[$self->col_index]; $self->set_well($well, $aData_Row->[$self->sample_index], $aData_Row->[$self->sample_type_index]); $self->count_well; } } sub row_index { my $self = shift; if ($self->get_column_id('v1.1 96-well plate row')){ return $self->get_column_id('v1.1 96-well plate row'); } elsif ($self->get_column_id('Row')){ return $self->get_column_id('Row'); } elsif ($self->get_column_id('row')){ return $self->get_column_id('row'); } else { die "Can't find a column in the file that contains a 'Row' field\n"; } } sub col_index { my $self = shift; if ($self->get_column_id('v1.1 96-well plate column')){ return $self->get_column_id('v1.1 96-well plate column'); } elsif ($self->get_column_id('Column')){ return $self->get_column_id('Column'); } elsif ($self->get_column_id('Col')){ return $self->get_column_id('Col'); } elsif ($self->get_column_id('column')){ return $self->get_column_id('column'); } elsif ($self->get_column_id('col')){ return $self->get_column_id('col'); } else { die "Can't find a column in the file that contains a 'Column' field\n"; } } sub sample_index { my $self = shift; $self->get_column_id('International clone ID'); } sub sample_type_index { my $self = shift; $self->get_column_id('Library'); } } 1; __END__ =head1 NAME LIMS::MT_Plate_File - A Perl module for managing microtitre plate file objects =head1 SYNOPSIS use LIMS::MT_Plate_File; my $sample_file = mt_plate_file->new("/file.txt"); =head1 DESCRIPTION LIMS::MT_Plate_File is an object-oriented Perl module for managing files describing the contents of a microtitre plate for import to the L module. There are two classes of MT_Plate_File object - the C class uses a single 'well' column to name the wells (e.g. 'A1') whereas the C class uses two separate columns 'row' and 'col'. =head1 METHODS =over =item B Pass these methods a well name to retrieve the sample name/type. =item B Returns an array ref of all sample names/types =item B Returns the plate barcode/type, the latter assumed from well/row numbers =item B The number of wells imported =back =head1 SEE ALSO L, L =head1 AUTHOR Christopher Jones, Gynaecological Cancer Research Laboratories, UCL EGA Institute for Women's Health, University College London. L c.jones@ucl.ac.uk =head1 COPYRIGHT AND LICENSE Copyright 2008 by Christopher Jones, University College London This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut