Answers.Body: <p>If I use <code>SeqIO.parse(filehandle, 'fasta')</code> to parse a FASTA file, then it will return a <code>SeqRecord</code> object where the <code>id</code> and <code>name</code> are the first word (everything before the first whitespace) of the line beginning with <code>&gt;</code> and the <code>description</code> is the complete line (all not including the initial <code>&gt;</code>). (This behaviour can overruled by providing <a href="https://github.com/biopython/biopython/blob/dbdf7c155af3e7f203ea966acedc12740271ed73/Bio/SeqIO/FastaIO.py#L102" rel="noreferrer">a custom <code>title2ids</code> function</a>).</p>
  
  <p>So, if I for example have a <code>original.fasta</code> file like:</p>
  
  <pre><code>&gt;Lorem|ipsum&gt;dolor sit amet
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  </code></pre>
  
  <p>Then I will get:</p>
  
  <pre><code>&gt;&gt;&gt; from Bio import SeqIO
  &gt;&gt;&gt; path = r'C:\path\to\original.fasta'
  &gt;&gt;&gt; records = SeqIO.parse(open(path), 'fasta')
  &gt;&gt;&gt; record = next(records)
  &gt;&gt;&gt; record.id
  'Lorem|ipsum&gt;dolor'
  &gt;&gt;&gt; record.name
  'Lorem|ipsum&gt;dolor'
  &gt;&gt;&gt; record.description
  'Lorem|ipsum&gt;dolor sit amet'
  </code></pre>
  
  <p>So, what happens in my case when you do </p>
  
  <pre><code>    if record.id == 'foo':
          record.id = 'bar'
  </code></pre>
  
  <p>is that the <code>record.id</code> is successfully changed from <code>foo</code> to <code>bar</code>, but that the <code>record.description</code> is not changed and stays <code>foo</code>. That's why, when the FASTA file is printed out, I see the described behaviour of </p>
  
  <pre><code>&gt;bar foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  </code></pre>
  
  <p>So, the solution to my problem is to both change the <code>id</code> AND the <code>description</code>:</p>
  
  <pre><code>from Bio import SeqIO
  
  original_file = r"path\to\original.fasta"
  corrected_file = r"path\to\corrected.fasta"
  
  with open(original_file) as original, open(corrected_file, 'w') as corrected:
      records = SeqIO.parse(original_file, 'fasta')
      for record in records:
          if record.id == 'foo':
              record.id = 'bar'
              record.description = 'bar'
          SeqIO.write(record, corrected, 'fasta')
  
  with open(corrected_file) as corrected:
      records = SeqIO.parse(corrected, 'fasta')
      for record in records:
          print record.id             # prints bar
          print record.name           # prints bar
          print record.description    # prints bar
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-05-31T14:36:06.500Z
Answers.LastActivityDate: 2017-05-31T19:39:46.323Z
Answers.LastEditDate: 2017-05-31T19:39:46.323Z
Answers.UserDisplayName: BioGeek
Body: <p>I have the following FASTA file, <code>original.fasta</code>:</p>
  
  <pre><code>&gt;foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  </code></pre>
  
  <p>I need to change the record id from <code>foo</code> to <code>bar</code>, so I wrote the following code:</p>
  
  <pre><code>from Bio import SeqIO
  
  original_file = r"path\to\original.fasta"
  corrected_file = r"path\to\corrected.fasta"
  
  with open(original_file) as original, open(corrected_file, 'w') as corrected:
      records = SeqIO.parse(original_file, 'fasta')
      for record in records:
          print record.id             # prints 'foo'
          if record.id == 'foo':
              record.id = 'bar'
          print record.id             # prints 'bar' as expected
          SeqIO.write(record, corrected, 'fasta')
  </code></pre>
  
  <p>We printed the record id before and after the change, and get the expected result. We can even doublecheck by reading in the corrected file again with BioPython and printing out the record id:</p>
  
  <pre><code>with open(corrected_file) as corrected:
      for record in SeqIO.parse(corrected, 'fasta'):
          print record.id                  # prints 'bar', as expected
  </code></pre>
  
  <p>However, if we open the corrected file in a text editor, we see that the record id is not <code>bar</code> but  <code>bar foo</code>:</p>
  
  <pre><code>&gt;bar foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  </code></pre>
  
  <p>We can confirm that this is what is written to the file if we read the file using plain Python:</p>
  
  <pre><code>with open(corrected_file) as corrected:
      print corrected.readlines()[0][1:] # prints 'bar foo'
  </code></pre>
  
  <p>Is this a bug in BioPython? And if not, what did I do wrong and how do I change the record id in a FASTA file using BioPython?</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T13:58:21.710Z
Comments.Text: Keep in mind that `record.id` is not equal to the full record header, as `record.description` is a second part of it. If you parse the headers and they contain two space separated entries, record.id will only print the first one.
Comments.UserDisplayName: Jenez
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:04:02.130Z
Comments.Text: In addition, it seems you open the original file unnecessarily since you never do anything with the `original` object.
Comments.UserDisplayName: Jenez
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:16:39.653Z
Comments.Text: I think @Jenez is completely correct; Also you asked the same question on Biostars and got the same answer https://www.biostars.org/p/156428/
Comments.UserDisplayName: Chris_Rands
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:23:05.713Z
Comments.Text: @Jenez why not post that as an answer?
Comments.UserDisplayName: terdon
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:24:18.933Z
Comments.Text: @Chris_Rands yes, but we need content here so BioGeek was nice enough to ask again so we can have another answered post! Now the next person who comes here with a similar issue will find an answer. Yay!
Comments.UserDisplayName: terdon
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:35:13.910Z
Comments.Text: Don’t write paths as `r"foo\bar"`, this only works on Windows. Write them as `"foo/bar"` (no raw string needed), this works everywhere (including Windows).
Comments.UserDisplayName: Konrad Rudolph
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T14:44:08.590Z
Comments.Text: @terdon Because I felt it didn't accurately answer the question fully. It was more of a nudge in the right direction.
Comments.UserDisplayName: Jenez
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-05-31T15:55:20.467Z
Comments.Text: Regarding file paths, I suppose it is even better to use `os.path.join`, which automatically choses the correct separator.
Comments.UserDisplayName: bli
Tags: <fasta><python>
Title: Changing the record id in a FASTA file using BioPython
ThreadText: # Changing the record id in a FASTA file using BioPython
  
  (Asked by: username_0 on 2017-05-31)
  
  I have the following FASTA file, `original.fasta`:
  
  ```
  >foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  
  ```
  
  I need to change the record id from `foo` to `bar`, so I wrote the following code:
  
  ```
  from Bio import SeqIO
  
  original_file = r"path\to\original.fasta"
  corrected_file = r"path\to\corrected.fasta"
  
  with open(original_file) as original, open(corrected_file, 'w') as corrected:
      records = SeqIO.parse(original_file, 'fasta')
      for record in records:
          print record.id             # prints 'foo'
          if record.id == 'foo':
              record.id = 'bar'
          print record.id             # prints 'bar' as expected
          SeqIO.write(record, corrected, 'fasta')
  
  ```
  
  We printed the record id before and after the change, and get the expected result. We can even doublecheck by reading in the corrected file again with BioPython and printing out the record id:
  
  ```
  with open(corrected_file) as corrected:
      for record in SeqIO.parse(corrected, 'fasta'):
          print record.id                  # prints 'bar', as expected
  
  ```
  
  However, if we open the corrected file in a text editor, we see that the record id is not `bar` but `bar foo`:
  
  ```
  >bar foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  
  ```
  
  We can confirm that this is what is written to the file if we read the file using plain Python:
  
  ```
  with open(corrected_file) as corrected:
      print corrected.readlines()[0][1:] # prints 'bar foo'
  
  ```
  
  Is this a bug in BioPython? And if not, what did I do wrong and how do I change the record id in a FASTA file using BioPython?
  
  **Tags:** fasta, python
  
  > **Comments:**
  > **username_1**: Keep in mind that `record.id` is not equal to the full record header, as `record.description` is a second part of it. If you parse the headers and they contain two space separated entries, record.id will only print the first one.  
  > **username_1**: In addition, it seems you open the original file unnecessarily since you never do anything with the `original` object.  
  > **username_2**: I think @username_1 is completely correct; Also you asked the same question on Biostars and got the same answer https://www.biostars.org/p/156428/  
  > **username_3**: @username_1 why not post that as an answer?  
  > **username_3**: @username_2 yes, but we need content here so username_0 was nice enough to ask again so we can have another answered post! Now the next person who comes here with a similar issue will find an answer. Yay!  
  > **username_4**: Don’t write paths as `r"foo\bar"`, this only works on Windows. Write them as `"foo/bar"` (no raw string needed), this works everywhere (including Windows).  
  > **username_1**: @username_3 Because I felt it didn't accurately answer the question fully. It was more of a nudge in the right direction.  
  > **username_5**: Regarding file paths, I suppose it is even better to use `os.path.join`, which automatically choses the correct separator.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2017-05-31. Score: 11 | Accepted answer
  
  If I use `SeqIO.parse(filehandle, 'fasta')` to parse a FASTA file, then it will return a `SeqRecord` object where the `id` and `name` are the first word (everything before the first whitespace) of the line beginning with `>` and the `description` is the complete line (all not including the initial `>`). (This behaviour can overruled by providing [a custom `title2ids` function](https://github.com/biopython/biopython/blob/dbdf7c155af3e7f203ea966acedc12740271ed73/Bio/SeqIO/FastaIO.py#L102)).
  
  So, if I for example have a `original.fasta` file like:
  
  ```
  >Lorem|ipsum>dolor sit amet
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  
  ```
  
  Then I will get:
  
  ```
  >>> from Bio import SeqIO
  >>> path = r'C:\path\to\original.fasta'
  >>> records = SeqIO.parse(open(path), 'fasta')
  >>> record = next(records)
  >>> record.id
  'Lorem|ipsum>dolor'
  >>> record.name
  'Lorem|ipsum>dolor'
  >>> record.description
  'Lorem|ipsum>dolor sit amet'
  
  ```
  
  So, what happens in my case when you do
  
  ```
      if record.id == 'foo':
          record.id = 'bar'
  
  ```
  
  is that the `record.id` is successfully changed from `foo` to `bar`, but that the `record.description` is not changed and stays `foo`. That's why, when the FASTA file is printed out, I see the described behaviour of
  
  ```
  >bar foo
  GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA
  
  ```
  
  So, the solution to my problem is to both change the `id` AND the `description`:
  
  ```
  from Bio import SeqIO
  
  original_file = r"path\to\original.fasta"
  corrected_file = r"path\to\corrected.fasta"
  
  with open(original_file) as original, open(corrected_file, 'w') as corrected:
      records = SeqIO.parse(original_file, 'fasta')
      for record in records:
          if record.id == 'foo':
              record.id = 'bar'
              record.description = 'bar'
          SeqIO.write(record, corrected, 'fasta')
  
  with open(corrected_file) as corrected:
      records = SeqIO.parse(corrected, 'fasta')
      for record in records:
          print record.id             # prints bar
          print record.name           # prints bar
          print record.description    # prints bar
  
  ```
  
  
  ---
  
  