Answers.Body: <p>Take your <code>BamFile(fake_bam)</code> and pass it through <code>open()</code>. That will return a value if <code>fake_bam</code> is a real BAM (or CRAM or maybe SAM) file and through an error otherwise. You can then wrap all of that in a <code>trycatch()</code>:</p>
  
  <pre><code>trycatch(open(BamFile(fake_bam)), do something, do something else)
  </code></pre>
  
  <p>Alternatively, ditch the <code>trycatch()</code> and let <code>open()</code> return the error if an invalid file in entered.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-02T05:33:28.687Z
Answers.LastActivityDate: 2018-05-02T05:33:28.687Z
Answers.UserDisplayName: Devon Ryan
Answers.Body: <p>Just expanding upon the answers by @DevonRyan and @KonradRudolph, here's one way to put this in an R package:</p>
  
  <p>Either using <code>open(BamFile()</code> from Devon's answer, which needs <code>Rsamtools</code>:</p>
  
  <pre><code>my_func = function(my_bam){
  
      out = tryCatch(open(Rsamtools::BamFile(my_bam)), error = function(e) e)
      if (inherits(out, "error")){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  }
  </code></pre>
  
  <p>Or from Konrad's answer</p>
  
  <pre><code>my_func = function(my_bam){
  
      magic = readChar(gzfile(filename, 'r'), 4)
      if (!identical(magic, 'BAM\1')){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-03T17:36:11.747Z
Answers.Text: R has a function that specifically performs `any(class(out) == 'error')`: `inherits(out, 'error')`. Besides being more readable this is also potentially more efficient (though it won’t matter here).
Answers.UserDisplayName: Konrad Rudolph
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-03T18:27:22.017Z
Answers.Text: @KonradRudolph You're right, I wasn't thinking clear. Edited.
Answers.UserDisplayName: EB2127
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-03T17:13:50.197Z
Answers.LastActivityDate: 2018-05-04T09:10:03.657Z
Answers.LastEditDate: 2018-05-04T09:10:03.657Z
Answers.UserDisplayName: EB2127
Answers.Body: <p>You won’t know whether it’s a valid BAM file until you attempt reading it in full; even Devon’s method (which I recommend) only does a superficial check — i.e. it checks whether (parts of) the BAM <em>header</em> can be read correctly. However, this doesn’t guarantee that the file isn’t truncated or contains invalid data.</p>
  <p>This is of course a more general problem, but it’s perhaps a bit stranger for BAMs (and other biological formats), as it’s relatively frequent to end up with technically invalid files that were produced by existing software. The only recourse is actually trying to use the file, and to handle errors appropriately.</p>
  <p>For a <em>very quick check</em>™ you could also pass the file through <code>gunzip</code> and test whether the “magic bytes” at the beginning of the file equal <code>'BAM\1'</code>:</p>
  <pre><code>bgzf_stream = gzfile(filename, 'r')
  on.exit(close(bgzf_stream))
  magic = readChar(bgzf_stream, 4)
  stopifnot(identical(magic, 'BAM\1'))
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-05-02T08:38:10.800Z
Answers.LastActivityDate: 2021-12-17T12:17:09.147Z
Answers.LastEditDate: 2021-12-17T12:17:09.147Z
Answers.UserDisplayName: Konrad Rudolph
Body: <p>I'm writing a function in R for an R package which takes as input a BAM. </p>
  
  <pre><code>my_func = function(my_bam){
      if (!file.exists(my_bam)){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  
  }
  </code></pre>
  
  <p>Trying to write robust software, I would like to do more of a check whether this BAM is actually a BAM. Above, I'm just using <code>file.exists()</code>. </p>
  
  <p>I could also do something simple like "check whether the file has the extension <code>*.bam</code>" with </p>
  
  <pre><code>grepl('*.bam', my_bam)  ## TRUE for file.bam, FALSE for file.txt
  </code></pre>
  
  <p>However, is there a quick way to check that the input <em>is</em> actually a BAM? I would prefer to throw an error here, if the user inputs a *txt or *bedpe. </p>
  
  <p>I don't think it's necessary to <em>validate</em> the BAM per se, whereby I believe most users rely upon Picard:</p>
  
  <p><a href="https://broadinstitute.github.io/picard/command-line-overview.html#ValidateSamFile" rel="noreferrer">https://broadinstitute.github.io/picard/command-line-overview.html#ValidateSamFile</a></p>
  
  <p>My first thought was Rsamtools for this operation:</p>
  
  <p><a href="https://bioconductor.org/packages/release/bioc/html/Rsamtools.html" rel="noreferrer">https://bioconductor.org/packages/release/bioc/html/Rsamtools.html</a></p>
  
  <p>However, it doesn't appear that there is a function here which checks the user inputs a BAM, e.g. <code>BamFile()</code> doesn't appear to throw an error</p>
  
  <pre><code>&gt; library(Rsamtools)
  &gt; fake_bam = 'nonsense_string.bam'   ## a string I made up, not a real BAM
  &gt; BamFile(fake_bam)
  class: BamFile 
  path: nonsense_string.bam
  index: NA
  isOpen: FALSE 
  yieldSize: NA 
  obeyQname: FALSE 
  asMates: FALSE 
  qnamePrefixEnd: NA 
  qnameSuffixStart: NA 
  </code></pre>
  
  <p>How could I "check" that the user is inputting a BAM file? Perhaps pipe to samtools (which doesn't feel very stable in terms of software)? </p>
  
Tags: <r><sam><bioconductor><samtools>
Title: Is there an efficient way to check an input BAM in R?
ThreadText: # Is there an efficient way to check an input BAM in R?
  
  (Asked by: username_0 on 2018-05-01)
  
  I'm writing a function in R for an R package which takes as input a BAM.
  
  ```
  my_func = function(my_bam){
      if (!file.exists(my_bam)){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  
  }
  
  ```
  
  Trying to write robust software, I would like to do more of a check whether this BAM is actually a BAM. Above, I'm just using `file.exists()`.
  
  I could also do something simple like "check whether the file has the extension `*.bam`" with
  
  ```
  grepl('*.bam', my_bam)  ## TRUE for file.bam, FALSE for file.txt
  
  ```
  
  However, is there a quick way to check that the input *is* actually a BAM? I would prefer to throw an error here, if the user inputs a \*txt or \*bedpe.
  
  I don't think it's necessary to *validate* the BAM per se, whereby I believe most users rely upon Picard:
  
  <https://broadinstitute.github.io/picard/command-line-overview.html#ValidateSamFile>
  
  My first thought was Rsamtools for this operation:
  
  <https://bioconductor.org/packages/release/bioc/html/Rsamtools.html>
  
  However, it doesn't appear that there is a function here which checks the user inputs a BAM, e.g. `BamFile()` doesn't appear to throw an error
  
  ```
  > library(Rsamtools)
  > fake_bam = 'nonsense_string.bam'   ## a string I made up, not a real BAM
  > BamFile(fake_bam)
  class: BamFile 
  path: nonsense_string.bam
  index: NA
  isOpen: FALSE 
  yieldSize: NA 
  obeyQname: FALSE 
  asMates: FALSE 
  qnamePrefixEnd: NA 
  qnameSuffixStart: NA 
  
  ```
  
  How could I "check" that the user is inputting a BAM file? Perhaps pipe to samtools (which doesn't feel very stable in terms of software)?
  
  **Tags:** r, sam, bioconductor, samtools
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_2 on 2018-05-02. Score: 6 | Accepted answer
  
  You won’t know whether it’s a valid BAM file until you attempt reading it in full; even username_1’s method (which I recommend) only does a superficial check — i.e. it checks whether (parts of) the BAM *header* can be read correctly. However, this doesn’t guarantee that the file isn’t truncated or contains invalid data.
  
  This is of course a more general problem, but it’s perhaps a bit stranger for BAMs (and other biological formats), as it’s relatively frequent to end up with technically invalid files that were produced by existing software. The only recourse is actually trying to use the file, and to handle errors appropriately.
  
  For a *very quick check*™ you could also pass the file through `gunzip` and test whether the “magic bytes” at the beginning of the file equal `'BAM\1'`:
  
  ```
  bgzf_stream = gzfile(filename, 'r')
  on.exit(close(bgzf_stream))
  magic = readChar(bgzf_stream, 4)
  stopifnot(identical(magic, 'BAM\1'))
  
  ```
  
  
  ---
  
  ### Answer by username_1 on 2018-05-02. Score: 3
  
  Take your `BamFile(fake_bam)` and pass it through `open()`. That will return a value if `fake_bam` is a real BAM (or CRAM or maybe SAM) file and through an error otherwise. You can then wrap all of that in a `trycatch()`:
  
  ```
  trycatch(open(BamFile(fake_bam)), do something, do something else)
  
  ```
  
  Alternatively, ditch the `trycatch()` and let `open()` return the error if an invalid file in entered.
  
  
  ---
  
  ### Answer by username_0 on 2018-05-03. Score: 1
  
  Just expanding upon the answers by @username_1 and @username_2, here's one way to put this in an R package:
  
  Either using `open(BamFile()` from username_1's answer, which needs `Rsamtools`:
  
  ```
  my_func = function(my_bam){
  
      out = tryCatch(open(Rsamtools::BamFile(my_bam)), error = function(e) e)
      if (inherits(out, "error")){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  }
  
  ```
  
  Or from username_2's answer
  
  ```
  my_func = function(my_bam){
  
      magic = readChar(gzfile(filename, 'r'), 4)
      if (!identical(magic, 'BAM\1')){
          stop("Input a valid BAM file.")
      }
  
      ## do awesome stuff with BAM
  }
  
  ```
  
  > **Comments:**
  > **username_2**: R has a function that specifically performs `any(class(out) == 'error')`: `inherits(out, 'error')`. Besides being more readable this is also potentially more efficient (though it won’t matter here).  
  > **username_0**: @username_2 You're right, I wasn't thinking clear. Edited.  
  
  ---
  
  