text: user1194: I have a code below:
  def FilterReads(in_file, out_file):
  
  def read_ok(read):
      """
      read_ok - reject reads with a low quality (<5) base call
      read - a PySam AlignedRead object
      returns: True if the read is ok
      """
      if any([ord(c)-33 < _BASE_QUAL_CUTOFF for c in list(read.qual)]):
          return False
      else:
          return True
  
  _BASE_QUAL_CUTOFF = 30
  
  bam_in = pysam.Samfile(in_file, 'rb')
  bam_out = pysam.Samfile(out_file, 'wb', template=bam_in)
  
  
  for read in bam_in.fetch():
      if read_ok(read):
          bam_out.write(read)
  
  This code works fine by 
  
  Rejecting reads having a base with phred quality score below five
  But it first takes a BAM file 
  And then creates a filtered BAM file for further analysis but this takes a lot of time. 
  
  So is there a way to reject these reads using pileup in pysam so that I may not have to create a file then sort it and again read it? 
  Or can I modify this code to perform the same function
  
  user163: For can do this by accessing the basecall qualities from PileupRead.alignment. For example:
  _BASE_QUAL_CUTOFF = 30
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              qual = read.alignment.query_qualities
              if all([ord(c)-33 >= _BASE_QUAL_CUTOFF for c in qual]):
                  # do some stuff
  
  This involves checking every read at every position. You could memoise this task:
  def check_quality(read):
      try:
          return passed_quality[read.query_name]
      except KeyError:
          qual = read.alignment.query_qualities 
          passed = all([ord(c)-33 >= _BASE_QUAL_CUTOFF for c in qual])
          passed_quality[read.query_name] = passed
          return passed_quality[read.query_name]
  
  _BASE_QUAL_CUTOFF = 30
  passed_quality = dict()
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              if check_quality(read):
                  # do some stuff
  
  Or, using functools.lru_cache (thanks @winni2k):
  from functools import lru_cache
  
  @lru_cache(maxsize=1000)
  def check_quality(read):
      qual = read.alignment.query_qualities 
      return all([ord(c)-33 >= _BASE_QUAL_CUTOFF for c in qual])
  
  _BASE_QUAL_CUTOFF = 30
  passed_quality = dict()
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              if check_quality(read):
                  # do some stuff
  
  
original_text: 1194: <p>I have a code below:</p>
  
  <pre><code>def FilterReads(in_file, out_file):
  
  def read_ok(read):
      """
      read_ok - reject reads with a low quality (&lt;5) base call
      read - a PySam AlignedRead object
      returns: True if the read is ok
      """
      if any([ord(c)-33 &lt; _BASE_QUAL_CUTOFF for c in list(read.qual)]):
          return False
      else:
          return True
  
  _BASE_QUAL_CUTOFF = 30
  
  bam_in = pysam.Samfile(in_file, 'rb')
  bam_out = pysam.Samfile(out_file, 'wb', template=bam_in)
  
  
  for read in bam_in.fetch():
      if read_ok(read):
          bam_out.write(read)
  </code></pre>
  
  <p>This code works fine by </p>
  
  <ul>
  <li>Rejecting reads having a base with phred quality score below five</li>
  <li>But it first takes a BAM file </li>
  <li>And then creates a filtered BAM file for further analysis but this takes a lot of time. </li>
  </ul>
  
  <p>So is there a way to reject these reads using pileup in pysam so that I may not have to create a file then sort it and again read it? 
  Or can I modify <a href="https://bioinformatics.stackexchange.com/questions/2131/filtering-bases-based-on-phred-qualities-with-pysam">this code</a> to perform the same function</p>
   163: <p>For can do this by accessing the basecall qualities from <a href="https://pysam.readthedocs.io/en/latest/api.html#pysam.PileupRead.alignment" rel="nofollow noreferrer"><code>PileupRead.alignment</code></a>. For example:</p>
  
  <pre><code>_BASE_QUAL_CUTOFF = 30
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              qual = read.alignment.query_qualities
              if all([ord(c)-33 &gt;= _BASE_QUAL_CUTOFF for c in qual]):
                  # do some stuff
  </code></pre>
  
  <p>This involves checking every read at every position. You could memoise this task:</p>
  
  <pre><code>def check_quality(read):
      try:
          return passed_quality[read.query_name]
      except KeyError:
          qual = read.alignment.query_qualities 
          passed = all([ord(c)-33 &gt;= _BASE_QUAL_CUTOFF for c in qual])
          passed_quality[read.query_name] = passed
          return passed_quality[read.query_name]
  
  _BASE_QUAL_CUTOFF = 30
  passed_quality = dict()
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              if check_quality(read):
                  # do some stuff
  </code></pre>
  
  <p>Or, using <code>functools.lru_cache</code> (thanks @winni2k):</p>
  
  <pre><code>from functools import lru_cache
  
  @lru_cache(maxsize=1000)
  def check_quality(read):
      qual = read.alignment.query_qualities 
      return all([ord(c)-33 &gt;= _BASE_QUAL_CUTOFF for c in qual])
  
  _BASE_QUAL_CUTOFF = 30
  passed_quality = dict()
  with pysam.Samfile(in_file, 'rb') as bam_in:
      for column in bam_in.pileup():
          for read in column:
              if check_quality(read):
                  # do some stuff
  </code></pre>
  