1 package Maasha::Matrix;
3 # Copyright (C) 2007 Martin A. Hansen.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # http://www.gnu.org/copyleft/gpl.html
22 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
25 # This modules contains subroutines for simple matrix manipulations.
28 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
34 use Storable qw( dclone );
37 use vars qw ( @ISA @EXPORT );
40 @ISA = qw( Exporter );
48 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> SUBROUTINES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
53 # Martin A. Hansen, April 2007
55 # returns the dimensions of a matrix: rows x cols
57 my ( $matrix, # AoA data structure
64 $rows = scalar @{ $matrix };
65 $cols = scalar @{ $matrix->[ 0 ] };
67 return wantarray ? ( $rows, $cols ) : [ $rows, $cols ];
73 # Martin A. Hansen, April 2007.
75 # Checks that the matrix of even columns.
76 # return 1 if ok else 0.
78 my ( $matrix, # AoA data structure
83 my ( $dims, $row, $check );
85 $dims = matrix_dims( $matrix );
87 $check = $dims->[ COLS ];
89 foreach $row ( @{ $matrix } ) {
90 return 0 if scalar @{ $row } != $check;
99 # Martin A. Hansen, April 2007.
101 # For each column in a given matrix print:
103 my ( $matrix, # AoA data structure
106 my ( $dims, $i, $col, $list, $type, $sort, $uniq, $min, $max, $mean );
108 die qq(ERROR: cannot summarize uneven matrix\n) if not matrix_check( $matrix );
110 $dims = matrix_dims( $matrix );
112 print join( "\t", "TYPE", "LEN", "UNIQ", "SORT", "MIN", "MAX", "MEAN" ), "\n";
114 for ( $i = 0; $i < $dims->[ COLS ]; $i++ )
116 $col = cols_get( $matrix, $i, $i );
117 $list = matrix_flip( $col )->[ 0 ];
119 if ( list_check_numeric( $list ) ) {
125 if ( list_check_sort( $list, $type ) ) {
131 if ( $type eq "num" )
133 if ( $sort eq "yes" )
136 $max = $list->[ -1 ];
140 ( $min, $max ) = Maasha::Calc::minmax( $list );
143 $mean = sprintf( "%.2f", Maasha::Calc::mean( $list ) );
152 $uniq = list_uniq( $list );
154 print join( "\t", $type, $dims->[ ROWS ], $uniq, $sort, $min, $max, $mean ), "\n";
161 # Martin A. Hansen, April 2007
163 # flips a matrix making rows to columns and visa versa.
165 my ( $matrix, # AoA data structure
170 my ( $i, $c, $dims, $AoA );
172 die qq(ERROR: cannot flip uneven matrix\n) if not matrix_check( $matrix );
174 $dims = matrix_dims( $matrix );
176 for ( $i = 0; $i < $dims->[ ROWS ]; $i++ )
178 for ( $c = 0; $c < $dims->[ COLS ]; $c++ ) {
179 $AoA->[ $c ]->[ $i ] = $matrix->[ $i ]->[ $c ];
185 return wantarray ? @{ $matrix } : $matrix;
189 sub matrix_rotate_right
191 # Martin A. Hansen, April 2007
193 # Rotates elements in a given matrix a given
194 # number of positions to the right by popping columns,
195 # from the right matrix edge and prefixed to the left edge.
197 my ( $matrix, # AoA data structure
198 $shift, # number of shifts - DEFAULT=1
203 my ( $i, $dims, $col, $AoA );
207 die qq(ERROR: cannot right rotate uneven matrix\n) if not matrix_check( $matrix );
209 $dims = matrix_dims( $matrix );
211 for ( $i = 0; $i < $shift; $i++ )
213 $col = cols_get( $matrix, $dims->[ COLS ] - 1, $dims->[ COLS ] - 1 );
214 $AoA = cols_get( $matrix, 0, $dims->[ COLS ] - 2 );
216 cols_unshift( $AoA, $col );
221 return wantarray ? @{ $matrix } : $matrix;
225 sub matrix_rotate_left
227 # Martin A. Hansen, April 2007
229 # Rotates elements in a given matrix a given
230 # number of positions to the left while columns
231 # are shifted from the left matrix edge and appended,
234 my ( $matrix, # AoA data structure
235 $shift, # number of shifts - DEFAULT=1
240 my ( $i, $dims, $col, $AoA );
244 die qq(ERROR: cannot right rotate uneven matrix\n) if not matrix_check( $matrix );
246 $dims = matrix_dims( $matrix );
248 for ( $i = 0; $i < $shift; $i++ )
250 $col = cols_get( $matrix, 0, 0 );
251 $AoA = cols_get( $matrix, 1, $dims->[ COLS ] - 1 );
253 cols_push( $AoA, $col );
258 return wantarray ? @{ $matrix } : $matrix;
264 # Martin A. Hansen, April 2007
266 # Rotates elements in a given matrix a given
267 # number of positions up while rows are shifted
268 # from the top of the matrix to the bottom.
270 my ( $matrix, # AoA data structure
271 $shift, # number of shifts - DEFAULT=1
276 my ( $dims, $i, $row, $AoA );
280 $dims = matrix_dims( $matrix );
282 for ( $i = 0; $i < $shift; $i++ )
284 $row = rows_get( $matrix, 0, 0 );
285 $AoA = rows_get( $matrix, 1, $dims->[ ROWS ] - 1 );
287 rows_push( $AoA, dclone $row );
292 return wantarray ? @{ $matrix } : $matrix;
296 sub matrix_rotate_down
298 # Martin A. Hansen, April 2007
300 # Rotates elements in a given matrix a given
301 # number of positions down while rows are shifted
302 # from the bottom matrix edge to the top edge.
304 my ( $matrix, # AoA data structure
305 $shift, # number of shifts - DEFAULT=1
310 my ( $dims, $i, $row, $AoA );
314 $dims = matrix_dims( $matrix );
316 for ( $i = 0; $i < $shift; $i++ )
318 $row = rows_get( $matrix, $dims->[ ROWS ] - 1, $dims->[ ROWS ] - 1 );
319 $AoA = rows_get( $matrix, 0, $dims->[ ROWS ] - 2 );
321 rows_unshift( $AoA, $row );
326 return wantarray ? @{ $matrix } : $matrix;
332 # Martin A. Hansen, April 2007
334 # returns a submatrix sliced from a given matrix
336 my ( $matrix, # AoA data structure
337 $row_beg, # first row - OPTIONAL (default 0)
338 $row_end, # last row - OPTIONAL (default last row)
339 $col_beg, # first col - OPTIONAL (default 0)
340 $col_end, # last col - OPTIONAL (default last col)
345 my ( $submatrix, $subsubmatrix );
347 $submatrix = rows_get( $matrix, $row_beg, $row_end );
348 $subsubmatrix = cols_get( $submatrix, $col_beg, $col_end );
350 return wantarray ? @{ $subsubmatrix } : $subsubmatrix;
356 # Martin A. Hansen, April 2008.
358 # Returns a single row from a given matrix.
360 my ( $matrix, # AoA data structure
366 my ( $dims, $i, @list );
368 $dims = matrix_dims( $matrix );
370 Maasha::Common::error( qq(Row->$row outside of matrix->$dims->[ ROWS ]) ) if $row > $dims->[ ROWS ];
372 @list = @{ $matrix->[ $row ] };
374 return wantarray ? @list : \@list;
380 # Martin A. Hansen, April 2007
382 # returns a range of requested rows from a given matrix.
384 my ( $matrix, # AoA data structure
385 $row_beg, # first row - OPTIONAL (default 0)
386 $row_end, # last row - OPTIONAL (default last row)
395 if ( not defined $row_end ) {
396 $row_end = scalar @{ $matrix };
399 if ( $row_end >= scalar @{ $matrix } )
401 warn qq(WARNING: row end larger than matrix\n);
402 $row_end = scalar( @{ $matrix } ) - 1;
405 die qq(ERROR: row begin "$row_beg" larger than row end "$row_end"\n) if $row_end < $row_beg;
407 if ( $row_beg == 0 and $row_end == scalar( @{ $matrix } ) - 1 ) {
408 @rows = @{ $matrix };
410 @rows = @{ $matrix }[ $row_beg .. $row_end ];
413 return wantarray ? @rows : \@rows;
419 # Martin A. Hansen, April 2008.
421 # Returns a single column from a given matrix.
423 my ( $matrix, # AoA data structure
424 $col, # column to get
429 my ( $dims, $i, @list );
431 $dims = matrix_dims( $matrix );
433 Maasha::Common::error( qq(Column->$col outside of matrix->$dims->[ COLS ]) ) if $col > $dims->[ COLS ];
435 for ( $i = 0; $i < $dims->[ ROWS ]; $i++ ) {
436 push @list, $matrix->[ $i ]->[ $col ];
439 return wantarray ? @list : \@list;
445 # Martin A. Hansen, April 2007
447 # returns a range of requested columns from a given matrix
449 my ( $matrix, # AoA data structure
450 $col_beg, # first column - OPTIONAL (default 0)
451 $col_end, # last column - OPTIONAL (default last column)
456 my ( $dims, @cols, $row, @AoA );
458 $dims = matrix_dims( $matrix );
462 if ( not defined $col_end ) {
463 $col_end = $dims->[ COLS ] - 1;
466 if ( $col_end > $dims->[ COLS ] - 1 )
468 warn qq(WARNING: column end larger than matrix\n);
469 $col_end = $dims->[ COLS ] - 1;
472 die qq(ERROR: column begin "$col_beg" larger than column end "$col_end"\n) if $col_end < $col_beg;
474 if ( $col_beg == 0 and $col_end == $dims->[ COLS ] - 1 )
480 foreach $row ( @{ $matrix } )
482 @cols = @{ $row }[ $col_beg .. $col_end ];
484 push @AoA, [ @cols ];
488 return wantarray ? @AoA : \@AoA;
500 $list = cols_get( $matrix, $col, $col );
501 $list = matrix_flip( $list )->[ 0 ];
503 die qq(ERROR: cannot sum non-nummerical column\n);
505 $sum = Maasha::Calc::sum( $list );
513 # Martin A. Hansen, April 2007.
515 # Appends one or more rows to a matrix.
517 my ( $matrix, # AoA data structure
518 $rows, # list of rows
523 push @{ $matrix }, @{ $rows };
525 return wantarray ? @{ $matrix } : $matrix;
531 # Martin A. Hansen, April 2007.
533 # Prefixes one or more rows to a matrix.
535 my ( $matrix, # AoA data structure
536 $rows, # list of rows
541 unshift @{ $matrix }, @{ $rows };
543 return wantarray ? @{ $matrix } : $matrix;
549 # Martin A. Hansen, April 2007.
551 # Appends one or more lists as columns to a matrix.
553 my ( $matrix, # AoA data structure
554 $cols, # list of columns
559 my ( $dims_matrix, $dims_cols, $i );
561 $dims_matrix = matrix_dims( $matrix );
562 $dims_cols = matrix_dims( $cols );
564 die qq(ERROR: Cannot merge columns with different row count\n) if $dims_matrix->[ ROWS ] != $dims_cols->[ ROWS ];
566 for ( $i = 0; $i < $dims_matrix->[ ROWS ]; $i++ )
568 push @{ $matrix->[ $i ] }, @{ $cols->[ $i ] };
571 return wantarray ? @{ $matrix } : $matrix;
577 # Martin A. Hansen, April 2007.
579 # Prefixes one or more lists as columns to a matrix.
581 my ( $matrix, # AoA data structure
582 $cols, # list of columns
587 my ( $dims_matrix, $dims_cols, $i );
589 $dims_matrix = matrix_dims( $matrix );
590 $dims_cols = matrix_dims( $cols );
592 die qq(ERROR: Cannot merge columns with different row count\n) if $dims_matrix->[ ROWS ] != $dims_cols->[ ROWS ];
594 for ( $i = 0; $i < $dims_matrix->[ ROWS ]; $i++ ) {
595 unshift @{ $matrix->[ $i ] }, @{ $cols->[ $i ] };
598 return wantarray ? @{ $matrix } : $matrix;
604 # Martin A. Hansen, April 2007.
606 # Given a matrix and a range of rows, rotates these rows
607 # left by shifting a given number of elements from
608 # the first position to the last.
610 my ( $matrix, # AoA data structure
611 $beg, # first row to shift
612 $end, # last row to shit
613 $shift, # number of shifts - DEFAULT=1
622 for ( $i = $beg; $i <= $end; $i++ )
624 $row = rows_get( $matrix, $i, $i );
626 for ( $c = 0; $c < $shift; $c++ )
628 $row = list_rotate_left( @{ $row } );
629 $matrix->[ $i ] = $row;
633 return wantarray ? @{ $matrix } : $matrix;
637 sub rows_rotate_right
639 # Martin A. Hansen, April 2007.
641 # Given a matrix and a range of rows, rotates these rows
642 # right by shifting a given number of elements from the
643 # last position to the first.
645 my ( $matrix, # AoA data structure
646 $beg, # first row to shift
647 $end, # last row to shit
648 $shift, # number of shifts - DEFAULT=1
653 my ( $dims, $i, $c, $row );
657 $dims = matrix_dims( $matrix );
659 die qq(ERROR: end < beg: $end < $beg\n) if $end < $beg;
660 die qq(ERROR: row outside matrix\n) if $end >= $dims->[ ROWS ];
662 for ( $i = $beg; $i <= $end; $i++ )
664 $row = rows_get( $matrix, $i, $i );
666 for ( $c = 0; $c < $shift; $c++ )
668 $row = list_rotate_right( @{ $row } );
669 $matrix->[ $i ] = $row;
673 return wantarray ? @{ $matrix } : $matrix;
679 # Martin A. Hansen, April 2007.
681 # Given a matrix and a range of columns, rotates these columns
682 # ups by shifting the the first cell of each row from the
683 # first position to the last.
685 my ( $matrix, # AoA data structure
686 $beg, # first row to shift
687 $end, # last row to shit
688 $shift, # number of shifts - DEFAULT=1
693 my ( $dims, $i, $c, $cols_pre, $col_select, $cols_post, $list );
697 $dims = matrix_dims( $matrix );
699 $cols_pre = cols_get( $matrix, 0, $beg - 1 ) if $beg > 0;
700 $cols_post = cols_get( $matrix, $end + 1, $dims->[ COLS ] - 1 ) if $end < $dims->[ COLS ] - 1;
702 for ( $i = $beg; $i <= $end; $i++ )
704 $col_select = cols_get( $matrix, $i, $i );
706 $list = matrix_flip( $col_select )->[ 0 ];
708 for ( $c = 0; $c < $shift; $c++ ) {
709 $list = list_rotate_left( $list );
712 $col_select = matrix_flip( [ $list ] );
715 cols_push( $cols_pre, $col_select );
717 $cols_pre = $col_select;
721 cols_push( $cols_pre, $cols_post ) if $cols_post;
725 return wantarray ? @{ $matrix } : $matrix;
731 # Martin A. Hansen, April 2007.
733 # Given a matrix and a range of columns, rotates these columns
734 # ups by shifting the the first cell of each row from the
735 # first position to the last.
737 my ( $matrix, # AoA data structure
738 $beg, # first row to shift
739 $end, # last row to shit
740 $shift, # number of shifts - DEFAULT=1
745 my ( $dims, $i, $c, $cols_pre, $col_select, $cols_post, $list );
749 $dims = matrix_dims( $matrix );
751 $cols_pre = cols_get( $matrix, 0, $beg - 1 ) if $beg > 0;
752 $cols_post = cols_get( $matrix, $end + 1, $dims->[ COLS ] - 1 ) if $end < $dims->[ COLS ] - 1;
754 for ( $i = $beg; $i <= $end; $i++ )
756 $col_select = cols_get( $matrix, $i, $i );
758 $list = matrix_flip( $col_select )->[ 0 ];
760 for ( $c = 0; $c < $shift; $c++ ) {
761 $list = list_rotate_right( $list );
764 $col_select = matrix_flip( [ $list ] );
767 cols_push( $cols_pre, $col_select );
769 $cols_pre = $col_select;
773 cols_push( $cols_pre, $cols_post ) if $cols_post;
777 return wantarray ? @{ $matrix } : $matrix;
783 # Martin A. Hansen, April 2007.
785 # given a list, shifts off the first element,
786 # and appends to the list, which is returned.
788 my ( $list, # list to rotate
791 my ( @new_list, $elem );
793 @new_list = @{ $list };
795 $elem = shift @new_list;
797 push @new_list, $elem;
799 return wantarray ? @new_list : \@new_list;
803 sub list_rotate_right
805 # Martin A. Hansen, April 2007.
807 # given a list, pops off the last element,
808 # and prefixes to the list, which is returned.
810 my ( $list, # list to rotate
813 my ( @new_list, $elem );
815 @new_list = @{ $list };
817 $elem = pop @new_list;
819 unshift @new_list, $elem;
821 return wantarray ? @new_list : \@new_list;
825 sub list_check_numeric
827 # Martin A. Hansen, April 2007.
829 # Checks if a given list only contains
830 # numerical elements. return 1 if numerical,
833 my ( $list, # list to check
840 foreach $elem ( @{ $list } ) {
841 return 0 if not $elem =~ /^\d+$/; # how about scientific notation ala 123.2312e-03 ?
850 # Martin A. Hansen, April 2007.
852 # Checks if a given list is sorted.
853 # If the sort type is not specified, we
854 # are going to check the type and make a guess.
855 # Returns 1 if sorted else 0.
857 my ( $list, # list to check
858 $type, # numerical of alphabetical
867 if ( list_check_numeric( $list ) ) {
875 if ( $type =~ /^a.*/i ) {
882 if ( @{ $list } > 1 )
886 for ( $i = 1; $i < @{ $list }; $i++ )
888 $cmp = $list->[ $i - 1 ] <=> $list->[ $i ];
890 return 0 if $cmp > 0;
895 for ( $i = 1; $i < @{ $list }; $i++ )
897 $cmp = $list->[ $i - 1 ] cmp $list->[ $i ];
899 return 0 if $cmp > 0;
910 # Martin A. Hansen, April 2007.
912 # returns the number of unique elements in a
920 my ( %hash, $count );
922 map { $hash{ $_ } = 1 } @{ $list };
924 $count = scalar keys %hash;
932 # Martin A. Hansen, April 2007.
934 my ( $matrix, # AoA data structure
938 my ( $dims, $list, $i, $max, $len, %hash, $elem, @list );
940 $dims = matrix_dims( $matrix );
942 $list = cols_get( $matrix, $col, $col );
943 $list = matrix_flip( $list )->[ 0 ];
947 for ( $i = 0; $i < @{ $list }; $i++ )
949 $hash{ $list->[ $i ] }++;
951 $len = length $list->[ $i ];
953 $max = $len if $len > $max;
958 if ( list_check_numeric( $list ) ) {
959 @list = sort { $a <=> $b } @list;
961 @list = sort { $a cmp $b } @list;
964 foreach $elem ( @list )
966 print $elem, " " x ( $max - length( $elem ) ),
967 sprintf( " %6s ", $hash{ $elem } ),
968 sprintf( "%.2f\n", ( $hash{ $elem } / $dims->[ ROWS ] ) * 100 );
975 # Martin A. Hansen, July 2008.
977 # Merge two given tables based on identifiers in a for each table
978 # specified column which should contain a unique identifier.
979 # Initially the tables are sorted and tab2 is merged onto tab1
982 my ( $tab1, # table 1 - an AoA.
983 $tab2, # table 2 - an AoA.
984 $col1, # identifier in row1
985 $col2, # identifier in row2
986 $sort_type, # alphabetical or numeric comparison
991 my ( $num, $cmp, $i, $c, @row_cpy, $max );
996 if ( $sort_type =~ /num/i )
1000 @{ $tab1 } = sort { $a->[ $col1 ] <=> $b->[ $col1 ] } @{ $tab1 };
1001 @{ $tab2 } = sort { $a->[ $col2 ] <=> $b->[ $col2 ] } @{ $tab2 };
1005 @{ $tab1 } = sort { $a->[ $col1 ] cmp $b->[ $col1 ] } @{ $tab1 };
1006 @{ $tab2 } = sort { $a->[ $col2 ] cmp $b->[ $col2 ] } @{ $tab2 };
1012 while ( $i < @{ $tab1 } and $c < @{ $tab2 } )
1015 $cmp = $tab1->[ $i ]->[ $col1 ] <=> $tab2->[ $c ]->[ $col2 ];
1017 $cmp = $tab1->[ $i ]->[ $col1 ] cmp $tab2->[ $c ]->[ $col2 ];
1022 @row_cpy = @{ $tab2->[ $c ] };
1024 splice @row_cpy, $col2, 1;
1026 push @{ $tab1->[ $i ] }, @row_cpy;
1037 map { push @{ $tab1->[ $i ] }, "null" } 0 .. ( scalar @{ $tab2->[ $c ] } - 2 );
1043 map { push @{ $tab1->[ -1 ] }, "null" } 0 .. ( scalar @{ $tab1->[ 0 ] } - scalar @{ $tab1->[ -1 ] } + 1 );
1047 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BINARY SEARCH <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1052 # Martin A. Hansen, February 2008.
1054 # Uses binary search to locate the interval containing a
1055 # given number. The intervals are defined by begin and end
1056 # positions in seperate columns in a matrix. If a interval is
1057 # found then the index of that matrix row is returned, otherwise
1060 my ( $matrix, # data structure
1061 $col1, # column with interval begins
1062 $col2, # column with interval ends
1063 $num, # number to search for
1066 # Returns an integer.
1068 my ( $high, $low, $try );
1071 $high = @{ $matrix };
1073 while ( $low < $high )
1075 $try = int( ( $high + $low ) / 2 );
1077 # print "num->$num low->$low high->$high try->$try int1->$matrix->[ $try ]->[ $col1 ] int2->$matrix->[ $try ]->[ $col2 ]\n";
1079 if ( $num < $matrix->[ $try ]->[ $col1 ] )
1083 elsif ( $num > $matrix->[ $try ]->[ $col2 ] )
1099 # Martin A. Hansen, February 2008.
1101 # Uses binary search to locate a number in a list of numbers.
1102 # If the number is found, then the index (the position of the number
1103 # in the list) is returned, otherwise -1 is returned.
1105 my ( $list, # list of numbers
1106 $num, # number to search for
1109 # Returns an integer.
1111 my ( $high, $low, $try );
1116 while ( $low < $high )
1118 $try = int( ( $high + $low ) / 2 );
1120 # print "num->$num low->$low high->$high try->$try int->$list->[ $try ]\n";
1122 if ( $num < $list->[ $try ] )
1126 elsif ( $num > $list->[ $try ] )
1140 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DISK SUBROUTINES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1145 # Martin A. Hansen, April 2007
1147 # Reads tabular data from file into a matrix
1148 # AoA data structure.
1150 my ( $path, # full path to file with data
1151 $delimiter, # column delimiter - OPTIONAL (default tab)
1152 $comments, # regex for comment lines to skip - OPTIONAL
1153 $fields_ok, # list of fields to accept - OPTIONAL
1158 my ( $fh, $line, @fields, @AoA );
1160 $delimiter ||= "\t";
1162 $fh = Maasha::Common::read_open( $path );
1164 while ( $line = <$fh> )
1168 next if $comments and $line =~ /^$comments/;
1170 @fields = split /$delimiter/, $line;
1172 map { splice( @fields, $_, 1 ) } @{ $fields_ok } if $fields_ok;
1174 push @AoA, [ @fields ];
1179 return wantarray ? @AoA : \@AoA;
1185 # Martin A. Hansen, April 2007
1187 # Writes a tabular data structure to STDOUT or file.
1189 my ( $matrix, # AoA data structure
1190 $path, # full path to output file - OPTIONAL (default STDOUT)
1191 $delimiter, # column delimiter - OPTIONAL (default tab)
1196 $fh = Maasha::Common::write_open( $path ) if $path;
1198 $delimiter ||= "\t";
1200 foreach $row ( @{ $matrix } )
1203 print $fh join( $delimiter, @{ $row } ), "\n";
1205 print join( $delimiter, @{ $row } ), "\n";
1215 # Martin A. Hansen, April 2007.
1217 # stores a matrix to a binary file.
1219 my ( $path, # full path to file
1220 $matrix, # data structure
1223 Maasha::Common::file_store( $path, $matrix );
1229 # Martin A. Hansen, April 2007.
1231 # retrieves a matrix from a binary file
1233 my ( $path, # full path to file
1236 my $matrix = Maasha::Common::file_retrieve( $path );
1238 return wantarray ? @{ $matrix } : $matrix;
1242 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<