Answers.Body: <p>I don't know how to do this with biopython, but it's simple enough in Perl using <a href="http://swissknife.sourceforge.net/" rel="nofollow noreferrer">Swisskinfe</a>:</p>
  
  <pre class="lang-perl prettyprint-override"><code>#!/usr/bin/env perl
  use strict;
  use warnings;
  use SWISS::Entry;
  
  my $flat=$ARGV[0]||die("Need a flat file\n");
  
  ## Change the line termination string so we read an 
  ## entire entry at a time
  local $/ = "\n//\n";
  
  my $fh;
  ## Deal with compressed or uncompressed files
  if($flat=~/\.gz$/){
      open($fh,"zcat $flat |")|| die("cannot open flat file $flat : $! \n");
  }
  else{
      open($fh,"$flat")|| die("cannot open flat file $flat : $!: $@\n");
  }
  ## Parse the file. 
  entry: while (my $current_entry = &lt;$fh&gt;) {
      ## Read the current entry as an "entry" object
      my $entry = SWISS::Entry-&gt;fromText($current_entry);
      ## Iterate over the entry's features
      foreach my $feature ($entry-&gt;FTs-&gt;elements()) {
          ## If any of the features are 'TRANSMEM', print the entry
          if ($feature-&gt;[0] eq 'TRANSMEM') {
              print "$current_entry\n";
              ## Skip to the next entry
              next entry;
          }
      }
  }
  </code></pre>
  
  <p>You need to install the Swissknife module first:</p>
  
  <ol>
  <li><p>Download Swissknife_1.73.tar.gz from <a href="https://sourceforge.net/projects/swissknife/files/latest/download" rel="nofollow noreferrer">here</a> (SourceForge link).</p></li>
  <li><p>Install</p>
  
  <pre><code>tar xvzf Swissknife.tar.gz
  cd Swissknife_1.73/
  perl Makefile.PL
  sudo make install
  </code></pre></li>
  </ol>
  
  <p>Now, make the script above executable and run with:</p>
  
  <pre><code>foo.pl file.flat
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-06-29T11:26:35.603Z
Answers.LastActivityDate: 2017-06-29T11:33:38.093Z
Answers.LastEditDate: 2017-06-29T11:33:38.093Z
Answers.UserDisplayName: terdon
Answers.Body: <p>Using <code>SeqIO.index</code> rather than <code>SeqIO.parse</code> lets you read all the records into a <code>dict</code>, from which you can then extract the raw entry:</p>
  
  <pre class="lang-python prettyprint-override"><code>from Bio import SeqIO
  
  record_dict = SeqIO.index('Input.txt', 'swiss')
  for key in record_dict:
      print(record_dict.get_raw(key).decode())
  </code></pre>
  
  <p>Now you should be able to apply your test for a transmembrane protein to each entry, and write out only the ones you want to keep.</p>
  
  <pre class="lang-python prettyprint-override"><code>from Bio import SeqIO
  
  record_dict = SeqIO.index('Input.txt', 'swiss')
  out = open('Output.txt', 'wb')
  for key in record_dict:
      record = record_dict[key]
      for i, feature in enumerate(record.features):
      if feature.type == "TRANSMEM":
          out.write(record_dict.get_raw(key).decode())
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-06-30T04:12:04.307Z
Answers.Text: Perfect solution, worked like a charm.
Answers.UserDisplayName: James
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-06-29T11:14:06.497Z
Answers.LastActivityDate: 2017-06-29T11:14:06.497Z
Answers.UserDisplayName: sjcockell
Body: <p>I have the following mwe for filtering a Swissprot file based on a certain feature, in this case, transmembrane regions. </p>
  
  <pre><code>from Bio import SeqIO
  records=[]
  for record in SeqIO.parse("Input.txt", "swiss"):
      transmembrane_protein=False
      print record.id
      for i, feature in enumerate(record.features):
          if feature.type == "TRANSMEM":
              transmembrane_protein=True
      if transmembrane_protein==True:
          records.append(record)
  SeqIO.write(records, "Output.txt", "swiss")
  </code></pre>
  
  <p>The script works when <code>SeqIO.write(records, "Output.txt", "swiss")</code> becomes <code>SeqIO.write(records, "Output.txt", "fasta")</code></p>
  
  <p>However, such a method is not yet supported.  </p>
  
  <pre><code>ValueError: Reading format 'swiss' is supported, but not writing
  </code></pre>
  
  <p>From the docs, I see that <a href="http://biopython.org/DIST/docs/api/Bio.SeqIO-module.html" rel="nofollow noreferrer">writing is not supported for swiss</a>:</p>
  
  <blockquote>
    <p>Note that while Bio.SeqIO can read all the above file formats, it cannot write to all of them.</p>
  </blockquote>
  
  <p>Is there any unofficial way of using biopython/python to write swissprot files from parsed swissprot files? </p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-06-29T09:12:53.440Z
Comments.Text: I read that "SeqIO cannot output the file format (e.g. the plain text SwissProt format, "swiss") ". But you could paste the proteins without using Biopython once you know the id of the features you want
Comments.UserDisplayName: llrs
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-06-29T09:20:23.733Z
Comments.Text: It must be in some of the docs somewhere I'm sure, I just haven't seen it explicitly stated, but it is pointed out in the error handling so that's good enough for me to know there is no easy way. I'm dealing with several proteomes. Manual pasting wouldn't be fun ;) I could really do with a programmatic solution.
Comments.UserDisplayName: James
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-06-29T09:22:05.313Z
Comments.Text: You could use grep, or awk to select the records and output them in another file using a pipe.
Comments.UserDisplayName: llrs
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-06-29T09:59:25.013Z
Comments.Text: @Llopis That would certainly be one way forward. However I'd like to keep the script in a single python file because it's cross platform and transportable.
Comments.UserDisplayName: James
Tags: <database><python>
Title: Is there any way of using biopython to write Swissprot files?
ThreadText: # Is there any way of using biopython to write Swissprot files?
  
  (Asked by: username_0 on 2017-06-29)
  
  I have the following mwe for filtering a Swissprot file based on a certain feature, in this case, transmembrane regions.
  
  ```
  from Bio import SeqIO
  records=[]
  for record in SeqIO.parse("Input.txt", "swiss"):
      transmembrane_protein=False
      print record.id
      for i, feature in enumerate(record.features):
          if feature.type == "TRANSMEM":
              transmembrane_protein=True
      if transmembrane_protein==True:
          records.append(record)
  SeqIO.write(records, "Output.txt", "swiss")
  
  ```
  
  The script works when `SeqIO.write(records, "Output.txt", "swiss")` becomes `SeqIO.write(records, "Output.txt", "fasta")`
  
  However, such a method is not yet supported.
  
  ```
  ValueError: Reading format 'swiss' is supported, but not writing
  
  ```
  
  From the docs, I see that [writing is not supported for swiss](http://biopython.org/DIST/docs/api/Bio.SeqIO-module.html):
  
  > Note that while Bio.SeqIO can read all the above file formats, it cannot write to all of them.
  
  Is there any unofficial way of using biopython/python to write swissprot files from parsed swissprot files?
  
  **Tags:** database, python
  
  > **Comments:**
  > **username_1**: I read that "SeqIO cannot output the file format (e.g. the plain text SwissProt format, "swiss") ". But you could paste the proteins without using Biopython once you know the id of the features you want  
  > **username_0**: It must be in some of the docs somewhere I'm sure, I just haven't seen it explicitly stated, but it is pointed out in the error handling so that's good enough for me to know there is no easy way. I'm dealing with several proteomes. Manual pasting wouldn't be fun ;) I could really do with a programmatic solution.  
  > **username_1**: You could use grep, or awk to select the records and output them in another file using a pipe.  
  > **username_0**: @Llopis That would certainly be one way forward. However I'd like to keep the script in a single python file because it's cross platform and transportable.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_3 on 2017-06-29. Score: 6 | Accepted answer
  
  Using `SeqIO.index` rather than `SeqIO.parse` lets you read all the records into a `dict`, from which you can then extract the raw entry:
  
  ```python
  from Bio import SeqIO
  
  record_dict = SeqIO.index('Input.txt', 'swiss')
  for key in record_dict:
      print(record_dict.get_raw(key).decode())
  
  ```
  
  Now you should be able to apply your test for a transmembrane protein to each entry, and write out only the ones you want to keep.
  
  ```python
  from Bio import SeqIO
  
  record_dict = SeqIO.index('Input.txt', 'swiss')
  out = open('Output.txt', 'wb')
  for key in record_dict:
      record = record_dict[key]
      for i, feature in enumerate(record.features):
      if feature.type == "TRANSMEM":
          out.write(record_dict.get_raw(key).decode())
  
  ```
  
  > **Comments:**
  > **username_0**: Perfect solution, worked like a charm.  
  
  ---
  
  ### Answer by username_2 on 2017-06-29. Score: 2
  
  I don't know how to do this with biopython, but it's simple enough in Perl using [Swisskinfe](http://swissknife.sourceforge.net/):
  
  ```perl
  #!/usr/bin/env perl
  use strict;
  use warnings;
  use SWISS::Entry;
  
  my $flat=$ARGV[0]||die("Need a flat file\n");
  
  ## Change the line termination string so we read an 
  ## entire entry at a time
  local $/ = "\n//\n";
  
  my $fh;
  ## Deal with compressed or uncompressed files
  if($flat=~/\.gz$/){
      open($fh,"zcat $flat |")|| die("cannot open flat file $flat : $! \n");
  }
  else{
      open($fh,"$flat")|| die("cannot open flat file $flat : $!: $@\n");
  }
  ## Parse the file. 
  entry: while (my $current_entry = <$fh>) {
      ## Read the current entry as an "entry" object
      my $entry = SWISS::Entry->fromText($current_entry);
      ## Iterate over the entry's features
      foreach my $feature ($entry->FTs->elements()) {
          ## If any of the features are 'TRANSMEM', print the entry
          if ($feature->[0] eq 'TRANSMEM') {
              print "$current_entry\n";
              ## Skip to the next entry
              next entry;
          }
      }
  }
  
  ```
  
  You need to install the Swissknife module first:
  
  1. Download Swissknife\_1.73.tar.gz from [here](https://sourceforge.net/projects/swissknife/files/latest/download) (SourceForge link).
  2. Install
  
     ```
     tar xvzf Swissknife.tar.gz
     cd Swissknife_1.73/
     perl Makefile.PL
     sudo make install
  
     ```
  
  Now, make the script above executable and run with:
  
  ```
  foo.pl file.flat
  
  ```
  
  
  ---
  
  