File Coverage

blib/lib/Bio/Trace/ABIF.pm
Criterion Covered Total %
statement 119 1302 9.1
branch 31 724 4.2
condition 1 87 1.1
subroutine 17 173 9.8
pod 157 157 100.0
total 325 2443 13.3


line stmt bran cond sub pod time code
1             package Bio::Trace::ABIF;
2              
3 2     2   44239 use warnings;
  2         5  
  2         59  
4 2     2   11 use strict;
  2         4  
  2         110  
5              
6             =head1 NAME
7              
8             Bio::Trace::ABIF - Perl extension for reading and parsing ABIF (Applied
9             Biosystems, Inc. Format) files
10            
11             =head1 VERSION
12              
13             Version 1.05
14              
15             =cut
16              
17             our $VERSION = '1.05';
18              
19             =head1 SYNOPSIS
20              
21             The ABIF file format is a binary format for storing data (especially, those
22             produced by sequencers), developed by Applied Biosystems, Inc. Typical file
23             suffixes for such files are C<.ab1> and C<.fsa>.
24              
25             The data inside ABIF files is organized in records, in the following referred
26             to as either I or I. Each data item is uniquely
27             identified by a pair made of a four character string and a number: we call such
28             pair a I and its components the I and the I,
29             respectively. Tags are defined in the official documentation for ABIF files
30             (see the L Section at the end of this document).
31              
32             This module provides methods for accessing any data item contained into an ABIF
33             file (with or without knowledge of the corresponding tag) and methods for
34             assessing the quality of the data (e.g., for computing LOR scores, clear ranges,
35             and so on). The module has also support for ABIF file modification, that is,
36             any directory entry can be overwritten (it is not possible, however, to add
37             new directory entries corresponding to tags not already present in the file).
38              
39             use Bio::Trace::ABIF;
40            
41             my $abif = Bio::Trace::ABIF->new();
42             $abif->open_abif('/Path/to/my/file.ab1');
43            
44             print $abif->sample_name(), "\n";
45             my @quality_values = $abif->quality_values();
46             my $sequence = $abif->sequence();
47             # etc...
48              
49             $abif->close_abif();
50              
51             =cut
52              
53             #use 5.008006;
54 2     2   11 use Carp;
  2         12  
  2         35632  
55              
56             require Exporter;
57              
58             our @ISA = qw(Exporter);
59             my $Debugging = 0;
60             my $DIR_SIZE = 28; # Size, in bytes, of a directory entry in an ABIF file
61             my $IS_BIG_ENDIAN = unpack("h*", pack("s", 1)) =~ /01/; # See perlport
62             my $IS_LITTLE_ENDIAN = unpack("h*", pack("s", 1)) =~ /^1/;
63             my $SHORT_MAX = 2**16;
64             my $SHORT_MID = 2**15;
65             my $LONG_MAX = 2**32;
66             my $LONG_MID = 2**31;
67             my $sshort_tmpl = ($IS_BIG_ENDIAN) ? 's' : 'C2';
68             my $slong_tmpl = ($IS_BIG_ENDIAN) ? 'l' : 'C4';
69              
70             # Items to export into callers namespace by default. Note: do not export
71             # names by default without a very good reason. Use EXPORT_OK instead.
72             # Do not simply export all your public functions/methods/constants.
73              
74             # This allows declaration use Bio::Trace::ABIF ':all';
75             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
76             # will save memory.
77             our %EXPORT_TAGS = ( 'all' => [ qw(
78            
79             ) ] );
80              
81             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
82              
83             our @EXPORT = qw(
84            
85             );
86              
87             # Standard types
88             our %TYPES = (
89             1 => 'byte', 2 => 'char', 3 => 'word', 4 => 'short', 5 => 'long',
90             7 => 'float', 8 => 'double', 10 => 'date', 11 => 'time', 18 => 'pString',
91             19 => 'cString', 12 => 'thumb', 13 => 'bool', 6 => 'rational', 9 => 'BCD',
92             14 => 'point', 15 => 'rect', 16 => 'vPoint', 17 => 'vRect', 20 => 'tag',
93             128 => 'deltaComp', 256 => 'LZWComp', 384 => 'deltaLZW'
94             ); # User defined data types have tags numbers >= 1024
95              
96              
97             # Specifies how to pack each data type
98             our %PACK_TMPL = (
99             'byte' => 'C', 'char' => 'c', 'word' => 'n', 'short' => 'n', 'long' => 'N',
100             # float and double needs special treatment
101             'date' => 'nCC', 'time' => 'CCCC', 'pString' => 'CA*', 'cString' => 'Z*',
102             'bool' => 'C', 'thumb' => 'NNCC', 'rational' => 'NN', 'point' => 'nn',
103             'rect' => 'nnnn', 'vPoint' => 'NN', 'vRect' => 'NNNN', 'tag' => 'NN'
104             );
105              
106             =head2 module_version()
107              
108             Usage : $version = Bio::Trace::ABIF->module_version();
109             Returns : This module's version number.
110            
111             =cut
112              
113             sub module_version {
114 0     0 1 0 return $VERSION;
115             }
116              
117             sub _endianness {
118 0 0   0   0 return ($IS_BIG_ENDIAN) ? 'big' : 'little';
119             }
120              
121             =head1 CONSTRUCTOR
122              
123             Creates a new ABIF object.
124              
125             =head2 new()
126              
127             Usage : my $abif = Bio::Trace::ABIF->new();
128             Returns : An instance of ABIF.
129              
130             Creates an ABIF object.
131              
132             =cut
133            
134             sub new {
135 1     1 1 14 my $class = shift;
136 1         4 my $foo = shift;
137 1         3 my $self = {};
138 1         3 $self->{'_FH'} = undef; # ABIF file handle
139 1         3 $self->{'_NUMELEM'} = undef;
140 1         3 $self->{'_DATAOFFSET'} = undef;
141             # Data type codes as specified by AB specification
142 1         4 $self->{'TYPES'} = \%TYPES;
143 1         3 bless($self, $class);
144            
145 1         4 return $self;
146             }
147              
148             =head1 OPENING AND CLOSING ABIF FILES
149              
150             The methods in this section allow you to open an ABIF file
151             (either read-only or for modification), to close it or
152             to verify the ABIF format version number.
153              
154             =cut
155              
156             =head2 open_abif()
157              
158             Usage : $abif->open_abif($pathname);
159             $abif->open_abif($pathname, 1); # Read/Write mode
160             Returns : 1 if the file is opened;
161             0 otherwise.
162              
163             Opens the specified file in binary format and checks whether it is in ABIF
164             format. If the second optional argument is not false then the file is opened in
165             read/write mode (by default, the file is opened in read only mode). Opening in
166             read/write mode is necessary only if you want to use C (see below).
167              
168             =cut
169              
170             sub open_abif {
171 2     2 1 1365 my $self = shift;
172 2         5 my $filename = shift;
173 2         4 my $rw = '<';
174 2 50       7 if (@_) {
175 0 0       0 $rw = '+<' if (shift);
176             }
177            
178             # Close previously opened file, if any
179 2         7 $self->close_abif();
180            
181 2 50       97 open($self->{'_FH'}, $rw, $filename) or return 0;
182 2         7 binmode($self->{'_FH'});
183 2 50       7 unless ($self->is_abif_format()) {
184 0         0 print STDERR "$filename is not an AB file...\n";
185 0         0 close($self->{'_FH'});
186 0         0 $self->{'_FH'} = undef;
187 0         0 return 0;
188             }
189             # Determine the number of items (stored in bytes 18-21)
190             # and the offset of the data (stored in bytes 26-29)
191 2         4 my $bytes;
192 2 50       38 unless (seek($self->{'_FH'}, 18, 0)) {
193 0         0 carp "Error on seeking file $filename";
194 0         0 return 0;
195             }
196             # Read bytes 18-29
197 2 50       17 unless (read($self->{'_FH'}, $bytes, 12)) {
198 0         0 carp "Error on reading $filename";
199 0         0 return 0;
200             }
201             # Unpack a 32 bit integer, skip four bytes and unpack another 32 bit integer
202 4 50       28 ($self->{'_NUMELEM'}, $self->{'_DATAOFFSET'}) =
203 2         10 map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX } unpack('Nx4N', $bytes);
204            
205             # Cache tags positions
206 2         12 return $self->_scan_tags();
207             }
208              
209             # Performs a linear scan of the file,
210             # and stores the tags's offsets in a hash, for fast retrieval
211             sub _scan_tags {
212 2     2   5 my $self = shift;
213 2         3 my ($tag_name, $tag_number, $field);
214 2         3 my $i = 0;
215 2         4 $self->{'_TAG_INDEX'} = { };
216 2         4 do {
217 5         18 my $offset = $self->{'_DATAOFFSET'} + ($DIR_SIZE * $i);
218 5 50       50 unless (seek($self->{'_FH'}, $offset, 0)) {
219 0         0 carp "IO Error (wrong offset within file)";
220 0         0 return 0;
221             }
222             # Read Tag name and number (8 bytes)
223 5 100       42 unless (read($self->{'_FH'}, $field, 8)) {
224 1         183 carp "IO Error (failed to read tag index)";
225 1         128 return 0;
226             }
227 4         18 ($tag_name, $tag_number) = unpack('A4N', $field);
228 4 50       16 $tag_number -= $LONG_MAX if ($tag_number >= $LONG_MID);
229 4         6 ${$self->{'_TAG_INDEX'}}{$tag_name . $tag_number} = $offset;
  4         18  
230 4         20 $i++;
231             }
232             while ($i < $self->{'_NUMELEM'});
233              
234 1         8 return 1;
235             }
236              
237             =head2 close_abif()
238              
239             Usage : $abif->close_abif();
240             Returns : Nothing.
241              
242             Closes the currently opened file.
243              
244             =cut
245              
246             sub close_abif {
247 3     3 1 10 my $self = shift;
248 3 100       75 close($self->{'_FH'}) if defined $self->{'_FH'};
249 3         11 foreach my $k (keys %$self) {
250 14 100       65 $self->{$k} = undef if $k =~ /^\_/;
251             }
252             }
253              
254             =head2 is_abif_open()
255              
256             Usage : if ($abif->is_abif_open()) { # ...
257             Returns : 1 if an ABIF file is open;
258             0 otherwise.
259              
260             =cut
261              
262             sub is_abif_open {
263 2     2 1 508 my $self = shift;
264 2         8 return defined $self->{'_FH'};
265             }
266              
267              
268             =head2 is_abif_format()
269              
270             Usage : if ($abif->is_abif_format()) { # ...
271             Returns : 1 if the file is in ABIF format;
272             0 otherwise.
273              
274             Checks that the file is in ABIF format.
275              
276             =cut
277              
278             sub is_abif_format {
279 2     2 1 4 my $self = shift;
280 2         4 my $file_signature;
281              
282             # Move to the beginning of the file
283 2 50       17 unless (seek($self->{'_FH'}, 0, 0)) {
284 0         0 carp "Error on reading file";
285 0         0 return 0;
286             }
287             # Read the first four bytes of the file
288             # and interpret them as ASCII characters
289 2 50       52 read($self->{'_FH'}, $file_signature, 4) or return 0;
290 2         13 $file_signature = unpack('A4', $file_signature);
291 2 50       12 if ($file_signature eq 'FIBA') {
292 0         0 print STDERR "Probably, an ABIF file stored in little endian order\n";
293 0         0 print STDERR "Unsupported ABIF file structure (because deprecated)\n";
294             }
295 2         20 return ($file_signature eq 'ABIF');
296             }
297              
298             =head2 abif_version()
299              
300             Usage : $v = $abif->abif_version();
301             Returns : The ABIF file version number (e.g., '1.01').
302              
303             Used to determine the ABIF file version number.
304            
305             =cut
306              
307             sub abif_version {
308 0     0 1 0 my $self = shift;
309 0         0 my $version;
310              
311 0 0       0 unless (defined $self->{'_ABIF_VERSION'}) {
312             # Version number is stored in bytes 4 and 5
313 0 0       0 seek($self->{'_FH'}, 4, 0) or croak "Error on reading file";
314 0 0       0 read($self->{'_FH'}, $version, 2) or croak "Error on reading file";
315 0         0 $version = unpack('n', $version);
316 0         0 $self->{'_ABIF_VERSION'} = $version / 100;
317             }
318 0         0 return $self->{'_ABIF_VERSION'};
319             }
320              
321             =head1 GENERAL METHODS
322              
323             The "low-level" methods of this section allow you to access
324             any directory entry in a file. It is up to the caller to correctly
325             interpret the values returned by these methods, so they should
326             be used only if the caller knows what (s)he is doing. In any case, it is
327             strongly recommended to use the accessor methods defined later
328             in this document: in most cases, they will do just fine.
329              
330             =cut
331              
332             =head2 num_dir_entries()
333              
334             Usage : $n = $abif->num_dir_entries();
335             Returns : The number of data items in the file.
336            
337             Used to determine the number of directory entries in the ABIF file.
338              
339             =cut
340              
341             sub num_dir_entries {
342 1     1 1 2 my $self = shift;
343 1         7 return $self->{'_NUMELEM'};
344             }
345              
346             =head2 data_offset()
347              
348             Usage : $n = $abif->data_offset();
349             Returns : The offset of the first data item, in bytes.
350            
351             Used to determine the offset of the first directory entry from the beginning
352             of the file.
353              
354             =cut
355              
356             sub data_offset {
357 1     1 1 5 my $self = shift;
358 1         7 return $self->{'_DATAOFFSET'};
359             }
360              
361             =head2 tags()
362              
363             Usage : @tags = $abif->tags();
364             Returns : A list of the tags in the file.
365              
366             =cut
367              
368             sub tags {
369 0     0 1 0 my $self = shift;
370 0         0 return keys %{$self->{'_TAG_INDEX'}};
  0         0  
371             }
372              
373             =head2 get_directory()
374              
375             Usage : %D = $abif->get_directory($tagname, $tagnum);
376             Returns : A hash of the content of the given data item;
377             () if the given tag is not found.
378            
379             Retrieves the directory entry identified by the pair (C<$tag_name>, C<$tag_num>).
380             The C<$tagname> must be a four letter ASCII code and C<$tagnum> must be an
381             integer (typically, 1 <= C<$tag_num> <= 1000). The returned hash has the
382             following keys:
383              
384             TAG_NAME: the tag name;
385             TAG_NUMBER: the tag number;
386             ELEMENT_TYPE: a string denoting the type of the data item
387             ('char', 'byte', 'float', etc...);
388             ELEMENT_SIZE: the size, in bytes, of one element;
389             NUM_ELEMENTS: the number of elements in the data item;
390             DATA_SIZE: the size, in bytes, of the data item;
391             DATA_ITEM: the raw sequence of bytes of the data item.
392              
393             Nota Bene: it is upon the caller to interpret the data item field correctly
394             (typically, by Cing the item).
395              
396             Refer to the L Section for further information.
397              
398             =cut
399              
400             sub get_directory {
401 2     2 1 3803 my ($self, $tag_name, $tag_number) = @_;
402 2         4 my %DirEntry;
403             my $field;
404 0         0 my ($et, $es, $ne, $ds);
405 0         0 my $raw_data;
406              
407 2 50       9 if ($self->search_tag($tag_name, $tag_number)) { # Found!
408 2         5 $DirEntry{TAG_NAME} = $tag_name;
409 2         5 $DirEntry{TAG_NUMBER} = $tag_number;
410             # Read and unpack the remaining bytes
411 2         20 read($self->{'_FH'}, $field, 4);
412 2 50       10 ($et, $es) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  4         35  
413             unpack('nn', $field);
414 2         9 read($self->{'_FH'}, $field, 8);
415 2 50       8 ($ne, $ds) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  4         19  
416             unpack('NN', $field);
417             # Element type code (signed 16 bit integer)
418 2 50       11 if ($et > 1023) {
419 0         0 $DirEntry{ELEMENT_TYPE} = 'user';
420             }
421             else {
422 2         9 $DirEntry{ELEMENT_TYPE} = $self->{TYPES}{$et};
423             }
424             # Element size (signed 16 bit integer)
425 2         5 $DirEntry{ELEMENT_SIZE} = $es;
426             # Number of element in this item (signed 32 bit integer)
427 2         6 $DirEntry{NUM_ELEMENTS} = $ne;
428             # Size of the item in bytes (signed 32 bit integer)
429 2         5 $DirEntry{DATA_SIZE} = $ds;
430             # Get data item
431 2 100       8 if ($DirEntry{DATA_SIZE} > 4) {
432             # The data item position is given by the data offset field
433 1         3 read($self->{'_FH'}, $field, 4);
434 1 50       3 ($field) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  1         6  
435             unpack('N', $field);
436 1         10 seek($self->{'_FH'}, $field, 0);
437 1         7 read($self->{'_FH'}, $raw_data, $DirEntry{DATA_SIZE});
438             }
439             else {
440             # if data size <= 4 then the data item is stored in the data offset field itself
441             # (the current file handle position)
442 1         4 read($self->{'_FH'}, $raw_data, $DirEntry{DATA_SIZE});
443             }
444 2         9 $DirEntry{DATA_ITEM} = $raw_data; # Return raw data
445              
446 2         27 return %DirEntry;
447             }
448            
449 0         0 return ();
450             }
451              
452             =head2 get_data_item()
453              
454             Usage : @data = $abif->get_data_item($tagname,
455             $tagnum,
456             $template
457             );
458             Returns : A list of elements unpacked according to $template;
459             (), if the tag is not found.
460            
461            
462             Retrieves the data item specified by the pair (C<$tagname>, C<$tagnum>) and
463             unpacks it according to C<$template>. The C<$tagname> is a four letter
464             ASCII code and C<$tagnum> is an integer (typically, 1 <= C<$tagnum> <= 1000).
465             The C<$template> has the same format as in the C function.
466              
467             Refer to the L Section for further information.
468              
469             =cut
470              
471             sub get_data_item {
472 2     2 1 3837 my $self = shift;
473 2         6 my $tag_name = shift;
474 2         2 my $tag_number = shift;
475 2         3 my $template = shift;
476 2         3 my $field;
477             my $data_size;
478 0         0 my $raw_data;
479 0         0 my @data;
480              
481 2 50       5 if ($self->search_tag($tag_name, $tag_number)) { # Found!
482             # Read the remaining bytes of the current directory entry
483 2         15 read($self->{'_FH'}, $field, 12);
484             # Unpack data size
485 2 50       9 ($data_size) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  2         11  
486             unpack('x8N', $field);
487 2 50       8 if ($data_size > 4) {
488             # The data item position is given by the data offset field
489 0         0 read($self->{'_FH'}, $field, 4);
490 0 0       0 ($field) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
491             unpack('N', $field);
492 0         0 seek($self->{'_FH'}, $field, 0);
493 0         0 read($self->{'_FH'}, $raw_data, $data_size);
494             }
495             else {
496             # if data size <= 4 then the data item is stored in the data offset field itself
497             # (the current file handle position)
498 2         7 read($self->{'_FH'}, $raw_data, $data_size);
499             }
500 2         6 @data = unpack($template, $raw_data);
501 2         8 return @data;
502             }
503 0         0 return ();
504             }
505              
506             =head1 SEARCHING AND OVERWRITING DATA
507              
508             The methods in this section allow you to search for a specific tag
509             and to overwrite existing data corresponding to a given tag.
510              
511             =head2 search_tag()
512              
513             Usage : $abif->search_tag($tagname, $tagnum)
514             Returns : 1 if the tag is found;
515             0, otherwise
516              
517             Searches for the the specified data tag. If the tag is found, then the file
518             handle is positioned just after the tag number (ready to read the element type).
519              
520             =cut
521              
522             sub search_tag {
523 4     4 1 8 my ($self, $tag_name, $tag_number) = @_;
524 4         6 my ($t1, $t2, $field);
525 4         5 my $offset = ${$self->{'_TAG_INDEX'}}{$tag_name . $tag_number};
  4         15  
526 4 50       14 if (defined $offset) {
527 4         40 seek($self->{'_FH'}, $offset + 8, 0);
528 4         17 return 1;
529             }
530             else {
531 0         0 return 0;
532             }
533             }
534              
535             =head2 write_tag()
536              
537             Usage : $abif->write_tag($tagname, $tagnum, $data);
538             $abif->write_tag($tagname, $tagnum, \@data);
539             $abif->write_tag($tagname, $tagnum, \$data_str);
540             Returns : 1 if the data item is overwritten;
541             0, otherwise.
542              
543             Overwrites an existing tag with the given data. You may find the tag name and
544             the tag number of each piece of data in an ABIF file in the documentation of the
545             corresponding method (see below). You must open the file in read/write mode if
546             you want to overwrite it (see C).
547              
548             REMEMBER TO BACKUP YOUR FILE BEFORE OVERWRITING IT!
549              
550             You must be careful when you overwrite data: the type of the new data must
551             match the type of the old one. There is no restriction on the length of the
552             data, e.g. you may overwrite the basecalled sequence with a longer or shorter
553             one. Examples of how to use this method follow.
554              
555             To overwrite the basecalled sequence:
556              
557             my $new_sequence = 'GATGCATCT...';
558             $abif->write_tag('PBAS', 1, \$new_sequence);
559             # ($new_sequence can be passed also by value)
560             print 'New sequence is: ', $abif->edited_sequence();
561              
562             To overwrite the quality values:
563              
564             my @qv = (10, 20, 30, ...); # All values must be < 128
565             $abif->write_tag('PCON', 1, \@qv); # Pass by reference!
566             print 'New qv's: ', $abif->edited_quality_values();
567            
568             To overwrite a date:
569              
570             # Date format: yyyy-mm-dd
571             $abif->write_tag('RUND', 3, '2007-01-22');
572             print 'New date: ', $abif->data_collection_start_date();
573              
574             To overwrite a time stamp:
575              
576             # Time format: hh:mm:ss.nn
577             $abif->write_tag('RUNT', 4, '16:01:30.45');
578             print 'New time: ', $abif->data_collection_stop_time();
579              
580             To overwrite a comment:
581              
582             $abif->write_tag('CMNT', 1, 'New comment');
583             print 'New comment: ', $abif->comment();
584            
585             To overwrite noise values:
586              
587             my @noise = (3.14, 2.71, ...);
588             $abif->write_tag('NOIS', 1, \@noise);
589             print 'Noise values: ', $abif->noise();
590            
591             To overwrite the capillary number:
592              
593             $abif->write_tag('LANE', 1, 95);
594             print 'Capillary number: ', $abif->capillary_number();
595            
596             and so on.
597              
598             =cut
599              
600             sub write_tag {
601 0     0 1 0 my ($self, $tag_name, $tag_number, $data) = @_;
602 0         0 my ($elem_type, $elem_size, $num_elems, $data_size);
603 0         0 my $field;
604 0         0 my $data_offset;
605 0         0 my $packed_data;
606 0         0 my $n_data; # Number of new elements
607 0         0 my $n_bytes; # New data size in bytes
608              
609 0 0       0 if ($self->search_tag($tag_name, $tag_number)) {
610 0         0 read($self->{'_FH'}, $field, 4);
611 0 0       0 my ($et, $elem_size) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
612             unpack('nn', $field);
613 0         0 read($self->{'_FH'}, $field, 8);
614 0 0       0 my ($num_elems, $data_size) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
615             unpack('NN', $field);
616             # Element type code (signed 16 bit integer)
617 0 0       0 return 0 if ($et > 1023); # User data type: don't know how to pack
618             # Unsupported data types
619 0 0 0     0 return 0 if ($et == 9 or $et == 128 or $et == 256 or $et == 384);
      0        
      0        
620 0         0 $elem_type = $self->{TYPES}{$et};
621 0 0       0 return 0 unless (defined $elem_type); # Unknown data type
622              
623             #############
624             # Pack data #
625             #############
626 0 0       0 if ($elem_type eq 'float') {
    0          
    0          
    0          
    0          
    0          
    0          
627 0 0       0 if (ref($data) eq 'ARRAY') { # $data is reference to array
    0          
628 0         0 $packed_data = '';
629 0         0 foreach my $fl (@$data) {
630 0         0 $packed_data .= $self->_decimal2ieee($fl);
631             }
632 0         0 $packed_data = pack('B*', $packed_data);
633 0         0 $n_data = scalar(@$data);
634             }
635             elsif (ref($data)) { # Reference to what?!
636 0         0 return 0;
637             }
638             else { # $data is scalar
639 0         0 $packed_data = pack('B32', $self->_decimal2ieee($data));
640 0         0 $n_data = 1;
641             }
642             }
643             elsif ($elem_type eq 'double') { # currently, double is never used in ABIF
644 0 0       0 if (ref($data) eq 'ARRAY') {
    0          
645 0         0 $packed_data = pack('d*', @$data); # NOT PORTABLE!!!
646 0         0 $n_data = scalar(@$data);
647             }
648             elsif (ref($data)) {
649 0         0 return 0;
650             }
651             else {
652 0         0 $packed_data = pack('d', $data); # NOT PORTABLE!!!
653 0         0 $n_data = 1;
654             }
655             }
656             elsif ($elem_type eq 'date') {
657 0 0       0 return 0 if (ref($data));
658 0         0 my ($yy, $mm, $dd) = ($data =~ /^(\d+)[^\d](\d+)[^\d](\d+)$/);
659 0 0 0     0 return 0 unless (defined $yy and defined $mm and defined $dd);
      0        
660 0         0 $packed_data = pack('nCC', $yy, $mm, $dd); # Assume $yy is non-negative
661 0         0 $n_data = 1;
662             }
663             elsif ($elem_type eq 'time') {
664 0 0       0 return 0 if (ref($data));
665 0         0 my ($hh, $min, $sec, $ms) = ($data =~ /^(\d+)[^\d](\d+)[^\d](\d+)[^\d](\d+)$/);
666 0 0 0     0 return 0 unless (defined $hh and defined $min and defined $sec and defined $ms);
      0        
      0        
667 0         0 $packed_data = pack('C4', $hh, $min, $sec, $ms);
668 0         0 $n_data = 1;
669             }
670             elsif ($elem_type eq 'pString') {
671 0 0       0 if (ref($data) eq 'SCALAR') {
    0          
672 0 0       0 return 0 if (length($$data) > 255);
673 0         0 $n_data = length($$data);
674 0         0 $packed_data = pack('CA*', $n_data, $$data);
675 0         0 $n_data++;
676             }
677             elsif (ref($data)) {
678 0         0 return 0;
679             }
680             else { # Assume $data is scalar
681 0 0       0 return 0 if (length($data) > 255);
682 0         0 $n_data = length($data);
683 0         0 $packed_data = pack('CA*', $n_data, $data);
684 0         0 $n_data++;
685             }
686             }
687             elsif ($elem_type eq 'cString') {
688 0 0       0 if (ref($data) eq 'SCALAR') {
    0          
689 0         0 $packed_data = pack('Z*', $$data);
690 0         0 $n_data = scalar($$data);
691             }
692             elsif (ref($data)) {
693 0         0 return 0;
694             }
695             else { # Assume $data is scalar
696 0         0 $packed_data = pack('Z*', $data);
697 0         0 $n_data = scalar($data);
698             }
699             }
700             elsif ($elem_type eq 'char') {
701 0 0       0 if (ref($data) eq 'ARRAY') { # Assume it's an array of numerical values
    0          
    0          
702 0         0 $packed_data = pack('c*', @$data);
703 0         0 $n_data = scalar(@$data);
704             }
705             elsif (ref($data) eq 'SCALAR') { # Assume it's a string
706 0         0 $packed_data = pack('A*', $$data);
707 0         0 $n_data = length($$data);
708             }
709             elsif (ref($data)) {
710 0         0 return 0;
711             }
712             else {
713 0         0 $packed_data = pack('A*', $data);
714 0         0 $n_data = length($data);
715             }
716             }
717             else {
718 0 0       0 if (ref($data) eq 'ARRAY') {
    0          
719 0         0 $packed_data = pack($PACK_TMPL{$elem_type} . '*', @$data);
720 0         0 $n_data = scalar(@$data);
721             }
722             elsif (ref($data)) {
723 0         0 return 0;
724             }
725             else {
726 0         0 $packed_data = pack($PACK_TMPL{$elem_type}, $data);
727 0         0 $n_data = 1;
728             }
729             }
730 0         0 $n_bytes = length($packed_data);
731              
732             ##############
733             # Write data #
734             ##############
735 0         0 seek($self->{'_FH'}, -8, 1); # Go back to numelements field...
736 0         0 print { $self->{'_FH'} } pack('NN', $n_data, $n_bytes); # ...and write new sizes
  0         0  
737             # Current file handle position is at dataoffset field
738 0 0       0 if ($n_bytes <= 4) { # Data can be stored in the data offset field
    0          
739 0         0 print { $self->{'_FH'} } $packed_data;
  0         0  
740             # Not necessary, but let's zero remaining bytes in the field, if any
741 0         0 for (my $pad = $n_bytes; $pad < 4; $pad++) {
742 0         0 print { $self->{'_FH'} } pack('x', 0);
  0         0  
743             }
744             }
745             # If data is bigger than 4 bytes, we must check whether it fits
746             # in the current position
747             elsif ($n_bytes <= $data_size) { # It fits!
748             # IMPORTANT: the following is from
749             #
750             # http://perldoc.perl.org/functions/seek.html
751             #
752             # "Due to the rules and rigors of ANSI C, on some systems you have
753             # to do a seek whenever you switch between reading and writing."
754             #
755             # Since the last i/o operation done at this point may well be a write,
756             # to be safe we perform a seek that does not change position:
757 0         0 seek($self->{'_FH'}, 0, 1); # Don't move, please :)
758             # The old data item position is in the data offset field
759 0         0 read($self->{'_FH'}, $field, 4);
760 0         0 $data_offset = unpack('N', $field);
761 0         0 seek($self->{'_FH'}, $data_offset, 0);
762 0         0 print { $self->{'_FH'} } $packed_data;
  0         0  
763             # Not really necessary, but let's make some cleaning
764 0         0 for (my $pad = $n_bytes; $pad < $data_size; $pad++) {
765 0         0 print { $self->{'_FH'} } pack('x', 0);
  0         0  
766             }
767             }
768             else { # It doesn't fit: append to the end of the file
769 0         0 my $curr_pos = tell($self->{'_FH'}); # Save current position
770 0         0 seek($self->{'_FH'}, 0, 2); # Seek the end of the file
771 0         0 my $new_offset = tell($self->{'_FH'}); # Save new offset
772 0         0 print { $self->{'_FH'} } $packed_data; # Append new data
  0         0  
773 0         0 seek($self->{'_FH'}, $curr_pos, 0); # Go back to offset field
774 0         0 print { $self->{'_FH'} } pack('N', $new_offset); # Update offset
  0         0  
775             }
776              
777 0         0 $self->{'_' . $tag_name . $tag_number} = undef; # To be re-read next time
778 0         0 return 1;
779             }
780            
781 0         0 return 0;
782             }
783              
784             =head1 ACCESSOR METHODS
785              
786             The methods in this section can be used to retrieve specific
787             information from a file without having to specify a tag.
788             It is strongly recommended that you read data from a file
789             by using one or more of these methods.
790              
791             =head2 analyzed_data_for_channel()
792              
793             Usage : @data = analyzed_data_for_channel($ch_num);
794             Returns : The channel analyzed data;
795             () if the channel number is out of range
796             or the data item is not in the file.
797             ABIF Tag : DATA9, DATA10, DATA11, DATA12, DATA205
798             ABIF Type : short array
799             File Type : ab1
800            
801             There are four channels in an ABIF file, numbered from 1 to 4. An optional
802             channel number 5 exists in some files. The channel number is the argument of
803             the method.
804              
805             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
806              
807             =cut
808              
809             sub analyzed_data_for_channel {
810 0     0 1 0 my ($self, $channel_number) = @_;
811 0 0       0 if ($channel_number == 5) {
812 0         0 $channel_number = 205;
813             }
814             else {
815 0         0 $channel_number += 8;
816             }
817 0 0 0     0 if ($channel_number < 9 or
      0        
818             ($channel_number > 12 and $channel_number != 205)) {
819 0         0 return ();
820             }
821 0         0 my $key = '_DATA' . $channel_number;
822 0 0       0 unless (defined $self->{$key}) {
823 0 0       0 my @data = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
824             $self->get_data_item('DATA', $channel_number, 'n*');
825 0 0       0 $self->{$key} = (@data) ? [ @data ] : [ ];
826             }
827 0         0 return @{$self->{$key}};
  0         0  
828             }
829              
830             =head2 analysis_protocol_settings_name()
831              
832             Usage : $s = $abif->analysis_protocol_settings_name();
833             Returns : The Analysis Protocol settings name;
834             undef if the data item is not in the file.
835             ABIF Tag : APrN1
836             ABIF Type : cString
837             File Type : ab1
838            
839             =cut
840              
841             sub analysis_protocol_settings_name {
842 0     0 1 0 my $self = shift;
843 0 0       0 unless (defined $self->{'_APrN1'}) {
844 0         0 ($self->{'_APrN1'}) = $self->get_data_item('APrN', 1, 'Z*');
845             }
846 0         0 return $self->{'_APrN1'};
847             }
848              
849             =head2 analysis_protocol_settings_version()
850              
851             Usage : $s = $abif->analysis_protocol_settings_version();
852             Returns : The Analysis Protocol settings version;
853             undef if the data item is not in the file.
854             ABIF Tag : APrV1
855             ABIF Type : cString
856             File Type : ab1
857              
858             =cut
859              
860             sub analysis_protocol_settings_version {
861 0     0 1 0 my $self = shift;
862 0 0       0 unless (defined $self->{'_APrV1'}) {
863 0         0 ($self->{'_APrV1'}) = $self->get_data_item('APrV', 1, 'Z*');
864             }
865 0         0 return $self->{'_APrV1'};
866             }
867              
868             =head2 analysis_protocol_xml()
869              
870             Usage : $xml = $abif->analysis_protocol_xml();
871             Returns : The Analysis Protocol XML string;
872             undef if the data item is not in the file.
873             ABIF Tag : APrX1
874             ABIF Type : char array
875             File Type : ab1
876            
877             =cut
878              
879             sub analysis_protocol_xml {
880 0     0 1 0 my $self = shift;
881 0 0       0 unless (defined $self->{'_APrX1'}) {
882 0         0 ($self->{'_APrX1'}) = $self->get_data_item('APrX', 1, 'A*');
883             }
884 0         0 return $self->{'_APrX1'};
885             }
886              
887             =head2 analysis_protocol_xml_schema_version()
888              
889             Usage : $s = $abif->analysis_protocol_xml_schema_version();
890             Returns : The Analysis Protocol XML schema version;
891             undef if the data item is not in the file.
892             ABIF Tag : APXV1
893             ABIF Type : cString
894             File Type : ab1
895            
896             =cut
897              
898             sub analysis_protocol_xml_schema_version {
899 0     0 1 0 my $self = shift;
900 0 0       0 unless (defined $self->{'_APXV1'}) {
901 0         0 ($self->{'_APXV1'}) = $self->get_data_item('APXV', 1, 'Z*');
902             }
903 0         0 return $self->{'_APXV1'};
904             }
905              
906             =head2 analysis_return_code()
907              
908             Usage : $rc = $abif->analysis_return_code();
909             Returns : The analysis return code;
910             undef if the data item is not in the file.
911             ABIF Tag : ARTN1
912             ABIF Type : long
913             File Type : ab1
914            
915             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
916            
917             =cut
918              
919             sub analysis_return_code {
920 0     0 1 0 my $self = shift;
921 0 0       0 unless (defined $self->{'_ARTN1'}) {
922 0 0       0 ($self->{'_ARTN1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
923             $self->get_data_item('ARTN', 1, 'N');
924             }
925 0         0 return $self->{'_ARTN1'};
926             }
927              
928             =head2 avg_peak_spacing()
929              
930             Usage : $aps = $abif->avg_peak_spacing();
931             Returns : The average peak spacing used in last analysis;
932             undef if the data item is not in the file.
933             ABIF Tag : SPAC1
934             ABIF Type : float
935             File Type : ab1
936            
937             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
938              
939             =cut
940              
941             sub avg_peak_spacing() {
942 0     0 1 0 my $self = shift;
943 0 0       0 unless (defined $self->{'_SPAC1'}) {
944 0         0 my $s = undef;
945 0         0 ($s) = $self->get_data_item('SPAC', 1, 'B32');
946 0 0       0 $self->{'_SPAC1'} = $self->_ieee2decimal($s) if (defined $s);
947             }
948 0         0 return $self->{'_SPAC1'};
949             }
950              
951             =head2 basecaller_apsf()
952              
953             Usage : $n = $abif->basecaller_apsf();
954             Returns : The basecaller adaptive processing success flag;
955             undef if the data item is not in the file.
956             ABIF Tag : ASPF1
957             ABIF Type : short
958             File Type : ab1
959            
960             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
961            
962             =cut
963              
964             sub basecaller_apsf {
965 0     0 1 0 my $self = shift;
966 0 0       0 unless (defined $self->{'_ASPF1'}) {
967 0 0       0 ($self->{'_ASPF1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
968             $self->get_data_item('ASPF', 1, 'n');
969             }
970 0         0 return $self->{'_ASPF1'};
971             }
972              
973             =head2 basecaller_bcp_dll()
974              
975             Usage : $v = basecaller_bcp_dll();
976             Returns : A string with the basecalled BCP/DLL;
977             undef if the data item is not in the file.
978             ABIF Tag : SPAC2
979             ABIF Type : pString
980             File Type : ab1
981            
982             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
983              
984             =cut
985              
986             sub basecaller_bcp_dll {
987 0     0 1 0 my $self = shift;
988 0 0       0 unless (defined $self->{'_SPAC2'}) {
989 0         0 ($self->{'_SPAC2'}) = $self->get_data_item('SPAC', 2, 'xA*');
990             }
991 0         0 return $self->{'_SPAC2'};
992             }
993              
994             =head2 basecaller_version()
995              
996             Usage : $v = $abif->basecaller_version();
997             Returns : The basecaller version (e.g., 'KB 1.3.0');
998             undef if the data item is not in the file.
999             ABIF Tag : SVER2
1000             ABIF Type : pString
1001             File Type : ab1
1002              
1003             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1004              
1005             =cut
1006              
1007             sub basecaller_version {
1008 0     0 1 0 my $self = shift;
1009 0 0       0 unless (defined $self->{'_SVER2'}) {
1010 0         0 ($self->{'_SVER2'}) = $self->get_data_item('SVER', 2, 'xA*');
1011             }
1012 0         0 return $self->{'_SVER2'};
1013             }
1014              
1015             =head2 basecalling_analysis_timestamp()
1016              
1017             Usage : $s = $abif->basecalling_analysis_timestamp();
1018             Returns : A time stamp;
1019             undef if the data item is not in the file.
1020             ABIF Tag : BCTS1
1021             ABIF Type : pString
1022             File Type : ab1
1023              
1024             Returns the time stamp for last successful basecalling analysis.
1025              
1026             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1027              
1028             =cut
1029              
1030             sub basecalling_analysis_timestamp {
1031 0     0 1 0 my $self = shift;
1032 0 0       0 unless (defined $self->{'_BCTS1'}) {
1033 0         0 ($self->{'_BCTS1'}) = $self->get_data_item('BCTS', 1, 'xA*');
1034             }
1035 0         0 return $self->{'_BCTS1'};
1036             }
1037              
1038             =head2 base_locations()
1039              
1040             Usage : @bl = $abif->base_locations();
1041             Returns : The list of base locations;
1042             () if the data item is not in the file.
1043             ABIF Tag : PLOC2
1044             ABIF Type : short array
1045             File Type : ab1
1046              
1047             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1048              
1049             =cut
1050              
1051             sub base_locations {
1052 0     0 1 0 my $self = shift;
1053 0 0       0 unless (defined $self->{'_PLOC2'}) {
1054 0 0       0 my @bl = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1055             $self->get_data_item('PLOC', 2, 'n*');
1056 0 0       0 $self->{'_PLOC2'} = (@bl) ? [ @bl ] : [ ];
1057             }
1058 0         0 return @{$self->{'_PLOC2'}};
  0         0  
1059             }
1060              
1061             =head2 base_locations_edited()
1062              
1063             Usage : @bl = $abif->base_locations_edited();
1064             Returns : The list of base locations (edited);
1065             () if the data item is not in the file.
1066             ABIF Tag : PLOC1
1067             ABIF Type : short array
1068             File Type : ab1
1069            
1070             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1071              
1072             =cut
1073              
1074             sub base_locations_edited {
1075 0     0 1 0 my $self = shift;
1076 0 0       0 unless (defined $self->{'_PLOC1'}) {
1077 0 0       0 my @bl = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1078             $self->get_data_item('PLOC', 1, 'n*');
1079 0 0       0 $self->{'_PLOC1'} = (@bl) ? [ @bl ] : [ ];
1080             }
1081 0         0 return @{$self->{'_PLOC1'}};
  0         0  
1082             }
1083              
1084             =head2 base_order()
1085              
1086             Usage : @bo = $abif->base_order();
1087             Returns : An array of characters sorted by channel number;
1088             () if the data item is not in the file.
1089             ABIF Tag : FWO_1
1090             ABIF Type : char array
1091             File Type : ab1
1092              
1093             Returns an array of characters sorted by increasing channel number.
1094             For example, if the list is C<('G', 'A', 'T', 'C')>
1095             then G is channel 1, A is channel 2, and so on. If you want to do
1096             the opposite, that is, mapping bases to their channels, use C
1097             instead. See also the C method.
1098              
1099             =cut
1100              
1101             sub base_order {
1102 0     0 1 0 my $self = shift;
1103 0 0       0 unless (defined $self->{'_FWO_1'}) {
1104 0         0 my ($bases) = $self->get_data_item('FWO_', 1, 'A*');
1105 0 0       0 if (defined $bases) {
1106 0         0 my @bo = split('', $bases);
1107 0         0 $self->{'_FWO_1'} = [ @bo ];
1108             }
1109             else {
1110 0         0 $self->{'_FWO_1'} = [ ];
1111             }
1112             }
1113 0         0 return @{$self->{'_FWO_1'}};
  0         0  
1114             }
1115              
1116             =head2 base_spacing()
1117              
1118             Usage : $spacing = $abif->base_spacing();
1119             Returns : The spacing;
1120             undef if the data item is not in the file.
1121             ABIF Tag : SPAC3
1122             ABIF Type : float
1123             File Type : ab1
1124            
1125             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1126              
1127             =cut
1128              
1129             sub base_spacing() {
1130 0     0 1 0 my $self = shift;
1131 0 0       0 unless (defined $self->{'_SPAC3'}) {
1132 0         0 my $s = undef;
1133 0         0 ($s) = $self->get_data_item('SPAC', 3, 'B32');
1134 0 0       0 $self->{'_SPAC3'} = $self->_ieee2decimal($s) if (defined $s);
1135              
1136             }
1137 0         0 return $self->{'_SPAC3'};
1138             }
1139              
1140             =head2 buffer_tray_temperature()
1141              
1142             Usage : @T = $abif->buffer_tray_temperature();
1143             Returns : The buffer tray heater temperature in °C;
1144             () if the data item is not in the file.
1145             ABIF Tag : BufT1
1146             ABIF Type : short array
1147             File Type : ab1
1148              
1149             =cut
1150              
1151             sub buffer_tray_temperature {
1152 0     0 1 0 my $self = shift;
1153 0 0       0 unless (defined $self->{'_BufT1'}) {
1154 0 0       0 my @T = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1155             $self->get_data_item('BufT', 1, 'n*');
1156 0 0       0 $self->{'_BufT1'} = (@T) ? [ @T ] : [ ];
1157             }
1158 0         0 return @{$self->{'_BufT1'}};
  0         0  
1159             }
1160              
1161             =head2 capillary_number()
1162              
1163             Usage : $cap_n = $abif->capillary_number();
1164             Returns : The LANE/Capillary number;
1165             undef if the data item is not in the file.
1166             ABIF Tag : LANE1
1167             ABIF Type : short
1168             File Type : ab1, fsa
1169            
1170             =cut
1171              
1172             sub capillary_number {
1173 0     0 1 0 my $self = shift;
1174 0 0       0 unless (defined $self->{'_LANE1'}) {
1175 0 0       0 ($self->{'_LANE1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1176             $self->get_data_item('LANE', 1, 'n');
1177             }
1178 0         0 return $self->{'_LANE1'};
1179             }
1180              
1181             =head2 channel()
1182              
1183             Usage : $n = $abif->channel($base);
1184             Returns : The channel number corresponding to a given base.
1185             undef if the data item is not in the file.
1186            
1187             Returns the channel number corresponding to the given base.
1188              
1189             The possible values for C<$base> are 'A', 'C', 'G' and 'T' (case insensitive).
1190              
1191             =cut
1192             sub channel {
1193 0     0 1 0 my $self = shift;
1194 0         0 my $base = shift;
1195 0         0 my %ob = ();
1196            
1197 0 0       0 $base =~ /^[ACGTacgt]$/ or return undef;
1198 0         0 %ob = $self->order_base();
1199 0         0 return $ob{uc($base)};
1200             }
1201              
1202             =head2 chem()
1203              
1204             Usage : $s = $abif->chem();
1205             Returns : The primer or terminator chemistry;
1206             undef if the data item is not in the file.
1207             ABIF Tag : phCH1
1208             ABIF Type : pString
1209             File Type : ab1
1210              
1211             Returns the primer or terminator chemistry (equivalent to CHEM in phd1 file).
1212              
1213             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1214              
1215             =cut
1216              
1217             sub chem {
1218 0     0 1 0 my $self = shift;
1219 0 0       0 unless (defined $self->{'_phCH1'}) {
1220 0         0 ($self->{'_phCH1'}) = $self->get_data_item('phCH', 1, 'xA*');
1221             }
1222 0         0 return $self->{'_phCH1'};
1223             }
1224              
1225             =head2 comment()
1226              
1227             Usage : $comment = $abif->comment();
1228             $comment = $abif->comment($n);
1229             Returns : The comment about the sample;
1230             undef if the data item is not in the file.
1231             ABIF Tag : CMNT1 ... CMNT 'N'
1232             ABIF Type : pString
1233             File Type : ab1, fsa
1234              
1235             This is an optional data item. In some files there is more than one comment: the
1236             optional argument is used to specify the number of the comment.
1237              
1238             =cut
1239              
1240             sub comment {
1241 0     0 1 0 my $self = shift;
1242 0         0 my $n = 1;
1243 0 0       0 $n = shift if (@_);
1244 0         0 my $tag_code = '_CMNT' . $n;
1245 0 0       0 unless (defined $self->{$tag_code}) {
1246 0         0 ($self->{$tag_code}) = $self->get_data_item('CMNT', $n, 'xA*');
1247             }
1248 0         0 return $self->{$tag_code};
1249             }
1250              
1251             =head2 comment_title()
1252              
1253             Usage : $comment_title = $abif->comment_title();
1254             Returns : The comment title;
1255             undef if the data item is not in the file.
1256             ABIF Tag : CTTL1
1257             ABIF Type : pString
1258             File Type : ab1, fsa
1259              
1260             =cut
1261              
1262             sub comment_title {
1263 0     0 1 0 my $self = shift;
1264 0 0       0 unless (defined $self->{'_CTTL1'}) {
1265 0         0 ($self->{'_CTTL1'}) = $self->get_data_item('CTTL', 1, 'xA*');
1266             }
1267 0         0 return $self->{'_CTTL1'};
1268             }
1269              
1270             =head2 container_identifier()
1271              
1272             Usage : $id = $abif->container_identifier();
1273             Returns : The container identifier, a.k.a. plate barcode;
1274             undef if the data item is not in the file.
1275             ABIF Tag : CTID1
1276             ABIF Type : cString
1277             File Type : ab1, fsa
1278              
1279             =cut
1280              
1281             sub container_identifier {
1282 0     0 1 0 my $self = shift;
1283 0 0       0 unless (defined $self->{'_CTID1'}) {
1284 0         0 ($self->{'_CTID1'}) = $self->get_data_item('CTID', 1, 'Z*');
1285             }
1286 0         0 return $self->{'_CTID1'};
1287             }
1288              
1289             =head2 container_name()
1290              
1291             Usage : $name = $abif->container_name();
1292             Returns : The container name;
1293             undef if the data item is not in the file.
1294             ABIF Tag : CTNM1
1295             ABIF Type : cString
1296             File Type : ab1, fsa
1297              
1298             Usually, this is identical to the container identifier.
1299              
1300             =cut
1301              
1302             sub container_name {
1303 0     0 1 0 my $self = shift;
1304 0 0       0 unless (defined $self->{'_CTNM1'}) {
1305 0         0 ($self->{'_CTNM1'}) = $self->get_data_item('CTNM', 1, 'Z*');
1306             }
1307 0         0 return $self->{'_CTNM1'};
1308             }
1309              
1310             =head2 container_owner()
1311              
1312             Usage : $owner = $abif->container_owner();
1313             Returns : The container's owner;
1314             : undef if the data item is not in the file.
1315             ABIF Tag : CTow1
1316             ABIF Type : cString
1317             File Type : ab1
1318            
1319             =cut
1320              
1321             sub container_owner {
1322 0     0 1 0 my $self = shift;
1323 0 0       0 unless (defined $self->{'_CTOw1'}) {
1324 0         0 ($self->{'_CTOw1'}) = $self->get_data_item('CTOw', 1, 'Z*');
1325             }
1326 0         0 return $self->{'_CTOw1'};
1327             }
1328              
1329             =head2 current()
1330              
1331             Usage : @c = $abif->current();
1332             Returns : Current, measured in milliamps;
1333             () if the data item is not in the file.
1334             ABIF Tag : DATA6
1335             ABIF Type : short array
1336             File Type : ab1, fsa
1337            
1338             =cut
1339              
1340             sub current {
1341 0     0 1 0 my $self = shift;
1342 0 0       0 unless (defined $self->{'_DATA6'}) {
1343 0 0       0 my @c = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1344             $self->get_data_item('DATA', 6, 'n*');
1345 0 0       0 $self->{'_DATA6'} = (@c) ? [ @c ] : [ ];
1346             }
1347 0         0 return @{$self->{'_DATA6'}};
  0         0  
1348             }
1349              
1350             =head2 data_collection_module_file()
1351              
1352             Usage : $s = $abif->data_collection_module_file();
1353             Returns : The data collection module file;
1354             undef if the data item is not in the file.
1355             ABIF Tag : MODF1
1356             ABIF Type : pString
1357             File Type : ab1, fsa
1358              
1359             =cut
1360              
1361             sub data_collection_module_file {
1362 0     0 1 0 my $self = shift;
1363 0 0       0 unless (defined $self->{'_MODF1'}) {
1364 0         0 ($self->{'_MODF1'}) = $self->get_data_item('MODF', 1, 'xA*');
1365             }
1366 0         0 return $self->{'_MODF1'};
1367             }
1368              
1369             =head2 data_collection_software_version()
1370              
1371             Usage : $v = $abif->data_collection_software_version();
1372             Returns : The data collection software version.
1373             undef if the data item is not in the file.
1374             ABIF Tag : SVER1
1375             ABIF Type : pString
1376             File Type : ab1, fsa
1377            
1378             =cut
1379              
1380             sub data_collection_software_version {
1381 0     0 1 0 my $self = shift;
1382 0 0       0 unless (defined $self->{'_SVER1'}) {
1383 0         0 ($self->{'_SVER1'}) = $self->get_data_item('SVER', 1, 'xA*');
1384             }
1385 0         0 return $self->{'_SVER1'};
1386             }
1387              
1388             =head2 data_collection_firmware_version()
1389              
1390             Usage : $v = $abif->data_collection_firmware_version();
1391             Returns : The data collection firmware version;
1392             undef if the data item is not in the file.
1393             ABIF Tag : SVER3
1394             ABIF Type : pString
1395             File Type : ab1, fsa
1396            
1397             =cut
1398              
1399             sub data_collection_firmware_version {
1400 0     0 1 0 my $self = shift;
1401 0 0       0 unless (defined $self->{'_SVER3'}) {
1402 0         0 ($self->{'_SVER3'}) = $self->get_data_item('SVER', 3, 'xA*');
1403             }
1404 0         0 return $self->{'_SVER3'};
1405             }
1406              
1407             =head2 data_collection_start_date()
1408              
1409             Usage : $date = $abif->data_collection_start_date();
1410             Returns : The Data Collection start date (yyyy-mm-dd);
1411             undef if the data item is not in the file.
1412             ABIF Tag : RUND3
1413             ABIF Type : date
1414             File Type : ab1, fsa
1415              
1416             =cut
1417              
1418             sub data_collection_start_date {
1419 0     0 1 0 my $self = shift;
1420 0 0       0 unless (defined $self->{'_RUND3'}) {
1421 0         0 my ($y, $m, $d) = $self->get_data_item('RUND', 3, 'nCC');
1422 0 0       0 if (defined $d) {
1423             # Ehm, the year is specified as a signed integer...
1424 0 0       0 $y -= $SHORT_MAX if ($y >= $SHORT_MID);
1425 0         0 $self->{'_RUND3'} = _make_date($y, $m, $d);
1426             }
1427             }
1428 0         0 return $self->{'_RUND3'};
1429             }
1430              
1431             =head2 data_collection_start_time()
1432              
1433             Usage : $time = $abif->data_collection_start_time();
1434             Returns : The Data Collection start time (hh:mm:ss.nn);
1435             undef if the data item is not in the file.
1436             ABIF Tag : RUNT3
1437             ABIF Type : time
1438             File Type : ab1, fsa
1439              
1440             =cut
1441              
1442             sub data_collection_start_time {
1443 0     0 1 0 my $self = shift;
1444 0 0       0 unless (defined $self->{'_RUNT3'}) {
1445 0         0 my ($hh, $mm, $ss, $nn) = $self->get_data_item('RUNT', 3, 'C4');
1446 0 0       0 $self->{'_RUNT3'} = _make_time($hh, $mm, $ss, $nn) if (defined $nn);
1447             }
1448 0         0 return $self->{'_RUNT3'};
1449             }
1450              
1451             =head2 data_collection_stop_date()
1452              
1453             Usage : $date = $abif->data_collection_stop_date();
1454             Returns : The Data Collection stop date (yyyy-mm-dd);
1455             undef if the data item is not in the file.
1456             ABIF Tag : RUND4
1457             ABIF Type : date
1458             File Type : ab1, fsa
1459              
1460             =cut
1461              
1462             sub data_collection_stop_date {
1463 0     0 1 0 my $self = shift;
1464 0 0       0 unless (defined $self->{'_RUND4'}) {
1465 0         0 my ($y, $m, $d) = $self->get_data_item('RUND', 4, 'nCC');
1466 0 0       0 if (defined $d) {
1467 0 0       0 $y -= $SHORT_MAX if ($y >= $SHORT_MID);
1468 0         0 $self->{'_RUND4'} = _make_date($y, $m, $d);
1469             }
1470             }
1471 0         0 return $self->{'_RUND4'};
1472             }
1473              
1474             =head2 data_collection_stop_time()
1475              
1476             Usage : $time = $abif->data_collection_stop_time();
1477             Returns : The Data Collection stop time (hh:mm:ss.nn);
1478             undef if the data item is not in the file.
1479             ABIF Tag : RUNT4
1480             ABIF Type : time
1481             File Type : ab1, fsa
1482              
1483             =cut
1484              
1485             sub data_collection_stop_time {
1486 0     0 1 0 my $self = shift;
1487 0 0       0 unless (defined $self->{'_RUNT4'}) {
1488 0         0 my ($hh, $mm, $ss, $nn) = $self->get_data_item('RUNT', 4, 'C4');
1489 0 0       0 $self->{'_RUNT4'} = _make_time($hh, $mm, $ss, $nn) if (defined $nn);
1490             }
1491 0         0 return $self->{'_RUNT4'};
1492             }
1493              
1494             =head2 detector_heater_temperature()
1495              
1496             Usage : $dt = $abif->detector_heater_temperature();
1497             Returns : The detector cell heater temperature in °C;
1498             undef if the data item is not in the file.
1499             ABIF Tag : DCHT1
1500             ABIF Type : short
1501             File Type : ab1
1502              
1503             =cut
1504              
1505             sub detector_heater_temperature {
1506 0     0 1 0 my $self = shift;
1507 0 0       0 unless (defined $self->{'_DCHT1'}) {
1508 0 0       0 ($self->{'_DCHT1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1509             $self->get_data_item('DCHT', 1, 'n');
1510             }
1511 0         0 return $self->{'_DCHT1'};
1512             }
1513              
1514             =head2 downsampling_factor()
1515              
1516             Usage : $df = $abif->downsampling_factor();
1517             Returns : The downsampling factor;
1518             undef if the data item is not in the file.
1519             ABIF Tag : DSam1
1520             ABIF Type : short
1521             File Type : ab1, fsa
1522              
1523             =cut
1524              
1525             sub downsampling_factor {
1526 0     0 1 0 my $self = shift;
1527 0 0       0 unless (defined $self->{'_DSam1'}) {
1528 0 0       0 ($self->{'_DSam1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1529             $self->get_data_item('DSam', 1, 'n');
1530             }
1531 0         0 return $self->{'_DSam1'};
1532             }
1533              
1534             =head2 dye_name()
1535              
1536             Usage : $n = $abif->dye_name($n);
1537             Returns : The name of dye number $n;
1538             undef if the data item is not in the file;
1539             undef if $n is not in the range [1..5].
1540             ABIF Tag : DyeN1, DyeN2, DyeN3, DyeN4, DyeN5
1541             ABIF Type : pString
1542             File Type : ab1, fsa
1543              
1544             Dye 5 name is an optional tag.
1545              
1546             =cut
1547              
1548             sub dye_name {
1549 0     0 1 0 my ($self, $n) = @_;
1550 0         0 my $k = '_DyeN'. $n;
1551 0 0       0 unless (defined $self->{$k}) {
1552 0 0 0     0 if ($n > 0 and $n <= 5) {
1553 0         0 ($self->{$k}) = $self->get_data_item('DyeN', $n, 'xA*');
1554             }
1555             }
1556 0         0 return $self->{$k};
1557             }
1558              
1559             =head2 dye_set_name()
1560              
1561             Usage : $dsn = $abif->dye_set_name();
1562             Returns : The dye set name;
1563             undef if the data item is not in the file.
1564             ABIF Tag : DySN1
1565             ABIF Type : pString
1566             File Type : ab1, fsa
1567              
1568             =cut
1569              
1570             sub dye_set_name {
1571 0     0 1 0 my $self = shift;
1572 0 0       0 unless (defined $self->{'_DySN1'}) {
1573 0         0 ($self->{'_DySN1'}) = $self->get_data_item('DySN', 1, 'xA*');
1574             }
1575 0         0 return $self->{'_DySN1'};
1576             }
1577              
1578             =head2 dye_significance()
1579              
1580             Usage : $dsn = $abif->dye_significance($n);
1581             Returns : The $n-th dye significance;
1582             undef if the data item is not in the file
1583             ABIF Tag : DyeB1, DyeB2, DyeB3, DyeB4, DyeB5
1584             ABIF Type : char
1585             File Type : fsa
1586              
1587             The argument must be an integer from 1 to 5. Dye significance 5 is optional.
1588             The returned value is 'S' for standard, ' ' for sample;
1589              
1590             =cut
1591              
1592             sub dye_significance {
1593 0     0 1 0 my ($self, $n) = @_;
1594 0         0 my $k = '_DyeB' . $n;
1595 0 0       0 unless (defined $self->{$k}) {
1596 0 0 0     0 if ($n > 0 and $n <= 5) {
1597 0         0 ($self->{$k}) = $self->get_data_item('DyeB', $n, 'A');
1598             }
1599             }
1600 0         0 return $self->{$k};
1601             }
1602              
1603             =head2 dye_type()
1604              
1605             Usage : $dsn = $abif->dye_type();
1606             Returns : The dye type;
1607             undef if the data item is not in the file.
1608             ABIF Tag : phDY1
1609             ABIF Type : pString
1610             File Type : ab1
1611              
1612             The dye type is equivalent to DYE in C files.
1613              
1614             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1615              
1616             =cut
1617              
1618             sub dye_type {
1619 0     0 1 0 my $self = shift;
1620 0 0       0 unless (defined $self->{'_phDY1'}) {
1621 0         0 ($self->{'_phDY1'}) = $self->get_data_item('phDY', 1, 'xA*');
1622             }
1623 0         0 return $self->{'_phDY1'};
1624             }
1625              
1626             =head2 dye_wavelength()
1627              
1628             Usage : $n = $abif->dye_wavelength($n);
1629             Returns : The wavelength of dye number $n;
1630             undef if the data item is not in the file;
1631             undef if $n is not in the range [1..5].
1632             ABIF Tag : DyeW1, DyeW2, DyeW3, DyeW4, DyeW5
1633             ABIF Type : short
1634             File Type : ab1, fsa
1635            
1636             Dye 5 wavelength is an optional data item.
1637            
1638             =cut
1639              
1640             sub dye_wavelength {
1641 0     0 1 0 my ($self, $n) = @_;
1642 0         0 my $k = '_DyeW'. $n;
1643 0 0       0 unless (defined $self->{$k}) {
1644 0 0 0     0 if ($n > 0 and $n <= 5) {
1645 0 0       0 ($self->{$k}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
1646             $self->get_data_item('DyeW', $n, 'n');
1647             }
1648             }
1649 0         0 return $self->{$k};
1650             }
1651              
1652             =head2 edited_quality_values()
1653              
1654             Usage : @qv = $abif->edited_quality_values();
1655             Returns : The list of edited quality values;
1656             () if the data item is not in the file.
1657             ABIF Tag : PCON1
1658             ABIF Type : char array
1659             File Type : ab1
1660              
1661             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1662            
1663             =cut
1664              
1665             sub edited_quality_values {
1666 0     0 1 0 my $self = shift;
1667 0 0       0 unless (defined $self->{'_PCON1'}) {
1668 0         0 my @qv = $self->get_data_item('PCON', 1, 'c*');
1669 0 0       0 $self->{'_PCON1'} = (@qv) ? [ @qv ] : [ ];
1670             }
1671 0         0 return @{$self->{'_PCON1'}};
  0         0  
1672             }
1673              
1674             =head2 edited_quality_values_ref()
1675              
1676             Usage : $ref_to_qv = $abif->edited_quality_values_ref();
1677             Returns : A reference to the list of edited quality values;
1678             a reference to the empty list if the data item
1679             is not in the file.
1680             ABIF Tag : PCON1
1681             File Type : ab1
1682              
1683             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1684            
1685             =cut
1686              
1687             sub edited_quality_values_ref {
1688 0     0 1 0 my $self = shift;
1689 0 0       0 unless (defined $self->{'_PCON1'}) {
1690 0         0 my @qv = $self->get_data_item('PCON', 1, 'c*');
1691 0 0       0 $self->{'_PCON1'} = (@qv) ? [ @qv ] : [ ];
1692             }
1693 0         0 return $self->{'_PCON1'};
1694             }
1695              
1696             =head2 edited_sequence()
1697              
1698             Usage : $sequence = edited_sequence();
1699             Returns : The string of the edited basecalled sequence;
1700             undef if the data item is not in the file.
1701             ABIF Tag : PBAS1
1702             ABIF Type : char array
1703             File Type : ab1
1704            
1705             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
1706            
1707             =cut
1708              
1709             sub edited_sequence {
1710 0     0 1 0 my $self = shift;
1711 0 0       0 unless (defined $self->{'_PBAS1'}) {
1712 0         0 ($self->{'_PBAS1'}) = $self->get_data_item('PBAS', 1, 'A*');
1713             }
1714 0         0 return $self->{'_PBAS1'};
1715             }
1716              
1717             =head2 edited_sequence_length()
1718              
1719             Usage : $l = edited_sequence_length();
1720             Returns : The length of the basecalled sequence;
1721             0 if the sequence is not in the file.
1722             File Type : ab1
1723            
1724             =cut
1725              
1726             sub edited_sequence_length() {
1727 0     0 1 0 my $self = shift;
1728 0         0 my $seq = $self->edited_sequence();
1729 0 0       0 return 0 unless defined $seq;
1730 0         0 return length($seq);
1731             }
1732              
1733             =head2 electrophoresis_voltage()
1734              
1735             Usage : $v = $abif->electrophoresis_voltage();
1736             Returns : The electrophoresis voltage setting in volts;
1737             undef if the data item is not found.
1738             ABIF Tag : EPVt1
1739             ABIF Type : long
1740             File Type : ab1, fsa
1741              
1742             =cut
1743              
1744             sub electrophoresis_voltage {
1745 0     0 1 0 my $self = shift;
1746 0 0       0 unless (defined $self->{'_EPVt1'}) {
1747 0 0       0 ($self->{'_EPVt1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
1748             $self->get_data_item('EPVt', 1, 'N');
1749             }
1750 0         0 return $self->{'_EPVt1'};
1751             }
1752              
1753             =head2 gel_type()
1754              
1755             Usage : $s = $abif->gel_type();
1756             Returns : The gel type description;
1757             undef if the data item is not in the file.
1758             ABIF Tag : GTyp1
1759             ABIF Type : pString
1760             File Type : ab1, fsa
1761              
1762             =cut
1763              
1764             sub gel_type {
1765 0     0 1 0 my $self = shift;
1766 0 0       0 unless (defined $self->{'_GTyp1'}) {
1767 0         0 ($self->{'_GTyp1'}) = $self->get_data_item('GTyp', 1, 'xA*');
1768             }
1769 0         0 return $self->{'_GTyp1'};
1770             }
1771              
1772             =head2 gene_mapper_analysis_method()
1773              
1774             Usage : $s = $abif->gene_mapper_analysis_method();
1775             Returns : The GeneMapper(R) software analysis method name;
1776             undef if the data item is not in the file.
1777             ABIF Tag : ANME1
1778             ABIF Type : cString
1779             File Type : fsa
1780              
1781             =cut
1782              
1783             sub gene_mapper_analysis_method {
1784 0     0 1 0 my $self = shift;
1785 0 0       0 unless (defined $self->{'_ANME1'}) {
1786 0         0 ($self->{'_ANME1'}) = $self->get_data_item('ANME', 1, 'Z*');
1787             }
1788 0         0 return $self->{'_ANME1'};
1789             }
1790              
1791             =head2 gene_mapper_panel_name()
1792              
1793             Usage : $s = $abif->gene_mapper_panel_name();
1794             Returns : The GeneMapper(R) software panel name;
1795             undef if the data item is not in the file.
1796             ABIF Tag : PANL1
1797             ABIF Type : cString
1798             File Type : fsa
1799              
1800             =cut
1801              
1802             sub gene_mapper_panel_name {
1803 0     0 1 0 my $self = shift;
1804 0 0       0 unless (defined $self->{'_PANL1'}) {
1805 0         0 ($self->{'_PANL1'}) = $self->get_data_item('PANL', 1, 'Z*');
1806             }
1807 0         0 return $self->{'_PANL1'};
1808             }
1809              
1810             =head2 gene_mapper_sample_type()
1811              
1812             Usage : $s = $abif->gene_mapper_sample_type();
1813             Returns : The GeneMapper(R) software Sample Type;
1814             undef if the data item is not in the file.
1815             ABIF Tag : STYP1
1816             ABIF Type : cString
1817             File Type : fsa
1818              
1819             =cut
1820              
1821             sub gene_mapper_sample_type {
1822 0     0 1 0 my $self = shift;
1823 0 0       0 unless (defined $self->{'_STYP1'}) {
1824 0         0 ($self->{'_STYP1'}) = $self->get_data_item('STYP', 1, 'Z*');
1825             }
1826 0         0 return $self->{'_STYP1'};
1827             }
1828              
1829             =head2 gene_scan_sample_name()
1830              
1831             Usage : $s = $abif->gene_scan_sample_name();
1832             Returns : The sample name for GeneScan(R) sample files;
1833             undef if the data item is not in the file.
1834             ABIF Tag : SpNm1
1835             ABIF Type : pString
1836             File Type : fsa
1837              
1838             =cut
1839              
1840             sub gene_scan_sample_name {
1841 0     0 1 0 my $self = shift;
1842 0 0       0 unless (defined $self->{'_SpNm1'}) {
1843 0         0 ($self->{'_SpNm1'}) = $self->get_data_item('SpNm', 1, 'xA*');
1844             }
1845 0         0 return $self->{'_SpNm1'};
1846             }
1847              
1848             =head2 injection_time()
1849              
1850             Usage : $t = $abif->injection_time();
1851             Returns : The injection time in seconds;
1852             undef if the data item is not in the file.
1853             ABIF Tag : InSc1
1854             ABIF Type : long
1855             File Type : ab1, fsa
1856              
1857             =cut
1858              
1859             sub injection_time {
1860 0     0 1 0 my $self = shift;
1861 0 0       0 unless (defined $self->{'_InSc1'}) {
1862 0 0       0 ($self->{'_InSc1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
1863             $self->get_data_item('InSc', 1, 'N');
1864             }
1865 0         0 return $self->{'_InSc1'};
1866             }
1867              
1868             =head2 injection_voltage()
1869              
1870             Usage : $t = $abif->injection_voltage();
1871             Returns : The injection voltage in volts;
1872             undef if the data item is not in the file
1873             ABIF Tag : InVt1
1874             ABIF Type : long
1875             File Type : ab1, fsa
1876              
1877             =cut
1878              
1879             sub injection_voltage {
1880 0     0 1 0 my $self = shift;
1881 0 0       0 unless (defined $self->{'_InVt1'}) {
1882 0 0       0 ($self->{'_InVt1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
1883             $self->get_data_item('InVt', 1, 'N');
1884             }
1885 0         0 return $self->{'_InVt1'};
1886             }
1887              
1888             =head2 instrument_class()
1889              
1890             Usage : $class = $abif->instrument_class();
1891             Returns : The instrument class;
1892             undef if the data item is not in the file.
1893             ABIF Tag : HCFG1
1894             ABIF Type : cString
1895             File Type : ab1
1896              
1897             =cut
1898              
1899             sub instrument_class {
1900 0     0 1 0 my $self = shift;
1901 0 0       0 unless (defined $self->{'_HCFG1'}) {
1902 0         0 ($self->{'_HCFG1'}) = $self->get_data_item('HCFG', 1, 'Z*');
1903             }
1904 0         0 return $self->{'_HCFG1'};
1905             }
1906              
1907             =head2 instrument_family()
1908              
1909             Usage : $class = $abif->instrument_family();
1910             Returns : The instrument family;
1911             undef if the data item is not in the file.
1912             ABIF Tag : HCFG2
1913             ABIF Type : cString
1914             File Type : ab1
1915              
1916             =cut
1917              
1918             sub instrument_family {
1919 0     0 1 0 my $self = shift;
1920 0 0       0 unless (defined $self->{'_HCFG2'}) {
1921 0         0 ($self->{'_HCFG2'}) = $self->get_data_item('HCFG', 2, 'Z*');
1922             }
1923 0         0 return $self->{'_HCFG2'};
1924             }
1925              
1926             =head2 instrument_name_and_serial_number()
1927              
1928             Usage : $sn = instrument_name_and_serial_number()
1929             Returns : The instrument name and the serial number;
1930             undef if the data item is not in the file.
1931             ABIF Tag : MCHN1
1932             ABIF Type : pString
1933             File Type : ab1, fsa
1934            
1935             =cut
1936              
1937             sub instrument_name_and_serial_number {
1938 0     0 1 0 my $self = shift;
1939 0 0       0 unless (defined $self->{'_MCHN1'}) {
1940 0         0 ($self->{'_MCHN1'}) = $self->get_data_item('MCHN', 1, 'xA*');
1941             }
1942 0         0 return $self->{'_MCHN1'};
1943             }
1944              
1945             =head2 instrument_param()
1946              
1947             Usage : $param = $abif->instrument_param();
1948             Returns : The instrument parameters;
1949             undef if the data item is not in the file.
1950             ABIF Tag : HCFG4
1951             ABIF Type : cString
1952             File Type : ab1
1953              
1954             =cut
1955              
1956             sub instrument_param {
1957 0     0 1 0 my $self = shift;
1958 0 0       0 unless (defined $self->{'_HCFG4'}) {
1959 0         0 ($self->{'_HCFG4'}) = $self->get_data_item('HCFG', 4, 'Z*');
1960             }
1961 0         0 return $self->{'_HCFG4'};
1962             }
1963              
1964             =head2 is_capillary_machine()
1965              
1966             Usage : $bool = $abif->is_capillary_machine();
1967             Returns : A value > 0 if the data item is true;
1968             0 if the data item is false;
1969             undef if the data item is not in the file.
1970             ABIF Tag : CpEP1
1971             ABIF Type : byte
1972             File Type : ab1, fsa
1973              
1974             =cut
1975              
1976             sub is_capillary_machine {
1977 0     0 1 0 my $self = shift;
1978 0 0       0 unless (defined $self->{'_CpEP1'}) {
1979 0         0 ($self->{'_CpEP1'}) = $self->get_data_item('CpEP', 1, 'C');
1980             }
1981 0         0 return $self->{'_CpEP1'};
1982             }
1983              
1984             =head2 laser_power()
1985              
1986             Usage : $n = $abif->laser_power();
1987             Returns : The laser power setting in microwatt;
1988             undef if the data item is not in the file.
1989             ABIF Tag : LsrP1
1990             ABIF Type : long
1991             File Type : ab1, fsa
1992            
1993             =cut
1994              
1995             sub laser_power {
1996 0     0 1 0 my $self = shift;
1997 0 0       0 unless (defined $self->{'_LsrP1'}) {
1998 0 0       0 ($self->{'_LsrP1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
1999             $self->get_data_item('LsrP', 1, 'N');
2000             }
2001 0         0 return $self->{'_LsrP1'};
2002             }
2003              
2004             =head2 length_to_detector()
2005              
2006             Usage : $n = $abif->length_to_detector();
2007             Returns : The length of detector in cm;
2008             undef if the data item is not in the file.
2009             ABIF Tag : LNTD1
2010             ABIF Type : short
2011             File Type : ab1, fsa
2012            
2013             =cut
2014              
2015             sub length_to_detector {
2016 0     0 1 0 my $self = shift;
2017 0 0       0 unless (defined $self->{'_LNTD1'}) {
2018 0 0       0 ($self->{'_LNTD1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2019             $self->get_data_item('LNTD', 1, 'n');
2020             }
2021 0         0 return $self->{'_LNTD1'};
2022             }
2023              
2024             =head2 mobility_file()
2025              
2026             Usage : $mb = $abif->mobility_file()
2027             Returns : The mobility file;
2028             undef if the data item is not in the file.
2029             ABIF Tag : PDMF2
2030             ABIF Type : pString
2031             File Type : ab1
2032            
2033             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2034              
2035             =cut
2036              
2037             sub mobility_file {
2038 0     0 1 0 my $self = shift;
2039 0 0       0 unless (defined $self->{'_PDMF2'}) {
2040 0         0 ($self->{'_PDMF2'}) = $self->get_data_item('PDMF', 2, 'xA*');
2041             }
2042 0         0 return $self->{'_PDMF2'};
2043             }
2044              
2045              
2046             =head2 mobility_file_orig()
2047              
2048             Usage : $mb = $abif->mobility_file_orig()
2049             Returns : The mobility file (orig);
2050             undef if the data item is not in the file.
2051             ABIF Tag : PDMF1
2052             ABIF Type : pString
2053             File Type : ab1
2054            
2055             =cut
2056              
2057             sub mobility_file_orig {
2058 0     0 1 0 my $self = shift;
2059 0 0       0 unless (defined $self->{'_PDMF1'}) {
2060 0         0 ($self->{'_PDMF1'} ) = $self->get_data_item('PDMF', 1, 'xA*');
2061             }
2062 0         0 return $self->{'_PDMF1'};
2063             }
2064              
2065             =head2 model_number()
2066              
2067             Usage : $mn = $abif->model_number();
2068             Returns : The model number;
2069             undef if the data item is not in the file.
2070             ABIF Tag : MODL1
2071             ABIF Type : char[4]
2072             File Type : ab1, fsa
2073            
2074             =cut
2075              
2076             sub model_number {
2077 0     0 1 0 my $self = shift;
2078 0 0       0 unless (defined $self->{'_MODL1'}) {
2079 0         0 ($self->{'_MODL1'}) = $self->get_data_item('MODL', 1, 'A4');
2080             }
2081 0         0 return $self->{'_MODL1'};
2082             }
2083              
2084             =head2 noise()
2085              
2086             Usage : %noise = $abif->noise();
2087             Returns : The estimated noise for each dye;
2088             () if the data item is not in the file.
2089             ABIF Tag : NOIS1
2090             ABIF Type : float array
2091             File Type : ab1
2092              
2093             The keys of the returned hash are the values retrieved with C.
2094             This is an optional data item. This method works only with files containing data
2095             processed by the KB(tm) Basecaller.
2096              
2097             =cut
2098              
2099             sub noise {
2100 0     0 1 0 my $self = shift;
2101 0 0       0 unless (defined $self->{'_NOIS1'}) {
2102 0         0 my %noise = ();
2103 0         0 my ($bits) = $self->get_data_item('NOIS', 1, 'B*');
2104 0 0       0 unless (defined $bits) {
2105 0         0 $self->{'_NOIS1'} = { };
2106             }
2107             else {
2108 0         0 my @bo = $self->base_order();
2109 0         0 for (my $i = 0; $i < length($bits); $i += 32) {
2110             # Convert to float
2111 0         0 $noise{$bo[$i / 32]} = $self->_ieee2decimal(substr($bits, $i, 32));
2112             }
2113 0         0 $self->{'_NOIS1'} = { %noise };
2114             }
2115             }
2116 0         0 return %{$self->{'_NOIS1'}};
  0         0  
2117             }
2118              
2119             =head2 num_capillaries()
2120              
2121             Usage : $nc = $abif->num_capillaries();
2122             Returns : The number of capillaries;
2123             undef if the data item is not in the file.
2124             ABIF Tag : NLNE1
2125             ABIF Type : short
2126             File Type : ab1, fsa
2127            
2128             =cut
2129              
2130             sub num_capillaries {
2131 0     0 1 0 my $self = shift;
2132 0 0       0 unless (defined $self->{'_NLNE1'}) {
2133 0 0       0 ($self->{'_NLNE1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2134             $self->get_data_item('NLNE', 1, 'n');
2135             }
2136 0         0 return $self->{'_NLNE1'};
2137             }
2138              
2139             =head2 num_dyes()
2140              
2141             Usage : $n = $abif->num_dyes();
2142             Returns : The number of dyes;
2143             undef if the data item is not in the file.
2144             ABIF Tag : Dye#1
2145             ABIF Type : short
2146             File Type : ab1, fsa
2147            
2148             =cut
2149              
2150             sub num_dyes {
2151 0     0 1 0 my $self = shift;
2152 0 0       0 unless (defined $self->{'_Dye#1'}) {
2153 0 0       0 ($self->{'_Dye#1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2154             $self->get_data_item('Dye#', 1, 'n');
2155             }
2156 0         0 return $self->{'_Dye#1'};
2157             }
2158              
2159             =head2 num_scans()
2160              
2161             Usage : $n = $abif->num_scans();
2162             Returns : The number of scans;
2163             undef if the data item is not in the file.
2164             ABIF Tag : SCAN1
2165             ABIF Type : long
2166             File Type : ab1, fsa
2167            
2168             =cut
2169              
2170             sub num_scans {
2171 0     0 1 0 my $self = shift;
2172 0 0       0 unless (defined $self->{'_SCAN1'}) {
2173 0 0       0 ($self->{'_SCAN1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
2174             $self->get_data_item('SCAN', 1, 'N');
2175             }
2176 0         0 return $self->{'_SCAN1'};
2177             }
2178              
2179             =head2 official_instrument_name()
2180              
2181             Usage : $name = $abif->official_instrument_name();
2182             Returns : The official instrument name;
2183             undef if the data item is not in the file.
2184             ABIF Tag : HCFG3
2185             ABIF Type : cString
2186             File Type : ab1
2187              
2188             =cut
2189              
2190             sub official_instrument_name {
2191 0     0 1 0 my $self = shift;
2192 0 0       0 unless (defined $self->{'_HCFG3'}) {
2193 0         0 ($self->{'_HCFG3'}) = $self->get_data_item('HCFG', 3, 'Z*');
2194             }
2195 0         0 return $self->{'_HCFG3'};
2196             }
2197              
2198             =head2 offscale_peaks()
2199              
2200             Usage : @bytes = $abif->offscale_peaks($n);
2201             Returns : The range of offscale peaks.
2202             () if the data item is not in the file.
2203             ABIF Tag : OffS1 ... OffS 'N'
2204             ABIF Type : user
2205             File Type : fsa
2206              
2207             This data item's type is a user defined data structure. As such, it is returned
2208             as a list of bytes that must be interpreted by the caller. This is an optional
2209             data item.
2210              
2211             =cut
2212              
2213             sub offscale_peaks {
2214 0     0 1 0 my $self = shift;
2215 0         0 my $n = shift;
2216 0         0 my $t = '_OffS' . $n;
2217 0 0       0 unless (defined $self->{$t}) {
2218 0         0 my (@bytes) = $self->get_data_item('OffS', $n, 'C*');
2219 0 0       0 $self->{$t} = (@bytes) ? [ @bytes ] : [ ];
2220             }\
2221 0         0 return @{$self->{$t}};
  0         0  
2222             }
2223              
2224              
2225             =head2 offscale_scans()
2226              
2227             Usage : @p = $abif->offscale_scans();
2228             Returns : A list of scans.
2229             () if the data item is not in the file.
2230             ABIF Tag : OfSc1
2231             ABIF Type : long array
2232             File Type : ab1, fsa
2233            
2234             Returns the list of scans that are marked off scale in Collection. This is an
2235             optional data item.
2236              
2237             =cut
2238              
2239             sub offscale_scans {
2240 0     0 1 0 my $self = shift;
2241 0 0       0 unless (defined $self->{'_OfSc1'}) {
2242 0 0       0 my @off = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
2243             $self->get_data_item('OfSc', 1, 'N*');
2244 0 0       0 $self->{'_OfSc1'} = (@off) ? [ @off ] : [ ];
2245             }
2246 0         0 return @{$self->{'_OfSc1'}};
  0         0  
2247             }
2248              
2249             =head2 order_base()
2250              
2251             Usage : %bases = $abif->order_base();
2252             Returns : A mapping of the four bases to their channel numbers;
2253             () if the base order is not in the file.
2254             File Type : ab1
2255              
2256             Returns the channel numbers corresponding to the bases.
2257             This method does the opposite as C does.
2258             See also the C method.
2259            
2260             =cut
2261              
2262             sub order_base {
2263 0     0 1 0 my $self = shift;
2264 0 0       0 unless (defined $self->{'_OB'}) {
2265 0         0 my @bo = $self->base_order();
2266 0         0 my %ob = ();
2267 0         0 for (my $i = 0; $i < scalar(@bo); $i++) {
2268 0         0 $ob{$bo[$i]} = $i+1;
2269             }
2270 0         0 $self->{'_OB'} = { %ob };
2271             }
2272 0         0 return %{$self->{'_OB'}};
  0         0  
2273             }
2274              
2275             =head2 peak1_location()
2276              
2277             Usage : $pl = peak1_location();
2278             Returns : The peak 1 location;
2279             undef if the data item is not in the file.
2280             ABIF Tag : B1Pt2
2281             ABIF Type : short
2282             File Type : ab1
2283              
2284             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2285              
2286             =cut
2287              
2288             sub peak1_location {
2289 0     0 1 0 my $self = shift;
2290 0 0       0 unless (defined $self->{'_B1Pt2'}) {
2291 0 0       0 ($self->{'_B1Pt2'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2292             $self->get_data_item('B1Pt', 2, 'n');
2293             }
2294 0         0 return $self->{'_B1Pt2'};
2295             }
2296              
2297             =head2 peak1_location_orig()
2298              
2299             Usage : $pl = peak1_location_orig();
2300             Returns : The peak 1 location (orig);
2301             undef if the data item is not in the file.
2302             ABIF Tag : B1Pt1
2303             ABIF Type : short
2304             File Type : ab1
2305            
2306             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2307              
2308             =cut
2309              
2310             sub peak1_location_orig {
2311 0     0 1 0 my $self = shift;
2312 0 0       0 unless (defined $self->{'_B1Pt1'}) {
2313 0 0       0 ($self->{'_B1Pt1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2314             $self->get_data_item('B1Pt', 1, 'n');
2315             }
2316 0         0 return $self->{'_B1Pt1'};
2317             }
2318              
2319             =head2 peak_area_ratio()
2320              
2321             Usage : $par = $abif->peak_area_ratio();
2322             Returns : The peak area ratio;
2323             undef if the data item is not in the file.
2324             ABIF Tag : phAR1
2325             ABIF Type : float
2326             File Type : ab1
2327              
2328             Returns the peak area ratio (equivalent to TRACE_PEAK_AREA_RATIO in phd1 file).
2329              
2330             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2331            
2332             =cut
2333              
2334             sub peak_area_ratio {
2335 0     0 1 0 my $self = shift;
2336 0 0       0 unless (defined $self->{'_phAR1'}) {
2337 0         0 my $r = undef;
2338 0         0 ($r) = $self->get_data_item('phAR', 1, 'B32');
2339 0 0       0 if (defined $r) {
2340 0         0 $self->{'_phAR1'} = $self->_ieee2decimal($r);
2341             }
2342             }
2343 0         0 return $self->{'_phAR1'};
2344             }
2345              
2346             =head2 peaks()
2347              
2348             Usage : @pks = $abif->peaks(1);
2349             Returns : An array of peak hashes. Each peak hash contains the following attributes:
2350             'position', 'height', 'beginPos', 'endPos', 'beginHI', 'endHI',
2351             'area', 'volume', 'fragSize', 'isEdited', 'label';
2352             () if the data item is not in the file.
2353            
2354             ABIF Tag : PEAK
2355             ABIF Type : user-defined structure
2356             File Type : fsa
2357              
2358             Returns the data associated with PEAK data structures.
2359              
2360             =cut
2361              
2362             sub peaks {
2363 0     0 1 0 my ($self, $n) = @_;
2364 0         0 my $k = '_PEAK' . $n;
2365 0         0 my ($position, $height, $beginPos, $endPos, $beginHI, $endHI, $area, $volume, $fragSize, $isEdited, $label);
2366 0         0 my $s = undef;
2367 0         0 my @raw_data;
2368             my @peak_array;
2369 0         0 my $i;
2370            
2371 0 0       0 unless (defined $self->{$k}) {
2372 0         0 @raw_data = $self->get_data_item('PEAK', $n, '(NnNNnnNNB32nZ64)*');
2373 0         0 for ($i = 0; $i < @raw_data; $i += 11) {
2374 0         0 ($position, $height, $beginPos, $endPos, $beginHI, $endHI, $area, $volume, $s, $isEdited, $label) = @raw_data[$i .. $i+10];
2375 0 0       0 $fragSize = $self->_ieee2decimal($s) if (defined $s);
2376 0         0 my $peak = {};
2377 0         0 $peak->{position} = $position;
2378 0         0 $peak->{height} = $height;
2379 0         0 $peak->{beginPos} = $beginPos;
2380 0         0 $peak->{endPos} = $endPos;
2381 0         0 $peak->{beginHI} = $beginHI;
2382 0         0 $peak->{endHI} = $endHI;
2383 0         0 $peak->{area} = $area;
2384 0         0 $peak->{volume} = $volume;
2385 0         0 $peak->{fragSize} = $fragSize;
2386 0         0 $peak->{isEdited} = $isEdited;
2387 0         0 $peak->{label} = $label;
2388 0         0 push @peak_array, $peak;
2389             }
2390 0 0       0 $self->{$k} = (@peak_array) ? [ @peak_array ] : [ ];
2391             }
2392 0         0 return @{$self->{$k}};
  0         0  
2393             }
2394              
2395             =head2 pixel_bin_size()
2396              
2397             Usage : $n = $abif->pixel_bin_size();
2398             Returns : The pixel bin size;
2399             undef if the data item is not in the file.
2400             ABIF Tag : PXLB1
2401             ABIF Type : long
2402             File Type : ab1, fsa
2403            
2404             =cut
2405              
2406             sub pixel_bin_size {
2407 0     0 1 0 my $self = shift;
2408 0 0       0 unless (defined $self->{'_PXLB1'}) {
2409 0 0       0 ($self->{'_PXLB1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
2410             $self->get_data_item('PXLB', 1, 'N');
2411             }
2412 0         0 return $self->{'_PXLB1'};
2413             }
2414              
2415             =head2 pixels_lane()
2416              
2417             Usage : $n = $abif->pixels_lane();
2418             Returns : The pixels averaged per lane;
2419             undef if the data item is not in the file.
2420             ABIF Tag : NAVG1
2421             ABIF Type : short
2422             File Type : ab1, fsa
2423            
2424             =cut
2425              
2426             sub pixels_lane {
2427 0     0 1 0 my $self = shift;
2428 0 0       0 unless (defined $self->{'_NAVG1'}) {
2429 0 0       0 ($self->{'_NAVG1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2430             $self->get_data_item('NAVG', 1, 'n');
2431             }
2432 0         0 return $self->{'_NAVG1'};
2433             }
2434              
2435             =head2 plate_type()
2436              
2437             Usage : $s = $abif->plate_type();
2438             Returns : The plate type;
2439             undef if the data item is not in the file.
2440             ABIF Tag : PTYP1
2441             ABIF Type : cString
2442             File Type : ab1, fsa
2443            
2444             Returns the plate type. Allowed values are 96-Well, 384-Well;
2445            
2446             =cut
2447              
2448             sub plate_type {
2449 0     0 1 0 my $self = shift;
2450 0 0       0 unless (defined $self->{'_PTYP1'}) {
2451 0         0 ($self->{'_PTYP1'}) = $self->get_data_item('PTYP', 1, 'Z*');
2452             }
2453 0         0 return $self->{'_PTYP1'};
2454             }
2455              
2456             =head2 plate_size()
2457              
2458             Usage : $n = $abif->plate_size();
2459             Returns : The plate size.
2460             undef if the data item is not in the file.
2461             ABIF Tag : PSZE1
2462             ABIF Type : long
2463             File Type : ab1, fsa
2464            
2465             Returns the number of sample positions in the container (allowed values are 96
2466             and 384);
2467            
2468             =cut
2469              
2470             sub plate_size {
2471 0     0 1 0 my $self = shift;
2472 0 0       0 unless (defined $self->{'_PSZE1'}) {
2473 0 0       0 ($self->{'_PSZE1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
2474             $self->get_data_item('PSZE', 1, 'N');
2475             }
2476 0         0 return $self->{'_PSZE1'};
2477             }
2478              
2479             =head2 polymer_expiration_date()
2480              
2481             Usage : $s = $abif->polymer_expiration_date()
2482             Returns : The polymer lot expiration date;
2483             undef if the data item is not in the file.
2484             ABIF Tag : SMED1
2485             ABIF Type : pString
2486             File Type : ab1, fsa
2487            
2488             The format of the date is implementation dependent.
2489              
2490             =cut
2491              
2492             sub polymer_expiration_date {
2493 0     0 1 0 my $self = shift;
2494 0 0       0 unless (defined $self->{'_SMED1'}) {
2495 0         0 ($self->{'_SMED1'}) = $self->get_data_item('SMED', 1, 'xA*');
2496             }
2497 0         0 return $self->{'_SMED1'};
2498             }
2499              
2500             =head2 polymer_lot_number()
2501              
2502             Usage : $s = $abif->polymer_lot_number();
2503             Returns : A string containing the polymer lot number;
2504             undef if the data item is not in the file.
2505             ABIF Tag : SMLt1
2506             ABIF Type : pString
2507             File Type : ab1, fsa
2508            
2509             The format of the date is implementation dependent.
2510              
2511             =cut
2512              
2513             sub polymer_lot_number {
2514 0     0 1 0 my $self = shift;
2515 0 0       0 unless (defined $self->{'_SMLt1'}) {
2516 0         0 ($self->{'_SMLt1'}) = $self->get_data_item('SMLt', 1, 'xA*');
2517             }
2518 0         0 return $self->{'_SMLt1'};
2519             }
2520              
2521             =head2 power()
2522              
2523             Usage : @p = $abif->power();
2524             Returns : The power, measured in milliwatts;
2525             () if the data item is not in the file.
2526             ABIF Tag : DATA7
2527             ABIF Type : short array
2528             File Type : ab1, fsa
2529            
2530             =cut
2531              
2532             sub power {
2533 0     0 1 0 my $self = shift;
2534 0 0       0 unless (defined $self->{'_DATA7'}) {
2535 0 0       0 my @p = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2536             $self->get_data_item('DATA', 7, 'n*');
2537 0 0       0 $self->{'_DATA7'} = (@p) ? [ @p ] : [ ];
2538             }
2539 0         0 return @{$self->{'_DATA7'}};
  0         0  
2540             }
2541              
2542             =head2 quality_levels()
2543              
2544             Usage : $n = $abif->quality_levels();
2545             Returns : The maximum quality value;
2546             undef if the data item is not in the file.
2547             ABIF Tag : phQL1
2548             ABIF Type : short
2549             File Type : ab1
2550              
2551             Returns the maximum quality value (equivalent to QUALITY_LEVELS in phd1 file).
2552              
2553             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2554            
2555             =cut
2556              
2557             sub quality_levels {
2558 0     0 1 0 my $self = shift;
2559 0 0       0 unless (defined $self->{'_phQL1'}) {
2560 0 0       0 ($self->{'_phQL1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2561             $self->get_data_item('phQL', 1, 'n');
2562             }
2563 0         0 return $self->{'_phQL1'};
2564             }
2565              
2566              
2567             =head2 quality_values()
2568              
2569             Usage : @qv = $abif->quality_values();
2570             Returns : The list of quality values;
2571             () if the data item is not in the file.
2572             ABIF Tag : PCON2
2573             ABIF Type : char array
2574             File Type : ab1
2575              
2576             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2577              
2578             =cut
2579              
2580             sub quality_values {
2581 0     0 1 0 my $self = shift;
2582 0 0       0 unless (defined $self->{'_PCON2'}) {
2583             # Load and cache quality values
2584 0         0 my @qv = $self->get_data_item('PCON', 2, 'c*');
2585 0 0       0 $self->{'_PCON2'} = (@qv) ? [ @qv ] : [ ];
2586             }
2587 0         0 return @{$self->{'_PCON2'}};
  0         0  
2588             }
2589              
2590             =head2 quality_values_ref()
2591              
2592             Usage : $qvref = $abif->quality_values_ref();
2593             Returns : A reference to the list of quality values;
2594             a reference to the empty list if
2595             the data item is not in the file.
2596             ABIF Tag : PCON2
2597             ABIF Type : char array
2598             File Type : ab1
2599              
2600             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
2601              
2602             =cut
2603              
2604             sub quality_values_ref {
2605 0     0 1 0 my $self = shift;
2606 0 0       0 unless (defined $self->{'_PCON2'}) {
2607             # Load and cache quality values
2608 0         0 my @qv = $self->get_data_item('PCON', 2, 'c*');
2609 0 0       0 $self->{'_PCON2'} = (@qv) ? [ @qv ] : [ ];
2610             }
2611 0         0 return $self->{'_PCON2'};
2612             }
2613              
2614             =head2 raw_data_for_channel()
2615              
2616             Usage : @data = $abif->raw_data_for_channel($channel_number);
2617             Returns : The channel $channel_number raw data;
2618             () if the data item is not in the file.
2619             ABIF Tag : DATA1, DATA2, DATA3, DATA4, DATA105
2620             ABIF Type : short array
2621             File Type : ab1, fsa
2622            
2623             There are four channels in an ABIF file, numbered from 1 to 4.
2624             An optional channel number 5 exists in some files.
2625              
2626             =cut
2627              
2628             sub raw_data_for_channel {
2629 0     0 1 0 my ($self, $channel_number) = @_;
2630 0 0       0 if ($channel_number == 5) {
2631 0         0 $channel_number = 105;
2632             }
2633 0 0 0     0 if ($channel_number < 1 or
      0        
2634             ($channel_number > 5 and $channel_number != 105)) {
2635 0         0 return ();
2636             }
2637 0         0 my $k = '_DATA' . $channel_number;
2638 0 0       0 unless (defined $self->{$k}) {
2639 0 0       0 my @data = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2640             $self->get_data_item('DATA', $channel_number, 'n*');
2641 0 0       0 $self->{$k} = (@data) ? [ @data ] : [ ];
2642             }
2643              
2644 0         0 return @{$self->{$k}};
  0         0  
2645             }
2646              
2647             =head2 raw_trace()
2648              
2649             Usage : @trace = $abif->raw_trace($base);
2650             Returns : The raw trace corresponding to $base;
2651             () if the data item is not in the file.
2652             File Type : ab1
2653            
2654             The possible values for C<$base> are 'A', 'C', 'G' and 'T' (case insensitive).
2655              
2656             =cut
2657              
2658             sub raw_trace {
2659 0     0 1 0 my ($self, $base) = @_;
2660 0         0 my %ob = ();
2661            
2662 0 0       0 $base =~ /^[ACGTacgt]$/ or return ();
2663 0         0 %ob = $self->order_base();
2664 0         0 return $self->raw_data_for_channel($ob{uc($base)});
2665             }
2666              
2667             =head2 rescaling()
2668              
2669             Usage : $name = $abif->rescaling();
2670             Returns : The rescaling divisor for color data;
2671             undef if the data item is not in the file.
2672             ABIF Tag : Scal1
2673             ABIF Type : float
2674             File Type : ab1, fsa
2675            
2676             =cut
2677              
2678             sub rescaling {
2679 0     0 1 0 my $self = shift;
2680 0 0       0 unless (defined $self->{'_Scal1'}) {
2681 0         0 my $r = undef;
2682 0         0 ($r) = $self->get_data_item('Scal', 1, 'B32');
2683 0 0       0 if (defined $r) {
2684 0         0 $self->{'_Scal1'} = $self->_ieee2decimal($r);
2685             }
2686             }
2687 0         0 return $self->{'_Scal1'};
2688             }
2689              
2690             =head2 results_group()
2691              
2692             Usage : $name = $abif->results_group();
2693             Returns : The results group name;
2694             undef if the data item is not in the file.
2695             ABIF Tag : RGNm1
2696             ABIF Type : cString
2697             File Type : ab1, fsa
2698            
2699             =cut
2700              
2701             sub results_group {
2702 0     0 1 0 my $self = shift;
2703 0 0       0 unless (defined $self->{'_RGNm1'}) {
2704 0         0 ($self->{'_RGNm1'}) = $self->get_data_item('RGNm', 1, 'Z*');
2705             }
2706 0         0 return $self->{'_RGNm1'};
2707             }
2708              
2709             =head2 results_group_comment()
2710              
2711             Usage : $s = $abif->results_group_comment();
2712             Returns : The results group comment;
2713             undef if the data item is not in the file.
2714             ABIF Tag : RGCm1
2715             ABIF Type : cString
2716             File Type : ab1, fsa
2717            
2718             This is an optional data item.
2719            
2720             =cut
2721              
2722             sub results_group_comment {
2723 0     0 1 0 my $self = shift;
2724 0 0       0 unless (defined $self->{'_RGCm1'}) {
2725 0         0 ($self->{'_RGCm1'}) = $self->get_data_item('RGCm', 1, 'Z*');
2726             }
2727 0         0 return $self->{'_RGCm1'};
2728             }
2729              
2730             =head2 results_group_owner()
2731              
2732             Usage : $s = $abif->results_group_owner();
2733             Returns : The results group owner;
2734             undef if the data item is not in the file.
2735             ABIF Tag : RGOw1
2736             ABIF Type : cString
2737             File Type : ab1
2738            
2739             Returns the name entered as the owner of the results group, in the Results Group
2740             editor. This is an optional data item.
2741            
2742             =cut
2743              
2744             sub results_group_owner {
2745 0     0 1 0 my $self = shift;
2746 0 0       0 unless (defined $self->{'_RGOw1'}) {
2747 0         0 ($self->{'_RGOw1'}) = $self->get_data_item('RGOw', 1, 'Z*');
2748             }
2749 0         0 return $self->{'_RGOw1'};
2750             }
2751              
2752             =head2 reverse_complement_flag()
2753              
2754             Usage : $n = $abif->reverse_complement_flag();
2755             Returns : The reverse complement flag;
2756             undef if the data item is not in the file.
2757             ABIF Tag : RevC1
2758             ABIF Type : short
2759             File Type : ab1
2760              
2761             This data item is from Sequencing Analysis v5.2 Software.
2762              
2763             =cut
2764              
2765             sub reverse_complement_flag {
2766 0     0 1 0 my $self = shift;
2767 0 0       0 unless (defined $self->{'_RevC1'}) {
2768 0 0       0 ($self->{'_RevC1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
2769             $self->get_data_item('RevC', 1, 'n');
2770             }
2771 0         0 return $self->{'_RevC1'};
2772             }
2773              
2774             =head2 run_module_name()
2775              
2776             Usage : $name = $abif->run_module_name();
2777             Returns : The run module name;
2778             undef if the data item is not in the file.
2779             ABIF Tag : RMdN1
2780             ABIF Type : cString
2781             File Type : ab1, fsa
2782            
2783             This should be the same as the value returned by C.
2784            
2785             =cut
2786              
2787             sub run_module_name {
2788 0     0 1 0 my $self = shift;
2789 0 0       0 unless (defined $self->{'_RMdN1'}) {
2790 0         0 ($self->{'_RMdN1'}) = $self->get_data_item('RMdN', 1, 'Z*');
2791             }
2792 0         0 return $self->{'_RMdN1'};
2793             }
2794              
2795             =head2 run_module_version()
2796              
2797             Usage : $name = $abif->run_module_version();
2798             Returns : The run module version;
2799             undef if the data item is not in the file.
2800             ABIF Tag : RMdV1
2801             ABIF Type : cString
2802             File Type : ab1, fsa
2803              
2804             =cut
2805              
2806             sub run_module_version {
2807 0     0 1 0 my $self = shift;
2808 0 0       0 unless (defined $self->{'_RMdV1'}) {
2809 0         0 ($self->{'_RMdV1'}) = $self->get_data_item('RMdV', 1, 'Z*');
2810             }
2811 0         0 return $self->{'_RMdV1'};
2812             }
2813              
2814             =head2 run_module_xml_schema_version()
2815              
2816             Usage : $vers = $abif->run_module_xml_schema_version();
2817             Returns : The run module XML schema version;
2818             undef if the data item is not in the file.
2819             ABIF Tag : RMXV1
2820             ABIF Type : cString
2821             File Type : ab1, fsa
2822            
2823             =cut
2824              
2825             sub run_module_xml_schema_version {
2826 0     0 1 0 my $self = shift;
2827 0 0       0 unless (defined $self->{'_RMXV1'}) {
2828 0         0 ($self->{'_RMXV1'}) = $self->get_data_item('RMXV', 1, 'Z*');
2829             }
2830 0         0 return $self->{'_RMXV1'};
2831             }
2832              
2833             =head2 run_module_xml_string()
2834              
2835             Usage : $xml = $abif->run_module_xml_string();
2836             Returns : The run module XML string;
2837             undef if the data item is not in the file.
2838             ABIF Tag : RMdX1
2839             ABIF Type : char array
2840             File Type : ab1, fsa
2841            
2842             =cut
2843              
2844             sub run_module_xml_string {
2845 0     0 1 0 my $self = shift;
2846 0 0       0 unless (defined $self->{'_RMdX1'}) {
2847 0         0 ($self->{'_RMdX1'}) = $self->get_data_item('RMdX', 1, 'A*');
2848             }
2849 0         0 return $self->{'_RMdX1'};
2850             }
2851              
2852             =head2 run_name()
2853              
2854             Usage : $name = $abif->run_name();
2855             Returns : The run name;
2856             undef if the data item is not in the file.
2857             ABIF Tag : RunN1
2858             ABIF Type : cString
2859             File Type : ab1, fsa
2860              
2861             =cut
2862              
2863             sub run_name {
2864 0     0 1 0 my $self = shift;
2865 0 0       0 unless (defined $self->{'_RunN1'}) {
2866 0         0 ($self->{'_RunN1'}) = $self->get_data_item('RunN', 1, 'Z*');
2867             }
2868 0         0 return $self->{'_RunN1'};
2869             }
2870              
2871             =head2 run_protocol_name()
2872              
2873             Usage : $xml = $abif->run_protocol_name();
2874             Returns : The run protocol name;
2875             undef if the data item is not in the file.
2876             ABIF Tag : RPrN1
2877             ABIF Type : cString
2878             File Type : ab1, fsa
2879            
2880             =cut
2881              
2882             sub run_protocol_name {
2883 0     0 1 0 my $self = shift;
2884 0 0       0 unless (defined $self->{'_RPrN1'}) {
2885 0         0 ($self->{'_RPrN1'}) = $self->get_data_item('RPrN', 1, 'Z*');
2886             }
2887 0         0 return $self->{'_RPrN1'};
2888             }
2889              
2890             =head2 run_protocol_version()
2891              
2892             Usage : $vers = $abif->run_protocol_version();
2893             Returns : The run protocol version;
2894             undef if the data item is not in the file.
2895             ABIF Tag : RPrV1
2896             ABIF Type : cString
2897             File Type : ab1, fsa
2898            
2899             =cut
2900              
2901             sub run_protocol_version {
2902 0     0 1 0 my $self = shift;
2903 0 0       0 unless (defined $self->{'_RPrV1'}) {
2904 0         0 ($self->{'_RPrV1'}) = $self->get_data_item('RPrV', 1, 'Z*');
2905             }
2906 0         0 return $self->{'_RPrV1'};
2907             }
2908              
2909             =head2 run_start_date()
2910              
2911             Usage : $date = $abif->run_start_date();
2912             Returns : The run start date (yyyy-mm-dd);
2913             undef if the data item is not in the file.
2914             ABIF Tag : RUND1
2915             ABIF Type : date
2916             File Type : ab1, fsa
2917              
2918             =cut
2919              
2920             sub run_start_date {
2921 0     0 1 0 my $self = shift;
2922 0 0       0 unless (defined $self->{'_RUND1'}) {
2923 0         0 my ($y, $m, $d) = $self->get_data_item('RUND', 1, 'nCC');
2924 0 0       0 if (defined $d) {
2925 0 0       0 $y -= $SHORT_MAX if ($y >= $SHORT_MID);
2926 0         0 $self->{'_RUND1'} = _make_date($y, $m, $d);
2927             }
2928             }
2929 0         0 return $self->{'_RUND1'};
2930             }
2931              
2932             =head2 run_start_time()
2933              
2934             Usage : $time = $abif->run_start_time();
2935             Returns : The run start time (hh:mm:ss.nn);
2936             undef if the data item is not in the file.
2937             ABIF Tag : RUNT1
2938             ABIF Type : time
2939             File Type : ab1, fsa
2940              
2941             =cut
2942              
2943             sub run_start_time {
2944 0     0 1 0 my $self = shift;
2945 0 0       0 unless (defined $self->{'_RUNT1'}) {
2946 0         0 my ($hh, $mm, $ss, $nn) = $self->get_data_item('RUNT', 1, 'C4');
2947 0 0       0 $self->{'_RUNT1'} = _make_time($hh, $mm, $ss, $nn) if (defined $nn);
2948             }
2949 0         0 return $self->{'_RUNT1'};
2950             }
2951              
2952             =head2 run_stop_date()
2953              
2954             Usage : $date = $abif->run_stop_date();
2955             Returns : The run stop date (yyyy-mm-dd);
2956             undef if the data item is not in the file.
2957             ABIF Tag : RUND2
2958             ABIF Type : date
2959             File Type : ab1, fsa
2960              
2961             =cut
2962              
2963             sub run_stop_date {
2964 0     0 1 0 my $self = shift;
2965 0 0       0 unless (defined $self->{'_RUND2'}) {
2966 0         0 my ($y, $m, $d) = $self->get_data_item('RUND', 2, 'nCC');
2967 0 0       0 if (defined $d) {
2968 0 0       0 $y -= $SHORT_MAX if ($y >= $SHORT_MID);
2969 0         0 $self->{'_RUND2'} = _make_date($y, $m, $d);
2970             }
2971             }
2972 0         0 return $self->{'_RUND2'};
2973             }
2974              
2975             =head2 run_stop_time()
2976              
2977             Usage : $time = $abif->run_stop_time();
2978             Returns : The run stop time (hh:mm:ss.nn);
2979             undef if the data item is not in the file.
2980             ABIF Tag : RUNT2
2981             ABIF Type : time
2982             File Type : ab1, fsa
2983              
2984             =cut
2985              
2986             sub run_stop_time {
2987 0     0 1 0 my $self = shift;
2988 0 0       0 unless (defined $self->{'_RUNT2'}) {
2989 0         0 my ($hh, $mm, $ss, $nn) = $self->get_data_item('RUNT', 2, 'C4');
2990 0 0       0 $self->{'_RUNT2'} = _make_time($hh, $mm, $ss, $nn) if (defined $nn);
2991             }
2992 0         0 return $self->{'_RUNT2'};
2993             }
2994              
2995             =head2 run_temperature()
2996              
2997             Usage : $temp = $abif->run_temperature();
2998             Returns : The run temperature setting in °C;
2999             undef if the data item is not in the file.
3000             ABIF Tag : Tmpr1
3001             ABIF Type : long
3002             File Type : ab1, fsa
3003            
3004             =cut
3005              
3006             sub run_temperature {
3007 0     0 1 0 my $self = shift;
3008 0 0       0 unless (defined $self->{'_Tmpr1'}) {
3009 0 0       0 ($self->{'_Tmpr1'}) = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
3010             $self->get_data_item('Tmpr', 1, 'N');
3011             }
3012 0         0 return $self->{'_Tmpr1'};
3013             }
3014              
3015             =head2 sample_file_format_version()
3016              
3017             Usage : $v = $abif->sample_file_format_version();
3018             Returns : The Sample File Format Version;
3019             undef if the data item is not in the file.
3020             ABIF Tag : SVER4
3021             ABIF Type : pString
3022             File Type : fsa
3023            
3024             The Sample File Format Version contains the version of the sample file format
3025             used to write the file.
3026              
3027             =cut
3028              
3029             sub sample_file_format_version {
3030 0     0 1 0 my $self = shift;
3031 0 0       0 unless (defined $self->{'_SVER4'}) {
3032 0         0 ($self->{'_SVER4'}) = $self->get_data_item('SVER', 4, 'xA*');
3033             }
3034 0         0 return $self->{'_SVER4'};
3035             }
3036              
3037             =head2 sample_name()
3038              
3039             Usage : $name = $abif->sample_name();
3040             Returns : The sample name;
3041             undef if the data item is not in the file.
3042             ABIF Tag : SMPL1
3043             ABIF Type : pString
3044             File Type : ab1
3045            
3046             =cut
3047              
3048             sub sample_name {
3049 0     0 1 0 my $self = shift;
3050 0 0       0 unless (defined $self->{'_SMPL1'}) {
3051 0         0 ($self->{'_SMPL1'}) = $self->get_data_item('SMPL', 1, 'xA*');
3052             }
3053 0         0 return $self->{'_SMPL1'};
3054             }
3055              
3056             =head2 sample_tracking_id()
3057              
3058             Usage : $sample_id = $abif->sample_tracking_id();
3059             Returns : The sample tracking ID;
3060             undef if the data item is not in the file.
3061             ABIF Tag : LIMS1
3062             ABIF Type : pString
3063             File Type : ab1, fsa
3064            
3065             =cut
3066              
3067             sub sample_tracking_id {
3068 0     0 1 0 my $self = shift;
3069 0 0       0 unless (defined $self->{'_LIMS1'}) {
3070 0         0 ($self->{'_LIMS1'}) = $self->get_data_item('LIMS', 1, 'xA*');
3071             }
3072 0         0 return $self->{'_LIMS1'};
3073             }
3074              
3075             =head2 scanning_rate()
3076              
3077             Usage : @bytes = $abif->scanning_rate();
3078             Returns : The scanning rate;
3079             () if the data item is not in the file.
3080             ABIF Tag : Rate1
3081             ABIF Type : user
3082             File Type : ab1, fsa
3083              
3084             This data item's type is a user defined data structure. As such, it is returned
3085             as a list of bytes that must be interpreted by the caller.
3086              
3087             =cut
3088              
3089             sub scanning_rate {
3090 0     0 1 0 my $self = shift;
3091 0 0       0 unless (defined $self->{'_Rate1'}) {
3092 0         0 my (@bytes) = $self->get_data_item('Rate', 1, 'C*');
3093 0 0       0 $self->{'_Rate1'} = (@bytes) ? [ @bytes ] : [ ];
3094             }
3095 0         0 return @{$self->{'_Rate1'}};
  0         0  
3096             }
3097              
3098             =head2 scan_color_data_values()
3099              
3100             Usage : @C = $abif->scan_color_data_values($n);
3101             Returns : A list of color data values;
3102             () if the data item is not in the file.
3103             ABIF Tag : OvrV1 ... OvrV 'N'
3104             ABIF Type : long array
3105             File Type : ab1, fsa
3106            
3107             Returns the list of color data values for the locations listed by
3108             C. This is an optional data item.
3109              
3110             =cut
3111              
3112             sub scan_color_data_values {
3113 0     0 1 0 my ($self, $n) = @_;
3114 0         0 my $k = '_OvrV' . $n;
3115 0 0       0 unless (defined $self->{$k}) {
3116 0 0       0 my @C = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
3117             $self->get_data_item('OvrV', $n, 'N*');
3118 0 0       0 $self->{$k} = (@C) ? [ @C ] : [ ];
3119             }
3120 0         0 return @{$self->{$k}};
  0         0  
3121             }
3122              
3123             =head2 scan_numbers()
3124              
3125             Usage : @N = $abif->scan_numbers();
3126             Returns : The scan numbers of data points;
3127             () if the data item is not in the file.
3128             ABIF Tag : Satd1
3129             ABIF Type : long array
3130             File Type : ab1, fsa
3131              
3132             Returns an array of integers representing the scan numbers of data points,
3133             which are flagged as saturated by data collection;
3134              
3135             This is an optional data item.
3136              
3137             =cut
3138              
3139             sub scan_numbers {
3140 0     0 1 0 my $self = shift;
3141 0 0       0 unless (defined $self->{'_Satd1'}) {
3142 0 0       0 my @N = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
3143             $self->get_data_item('Satd', 1, 'N*');
3144 0 0       0 $self->{'_Satd1'} = (@N) ? [ @N ] : [ ];
3145             }
3146 0         0 return @{$self->{'_Satd1'}};
  0         0  
3147             }
3148              
3149             =head2 scan_number_indices()
3150              
3151             Usage : @I = $abif->scan_number_indices($n);
3152             Returns : A list of scan number indices;
3153             () if the data item is not in the file.
3154             ABIF Tag : OvrI1 ... OvrI 'N'
3155             ABIF Type : long array
3156             File Type : ab1, fsa
3157              
3158             Returns the list of scan number indices for scans with color data value greater
3159             than 32767.
3160              
3161             This is an optional data item.
3162              
3163             =cut
3164              
3165             sub scan_number_indices {
3166 0     0 1 0 my ($self, $n) = @_;
3167 0         0 my $k = '_OvrI' . $n;
3168 0 0       0 unless (defined $self->{$k}) {
3169 0 0       0 my @I = map { ($_ < $LONG_MID) ? $_ : $_ - $LONG_MAX }
  0         0  
3170             $self->get_data_item('OvrI', $n, 'N*');
3171 0 0       0 $self->{$k} = (@I) ? [ @I ] : [ ];
3172             }
3173 0         0 return @{$self->{$k}};
  0         0  
3174             }
3175              
3176             =head2 seqscape_project_name()
3177              
3178             Usage : $name = $abif->seqscape_project_name();
3179             Returns : SeqScape(R) project name;
3180             undef if the data item is not in the file.
3181             ABIF Tag : PROJ4
3182             ABIF Type : cString
3183             File Type : ab1
3184            
3185             This data item is in SeqScape(R) software sample files only. This is an optional
3186             data item.
3187            
3188             =cut
3189              
3190             sub seqscape_project_name {
3191 0     0 1 0 my $self = shift;
3192 0 0       0 unless (defined $self->{'_PROJ4'}) {
3193 0         0 ($self->{'_PROJ4'}) = $self->get_data_item('PROJ', 4, 'Z*');
3194             }
3195 0         0 return $self->{'_PROJ4'};
3196             }
3197              
3198             =head2 seqscape_project_template()
3199              
3200             Usage : name = $abif->seqscape_project_template();
3201             Returns : SeqScape(R) project template name;
3202             undef if the data item is not in the file.
3203             ABIF Tag : PRJT1
3204             ABIF Type : cString
3205             File Type : ab1
3206            
3207             This data item is in SeqScape(R) software sample files only. This is an optional
3208             data item.
3209            
3210             =cut
3211              
3212             sub seqscape_project_template {
3213 0     0 1 0 my $self = shift;
3214 0 0       0 unless (defined $self->{'_PRJT1'}) {
3215 0         0 ($self->{'_PRJT1'}) = $self->get_data_item('PRJT', 1, 'Z*');
3216             }
3217 0         0 return $self->{'_PRJT1'};
3218             }
3219              
3220             =head2 seqscape_specimen_name()
3221              
3222             Usage : $name = $abif->seqscape_specimen_name();
3223             Returns : SeqScape(R) specimen name;
3224             undef if the data item is not in the file.
3225             ABIF Tag : SPEC1
3226             ABIF Type : cString
3227             File Type : ab1
3228            
3229             This data item is in SeqScape(R) software sample files only. This is an optional
3230             data item.
3231            
3232             =cut
3233              
3234             sub seqscape_specimen_name {
3235 0     0 1 0 my $self = shift;
3236 0 0       0 unless (defined $self->{'_SPEC1'}) {
3237 0         0 ($self->{'_SPEC1'}) = $self->get_data_item('SPEC', 1, 'Z*');
3238             }
3239 0         0 return $self->{'_SPEC1'};
3240             }
3241              
3242             =head2 sequence()
3243              
3244             Usage : $sequence = sequence();
3245             Returns : The basecalled sequence;
3246             undef if the data item is not in the file.
3247             ABIF Tag : PBAS2
3248             ABIF Type : char array
3249             File Type : ab1
3250            
3251             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3252            
3253             =cut
3254              
3255             sub sequence {
3256 0     0 1 0 my $self = shift;
3257 0 0       0 unless (defined $self->{'_PBAS2'}) {
3258 0         0 ($self->{'_PBAS2'}) = $self->get_data_item('PBAS', 2, 'A*');
3259             }
3260 0         0 return $self->{'_PBAS2'};
3261             }
3262              
3263             =head2 sequence_length()
3264              
3265             Usage : $l = sequence_length();
3266             Returns : The length of the base called sequence;
3267             0 if the sequence is not in the file.
3268             File Type : ab1
3269            
3270             =cut
3271              
3272             sub sequence_length() {
3273 0     0 1 0 my $self = shift;
3274 0         0 my $seq = $self->sequence();
3275 0 0       0 return 0 unless defined $seq;
3276 0         0 return length($seq);
3277             }
3278              
3279             =head2 sequencing_analysis_param_filename()
3280              
3281             Usage : $f = sequencing_analysis_param_filename();
3282             Returns : The Sequencing Analysis parameters filename;
3283             undef if the data item is not in the file.
3284             ABIF Tag : APFN2
3285             ABIF Type : pString
3286             File Type : ab1
3287            
3288             =cut
3289              
3290             sub sequencing_analysis_param_filename {
3291 0     0 1 0 my $self = shift;
3292 0 0       0 unless (defined $self->{'_APFN2'}) {
3293 0         0 ($self->{'_APFN2'}) = $self->get_data_item('APFN', 2, 'xA*');
3294             }
3295 0         0 return $self->{'_APFN2'};
3296             }
3297              
3298             =head2 signal_level()
3299              
3300             Usage : %signal_level = $abif->signal_level();
3301             Returns : The signal level for each dye;
3302             () if the data item is not in the file.
3303             ABIF Tag : S/N%1
3304             ABIF Type : short array
3305             File Type : ab1
3306            
3307             The keys of the returned hash are the values retrieved with C.
3308              
3309             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3310              
3311             =cut
3312              
3313             sub signal_level {
3314 0     0 1 0 my $self = shift;
3315 0 0       0 unless (defined $self->{'_S/N%1'}) {
3316 0 0       0 my @sl = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3317             $self->get_data_item('S/N%', 1, 'n*');
3318 0 0       0 unless (@sl) {
3319 0         0 $self->{'_S/N%1'} = { };
3320             }
3321             else {
3322 0         0 my %signal = ();
3323 0         0 my @bo = $self->base_order();
3324 0         0 for (my $i = 0; $i < scalar(@sl); $i++) {
3325 0         0 $signal{$bo[$i]} = $sl[$i];
3326             }
3327 0         0 $self->{'_S/N%1'} = { %signal };
3328             }
3329             }
3330 0         0 return %{$self->{'_S/N%1'}};
  0         0  
3331             }
3332              
3333             =head2 size_standard_filename()
3334              
3335             Usage : $s = $abif->size_standard_filename();
3336             Returns : The Size Standard file name;
3337             undef if the data item is not in the file.
3338             ABIF Tag : StdF1
3339             ABIF Type : pString
3340             File Type : fsa
3341            
3342             =cut
3343              
3344             sub size_standard_filename {
3345 0     0 1 0 my $self = shift;
3346 0 0       0 unless (defined $self->{'_StdF1'}) {
3347 0         0 ($self->{'_StdF1'}) = $self->get_data_item('StdF', 1, 'xA*');
3348             }
3349 0         0 return $self->{'_StdF1'};
3350             }
3351              
3352             =head2 snp_set_name()
3353              
3354             Usage : $s = $abif->snp_set_name();
3355             Returns : SNP set name;
3356             undef if the data item is not in the file.
3357             ABIF Tag : SnpS1
3358             ABIF Type : pString
3359             File Type : fsa
3360              
3361             This is an optional data item.
3362            
3363             =cut
3364              
3365             sub snp_set_name {
3366 0     0 1 0 my $self = shift;
3367 0 0       0 unless (defined $self->{'_SnpS1'}) {
3368 0         0 ($self->{'_SnpS1'}) = $self->get_data_item('SnpS', 1, 'xA*');
3369             }
3370 0         0 return $self->{'_SnpS1'};
3371             }
3372              
3373             =head2 start_collection_event()
3374              
3375             Usage : $s = $abif->start_collection_event();
3376             Returns : The start collection event;
3377             undef if the data item is not in the file.
3378             ABIF Tag : EVNT3
3379             ABIF Type : pString
3380             File Type : ab1, fsa
3381            
3382             =cut
3383              
3384             sub start_collection_event {
3385 0     0 1 0 my $self = shift;
3386 0 0       0 unless (defined $self->{'_EVNT3'}) {
3387 0         0 ($self->{'_EVNT3'}) = $self->get_data_item('EVNT', 3, 'xA*');
3388             }
3389 0         0 return $self->{'_EVNT3'};
3390             }
3391              
3392             =head2 start_point()
3393              
3394             Usage : $n = $abif->start_point();
3395             Returns : The start point;
3396             undef if the data item is not in the file.
3397             ABIF Tag : ASPt2
3398             ABIF Type : short
3399             File Type : ab1
3400              
3401             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3402              
3403             =cut
3404              
3405             sub start_point {
3406 0     0 1 0 my $self = shift;
3407 0 0       0 unless (defined $self->{'_ASPt2'}) {
3408 0 0       0 ($self->{'_ASPt2'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3409             $self->get_data_item('ASPt', 2, 'n');
3410             }
3411 0         0 return $self->{'_ASPt2'};
3412             }
3413              
3414             =head2 start_point_orig()
3415              
3416             Usage : $n = $abif->start_point_orig();
3417             Returns : The start point (orig);
3418             undef if the data item is not in the file.
3419             ABIF Tag : ASPt1
3420             ABIF Type : short
3421             File Type : ab1
3422              
3423             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3424              
3425             =cut
3426              
3427             sub start_point_orig {
3428 0     0 1 0 my $self = shift;
3429 0 0       0 unless (defined $self->{'_ASPt1'}) {
3430 0 0       0 ($self->{'_ASPt1'} ) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3431             $self->get_data_item('ASPt', 1, 'n');
3432             }
3433 0         0 return $self->{'_ASPt1'};
3434             }
3435              
3436             =head2 start_run_event()
3437              
3438             Usage : $s = $abif->start_run_event();
3439             Returns : The start run event;
3440             undef if the data item is not in the file.
3441             ABIF Tag : EVNT1
3442             ABIF Type : pString
3443             File Type : ab1, fsa
3444            
3445             =cut
3446              
3447             sub start_run_event {
3448 0     0 1 0 my $self = shift;
3449 0 0       0 unless (defined $self->{'_EVNT1'}) {
3450 0         0 ($self->{'_EVNT1'}) = $self->get_data_item('EVNT', 1, 'xA*');
3451             }
3452 0         0 return $self->{'_EVNT1'};
3453             }
3454              
3455             =head2 stop_collection_event()
3456              
3457             Usage : $s = $abif->stop_collection_event();
3458             Returns : The stop collection event;
3459             undef if the data item is not in the file.
3460             ABIF Tag : EVNT4
3461             ABIF Type : pString
3462             File Type : ab1, fsa
3463            
3464             =cut
3465              
3466             sub stop_collection_event {
3467 0     0 1 0 my $self = shift;
3468 0 0       0 unless (defined $self->{'_EVNT4'}) {
3469 0         0 ($self->{'_EVNT4'}) = $self->get_data_item('EVNT', 4, 'xA*');
3470             }
3471 0         0 return $self->{'_EVNT4'};
3472             }
3473              
3474             =head2 stop_point()
3475              
3476             Usage : $n = $abif->stop_point();
3477             Returns : The stop point;
3478             undef if the data item is not in the file.
3479             ABIF Tag : AEPt2
3480             ABIF Type : short
3481             File Type : ab1
3482              
3483             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3484              
3485             =cut
3486              
3487             sub stop_point {
3488 0     0 1 0 my $self = shift;
3489 0 0       0 unless (defined $self->{'_AEPt2'}) {
3490 0 0       0 ($self->{'_AEPt2'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3491             $self->get_data_item('AEPt', 2, 'n');
3492             }
3493 0         0 return $self->{'_AEPt2'};
3494             }
3495              
3496             =head2 stop_point_orig()
3497              
3498             Usage : $n = $abif->stop_point_orig();
3499             Returns : The stop point (orig);
3500             undef if the data item is not in the file.
3501             ABIF Tag : AEPt1
3502             ABIF Type : short
3503             File Type : ab1
3504              
3505             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3506              
3507             =cut
3508              
3509             sub stop_point_orig {
3510 0     0 1 0 my $self = shift;
3511 0 0       0 unless (defined $self->{'_AEPt1'}) {
3512 0 0       0 ($self->{'_AEPt1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3513             $self->get_data_item('AEPt', 1, 'n');
3514             }
3515 0         0 return $self->{'_AEPt1'};
3516             }
3517              
3518              
3519             =head2 stop_run_event()
3520              
3521             Usage : $s = $abif->stop_run_event();
3522             Returns : The stop run event;
3523             undef if the data item is not in the file.
3524             ABIF Tag : EVNT2
3525             ABIF Type : pString
3526             File Type : ab1, fsa
3527            
3528             =cut
3529              
3530             sub stop_run_event {
3531 0     0 1 0 my $self = shift;
3532 0 0       0 unless (defined $self->{'_EVNT2'}) {
3533 0         0 ($self->{'_EVNT2'}) = $self->get_data_item('EVNT', 2, 'xA*');
3534             }
3535 0         0 return $self->{'_EVNT2'};
3536             }
3537              
3538             =head2 temperature()
3539              
3540             Usage : @t = $abif->temperature();
3541             Returns : The temperature, measured in °C
3542             () if the data item is not in the file.
3543             ABIF Tag : DATA8
3544             ABIF Type : short array
3545             File Type : ab1, fsa
3546            
3547             =cut
3548              
3549             sub temperature {
3550 0     0 1 0 my $self = shift;
3551 0 0       0 unless (defined $self->{'_DATA8'}) {
3552 0 0       0 my @t = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3553             $self->get_data_item('DATA', 8, 'n*');
3554 0 0       0 $self->{'_DATA8'} = (@t) ? [ @t ] : [ ];
3555             }
3556 0         0 return @{$self->{'_DATA8'}};
  0         0  
3557             }
3558              
3559             =head2 trace()
3560              
3561             Usage : @trace = $abif->trace($base);
3562             Returns : The (analyzed) trace corresponding to $base;
3563             () if the data item is not in the file.
3564             File Type : ab1
3565            
3566             The possible values for C<$base> are 'A', 'C', 'G' and 'T'.
3567              
3568             =cut
3569              
3570             sub trace {
3571 0     0 1 0 my ($self, $base) = @_;
3572 0         0 my %ob = ();
3573            
3574 0 0       0 $base =~ /^[ACGTacgt]$/ or return ();
3575 0         0 %ob = $self->order_base();
3576 0         0 return $self->analyzed_data_for_channel($ob{uc($base)});
3577             }
3578              
3579             =head2 trim_probability_threshold()
3580              
3581             Usage : $pr = $abif->trim_probability_threshold();
3582             Returns : The trim probability threshold used;
3583             undef if the data item is not in the file.
3584             ABIF Tag : phTR2
3585             ABIF Type : float
3586             File Type : ab1
3587              
3588             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3589              
3590             =cut
3591              
3592             sub trim_probability_threshold {
3593 0     0 1 0 my $self = shift;
3594 0 0       0 unless (defined $self->{'_phTR2'}) {
3595 0         0 my $pr = undef;
3596 0         0 ($pr) = $self->get_data_item('phTR', 2, 'B32');
3597 0 0       0 $self->{'_phTR2'} = $self->_ieee2decimal($pr) if (defined $pr);
3598             }
3599 0         0 return $self->{'_phTR2'};
3600             }
3601              
3602             =head2 trim_region()
3603              
3604             Usage : $n = $abif->trim_region();
3605             Returns : The read positions;
3606             undef if the data item is not in the file.
3607             ABIF Tag : phTR1
3608             ABIF Type : short
3609             File Type : ab1
3610              
3611             Returns the read positions of the first and last bases in trim region; along
3612             with C, this is equivalent to TRIM in phd1 file.
3613              
3614             This data item is from SeqScape(R) v2.5 and Sequencing Analysis v5.2 Software.
3615              
3616             =cut
3617              
3618             sub trim_region {
3619 0     0 1 0 my $self = shift;
3620 0 0       0 unless (defined $self->{'_phTR1'}) {
3621 0 0       0 ($self->{'_phTR1'}) = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3622             $self->get_data_item('phTR', 1, 'n');
3623             }
3624 0         0 return $self->{'_phTR1'};
3625             }
3626              
3627              
3628             =head2 voltage()
3629              
3630             Usage : @v = $abif->voltage();
3631             Returns : The voltage, measured in decavolts;
3632             () if the data item is not in the file.
3633             ABIF Tag : DATA5
3634             ABIF Type : short array
3635             File Type : ab1, fsa
3636              
3637             =cut
3638              
3639             sub voltage {
3640 0     0 1 0 my $self = shift;
3641 0 0       0 unless (defined $self->{'_DATA5'}) {
3642 0 0       0 my @v = map { ($_ < $SHORT_MID) ? $_ : $_ - $SHORT_MAX }
  0         0  
3643             $self->get_data_item('DATA', 5, 'n*');
3644 0 0       0 $self->{'_DATA5'} = (@v) ? [ @v ] : [ ];
3645             }
3646 0         0 return @{$self->{'_DATA5'}};
  0         0  
3647             }
3648              
3649             =head2 user()
3650              
3651             Usage : $user = $abif->user();
3652             Returns : The name of the user who created the plate;
3653             undef if the data item is not in the file.
3654             ABIF Tag : User1
3655             ABIF Type : pString
3656             File Type : ab1, fsa
3657            
3658             This is an optional data item.
3659              
3660             =cut
3661              
3662             sub user {
3663 0     0 1 0 my $self = shift;
3664 0 0       0 unless (defined $self->{'_User1'}) {
3665 0         0 ($self->{'_User1'}) = $self->get_data_item('User', 1, 'xA*');
3666             }
3667 0         0 return $self->{'_User1'};
3668             }
3669              
3670             =head2 well_id()
3671              
3672             Usage : $well_id = $abif->well_id();
3673             Returns : The well ID;
3674             undef if the data item is not in the file.
3675             ABIF Tag : TUBE1
3676             ABIF Type : pString
3677             File Type : ab1, fsa
3678            
3679             =cut
3680              
3681             sub well_id {
3682 0     0 1 0 my $self = shift;
3683 0 0       0 unless (defined $self->{'_TUBE1'}) {
3684 0         0 ($self->{'_TUBE1'}) = $self->get_data_item('TUBE', 1, 'xA*');
3685             }
3686 0         0 return $self->{'_TUBE1'};
3687             }
3688              
3689             #==============================================================================
3690              
3691             =head1 METHODS FOR ASSESSING QUALITY
3692              
3693             The following methods compute some values that help assessing the quality
3694             of the data.
3695              
3696             =head2 avg_signal_to_noise_ratio()
3697              
3698             Usage : $sn_ratio = $abif->avg_signal_to_noise_ratio()
3699             Returns : The average signal to noise ratio;
3700             0 on error.
3701              
3702             This method works only with files containing data processed by the KB(tm)
3703             Basecaller. If the information needed to compute such value is missing, it
3704             returns 0.
3705              
3706             =cut
3707              
3708             sub avg_signal_to_noise_ratio {
3709 0     0 1 0 my $self = shift;
3710 0         0 my %sl = $self->signal_level();
3711 0 0       0 return 0 unless %sl;
3712 0         0 my %noise = $self->noise();
3713 0 0       0 return 0 unless %noise;
3714 0         0 my $avg = 0;
3715 0         0 foreach my $base (keys %sl) {
3716 0         0 $avg += $sl{$base} / $noise{$base};
3717             }
3718 0         0 return $avg / scalar(keys %sl);
3719             }
3720              
3721              
3722             =head2 clear_range()
3723              
3724             Usage : ($b, $e) = $abif->clear_range();
3725             ($b, $e) = $abif->clear_range(
3726             $window_width,
3727             $bad_bases_threshold,
3728             $quality_threshold
3729             );
3730             Returns : The clear range of the sequence;
3731             (-1, -1) if there is no clear range.
3732              
3733             The Sequencing Analysis program determines the clear range of the sequence by
3734             trimming bases from the 5' to 3' ends until fewer than 4 bases out of 20 have a
3735             quality value less than 20. You can change these parameters by explicitly
3736             passing arguments to this method (the default values are C<$window_width> = 20,
3737             C<$bad_bases_threshold> = 4, C<$quality_threshold> = 20). Note that Sequencing
3738             Analysis counts the bases starting from one, so you have to add one to the
3739             return values to get consistent results.
3740              
3741             =cut
3742              
3743             sub clear_range {
3744 0     0 1 0 my $self = shift;
3745 0         0 my $window = 20;
3746 0         0 my $bad_bases = 4;
3747 0         0 my $threshold = 20;
3748 0 0       0 if (@_) {
3749 0         0 $window = shift;
3750 0         0 $bad_bases = shift;
3751 0         0 $threshold = shift;
3752             }
3753 0         0 return ($self->clear_range_start($window, $bad_bases, $threshold),
3754             $self->clear_range_stop($window, $bad_bases, $threshold));
3755             }
3756              
3757             =head2 clear_range_start()
3758              
3759             Usage : $b = $abif->clear_range_start();
3760             $b = $abif->clear_range_start(
3761             $window_width,
3762             $bad_bases_threshold,
3763             $quality_threshold
3764             );
3765             Returns : The clear range start position;
3766             -1 if no clear range exists.
3767            
3768             See C.
3769              
3770             =cut
3771              
3772             sub clear_range_start {
3773 0     0 1 0 my $self = shift;
3774 0         0 my $window = 20;
3775 0         0 my $bad_bases = 4;
3776 0         0 my $threshold = 20;
3777 0 0       0 if (@_) {
3778 0         0 $window = shift;
3779 0         0 $bad_bases = shift;
3780 0         0 $threshold = shift;
3781             }
3782 0         0 my $qv_ref = $self->quality_values_ref();
3783 0 0       0 return -1 unless defined $qv_ref;
3784              
3785 0         0 my $N = scalar(@$qv_ref);
3786 0 0       0 return -1 if ($N < $window); # Not enough quality values
3787            
3788 0         0 my $j; # Points to the rightmost element of next window
3789 0         0 my $n = 0; # Number of bad quality bases
3790 0         0 for ($j = 0; $j < $window; $j++) {
3791 0 0       0 if ($$qv_ref[$j] < $threshold) {
3792 0         0 $n++;
3793             }
3794             }
3795 0   0     0 while ($n >= $bad_bases and $j < $N) {
3796 0 0       0 if ($$qv_ref[$j - $window] < $threshold) {
3797 0         0 $n--;
3798             }
3799 0 0       0 if ($$qv_ref[$j] < $threshold) {
3800 0         0 $n++;
3801             }
3802 0         0 $j++;
3803             }
3804 0 0       0 return -1 if ($n >= $bad_bases); # No clear range
3805 0         0 return $j - $window;
3806             }
3807              
3808              
3809             =head2 clear_range_stop()
3810              
3811             Usage : $e = $abif->clear_range_stop();
3812             $e = $abif->clear_range_stop(
3813             $window_width,
3814             $bad_bases_threshold,
3815             $quality_threshold
3816             );
3817             Returns : The clear range stop position;
3818             -1 if no clear range exists.
3819            
3820             See C.
3821              
3822             =cut
3823              
3824             sub clear_range_stop {
3825 0     0 1 0 my $self = shift;
3826 0         0 my $window = 20;
3827 0         0 my $bad_bases = 4;
3828 0         0 my $threshold = 20;
3829 0 0       0 if (@_) {
3830 0         0 $window = shift;
3831 0         0 $bad_bases = shift;
3832 0         0 $threshold = shift;
3833             }
3834 0         0 my $qv_ref = $self->quality_values_ref();
3835 0 0       0 return -1 unless defined $qv_ref;
3836            
3837 0         0 my $N = scalar(@$qv_ref);
3838 0 0       0 return -1 if ($N < $window); # Not enough quality values
3839            
3840 0         0 my $j; # Points to the leftmost element of next window
3841 0         0 my $n = 0; # Number of bad quality bases
3842 0         0 for ($j = $N - 1; $j >= $N - $window; $j--) {
3843 0 0       0 if ($$qv_ref[$j] < $threshold) {
3844 0         0 $n++;
3845             }
3846             }
3847 0   0     0 while ($n >= $bad_bases and $j >= 0) {
3848 0 0       0 if ($$qv_ref[$j + $window] < $threshold) {
3849 0         0 $n--;
3850             }
3851 0 0       0 if ($$qv_ref[$j] < $threshold) {
3852 0         0 $n++;
3853             }
3854 0         0 $j--;
3855             }
3856 0 0       0 return -1 if ($n >= $bad_bases); # No clear range
3857 0         0 return $j + $window;
3858             }
3859              
3860             =head2 contiguous_read_length()
3861              
3862             Usage : ($b, $e) = $abif->contiguous_read_length(
3863             $window_width,
3864             $quality_threshold
3865             );
3866             ($b, $e) = $abif->contiguous_read_length(
3867             $window_width,
3868             $quality_threshold,
3869             $trim_ends
3870             );
3871             Returns : The start and stop position of the CRL;
3872             (-1, -1) if there is no CRL.
3873              
3874             The CRL is (the length of) the longest uninterrupted stretch in a read such that
3875             the average quality of any interval of C<$window_width> bases that is inside such
3876             stretch never goes below C<$threshold>. The threshold must be at least 10. The
3877             positions are counted from zero. If C<$trim_ends> is true, the ends of the CRL
3878             are trimmed until there are no bases with quality values less than 10 within the
3879             first five and the last five bases. Trimming is not applied by default. If there
3880             is more than one CRL, the position of the first one is reported.
3881              
3882             =cut
3883              
3884             sub contiguous_read_length {
3885 0     0 1 0 my $self = shift;
3886 0         0 my $window_width = shift;
3887 0         0 my $qv_threshold = shift;
3888 0         0 my $trim = 0;
3889 0 0       0 $trim = shift if (@_);
3890            
3891 0         0 my $qv_ref = $self->quality_values_ref();
3892 0         0 my $N = scalar(@$qv_ref);
3893 0 0       0 return (-1, -1) if ($N < $window_width);
3894 0         0 my $crl = 0; # 1 if we are inside a crl, 0 otherwise
3895 0         0 my $start = 0;
3896 0         0 my $new_start = 0;
3897 0         0 my $stop = 0;
3898 0         0 my $threshold = $window_width * $qv_threshold;
3899 0         0 my $q = 0;
3900 0         0 my $i;
3901 0         0 for ($i = 0; $i < $window_width; $i++) {
3902 0         0 $q += $$qv_ref[$i];
3903             }
3904 0 0       0 $crl = 1 if ($q >= $threshold);
3905 0         0 while ($i < $N) {
3906 0         0 $q -= $$qv_ref[$i - $window_width];
3907 0         0 $q += $$qv_ref[$i];
3908 0 0 0     0 if ($crl and $q < $threshold) {
    0 0        
3909 0         0 $crl = 0;
3910 0 0       0 if ($stop - $start < $i - $new_start - 1) {
3911 0         0 $start = $new_start;
3912 0         0 $stop = $i - 1;
3913             }
3914             }
3915             elsif ( (not $crl) and $q >= $threshold) {
3916 0         0 $crl = 1;
3917 0         0 $new_start = $i - $window_width + 1;
3918             }
3919 0         0 $i++;
3920             }
3921 0 0 0     0 if ($crl and $stop - $start < $N - $new_start - 1) {
3922 0         0 $start = $new_start;
3923 0         0 $stop = $N - 1;
3924             }
3925 0 0       0 return ($start, $stop) unless $trim;
3926            
3927 0         0 my $j = 0;
3928 0   0     0 while ($start + 4 <= $stop and ($j < 5)) { # Trim the beginning
3929 0 0       0 if ($$qv_ref[$start + $j] < 10) {
3930 0         0 $start += $j + 1;
3931 0         0 $j = 0;
3932             }
3933             else {
3934 0         0 $j++;
3935             }
3936             }
3937 0         0 $j = 0;
3938 0   0     0 while ($start + 4 <= $stop and ($j < 5)) { # Trim the end
3939 0 0       0 if ($$qv_ref[$stop - $j] < 10) {
3940 0         0 $stop -= ($j + 1);
3941 0         0 $j = 0;
3942             }
3943             else {
3944 0         0 $j++;
3945             }
3946             }
3947 0 0       0 if ($stop - $start < 4) {
3948 0         0 for (my $k = $start; $k <= $stop; $k++) {
3949 0 0       0 if ($$qv_ref[$k] < 10) {
3950 0         0 return (-1, -1);
3951             }
3952             }
3953             }
3954 0         0 return ($start, $stop);
3955             }
3956              
3957             =head2 length_of_read()
3958              
3959             Usage : $LOR = $abif->length_of_read(
3960             $window_width,
3961             $quality_threshold
3962             );
3963             $LOR = $abif->length_of_read(
3964             $window_width,
3965             $quality_threshold,
3966             $method
3967             );
3968             Returns : The Length Of Read (LOR) value.
3969              
3970             The Length Of Read (LOR) score gives an approximate measure of the
3971             usable range of high-quality or high-accuracy bases determined by quality
3972             values. Such range can be determined in several ways. Two possible procedures
3973             are currently implemented and described below.
3974              
3975             If C<$method> is the string 'SequencingAnalysis' then the LOR is computed as the
3976             widest range starting and ending with C<$window_width> bases whose average
3977             quality is greater than or equal to C<$quality_threshold>. This is the default
3978             method that is applied if this optional argument is omitted.
3979              
3980             If C<$method> is the string 'GoodQualityWindows' then the LOR is computed as the
3981             number of intervals of C<$window_width> bases whose average quality is greater
3982             than or equal to C<$quality_threshold>.
3983              
3984             =cut
3985              
3986             sub length_of_read {
3987 0     0 1 0 my $self = shift;
3988 0         0 my $window = shift;
3989 0         0 my $qv_threshold = shift;
3990 0         0 my $method = 'SequencingAnalysis';
3991 0 0       0 if (@_) { $method = shift; }
  0         0  
3992            
3993 0         0 my $qv_ref = $self->quality_values_ref();
3994 0 0       0 return 0 unless defined $qv_ref;
3995 0         0 my $LOR = 0;
3996 0         0 my $first = 0;
3997 0         0 my $last = 0;
3998 0         0 my $sum = 0;
3999             #my $avg = 0;
4000            
4001 0         0 my $threshold = $window * $qv_threshold;
4002 0         0 my $N = scalar(@$qv_ref);
4003 0 0       0 if ($N < $window) {
4004             #print STDERR "Not enough bases to compute LOR.\n";
4005             #print STDERR "At least $window bases are needed.\n";
4006 0         0 return 0;
4007             }
4008            
4009             # Dispatch according to the chosen method
4010 0 0       0 if ($method eq 'SequencingAnalysis') {
4011             # Compute the LOR score as the Sequencing Analysis program does
4012             # Compute the average quality value in the first window
4013 0         0 my $i;
4014             # Determine the first window with average qv >= $qv_threshold
4015 0         0 my $start = 0;
4016 0         0 $sum = 0;
4017 0         0 for ($i = 0; $i < $window; $i++) {
4018 0         0 $sum += $$qv_ref[$i];
4019             }
4020 0 0       0 if ($sum < $threshold) {
4021 0   0     0 do {
4022 0         0 $sum -= $$qv_ref[$i - $window];
4023 0         0 $sum += $$qv_ref[$i];
4024 0         0 $i++;
4025             } while ($sum < $threshold and $i < $N);
4026 0         0 $start = $i - $window;
4027             }
4028            
4029             # Determine the last window with average qv >= $qv_threshold
4030 0         0 my $stop = $N - 1;
4031 0         0 $sum = 0;
4032 0         0 for ($i = $stop; $i > $stop - $window; $i--) {
4033 0         0 $sum += $$qv_ref[$i];
4034             }
4035 0 0       0 if ($sum < $threshold) {
4036 0   0     0 do {
4037 0         0 $sum -= $$qv_ref[$i + $window];
4038 0         0 $sum += $$qv_ref[$i];
4039 0         0 $i--;
4040             } while ($sum < $threshold and $i >= 0);
4041 0         0 $stop = $i + $window;
4042             }
4043            
4044 0 0       0 $LOR = ($stop > $start) ? ($stop - $start + 1) : 0;
4045             } # end if ($method eq 'SequencingAnalysis')
4046             else {
4047             # This method computes the LOR as the number
4048             # of windows of size $window having average quality value >= $threshold
4049              
4050             # Compute the average quality value in the first window
4051 0         0 $sum = 0;
4052 0         0 my $i; # Points to the right end of the next window to be processed
4053 0         0 for ($i = 0; $i < $window; $i++) {
4054 0         0 $sum += $$qv_ref[$i];
4055             }
4056             #$avg = $sum / $window;
4057             #if ($avg >= $qv_threshold) {
4058 0 0       0 if ($sum >= $threshold) {
4059 0         0 $LOR++;
4060             }
4061 0         0 while ($i < $N) {
4062             # Compute the average of the shifted window
4063 0         0 $sum -= $$qv_ref[$i - $window];
4064 0         0 $sum += $$qv_ref[$i];
4065             #$avg = $sum / $window;
4066             #if ($avg >= $qv_threshold) {
4067 0 0       0 if ($sum >= $threshold) {
4068 0         0 $LOR++;
4069             }
4070 0         0 $i++;
4071             }
4072             }
4073            
4074 0         0 return $LOR;
4075             }
4076              
4077             =head2 num_low_quality_bases()
4078              
4079             Usage : $n = $abif->num_low_quality_bases($threshold);
4080             $n = $abif->num_low_quality_bases(
4081             $threshold,
4082             $start,
4083             $stop
4084             );
4085             Returns : The number of low quality bases;
4086             -1 on error.
4087              
4088             Returns the number of quality bases in the range C<[$start,$stop]>, or in
4089             the whole sequence if no range is specified, with quality value less than or
4090             equal to C<$threshold>. Returns -1 if the information needed to compute such
4091             value (i.e., the quality values) is missing from the file.
4092              
4093             =cut
4094              
4095             sub num_low_quality_bases {
4096 0     0 1 0 my $self = shift;
4097 0         0 my $max = shift;
4098 0         0 my $start;
4099             my $stop;
4100 0 0       0 if (@_) {
4101 0         0 $start = shift;
4102 0         0 $stop = shift;
4103             }
4104             else {
4105 0         0 $start = 0;
4106 0         0 $stop = -1;
4107             }
4108            
4109 0         0 my $qv_ref = $self->quality_values_ref();
4110 0 0       0 return -1 unless defined $qv_ref;
4111 0         0 my $n = 0;
4112 0 0       0 if ($start <= $stop) {
4113 0         0 for (my $i = $start; $i <= $stop; $i++) {
4114 0 0       0 if ($$qv_ref[$i] <= $max) {
4115 0         0 $n++;
4116             }
4117             }
4118             }
4119             else { # Count all the quality values
4120 0         0 foreach my $qv (@$qv_ref) {
4121 0 0       0 if ($qv <= $max) {
4122 0         0 $n++;
4123             }
4124             }
4125             }
4126 0         0 return $n;
4127             }
4128              
4129             =head2 num_high_quality_bases()
4130              
4131             Usage : $n = $abif->num_high_quality_bases($threshold);
4132             $n = $abif->num_high_quality_bases(
4133             $threshold,
4134             $start,
4135             $stop
4136             );
4137             Returns : The number of high quality bases;
4138             -1 on error.
4139              
4140             Returns the number of quality bases in the range C<[$start,$stop]>, or in
4141             the whole sequence if no range is specified, with quality value greater than or
4142             equal to C<$threshold>. Returns -1 if the information needed to compute such
4143             value (i.e., the quality values) is missing from the file.
4144              
4145             =cut
4146              
4147             sub num_high_quality_bases {
4148 0     0 1 0 my $self = shift;
4149 0         0 my $min = shift;
4150 0         0 my $start;
4151             my $stop;
4152 0 0       0 if (@_) {
4153 0         0 $start = shift;
4154 0         0 $stop = shift;
4155             }
4156             else {
4157 0         0 $start = 0;
4158 0         0 $stop = -1;
4159             }
4160            
4161 0         0 my $qv_ref = $self->quality_values_ref();
4162 0 0       0 return -1 unless defined $qv_ref;
4163 0         0 my $n = 0;
4164 0 0       0 if ($start <= $stop) {
4165 0         0 for (my $i = $start; $i <= $stop; $i++) {
4166 0 0       0 if ($$qv_ref[$i] >= $min) {
4167 0         0 $n++;
4168             }
4169             }
4170             }
4171             else { # Count all the quality values
4172 0         0 foreach my $qv (@$qv_ref) {
4173 0 0       0 if ($qv >= $min) {
4174 0         0 $n++;
4175             }
4176             }
4177             }
4178 0         0 return $n;
4179             }
4180              
4181             =head2 num_medium_quality_bases()
4182              
4183             Usage : $n = $abif->num_medium_quality_bases(
4184             $min_qv,
4185             $max_qv
4186             );
4187             $n = $abif->num_medium_quality_bases(
4188             $min_qv,
4189             $max_qv,
4190             $start,
4191             $stop
4192             );
4193             Returns : The number of medium quality bases;
4194             -1 on error.
4195              
4196             Returns the number of quality bases in the range C<[$start,$stop]>, or in
4197             the whole sequence if no range is specified, whose quality value is in the
4198             (closed) range C<[$min_qv,$max_qv]>. Returns -1 if the information needed to
4199             compute such value (i.e., the quality values) is missing from the file.
4200              
4201             =cut
4202              
4203             sub num_medium_quality_bases {
4204 0     0 1 0 my $self = shift;
4205 0         0 my $min = shift;
4206 0         0 my $max = shift;
4207 0         0 my $start;
4208             my $stop;
4209 0 0       0 if (@_) {
4210 0         0 $start = shift;
4211 0         0 $stop = shift;
4212             }
4213             else {
4214 0         0 $start = 0;
4215 0         0 $stop = -1;
4216             }
4217              
4218 0         0 my $qv_ref = $self->quality_values_ref();
4219 0 0       0 return -1 unless defined $qv_ref;
4220 0         0 my $n = 0;
4221 0 0       0 if ($start <= $stop) {
4222 0         0 for (my $i = $start; $i <= $stop; $i++) {
4223 0 0 0     0 if ($$qv_ref[$i] >= $min and $$qv_ref[$i] <= $max) {
4224 0         0 $n++;
4225             }
4226             }
4227             }
4228             else { # Count all the quality values
4229 0         0 foreach my $qv (@$qv_ref) {
4230 0 0 0     0 if ($qv >= $min and $qv <= $max) {
4231 0         0 $n++;
4232             }
4233             }
4234             }
4235 0         0 return $n;
4236             }
4237              
4238             =head2 sample_score()
4239              
4240             Usage : $ss = $abif->sample_score();
4241             : $ss = $abif->sample_score(
4242             $window_width,
4243             $bad_bases_threshold,
4244             $quality_threshold
4245             );
4246             Returns : The sample score of the sequence.
4247            
4248             The sample score is the average quality value of the bases in the clear range of
4249             the sequence (see C). The method returns 0 if the information
4250             needed to compute such value is missing or if the clear range is empty.
4251              
4252             =cut
4253              
4254             sub sample_score {
4255 0     0 1 0 my $self = shift;
4256 0         0 my $start;
4257             my $stop;
4258 0 0       0 if (@_) {
4259 0         0 my $window = shift;
4260 0         0 my $bad_bases = shift;
4261 0         0 my $threshold = shift;
4262 0         0 $start = $self->clear_range_start($window, $bad_bases, $threshold);
4263 0         0 $stop = $self->clear_range_stop($window, $bad_bases, $threshold);
4264             }
4265             else {
4266 0         0 $start = $self->clear_range_start();
4267 0         0 $stop = $self->clear_range_stop();
4268             }
4269 0         0 my $qv_ref = $self->quality_values_ref();
4270 0 0 0     0 return 0 unless ($start >= 0) and ($start <= $stop) and defined $qv_ref;
      0        
4271             # Compute average quality value in the clear range
4272 0         0 my $sum = 0;
4273 0         0 for (my $i = $start; $i <= $stop; $i++) {
4274 0         0 $sum += $$qv_ref[$i];
4275             }
4276 0         0 return $sum / ($stop - $start + 1);
4277             }
4278              
4279             #==============================================================================
4280              
4281             #=head1 HELPER FUNCTIONS
4282             #
4283             #The following methods are convenience methods to convert binary
4284             #representations into decimal and vice versa.
4285             #
4286             # Although not documented, float numbers in ABI files
4287             # apparently use standard IEEE representation.
4288             #
4289             #=cut
4290             #
4291             ## See http://perldoc.perl.org/perlfaq4.html
4292             #
4293             #=head2 _bin2uint()
4294             #
4295             # Usage : _bin2uint($bit_string)
4296             # Returns : the unsigned integer corresponding to the given bit string.
4297             #
4298             #Interprets the bit string as an unsigned integer. It works for binary strings
4299             #up to 32 bits.
4300             #
4301             #=cut
4302              
4303             sub _bin2uint {
4304 0     0   0 my $self = shift;
4305 0         0 return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
4306             }
4307              
4308             #=head2 _uint2bin()
4309             #
4310             # Usage : _uint2bin($n)
4311             # Returns : a 32 bit string representation of the given unsigned integer.
4312             #
4313             #Translates the given non negative integer into a 32 bit string.
4314             #
4315             #=cut
4316              
4317             sub _uint2bin {
4318 0     0   0 my $self = shift;
4319 0         0 return unpack("B32", pack("N", shift));
4320             }
4321              
4322             #=head2 _bin2decimal()
4323             #
4324             # Usage : _bin2decimal($fractional_bit_string)
4325             # Returns : the decimal value of the given fractional bit string.
4326             #
4327             #Converts a fractional binary number into its decimal value, e.g., 010.01000 is
4328             #turned into 2.25.
4329             #
4330             #=cut
4331              
4332             sub _bin2decimal {
4333 0     0   0 my $self = shift;
4334 0         0 my ($i, $f) = split('\.', shift);
4335 0         0 return _bin2uint($i) + (_bin2uint($f) / 2**length($f));
4336             }
4337              
4338             #=head2 _ieee2decimal()
4339             #
4340             # Usage : _ieee2decimal($string_32_bits)
4341             # Returns : the floating number corresponding to the given 32 bit string.
4342             #
4343             #Interprets the 32 bit string in the standard IEEE format:
4344             #
4345             #
4346             #
4347             #The value is computed as:
4348             #
4349             # sign * 1.mantissa * 2**(exponent - 127)
4350             #
4351             #=cut
4352              
4353             sub _ieee2decimal {
4354 1     1   6 my $self = shift;
4355 1         2 my $b = shift;
4356 1 50       4 my $sign = (substr($b, 0, 1) eq '0') ? 1 : -1;
4357 1         7 my $exp = unpack("N", pack("B32", substr("0" x 32 . substr($b, 1, 8), -32)));
4358 1         6 my $m = 1 + (unpack("N", pack("B32", substr("0" x 32 . substr($b, 9, 23), -32))) / (2**23));
4359 1         5 return $sign * $m * (2**($exp - 127));
4360             }
4361              
4362              
4363             #=head2 _decimal2ieee()
4364             #
4365             # Usage : _decimal2ieee($decimal_number)
4366             # Returns : the 32 bit IEEE representation of (an approximation of) $decimal_number
4367             #
4368             # Very trivial sub-optimal non-optimized in-some-cases-erroneous
4369             # conversion into IEEE-754 32 bit float.
4370             #=cut
4371              
4372             sub _decimal2ieee {
4373 0     0   0 my $self = shift;
4374 0         0 my $decimal_number = shift;
4375 0         0 my $ieee;
4376             my $mantissa;
4377 0         0 my $exp;
4378 0 0       0 if ($decimal_number == 0.0) {
4379 0         0 return '00000000000000000000000000000000';
4380             }
4381             # First of all, let's try built-in packing
4382 0         0 $ieee = unpack('B32', pack('f', $decimal_number));
4383             # Check whether it's IEEE-754
4384 0         0 my $ff = $self->_ieee2decimal($ieee);
4385 0 0       0 if (abs(($decimal_number - $ff) / $ff) < 0.0001) { # Quick and dirty...
4386 0         0 return $ieee;
4387             }
4388            
4389             # If we get here, we've been unlucky...
4390 0         0 my $sign = '0';
4391 0 0       0 if ($decimal_number =~ /^-/) {
4392 0         0 $sign = '1';
4393 0         0 $decimal_number = abs($decimal_number);
4394             }
4395 0         0 my ($i, $f) = ($decimal_number =~ /^(\d*)(\.?\d*)$/);
4396 0 0       0 $i = 0 unless ($i);
4397 0 0       0 $f = 0 unless ($f);
4398 0         0 $mantissa = _uint2bin($i);
4399 0         0 $mantissa .= _fraction2bin($f);
4400             # Normalize
4401 0         0 $mantissa =~ /\./g;
4402 0         0 $exp = pos($mantissa);
4403 0         0 $mantissa =~ /[^\d]/g; # Failed match to reset pos()
4404 0 0       0 if ($mantissa =~ /1/g) {
4405 0         0 $exp -= pos($mantissa);
4406             }
4407             else {
4408 0         0 return '00000000000000000000000000000000'
4409             }
4410             # Bias exponent
4411 0 0       0 $exp = ($exp > 0) ? $exp += 126 : $exp += 127;
4412 0         0 $exp = _uint2bin($exp); # assume it is positive...
4413 0         0 $mantissa =~ s/\.//g;
4414 0         0 ($mantissa) = ($mantissa =~ /^0*1(\d*)$/);
4415 0 0       0 $mantissa = 0 unless ($mantissa);
4416 0         0 while (length($mantissa) < 23) {
4417 0         0 $mantissa .= '0';
4418             }
4419 0         0 $mantissa = substr($mantissa, 0, 23);
4420             # (I should increase the last digit by 1 in some cases,
4421             # but I'm too lazy to implement it now...)
4422 0         0 $ieee = $sign;
4423 0         0 $ieee .= substr($exp, -8);
4424 0         0 $ieee .= $mantissa;
4425              
4426 0         0 return $ieee;
4427             }
4428              
4429             #=head2 _fraction2bin()
4430             #
4431             # Usage : _fraction2bin($fraction)
4432             # _fraction2bin($fraction, $prec)
4433             # Returns : a binary representation of $fraction.
4434             #
4435             # A very simple implementation of decimal to binary conversion of fractions.
4436             # $fraction must be 0 <= $fraction < 1;
4437             #
4438             #=cut
4439             sub _fraction2bin {
4440 0     0   0 my $self = shift;
4441 0         0 my $f = shift;
4442 0         0 my $prec = 23;
4443 0 0       0 $prec = shift if @_;
4444 0         0 my $digit;
4445 0         0 my $result = '.';
4446 0         0 for (my $i = 0; $i < $prec; $i++) {
4447 0         0 $f *= 2;
4448 0         0 $digit = int($f);
4449 0         0 $result .= $digit;
4450 0         0 $f -= $digit;
4451             }
4452 0         0 return $result;
4453             }
4454              
4455             ########################################################################
4456              
4457             # Takes year, month, day and makes a date of the form yyyy-mm-dd
4458             sub _make_date {
4459 0     0   0 my ($y, $m, $d) = @_;
4460 0         0 my $date = $y . '-';
4461 0 0       0 $date .= ($m < 10) ? '0' . $m : $m;
4462 0         0 $date .= '-';
4463 0 0       0 $date .= ($d < 10) ? '0' . $d : $d;
4464 0         0 return $date;
4465             }
4466              
4467             # Returns time in the format hh-mm-ss.nn
4468             sub _make_time {
4469 0     0   0 my ($hh, $mm, $ss, $nn) = @_;
4470 0         0 my $time = '';
4471 0 0       0 $time .= ($hh < 10) ? '0' . $hh : $hh;
4472 0         0 $time .= ':';
4473 0 0       0 $time .= ($mm < 10) ? '0' . $mm : $mm;
4474 0         0 $time .= ':';
4475 0 0       0 $time .= ($ss < 10) ? '0' . $ss : $ss;
4476 0         0 $time .= '.';
4477 0 0       0 $time .= ($nn < 10) ? '0' . $nn : $nn;
4478 0         0 return $time;
4479             }
4480              
4481             sub _debug {
4482 0     0   0 my $self = shift;
4483 0 0       0 confess "usage: thing->_debug(level)" unless @_ == 1;
4484 0         0 my $level = shift;
4485 0 0       0 if (ref($self)) {
4486 0         0 $self->{"_DEBUG"} = $level; # just myself
4487             }
4488             else {
4489 0         0 $Debugging = $level; # whole class
4490             }
4491             }
4492              
4493             sub DESTROY {
4494 1     1   386 my $self = shift;
4495 1 50 33     106 if ($Debugging || $self->{"_DEBUG"}) {
4496 0           carp "Destroying $self " . $self->name;
4497             }
4498             }
4499              
4500             sub END {
4501 2 50   2   295 if ($Debugging) {
4502 0         0 print "All ABIF objects are going away now.\n";
4503             }
4504             }
4505            
4506             =head1 AUTHOR
4507              
4508             Nicola Vitacolonna, C<< >>
4509              
4510             =head1 BUGS
4511              
4512             Please report any bugs or feature requests to
4513             C, or through the web interface at
4514             L.
4515             I will be notified, and then you'll automatically be notified of progress on
4516             your bug as I make changes.
4517              
4518             =head1 SUPPORT
4519              
4520             You can find documentation for this module with the perldoc command.
4521              
4522             perldoc Bio::Trace::ABIF
4523              
4524             You can also look for information at:
4525              
4526             =over 4
4527              
4528             =item * AnnoCPAN: Annotated CPAN documentation
4529              
4530             L
4531              
4532             =item * CPAN Ratings
4533              
4534             L
4535              
4536             =item * RT: CPAN's request tracker
4537              
4538             L
4539              
4540             =item * Search CPAN
4541              
4542             L
4543              
4544             =back
4545              
4546             =head1 SEE ALSO
4547              
4548             See L for the ABIF format file
4549             specification sheet.
4550              
4551             There is an ABI module on CPAN (L).
4552              
4553             bioperl-ext also parses ABIF files and other trace formats.
4554              
4555             You are welcome at L!
4556              
4557             =head1 ACKNOWLEDGEMENTS
4558              
4559             Thanks to Simone Scalabrin for many helpful suggestions and for the first
4560             implementation of the C method the way Sequencing Analysis
4561             does it (and for rating this module five stars)!
4562             Thanks to Fabrizio Levorin and other people reporting bugs!
4563              
4564             Some explanation about how Sequencing Analysis computes some parameters has
4565             been found at L.
4566              
4567             =head1 COPYRIGHT & LICENSE
4568              
4569             Copyright 2006-2010 Nicola Vitacolonna, all rights reserved.
4570              
4571             This program is free software; you can redistribute it and/or modify it under
4572             the same terms as Perl itself.
4573              
4574             Feel free to rate this module on CPAN!
4575              
4576             =cut
4577              
4578             =head1 DISCLAIMER
4579              
4580             This software is provided "as is" without warranty of any kind.
4581              
4582             =cut
4583              
4584             1; # End of Bio::Trace::ABIF