1
# $Id: Generic.pm,v 1.3 2003/09/08 12:17:12 heikki Exp $
3
# BioPerl module for Bio::Matrix::Generic
5
# Cared for by Jason Stajich <jason-at-bioperl-dot-org>
7
# Copyright Jason Stajich
9
# You may distribute this module under the same terms as perl itself
11
# POD documentation - main docs before the code
15
Bio::Matrix::GenericMatrix - A generic matrix implementation
19
# A matrix has columns and rows
20
my $matrix = new Bio::Matrix::GenericMatrix();
21
$matrix->add_column_num(1,$column1);
22
$matrix->add_column_num(2,$column2);
24
my $element = $matrix->element(1,2);
25
$matrix->element(1,2,$newval);
27
my $entry = $matrix->entry('human', 'mouse');
29
$matrix->entry('human','mouse', $newval);
34
This is a general purpose matrix object for dealing with row+column
35
data which is typical when enumerating all the pairwise combinations
36
and desiring to get slices of the data.
38
Data can be accessed by column and row names or indexes. Matrix
45
User feedback is an integral part of the evolution of this and other
46
Bioperl modules. Send your comments and suggestions preferably to
47
the Bioperl mailing list. Your participation is much appreciated.
49
bioperl-l@bioperl.org - General discussion
50
http://bioperl.org/MailList.shtml - About the mailing lists
54
Report bugs to the Bioperl bug tracking system to help us keep track
55
of the bugs and their resolution. Bug reports can be submitted via
58
http://bugzilla.bioperl.org/
60
=head1 AUTHOR - Jason Stajich
62
Email jason-at-bioperl-dot-org
64
Describe contact details here
68
Additional contributors names and emails here
72
The rest of the documentation details each of the object methods.
73
Internal methods are usually preceded with a _
77
package Bio::Matrix::Generic;
82
use Bio::Matrix::MatrixI;
84
@ISA = qw(Bio::Root::Root Bio::Matrix::MatrixI );
89
Usage : my $obj = new Bio::Matrix::Generic();
90
Function: Builds a new Bio::Matrix::Generic object
91
Returns : an instance of Bio::Matrix::Generic
98
my($class,@args) = @_;
100
my $self = $class->SUPER::new(@args);
101
my ($values, $rownames, $colnames,
103
$self->_rearrange([qw(VALUES ROWNAMES COLNAMES
104
MATRIX_ID MATRIX_NAME)],@args);
105
$self->matrix_id($id) if defined $id;
106
$self->matrix_name($name) if defined $name;
107
if( defined $rownames && defined $colnames && defined $values ) {
108
if( ref($rownames) !~ /ARRAY/i ) {
109
$self->throw("need an arrayref for the -rownames option");
111
# insure we copy the values
112
$self->{'_rownames'} = [ @$rownames ];
114
%{$self->{'_rownamesmap'}} = map { $_ => $count++ } @$rownames;
116
if( ref($colnames) !~ /ARRAY/i ) {
117
$self->throw("need an arrayref for the -colnames option");
119
# insure we copy the values
120
$self->{'_colnames'} = [ @$colnames ];
122
%{$self->{'_colnamesmap'}} = map { $_ => $count++ } @$colnames;
123
if( ref($values) !~ /ARRAY/i ) {
124
$self->throw("Need an arrayref of arrayrefs (matrix) for -values option");
126
$self->{'_values'} = [];
127
foreach my $v ( @$values ) {
128
if( ref($v) !~ /ARRAY/i ) {
129
$self->throw("Need and array of arrayrefs (matrix) for -values option");
131
push @{$self->{'_values'}}, [@$v];
133
} elsif( ! defined $rownames && ! defined $colnames && ! defined $values ) {
134
$self->{'_values'} = [];
135
$self->{'_rownames'} = $self->{'_colnames'} = [];
137
$self->throw("Must have either provided no values/colnames/rownames or provided all three");
147
Usage : my $id = $matrix->matrix_id
148
Function: Get/Set the matrix ID
149
Returns : scalar value
150
Args : [optional] new id value to store
157
return $self->{'_matid'} = shift if @_;
158
return $self->{'_matid'};
166
Usage : my $name = $matrix->matrix_name();
167
Function: Get/Set the matrix name
168
Returns : scalar value
169
Args : [optional] new matrix name value
176
return $self->{'_matname'} = shift if @_;
177
return $self->{'_matname'};
184
Usage : my $entry = $matrix->entry($row,$col)
185
Function: Get the value for a specific cell as specified
186
by the row and column names
187
Returns : scalar value or undef if row or col does not
189
Args : $rowname - name of the row
190
$colname - column name
195
my ($self,$row,$column,$newvalue) = @_;
196
if( ! defined $row || ! defined $column ) {
197
$self->throw("Need at least 2 ids");
201
my ($rownum) = $self->row_num_for_name($row);
202
my ($colnum) = $self->column_num_for_name($column);
203
return $self->entry_by_num($rownum,$colnum,$newvalue);
209
Usage : my $entry = $matrix->get_entry($rowname,$columname)
210
Function: Get the entry for a given row,column pair
218
sub get_entry{ $_[0]->entry($_[1],$_[2]) }
222
Title : entry_by_name
223
Usage : my $entry = $matrix->entry_by_name($rowname,$colname)
224
Function: Get an entry by row and column numbers instead of by name
225
(rows and columns start at 0)
226
Returns : scalar value or undef if row or column name does not
228
Args : $row - row number
230
[optional] $newvalue to store at this cell
235
my ($self,$row,$col,$newvalue) = @_;
236
if( ! defined $row || ! defined $col ||
239
$self->warn("expected to get 2 number for entry_by_num");
243
if( defined $newvalue ) {
244
return $self->_values->[$row][$col] = $newvalue;
246
return $self->_values->[$row][$col];
250
sub get_element { $_[0]->entry($_[1]) }
256
Usage : my @col = $matrix->column('ALPHA');
258
$matrix->column('ALPHA', \@col);
259
Function: Get/Set a particular column
260
Returns : Array (in array context) or arrayref (in scalar context)
262
For setting will warn if the new column is of a different
263
length from the rest of the columns.
264
Args : name of the column
265
[optional] new column to store here
270
my ($self,$column,$newcol) = @_;
272
if( ! defined $column ) {
273
$self->warn("Need at least a column id");
276
my $colnum = $self->column_num_for_name($column);
277
if( ! defined $colnum ) {
278
$self->warn("could not find column number for $column");
281
return $self->column_by_num($colnum,$newcol);
288
Usage : my @row = $matrix->get_column('ALPHA');
289
Function: Get a particular column
290
Returns : Array (in array context) or arrayref (in scalar context)
292
Args : name of the column
297
sub get_column { $_[0]->column($_[1]) }
302
Title : column_by_num
303
Usage : my @col = $matrix->column_by_num(1);
305
$matrix->column_by_num(1,\@newcol);
306
Function: Get/Set a column by its number instead of name
307
(cols/rows start at 0)
308
Returns : Array (in array context) or arrayref (in scalar context)
310
Args : name of the column
311
[optional] new value to store for a particular column
316
my ($self,$colnum,$newcol) = @_;
317
if( ! defined $colnum ) {
318
$self->warn("need at least a column number");
321
my $rowcount = $self->num_rows;
324
if( defined $newcol ) {
325
if( ref($newcol) !~ /ARRAY/i) {
326
$self->warn("expected a valid arrayref for resetting a column");
329
if( scalar @$newcol != $rowcount ) {
330
$self->warn("new column is not the correct length ($rowcount) - call add or remove row to shrink or grow the number of rows first");
333
for(my $i=0; $i < $rowcount; $i++) {
334
$self->entry_by_num($i,$colnum,$newcol->[$i]);
339
for(my $i=0; $i < $rowcount; $i++) {
340
push @$ret,$self->entry_by_num($i,$colnum);
343
if( wantarray ) { return @$ret }
351
Usage : my @row = $matrix->row($rowname);
353
$matrix->row($rowname,\@rowvalues);
354
Function: Get/Set the row of the matrix
355
Returns : Array (in array context) or arrayref (in scalar context)
357
[optional] new value of row to store
363
my ($self,$row,$newrow) = @_;
364
if( ! defined $row) {
365
$self->warn("Need at least a row id");
368
my $rownum = $self->row_num_for_name($row);
369
return $self->row_by_num($rownum,$newrow);
376
Usage : my @row = $matrix->get_row('ALPHA');
377
Function: Get a particular row
378
Returns : Array (in array context) or arrayref (in scalar context)
380
Args : name of the row
384
sub get_row { $_[0]->row($_[1]) }
389
Usage : my @row = $matrix->row_by_num($rownum);
391
$matrix->row($rownum,\@rowvalues);
392
Function: Get/Set the row of the matrix
393
Returns : Array (in array context) or arrayref (in scalar context)
395
[optional] new value of row to store
400
my ($self,$rownum,$newrow) = @_;
401
if( ! defined $rownum ) {
402
$self->warn("need at least a row number");
405
my $colcount = $self->num_columns;
407
if( defined $newrow ) {
408
if( ref($newrow) !~ /ARRAY/i) {
409
$self->warn("expected a valid arrayref for resetting a row");
412
if( scalar @$newrow != $colcount ) {
413
$self->warn("new row is not the correct length ($colcount) - call add or remove column to shrink or grow the number of columns first");
416
for(my $i=0; $i < $colcount; $i++) {
417
$self->entry_by_num($rownum,$i, $newrow->[$i]);
422
for(my $i=0; $i < $colcount; $i++) {
423
# we're doing this to explicitly
424
# copy the entire row
425
push @$ret, $self->entry_by_num($rownum,$i);
428
if( wantarray ) { return @$ret }
438
Usage : my @diagonal = $matrix->get_diagonal()
439
Function: Get the diagonal of a matrix
440
Returns : Array (in array context) or arrayref (in scalar context)
441
of values which lie along the diagonal
450
my $rowcount = $self->num_rows;
451
my $colcount = $self->num_columns;
452
for(my $i = 0; $i < $rowcount; $i++ ) {
453
push @diag, $self->entry_by_num($i,$i);
462
Usage : $matrix->add_row($index,\@newrow);
463
Function: Adds a row at particular location in the matrix.
464
If $index < the rowcount will shift all the rows down
465
by the number of new rows.
466
To add a single empty row, simply call
467
$matrix->add_row($index,undef);
468
Returns : the updated number of total rows in the matrix
469
Args : index to store
470
name of the row (header)
471
newrow to add, if this is undef will add a single
472
row with all values set to undef
477
my ($self,$index,$name,$newrow) = @_;
478
if( !defined $index ||
479
$index !~ /^\d+$/ ) {
480
$self->warn("expected a valid row index in add_row");
482
} elsif( ! defined $name) {
483
$self->warn("Need a row name or heading");
485
} elsif( defined $self->row_num_for_name($name) ) {
486
$self->warn("Need a unqiue name for the column heading, $name is already used");
489
my $colcount = $self->num_columns;
490
my $rowcount = $self->num_rows;
492
if( $index > $rowcount ) {
493
$self->warn("cannot add a row beyond 1+last row at the end ($rowcount) not $index - adding at $rowcount instead");
497
if( ! defined $newrow ) {
499
$newrow->[$colcount] = undef;
500
} elsif( ref($newrow) !~ /ARRAY/i ) {
501
$self->throw("Expected either undef or a valid arrayref for add_row");
503
# add this row to the matrix by carving out space for it with
505
splice(@{$self->{'_values'}}, $index,0,[]);
506
for( my $i = 0; $i < $colcount; $i++ ) {
507
$self->entry_by_num($index,$i,$newrow->[$i]);
509
splice(@{$self->{'_rownames'}}, $index,0,$name);
510
# Sadly we have to remap these each time (except for the case
511
# when we're adding a new column to the end, but I don't think
512
# the speedup for that case warrants the extra code at this time.
514
%{$self->{'_rownamesmap'}} = map { $_ => $ct++} @{$self->{'_rownames'}};
515
return $self->num_rows;
521
Usage : $matrix->remove_row($colnum)
522
Function: remove a row from the matrix shifting all the rows
524
Returns : Updated number of rows in the matrix
531
my ($self,$rowindex) = @_;
532
my $rowcount = $self->num_rows;
534
if( $rowindex > $rowcount ) {
535
$self->warn("colindex $rowindex is greater than number of rows $rowcount, cannot process");
538
splice(@{$self->_values},$rowindex,1);
539
delete $self->{'_rownamesmap'}->{$self->{'_rownames'}->[$rowindex]};
540
splice(@{$self->{'_rownames'}},$rowindex,1);
542
return $self->num_rows;
548
Usage : $matrix->add_column($index,$colname,\@newcol);
549
Function: Adds a column at particular location in the matrix.
550
If $index < the colcount will shift all the columns right
551
by the number of new columns.
552
To add a single empty column, simply call
553
$matrix->add_column($index,undef);
554
Returns : the updated number of total columns in the matrix
555
Args : index to store
556
name of the column (header)
557
newcolumn to add, if this is undef will add a single
558
column with all values set to undef
565
my ($self,$index,$name,$newcol) = @_;
566
if( !defined $index ||
567
$index !~ /^\d+$/ ) {
568
$self->warn("expected a valid col index in add_column");
570
} elsif( ! defined $name) {
571
$self->warn("Need a column name or heading");
573
} elsif( defined $self->column_num_for_name($name) ) {
574
$self->warn("Need a unqiue name for the column heading, $name is already used");
577
my $colcount = $self->num_columns;
578
my $rowcount = $self->num_rows;
579
if( $index > $colcount ) {
580
$self->warn("cannot add a column beyond 1+last column at the end ($colcount) not $index - adding at $colcount instead");
584
if( ! defined $newcol ) {
586
$newcol->[$rowcount] = undef; # make the array '$rowcount' long
587
} elsif( ref($newcol) !~ /ARRAY/i ) {
588
$self->throw("Expected either undef or a valid arrayref for add_row");
590
for( my $i = 0; $i < $rowcount; $i++ ) {
591
# add this column to each row
592
splice(@{$self->_values->[$i]},$index,0,[]);
593
$self->entry_by_num($i,$index,$newcol->[$i]);
595
splice(@{$self->{'_colnames'}}, $index,0,$name);
596
# Sadly we have to remap these each time (except for the case
597
# when we're adding a new column to the end, but I don't think
598
# the speedup for that case warrants the extra code at this time.
600
%{$self->{'_colnamesmap'}} = map {$_ => $ct++} @{$self->{'_colnames'}};
601
return $self->num_columns;
606
Title : remove_column
607
Usage : $matrix->remove_column($colnum)
608
Function: remove a column from the matrix shifting all the columns
610
Returns : Updated number of columns in the matrix
617
my ($self,$colindex) = @_;
619
my $rowcount = $self->num_rows;
621
if( $colindex > $rowcount ) {
622
$self->warn("colindex $colindex is greater than number of rows $rowcount, cannot process");
625
for(my $i = 0; $i < $rowcount; $i++ ) {
626
splice(@{$self->_values->[$i]},$colindex,1);
628
delete $self->{'_colnamesmap'}->{$self->{'_colnames'}->[$colindex]};
629
splice(@{$self->{'_colnames'}},$colindex,1);
631
return $self->column_count;
634
=head2 column_num_for_name
636
Title : column_num_for_name
637
Usage : my $num = $matrix->column_num_for_name($name)
638
Function: Gets the column number for a particular column name
645
sub column_num_for_name{
646
my ($self,$name) = @_;
648
return $self->{'_colnamesmap'}->{$name};
651
=head2 row_num_for_name
653
Title : row_num_for_name
654
Usage : my $num = $matrix->row_num_for_name
655
Function: Gets the row number for a particular row name
662
sub row_num_for_name{
663
my ($self,$name) = @_;
664
return $self->{'_rownamesmap'}->{$name}
670
Title : column_header
671
Usage : my $name = $matrix->column_header(0)
672
Function: Gets the column header for a particular column number
680
my ($self,$num) = @_;
681
return $self->{'_colnames'}->[$num];
688
Usage : my $name = $matrix->row_header(0)
689
Function: Gets the row header for a particular row number
697
my ($self,$num) = @_;
698
return $self->{'_rownames'}->[$num];
704
Usage : my $rowcount = $matrix->num_rows;
705
Function: Get the number of rows
714
return scalar @{$self->_values};
721
Usage : my $colcount = $matrix->num_columns
722
Function: Get the number of columns
731
return scalar @{$self->_values->[0]};
738
Usage : my @rows = $matrix->row_names
739
Function: The names of all the rows
740
Returns : array in array context, arrayref in scalar context
748
return @{shift->{'_rownames'}};
750
return shift->{'_rownames'};
758
Usage : my @columns = $matrix->column_names
759
Function: The names of all the columns
760
Returns : array in array context, arrayref in scalar context
768
return @{shift->{'_colnames'}};
770
return shift->{'_colnames'};
774
=head2 private methods
776
Private methods for a Generic Matrix
781
Usage : $matrix->_values();
782
Function: get/set for array ref of the matrix containing
784
Returns : an array reference
785
Args : an array reference
791
my ($self,$val) = @_;
793
$self->{'_values'} = $val;
795
return $self->{'_values'};