File Coverage

Bio/Seq/SimulatedRead.pm
Criterion Covered Total %
statement 224 244 91.8
branch 111 138 80.4
condition 29 44 65.9
subroutine 22 22 100.0
pod 7 7 100.0
total 393 455 86.3


line stmt bran cond sub pod time code
1             package Bio::Seq::SimulatedRead;
2              
3              
4             =head1 NAME
5              
6             Bio::Seq::SimulatedRead - Read with sequencing errors taken from a reference sequence
7              
8             =head1 SYNOPSIS
9              
10             use Bio::Seq::SimulatedRead;
11             use Bio::PrimarySeq;
12            
13             # Create a reference sequence
14             my $genome = Bio::PrimarySeq->new( -id => 'human_chr2',
15             -seq => 'TAAAAAAACCCCTG',
16             -desc => 'The human genome' );
17              
18             # A 10-bp error-free read taken from a genome
19             my $read = Bio::Seq::SimulatedRead->new(
20             -reference => $genome , # sequence to generate the read from
21             -id => 'read001', # read ID
22             -start => 3 , # start of the read on the genome forward strand
23             -end => 12 , # end of the read on the genome forward strand
24             -strand => 1 , # genome strand that the read is on
25             );
26              
27             # Display the sequence of the read
28             print $read->seq."\n";
29              
30             # Add a tag or MID to the beginning of the read
31             $read->mid('ACGT');
32              
33             # Add sequencing errors (error positions are 1-based and relative to the
34             # error-free MID-containing read)
35             my $errors = {};
36             $errors->{'8'}->{'+'} = 'AAA'; # insertion of AAA after residue 8
37             $errors->{'1'}->{'%'} = 'G'; # substitution of residue 1 by a G
38             $errors->{'4'}->{'-'} = undef; # deletion of residue 4
39             $read->errors($errors);
40              
41             # Display the sequence of the read with errors
42             print $read->seq."\n";
43              
44             # String representation of where the read came from and its errors
45             print $read->desc."\n";
46              
47             =head1 DESCRIPTION
48              
49             This object is a simulated read with sequencing errors. The user can provide a
50             reference sequence to take a read from, the position and orientation of the
51             read on the reference sequence, and the sequencing errors to generate.
52              
53             The sequence of the read is automatically calculated based on this information.
54             By default, the description of the reads contain tracking information and will
55             look like this (Bioperl-style):
56              
57             reference=human_chr2 start=3 end=12 strand=-1 mid=ACGT errors=1%G,4-,8+AAA description="The human genome"
58              
59             or Genbank-style:
60              
61             reference=human_chr2 position=complement(3..12) mid=ACGT errors=1%G,4-,8+AAA description="The human genome"
62              
63             Creating a simulated read follows these steps:
64             1/ Define the read start(), end(), strand() and qual_levels() if you want
65             quality scores to be generated. Do not change these values once set because
66             the read will not be updated.
67             2/ Specify the reference sequence that the read should be taken from. Once
68             this is done, you have a fully functional read. Do not use the reference()
69             method again after you have gone to the next step.
70             3/ Use mid() to input a MID (or tag or barcode) to add to the beginning of the
71             read. You can change the MID until you go to next step.
72             4/ Give sequencing error specifications using errors() as the last step. You
73             can do that as many times as you like, and the read will be updated.
74              
75             =head1 AUTHOR
76              
77             Florent E Angly Eflorent . angly @ gmail-dot-comE.
78              
79             Copyright (c) 2011 Florent E Angly.
80              
81             This library is free software; you can redistribute it under the GNU General
82             Public License version 3.
83              
84             =cut
85              
86              
87 1     1   1837 use strict;
  1         2  
  1         27  
88 1     1   6 use warnings;
  1         1  
  1         27  
89 1     1   4 use Bio::LocatableSeq;
  1         1  
  1         18  
90 1     1   4 use base qw( Bio::Seq::Quality Bio::LocatableSeq );
  1         2  
  1         2172  
91              
92              
93             =head2 new
94              
95             Title : new
96             Function : Create a new simulated read object
97             Usage : my $read = Bio::Seq::SimulatedRead->new(
98             -id => 'read001',
99             -reference => $seq_obj ,
100             -errors => $errors ,
101             -start => 10 ,
102             -end => 135 ,
103             -strand => 1 ,
104             );
105             Arguments: -reference => Bio::SeqI, Bio::PrimarySeqI object representing the
106             reference sequence to take the read from. See
107             reference().
108             -errors => Hashref representing the position of errors in the read
109             See errors().
110             -mid => String of a MID to prepend to the read. See mid().
111             -track => Track where the read came from in the read description?
112             See track().
113             -coord_style => Define what coordinate system to use. See coord_style().
114             All other methods from Bio::LocatableSeq are available.
115             Returns : new Bio::Seq::SimulatedRead object
116              
117             =cut
118              
119             sub new {
120 46     46 1 464 my ($class, @args) = @_;
121 46         152 my $self = $class->SUPER::new(@args);
122 46         155 my ($qual_levels, $reference, $mid, $errors, $track, $coord_style) =
123             $self->_rearrange([qw(QUAL_LEVELS REFERENCE MID ERRORS TRACK COORD_STYLE)], @args);
124 46 100       117 $coord_style = defined $coord_style ? $coord_style : 'bioperl';
125 46         121 $self->coord_style($coord_style);
126 46 100       88 $track = defined $track ? $track : 1;
127 46         107 $self->track($track);
128 46 100       75 $qual_levels = defined $qual_levels ? $qual_levels : [];
129 46 50       117 $self->qual_levels($qual_levels) if defined $qual_levels;
130 46 100       120 $self->reference($reference) if defined $reference;
131 46 100       80 $self->mid($mid) if defined $mid;
132 46         69 $self->{_mutated} = 0;
133 46 100       117 $self->errors($errors) if defined $errors;
134 46         209 return $self;
135             }
136              
137              
138             =head2 qual_levels
139              
140             Title : qual_levels
141             Function : Get or set the quality scores to give to the read. By default, if your
142             reference sequence does not have quality scores, no quality scores
143             are generated for the simulated read. The generated quality scores
144             are very basic. If a residue is error-free, it gets the quality score
145             defined for good residues. If the residue has an error (is an
146             addition or a mutation), the residue gets the quality score specified
147             for bad residues. Call the qual_levels() method before using the
148             reference() method.
149             Usage : my $qual_levels = $read->qual_levels( );
150             Arguments: Array reference containing the quality scores to use for:
151             1/ good residues (e.g. 30)
152             2/ bad residues (e.g. 10)
153             Returns : Array reference containing the quality scores to use.
154              
155             =cut
156              
157             sub qual_levels {
158 153     153 1 198 my ($self, $qual_levels) = @_;
159 153 100       218 if (defined $qual_levels) {
160 48 50 66     119 if ( (scalar @$qual_levels != 0) && (scalar @$qual_levels != 2) ) {
161 0         0 $self->throw("The quality score specification must define the score".
162             " to use for good and for bad residues\n");
163             }
164 48         62 $self->{qual_levels} = $qual_levels;
165             }
166 153         376 return $self->{qual_levels};
167             }
168              
169              
170             =head2 reference
171              
172             Title : reference
173             Function : Get or set the reference sequence that the read comes from. Once the
174             reference has been set, you have a functional simulated read which
175             supports all the Bio::LocatableSeq methods. This method must be
176             called after qual_levels() but before mid() or errors().
177             Usage : my $seq_obj = $read->reference();
178             Arguments: Bio::SeqI or Bio::PrimarySeqI object
179             Returns : Bio::SeqI or Bio::PrimarySeqI object
180              
181             =cut
182              
183             sub reference {
184 353     353 1 458 my ($self, $reference) = @_;
185 353 100       475 if (defined $reference) {
186             # Sanity check 1
187 45 50 66     198 if ( (not $reference->isa('Bio::SeqI')) && (not $reference->isa('Bio::PrimarySeqI')) ) {
188 0         0 $self->throw("Expected a Bio::SeqI object as reference, but got: $reference\n");
189             }
190             # Sanity check 2
191 45 50 33     177 if ($self->{mid} || $self->{errors}) {
192 0         0 $self->throw("Cannot change the reference sequence after an MID or ".
193             "sequencing errors have been added to the read\n");
194             }
195             # Use beginning of reference sequence as start default
196 45 100       114 if (not defined $self->start) {
197 40         62 $self->start(1);
198             }
199             # Use end of reference sequence as end default
200 45 100       91 if (not defined $self->end) {
201 40         95 $self->end($reference->length);
202             }
203             # Use strand 1 as strand default
204 45 100       84 if (not defined $self->strand) {
205 39         60 $self->strand(1);
206             }
207             # Set the reference sequence object
208 45         78 $self->{reference} = $reference;
209             # Create a sequence, quality scores and description from the reference
210 45         107 $self->_create_seq;
211 45 100       77 $self->_create_qual if scalar @{$self->qual_levels};
  45         79  
212 45 100       81 $self->_create_desc if $self->track;
213             }
214 353         689 return $self->{reference};
215             }
216              
217              
218             sub _create_seq {
219 45     45   76 my $self = shift;
220             # Get a truncation of the reference sequence
221 45         91 my $reference = $self->reference;
222 45         97 my $read_obj = $reference->trunc( $self->start, $self->end );
223             # Reverse complement the read if needed
224 45 100       168 if ($self->strand == -1) {
225 4         17 $read_obj = $read_obj->revcom();
226             }
227 45         98 $self->seq($read_obj->seq);
228 45         153 return 1;
229             }
230              
231              
232             sub _create_qual {
233 13     13   21 my $self = shift;
234 13         24 $self->qual([ ($self->qual_levels->[0]) x ($self->end - $self->start + 1) ]);
235 13         21 return 1;
236             }
237              
238              
239             sub _create_desc {
240             # Create the read description of the error-free read
241 45     45   53 my $self = shift;
242             # Reference sequence ID
243 45         53 my $desc_str = '';
244 45         86 my $ref_id = $self->reference->id;
245 45 100       85 if (defined $ref_id) {
246 43         110 $desc_str .= 'reference='.$ref_id.' ';
247             }
248             # Position of read on reference sequence: start, end and strand
249 45         86 my $strand = $self->strand;
250 45 100       84 if ($self->coord_style eq 'bioperl') {
251 41         112 $desc_str .= 'start='.$self->start.' end='.$self->end.' ';
252 41 50       90 if (defined $strand) {
253             # Strand of the reference sequence that the read is on
254 41 100       75 $strand = '+1' if $strand == 1;
255 41         72 $desc_str .= 'strand='.$strand.' ';
256             }
257             } else {
258 4 100 66     21 if ( (defined $strand) && ($strand == -1) ) {
259             # Reverse complemented
260 1         2 $desc_str .= 'position=complement('.$self->start.'..'.$self->end.') ';
261             } else {
262             # Regular (forward) orientation
263 3         9 $desc_str .= 'position='.$self->start.'..'.$self->end.' ';
264             }
265             }
266             # Description of the original sequence
267 45         76 my $ref_desc = $self->reference->desc;
268 45 100 66     70 if ( (defined $self->reference->desc) && ($self->reference->desc !~ m/^\s*$/) ) {
269 42         87 $ref_desc =~ s/"/\\"/g; # escape double-quotes to \"
270 42         83 $desc_str .= 'description="'.$ref_desc.'" ';
271             }
272 45         172 $desc_str =~ s/\s$//g;
273             # Record new description
274 45         116 $self->desc($desc_str);
275 45         73 return 1;
276             }
277              
278              
279             =head2 mid
280              
281             Title : mid
282             Function : Get or set a multiplex identifier (or MID, or tag, or barcode) to
283             add to the read. By default, no MID is used. This method must be
284             called after reference() but before errors().
285             Usage : my $mid = read->mid();
286             Arguments: MID sequence string (e.g. 'ACGT')
287             Returns : MID sequence string
288              
289             =cut
290              
291             sub mid {
292 11     11 1 24 my ($self, $mid) = @_;
293 11 100       24 if (defined $mid) {
294             # Sanity check 1
295 8 50       14 if (not defined $self->reference) {
296 0         0 $self->throw("Cannot add MID because the reference sequence was not ".
297             "set\n");
298             }
299             # Sanity check 2
300 8 50       19 if ($self->{errors}) {
301 0         0 $self->throw("Cannot add an MID after sequencing errors have been ".
302             "introduced in the read\n");
303             }
304             # Sanity check 3
305 8 50       19 if (not $self->validate_seq($mid)) {
306 0         0 $self->throw("MID is not a valid DNA sequence\n");
307             }
308             # Update sequence, quality scores and description with the MID
309 8         23 $self->_update_seq_mid($mid);
310 8 100       9 $self->_update_qual_mid($mid) if scalar @{$self->qual_levels};
  8         14  
311 8 50       18 $self->_update_desc_mid($mid) if $self->track;
312             # Set the MID value
313 8         16 $self->{mid} = $mid;
314             }
315             return $self->{mid}
316 11         34 }
317              
318              
319             sub _update_seq_mid {
320             # Update the MID of a sequence
321 8     8   16 my ($self, $mid) = @_;
322             # Remove old MID
323 8         16 my $seq = $self->seq;
324 8         13 my $old_mid = $self->{mid};
325 8 100       16 if (defined $old_mid) {
326 2         28 $seq =~ s/^$old_mid//;
327             }
328             # Add new MID
329 8         12 $seq = $mid . $seq;
330 8         19 $self->seq( $seq );
331 8         9 return 1;
332             }
333              
334              
335             sub _update_qual_mid {
336             # Update the MID of a quality scores
337 4     4   9 my ($self, $mid) = @_;
338             # Remove old MID
339 4         10 my $qual = $self->qual;
340 4         6 my $old_mid = $self->{mid};
341 4 100       10 if (defined $old_mid) {
342 1         4 splice @$qual, 0, length($old_mid);
343             }
344 4         9 $qual = [($self->qual_levels->[0]) x length($mid), @$qual];
345 4         10 $self->qual( $qual );
346 4         6 return 1;
347             }
348              
349              
350             sub _update_desc_mid {
351             # Update MID specifications in the read description
352 9     9   16 my ($self, $mid) = @_;
353 9 100       17 if ($mid) {
354             # Sequencing errors introduced in the read
355 7         15 my $mid_str = "mid=".$mid;
356 7         13 my $desc_str = $self->desc;
357 7         93 $desc_str =~ s/((position|strand)=\S+)( mid=\S+)?/$1 $mid_str/g;
358 7         20 $self->desc( $desc_str );
359             }
360 9         13 return 1;
361             }
362              
363              
364             =head2 errors
365              
366             Title : errors
367             Function : Get or set the sequencing errors and update the read. By default, no
368             errors are made. This method must be called after the mid() method.
369             Usage : my $errors = $read->errors();
370             Arguments: Reference to a hash of the position and nature of sequencing errors.
371             The positions are 1-based relative to the error-free MID-containing
372             read (not relative to the reference sequence). For example:
373             $errors->{34}->{'%'} = 'T' ; # substitution of residue 34 by a T
374             $errors->{23}->{'+'} = 'GG' ; # insertion of GG after residue 23
375             $errors->{45}->{'-'} = undef; # deletion of residue 45
376             Substitutions and deletions are for a single residue, but additions
377             can be additions of several residues.
378             An alternative way to specify errors is by using array references
379             instead of scalar for the hash values. This allows one to specify
380             redundant mutations. For example, the case presented above would
381             result in the same read sequence as the example below:
382             $errors->{34}->{'%'} = ['C', 'T'] ; # substitution by a C and then a T
383             $errors->{23}->{'+'} = ['G', 'G'] ; # insertion of G and then a G
384             $errors->{45}->{'-'} = [undef, undef]; # deletion of residue, and again
385             Returns : Reference to a hash of the position and nature of sequencing errors.
386              
387             =cut
388              
389             sub errors {
390 93     93 1 142 my ($self, $errors) = @_;
391 93 100       169 if (defined $errors) {
392             # Verify that we have a hashref
393 28 50 33     119 if ( (not defined ref $errors) || (not ref $errors eq 'HASH') ) {
394 0         0 $self->throw("Error specification has to be a hashref. Got: $errors\n");
395             }
396             # Verify that we have a reference sequence
397 28 50       62 if (not defined $self->reference) {
398 0         0 $self->throw("Cannot add errors because the reference sequence was not set\n");
399             }
400             # Convert scalar error specs to arrayref specs
401 28         65 $errors = $self->_scalar_to_arrayref($errors);
402             # Check validity of error specifications
403 28         60 $errors = $self->_validate_error_specs($errors);
404             # Set the error specifications
405 28         53 $self->{errors} = $errors;
406             # Need to recalculate the read from the reference if previously mutated
407 28 50       56 if ($self->{_mutated}) {
408 0         0 $self->_create_seq;
409 0 0       0 $self->_create_qual if scalar @{$self->qual_levels};
  0         0  
410 0 0       0 $self->_create_desc if $self->track;
411             }
412             # Now mutate the read, quality score and description
413 28         66 $self->_update_seq_errors;
414 28 100       40 $self->_update_qual_errors if scalar @{$self->qual_levels};
  28         47  
415 28 50       68 $self->_update_desc_errors if $self->track;
416              
417             }
418 93         145 return $self->{errors};
419             }
420              
421              
422             sub _scalar_to_arrayref {
423             # Replace the scalar values in the error specs by more versatile arrayrefs
424 28     28   44 my ($self, $errors) = @_;
425 28         112 while ( my ($pos, $ops) = each %$errors ) {
426 38         109 while ( my ($op, $res) = each %$ops ) {
427 40 100       87 if (ref $res eq '') {
428 36   100     137 my $arr = [ split //, ($res || '') ];
429 36 100       102 $arr = [undef] if scalar @$arr == 0;
430 36         148 $$errors{$pos}{$op} = $arr;
431             }
432             }
433             }
434 28         46 return $errors;
435             }
436              
437              
438             sub _validate_error_specs {
439             # Clean error specifications and warn of any issues encountered
440 28     28   53 my ($self, $errors) = @_;
441 28         81 my %valid_ops = ('%' => undef, '-' => undef, '+' => undef); # valid operations
442              
443             # Calculate read length
444 28         75 my $read_length = $self->length;
445 28         87 while ( my ($pos, $ops) = each %$errors ) {
446              
447             # Position cannot be no longer than the read length
448 38 100 66     131 if ( (defined $read_length) && ($pos > $read_length) ) {
449 3         19 $self->warn("Position $pos is beyond end of read ($read_length ".
450             "residues). Skipping errors specified at this position.\n");
451 3         7 delete $errors->{$pos};
452             }
453              
454             # Position has to be 0+ for addition, 1+ for substitution and deletion
455 38 100 100     91 if ( $pos < 1 && (exists $ops->{'%'} || exists $ops->{'-'}) ) {
      100        
456 2         27 $self->warn("Positions of substitutions and deletions have to be ".
457             "strictly positive but got $pos. Skipping substitution or deletion".
458             " at this position\n");
459 2         7 delete $ops->{'%'};
460 2         6 delete $ops->{'-'};
461             }
462 38 0 33     68 if ( $pos < 0 && exists $ops->{'+'}) {
463 0         0 $self->warn("Positions of additions have to be zero or more. ".
464             "Skipping addition at position $pos.\n");
465 0         0 delete $ops->{'+'};
466             }
467              
468             # Valid operations are '%', '+' and '-'
469 38         96 while ( my ($op, $res) = each %$ops ) {
470 38 50       69 if (not exists $valid_ops{$op}) {
471 0         0 $self->warn("Skipping unknown error operation '$op' at position".
472             " $pos\n");
473 0         0 delete $ops->{$op};
474             } else {
475             # Substitutions: have to have at least one residue to substitute
476 38 50 66     98 if ( ($op eq '%') && (scalar @$res < 1) ) {
477 0         0 $self->warn("At least one residue must be provided for substitutions,".
478             "but got ".scalar(@$res)." at position $pos.\n");
479             }
480             # Additions: have to have at least one residue to add
481 38 50 66     98 if ( ($op eq '+') && (scalar @$res < 1) ) {
482 0         0 $self->warn("At least one residue must be provided for additions,".
483             "but got ".scalar(@$res)." at position $pos.\n");
484             }
485             # Deletions
486 38 50 66     133 if ( ($op eq '-') && (scalar @$res < 1) ) {
487 0         0 $self->warn("At least one 'undef' must be provided for deletions,".
488             "but got ".scalar(@$res)." at position $pos.\n");
489             }
490             }
491             }
492              
493 38 100       138 delete $errors->{$pos} unless scalar keys %$ops;
494             }
495              
496 28         64 return $errors;
497             }
498              
499              
500             sub _update_seq_errors {
501 28     28   36 my $self = shift;
502 28         89 my $seq_str = $self->seq;
503 28         56 my $errors = $self->errors;
504 28 100       68 if (scalar keys %$errors > 0) {
505 22         39 my $off = 0;
506 22         90 for my $pos ( sort {$a <=> $b} (keys %$errors) ) {
  14         41  
507             # Process sequencing errors at that position
508 33         74 for my $type ( '%', '-', '+' ) {
509 99 100       184 next if not exists $$errors{$pos}{$type};
510 35         49 my $arr = $$errors{$pos}{$type};
511 35 100       89 if ($type eq '%') {
    100          
    50          
512             # Substitution at residue position. If there are multiple
513             # substitutions to do, directly skip to the last one.
514 9         43 substr $seq_str, $pos - 1 + $off, 1, $$arr[-1];
515             } elsif ($type eq '-') {
516             # Deletion at residue position
517 10         22 substr $seq_str, $pos - 1 + $off, 1, '';
518 10         15 $off--;
519             } elsif ($type eq '+') {
520             # Insertion after residue position
521 16         60 substr $seq_str, $pos + $off, 0, join('', @$arr);
522 16         41 $off += scalar @$arr;
523             }
524             }
525             }
526 22         49 $self->{_mutated} = 1;
527             } else {
528 6         13 $self->{_mutated} = 0;
529             }
530 28         63 $self->seq($seq_str);
531 28         42 return 1;
532             }
533              
534              
535             sub _update_qual_errors {
536 6     6   14 my $self = shift;
537 6         20 my $qual = $self->qual;
538 6         18 my $errors = $self->errors;
539 6         17 my $bad_qual = $self->qual_levels->[1];
540 6 50       26 if (scalar keys %$errors > 0) {
541 6         13 my $off = 0;
542 6         25 for my $pos ( sort {$a <=> $b} (keys %$errors) ) {
  5         15  
543             # Process sequencing errors at that position
544 10         20 for my $type ( '%', '-', '+' ) {
545 30 100       67 next if not exists $$errors{$pos}{$type};
546 10         19 my $arr = $$errors{$pos}{$type};
547 10 100       41 if ($type eq '%') {
    100          
    50          
548             # Substitution at residue position
549 3         16 splice @$qual, $pos - 1 + $off, 1, $bad_qual;
550             } elsif ($type eq '-') {
551             # Deletion at residue position
552 2         7 splice @$qual, $pos - 1 + $off, 1;
553 2         5 $off--;
554             } elsif ($type eq '+') {
555             # Insertion after residue position
556 5         26 splice @$qual, $pos + $off, 0, ($bad_qual) x scalar(@$arr);
557 5         15 $off += scalar @$arr;
558             }
559             }
560             }
561             }
562 6         21 $self->qual($qual);
563 6         13 return 1;
564             }
565              
566              
567             sub _update_desc_errors {
568             # Add or update error specifications in the read description
569 29     29   45 my $self = shift;
570 29         52 my $errors = $self->errors;
571 29 100 66     114 if (defined $errors and scalar keys %$errors > 0) {
572             # Sequencing errors introduced in the read
573 23         40 my $err_str = 'errors=';
574 23         72 for my $pos ( sort {$a <=> $b} (keys %$errors) ) {
  14         33  
575             # Process sequencing errors at that position
576 34         56 for my $type ( '%', '-', '+' ) {
577 102 100       174 next if not exists $$errors{$pos}{$type};
578 36         46 for my $val ( @{$$errors{$pos}{$type}} ) {
  36         82  
579 50 100       80 $val = '' if not defined $val;
580 50         108 $err_str .= $pos . $type . $val . ',';
581             }
582             }
583             }
584 23         112 $err_str =~ s/,$//;
585 23         64 my $desc_str = $self->desc;
586 23         333 $desc_str =~ s/((position|strand)=\S+( mid=\S+)?)( errors=\S+)?/$1 $err_str/g;
587 23         110 $self->desc( $desc_str );
588             }
589 29         40 return 1;
590             }
591              
592              
593             =head2 track
594              
595             Title : track
596             Function : Get or set the tracking status in the read description. By default,
597             tracking is on. This method can be called at any time.
598             Usage : my $track = $read->track();
599             Arguments: 1 for tracking, 0 otherwise
600             Returns : 1 for tracking, 0 otherwise
601              
602             =cut
603              
604             sub track {
605 134     134 1 184 my ($self, $track) = @_;
606 134 100       209 if (defined $track) {
607 48 100       106 if (defined $self->reference) {
608 2 100       5 if ($track == 1) {
609 1         4 $self->_create_desc;
610 1         3 $self->_update_desc_mid($self->mid);
611 1         2 $self->_update_desc_errors;
612             } else {
613 1         3 $self->desc(undef);
614             }
615             }
616 48         68 $self->{track} = $track;
617             }
618 134         301 return $self->{track};
619             }
620              
621              
622             =head2 coord_style
623              
624             Title : coord_style
625             Function : When tracking is on, define which 1-based coordinate system to use
626             in the read description:
627             * 'bioperl' uses the start, end and strand keywords (default),
628             similarly to the GFF3 format. Example:
629             start=1 end=10 strand=+1
630             start=1 end=10 strand=-1
631             * 'genbank' does only provide the position keyword. Example:
632             position=1..10
633             position=complement(1..10)
634             Usage : my $coord_style = $read->track();
635             Arguments: 'bioperl' or 'genbank'
636             Returns : 'bioperl' or 'genbank'
637              
638             =cut
639              
640             sub coord_style {
641 91     91 1 141 my ($self, $coord_style) = @_;
642 91         197 my %styles = ( 'bioperl' => undef, 'genbank' => undef );
643 91 100       141 if (defined $coord_style) {
644 46 50       78 if (not exists $styles{$coord_style}) {
645 0         0 die "Error: Invalid coordinate style '$coord_style'\n";
646             }
647 46         103 $self->{coord_style} = $coord_style;
648             }
649 91         210 return $self->{coord_style};
650             }
651              
652              
653             1;