<p>This is because you are also parsing your output file. Remember, the first rule of debugging is to print all the things! Most bugs are because some variable doesn't actually have the value you think it has, and printing them is the best way of finding the problem. I reproduced what (I am guessing) is your setup here:</p>
<pre><code>$ ls
OG0015396-PROT.fa  OG0020551-PROT.fa  OG0025647-PROT.fa
</code></pre>
<p>I then ran your script with an extra <code>print</code> statement:</p>
<pre class="lang-py prettyprint-override"><code>#!/usr/bin/env python3
import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
       for file in os.listdir(&quot;.&quot;):
              print(&quot;FF:&quot;,file)
              seq = SeqIO.parse(file, 'fasta')
              ortog = Path(file).stem
              for record in seq:
                     record.description = ortog
              SeqIO.write(record, output, 'fasta')
</code></pre>
<p>Which printed:</p>
<pre><code>$ foo.py
FF: OG0015396-PROT.fa
FF: OG0020551-PROT.fa
FF: output.fasta
FF: OG0025647-PROT.fa
</code></pre>
<p>As you can see, since the <code>output.fasta</code> file is created by the <code>open()</code> call, by the time you use <code>listdir</code>, it's already there and included. This results in duplicated sequences (not always the last one). I'm sure there are more elegant solutions, but a simple workaround is to skip the output file name:</p>
<pre><code>#!/usr/bin/env python3
import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
       for file in os.listdir(&quot;.&quot;):
              if file == &quot;output.fasta&quot;:
                     continue
              seq = SeqIO.parse(file, 'fasta')
              ortog = Path(file).stem
              for record in seq:
                     record.description = ortog
              SeqIO.write(record, output, 'fasta')
</code></pre>
<p>Of course, this whole thing is a bit overkill for such a simple task and you could just use <code>sed</code> and the shell instead:</p>
<pre><code>for file in *fa; do sed &quot;1s|$| ${file//.fa}|&quot; &quot;$file&quot;; done &gt; output.fasta 
</code></pre>

CC BY-SA 4.0
2022-10-21T20:26:09.033Z
Thank you! It makes so much sense now. I managed to solve the problem by changing the identation of the SeqIO.write() function to the last for loop, but I didn't understand what was wrong before. Your resolution makes it clearer.
Eduardo Menotti
CC BY-SA 4.0
2022-10-21T20:32:13.690Z
You're welcome @EduardoMenotti. But please also take M__'s advice, I'm sure he's right about using the `id` and he makes a very good point about not using `seq` as a variable name. Just make sure to skip the output file or simply save the output to a different directory or just write to standard output and redirect to a file.
terdon
CC BY-SA 4.0
2022-10-21T20:19:05.517Z
2022-10-21T20:19:05.517Z
terdon
<p>I have several fasta files that represent the proteins from different orthogroups. However, the orthogroup that each of the proteins belongs to is not indicated within the files. I am leveraging <a href="https://biopython.org" rel="nofollow noreferrer">BioPython</a> and I want to add this information to the header of each sequence in the fasta files.</p>
<pre class="lang-py prettyprint-override"><code>import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
    for file in os.listdir(dirname):
        seq = SeqIO.parse(file, 'fasta')
        ortog = Path(file).stem
        for record in seq:
            record.description = ortog
        SeqIO.write(record, output, 'fasta')
</code></pre>
<p>However, the output always appears with the last sequence duplicated. In the case of three fasta files, the output appears as:</p>
<pre><code>&gt;BBC_8_672 OG0015396-PROT
MKFSSVTAITLATVATVATAKKGEHDFTTTLTLSSDGSLTTTTSTHTTHKYGKFNKTSKS
KTPNHTGTHKYGKFNKTSKSKTP
&gt;CAT_6_3128 OG0020551-PROT
MEKIKEKLNSLKLESESWQEKYEELREQLKELEQSNTEKENEIKSLSAKNEQLDSEVEKL
ESQLSDTKQLAEDSNNLRSNNENYTKKNQDLEQQLEDSEAKLKEAMDKLKEADLNSEQMG
RRIVALEEERDEWEKKCEEFQSKYEEAQKELDEIANSLENL
&gt;ZSA_0_3121 OG0025647-PROT
LLLQYQLHPALLPKALLLQYQLHQALLLKALLLQ*PALLLKALLLQYQLHQALLLKALLL
QYQLHPALLLKALLLQYQLHP
&gt;ZSA_0_3121 OG0025647-PROT
LLLQYQLHPALLPKALLLQYQLHQALLLKALLLQ*PALLLKALLLQYQLHQALLLKALLL
QYQLHPALLLKALLLQYQLHP
</code></pre>
<p>Could anyone tell me why this is happening?</p>

CC BY-SA 4.0
2022-10-21T20:08:17.500Z
So what do you see when you add `print(file)` in the `for file` loop? Are some of the file names repeated?
terdon
<python><phylogenetics><orthologues><multi-fasta>
Add file name to FASTA file header using SeqIO
# Add file name to FASTA file header using SeqIO

(Asked by: username_0 on 2022-10-21)

I have several fasta files that represent the proteins from different orthogroups. However, the orthogroup that each of the proteins belongs to is not indicated within the files. I am leveraging BioPython and I want to add this information to the header of each sequence in the fasta files.
import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
    for file in os.listdir(dirname):
        seq = SeqIO.parse(file, 'fasta')
        ortog = Path(file).stem
        for record in seq:
            record.description = ortog
        SeqIO.write(record, output, 'fasta')

However, the output always appears with the last sequence duplicated. In the case of three fasta files, the output appears as:
>BBC_8_672 OG0015396-PROT
MKFSSVTAITLATVATVATAKKGEHDFTTTLTLSSDGSLTTTTSTHTTHKYGKFNKTSKS
KTPNHTGTHKYGKFNKTSKSKTP
>CAT_6_3128 OG0020551-PROT
MEKIKEKLNSLKLESESWQEKYEELREQLKELEQSNTEKENEIKSLSAKNEQLDSEVEKL
ESQLSDTKQLAEDSNNLRSNNENYTKKNQDLEQQLEDSEAKLKEAMDKLKEADLNSEQMG
RRIVALEEERDEWEKKCEEFQSKYEEAQKELDEIANSLENL
>ZSA_0_3121 OG0025647-PROT
LLLQYQLHPALLPKALLLQYQLHQALLLKALLLQ*PALLLKALLLQYQLHQALLLKALLL
QYQLHPALLLKALLLQYQLHP
>ZSA_0_3121 OG0025647-PROT
LLLQYQLHPALLPKALLLQYQLHQALLLKALLLQ*PALLLKALLLQYQLHQALLLKALLL
QYQLHPALLLKALLLQYQLHP

Could anyone tell me why this is happening?

**Tags:** python, phylogenetics, orthologues, multi-fasta
> **Comments:**
> **username_1**: So what do you see when you add `print(file)` in the `for file` loop? Are some of the file names repeated?  

---

## 1 answers

### Answer by username_1 on 2022-10-21. Score: 0 | Accepted answer

This is because you are also parsing your output file. Remember, the first rule of debugging is to print all the things! Most bugs are because some variable doesn't actually have the value you think it has, and printing them is the best way of finding the problem. I reproduced what (I am guessing) is your setup here:
$ ls
OG0015396-PROT.fa  OG0020551-PROT.fa  OG0025647-PROT.fa

I then ran your script with an extra print statement:
#!/usr/bin/env python3
import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
       for file in os.listdir("."):
              print("FF:",file)
              seq = SeqIO.parse(file, 'fasta')
              ortog = Path(file).stem
              for record in seq:
                     record.description = ortog
              SeqIO.write(record, output, 'fasta')

Which printed:
$ foo.py
FF: OG0015396-PROT.fa
FF: OG0020551-PROT.fa
FF: output.fasta
FF: OG0025647-PROT.fa

As you can see, since the output.fasta file is created by the open() call, by the time you use listdir, it's already there and included. This results in duplicated sequences (not always the last one). I'm sure there are more elegant solutions, but a simple workaround is to skip the output file name:
#!/usr/bin/env python3
import os
from pathlib import Path
from Bio import SeqIO

with open('output.fasta', 'w') as output:
       for file in os.listdir("."):
              if file == "output.fasta":
                     continue
              seq = SeqIO.parse(file, 'fasta')
              ortog = Path(file).stem
              for record in seq:
                     record.description = ortog
              SeqIO.write(record, output, 'fasta')

Of course, this whole thing is a bit overkill for such a simple task and you could just use sed and the shell instead:
for file in *fa; do sed "1s|$| ${file//.fa}|" "$file"; done > output.fasta

> **Comments:**
> **username_0**: Thank you! It makes so much sense now. I managed to solve the problem by changing the identation of the SeqIO.write() function to the last for loop, but I didn't understand what was wrong before. Your resolution makes it clearer.  
> **username_1**: You're welcome @EduardoMenotti. But please also take M__'s advice, I'm sure he's right about using the `id` and he makes a very good point about not using `seq` as a variable name. Just make sure to skip the output file or simply save the output to a different directory or just write to standard output and redirect to a file.  

---

