Repository: biopython/biopython

Issue:
SeqIO error: local variable 'qual' referenced before assignment
### Setup

I am reporting a problem with Biopython version, Python version, and operating
system as follows:

```python
import sys; print(sys.version)
3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)]

import platform; print(platform.python_implementation()); print(platform.platform())
CPython
Windows-10-10.0.18362-SP0

import Bio; print(Bio.__version__)
1.76
```

### Expected behaviour

I send some samples for Sanger sequencing to a commercial facility. I'm able to read the files they send using the command
```
from Bio import SeqIO
from Bio import Seq
rec = SeqIO.read("isolation-round4/3dr23_Forward.ab1",'abi-trim').seq
```

This worked fine until now. 
### Actual behaviour
But recently, due to a move, we had to send the samples elsewhere for sequencing. Now, if I try to run the same command on the files they send to me, I get an error:
``UnboundLocalError: local variable 'qual' referenced before assignment    in
  File "C:\Users\Anaconda3\lib\site-packages\Bio\SeqIO\AbiIO.py", line 462, in AbiIterator
    letter_annotations={"phred_quality": qual}``

### Steps to reproduce

I have uploaded two files, one that works with the above code and one that does not.  They can be downloaded here: [https://easyupload.io/m/k2f60x](url) 

I posted this problem on Biostars ([https://www.biostars.org/p/455577/#455598](url)) and was told to open an issue here. I had also posted it on Stackoverflow ([https://stackoverflow.com/questions/63420626/biopython-seqio-error-local-variable-qual-referenced-before-assignment](url))

This is my first time opening an issue here, so please let me know if you need any more information from me. 
I would appreciate any help with this!
Thank you. 


Discussion:
I think this was fixed in #1037, can you try Biopython 1.77 please?
I upgraded it to 1.77, but still get the same error. :( 
Ah. I was hoping this would be very easy. On the bright side, your example breaks for me too (macOS):

```
$ python -c "from Bio import SeqIO; print(SeqIO.read('Works.ab1', 'abi').seq)"
NNCTACGGTAGGGGTGCAAGCGTTAATCGGAATTACTGGGCGTAAAGCGTGCGCAGGCGGTTCGGAAAGAAAGATGTGAAATCCCAGAGCTTAACTTTGGAACTGCATTTTTAACTACCGAGCTAGAGTGTGTCAGAGGGAGGTGGAATTCCGCGTGTAGCAGTGAAATGCGTAGATATGCGGAGGAACACCGATGGCGAAGGCAGCCTCCTGGGATAACACTGACGCTCATGCACGAAAGCGTGGGGAGCAAACAGGATTAGATACCCCGGTAGTCCGGCTGACTGACTTAGCTCGTAACTATCTCGTATGCCGTCTTTCTGCTTGAGA
```

And,

```
$ python -c "from Bio import SeqIO; print(SeqIO.read('Doesnotwork.ab1', 'abi').seq)"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/Users/xxx/site-packages/Bio/SeqIO/__init__.py", line 656, in read
    record = next(iterator)
  File "/Users/xxx/site-packages/Bio/SeqIO/Interfaces.py", line 71, in __next__
    return next(self.records)
  File "/Users/xxx/site-packages/Bio/SeqIO/AbiIO.py", line 444, in iterate
    letter_annotations={"phred_quality": qual},
UnboundLocalError: local variable 'qual' referenced before assignment
```
Interesting. The problem file does not have the PCON2 field (or the PCON1 field) for quality scores - only:

``['AEPt1', 'AEPt2', 'ASPt1', 'ASPt2', 'B1Pt1', 'B1Pt2', 'CMNT1', 'CTTL1', 'DATA1', 'DATA2', 'DATA3', 'DATA4', 'DATA5', 'DATA6', 'DATA7', 'DATA8', 'DATA9', 'DATA10', 'DATA11', 'DATA12', 'EVNT1', 'EVNT2', 'EVNT3', 'EVNT4', 'FWO_1', 'LANE1', 'LIMS1', 'MCHN1', 'MODL1', 'NAVG1', 'NLNE1', 'PBAS1', 'PBAS2', 'PDMF1', 'PDMF2', 'PLOC1', 'PLOC2', 'RUND1', 'RUND2', 'RUND3', 'RUND4', 'RUNT1', 'RUNT2', 'RUNT3', 'RUNT4', 'RevC1', 'S/N%1', 'SMPL1', 'SPAC1', 'SPAC2', 'SPAC3', 'SVER1', 'SVER2', 'SVER3', 'THUM1', 'THUM2']``

The following patch "works" in that you can parse the file and get a sequence, but I'd like to know what is different here:

```
$ git diff
diff --git a/Bio/SeqIO/AbiIO.py b/Bio/SeqIO/AbiIO.py
index 89c3a391f..1a0c3e90a 100644
--- a/Bio/SeqIO/AbiIO.py
+++ b/Bio/SeqIO/AbiIO.py
@@ -382,6 +382,7 @@ class AbiIterator(SequenceIterator):
         sample_id = "<unknown id>"
 
         raw = {}
+        seq = qual = sample_id = None
         for tag_name, tag_number, tag_data in _abi_parse_header(header, handle):
             key = tag_name + str(tag_number)
 
@@ -441,8 +442,10 @@ class AbiIterator(SequenceIterator):
                 name=file_name,
                 description="",
                 annotations=annot,
-                letter_annotations={"phred_quality": qual},
             )
+        if qual:
+            # Expect this to be missing for FSA files.
+            record.letter_annotations["phred_quality"] = qual
 
         if self.trim and not is_fsa_file:
             record = _abi_trim(record)
```

Presumably the second sequencing centre have their ABI machine setup differently... but how and why?

Can you take a look please @bow?

Resolving patch:
diff --git a/Bio/SeqIO/AbiIO.py b/Bio/SeqIO/AbiIO.py
--- a/Bio/SeqIO/AbiIO.py
+++ b/Bio/SeqIO/AbiIO.py
@@ -382,6 +382,7 @@ def iterate(self, handle):
         sample_id = "<unknown id>"
 
         raw = {}
+        seq = qual = None
         for tag_name, tag_number, tag_data in _abi_parse_header(header, handle):
             key = tag_name + str(tag_number)
 
@@ -441,7 +442,14 @@ def iterate(self, handle):
                 name=file_name,
                 description="",
                 annotations=annot,
-                letter_annotations={"phred_quality": qual},
+            )
+        if qual:
+            # Expect this to be missing for FSA files.
+            record.letter_annotations["phred_quality"] = qual
+        elif not is_fsa_file and not qual and self.trim:
+            raise ValueError(
+                "The 'abi-trim' format can not be used for files without"
+                " quality values."
             )
 
         if self.trim and not is_fsa_file:


Test patch: