Answers.Body: <p>Presuming you still have your BAM file sitting around somewhere:</p>
  
  <pre><code>#!/usr/bin/env python
  import pysam
  import pyBigWig
  
  bam = pysam.AlignmentFile("alignments.bam")
  ifile = pyBigWig.open("your current file.bw")
  ofile = pyBigWig.open("your new file.bw", "w")
  
  # Create/Add the header
  hdr = []
  for chrom in bam.header['SQ']: 
      hdr.append((chrom['SN'], chrom['LN']))
  bam.close()
  ofile.addHeader(hdr)
  
  # Write the bigWig
  for _ in hdr:
      try:
          ints = ifile.intervals(_[0])
          starts = [x[0] for x in ints]
          ends = [x[1] for x in ints]
          vals = [x[2] for x in ints]
          ofile.addEntries([_[0]] * len(starts), starts, ends=ends, values=vals)
      except:
          # intervals() will throw an error if the chromosome isn't present
          pass
  ofile.close()
  ifile.close()
  </code></pre>
  
  <p>The reason you can't append to a bigWig file is that it has a various indices and zoom levels typically built in. You'd have to add to them without overwriting neighboring blocks of data. In theory this might sometimes be theoretically possible, but not typically and I'm not aware of tools that support this.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T08:38:40.333Z
Answers.Text: If I understand correctly, the bam file is not necessary in my case, because I already have the `chrom_sizes` list, which should be the same as the `hdr` you obtain by parsing the bam header.
Answers.UserDisplayName: bli
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T08:42:24.000Z
Answers.Text: Correct, if you already have such a list then you don’t need a BAM file.
Answers.UserDisplayName: Devon Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T08:44:10.723Z
Answers.Text: Just a detail: It seems strange to me to use a `_` placeholder as looping variable if you then use it to access its first element. I suppose `for (chrom, _) in hdr:` would work as well while avoiding you the `_[0]`.
Answers.UserDisplayName: bli
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T08:48:03.333Z
Answers.Text: Yup that’d work too.
Answers.UserDisplayName: Devon Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-30T19:37:06.637Z
Answers.LastActivityDate: 2017-10-30T19:37:06.637Z
Answers.UserDisplayName: Devon Ryan
Body: <p>I generate bigwig files using a shell script based on <code>bedtools genomecov</code> (to generate a bedgraph from a bam file) <code>bedmap</code> (to compute means across 10 bp bins) and <code>bedGraphToBigWig</code> to convert the binned bedgraph into bigwig.</p>
  
  <p>Sometimes, the bam file has no data on some chromosomes, this results in a bedgraph file with no entries for the empty chromosomes.</p>
  
  <p>I would like to add the missing entries. How could I do this?</p>
  
  <p>I tried to see what I could do with pyBigWig, opening the bedgraph file in "a" mode, but don't really know how to proceed:</p>
  
  <pre><code># I have the chromosome sizes for my genome of interest already in a list:
  chrom_sizes
  #[('I', 15072434),
  # ('II', 15279421),
  # ('III', 13783801),
  # ('IV', 17493829),
  # ('MtDNA', 13794),
  # ('V', 20924180),
  # ('X', 17718942)]
  bw_test = pyBigWig.open("path/to/bigwig", "a")
  bw_test.chroms()
  # {'IV': 17493829, 'V': 20924180, 'X': 17718942}
  bw_test.addHeader(chrom_sizes)
  # RuntimeError: Received an error in bwCreateHdr
  </code></pre>
  
Tags: <python><bigwig>
Title: Adding entries to bigwig file
ThreadText: # Adding entries to bigwig file
  
  (Asked by: username_0 on 2017-10-30)
  
  I generate bigwig files using a shell script based on `bedtools genomecov` (to generate a bedgraph from a bam file) `bedmap` (to compute means across 10 bp bins) and `bedGraphToBigWig` to convert the binned bedgraph into bigwig.
  
  Sometimes, the bam file has no data on some chromosomes, this results in a bedgraph file with no entries for the empty chromosomes.
  
  I would like to add the missing entries. How could I do this?
  
  I tried to see what I could do with pyBigWig, opening the bedgraph file in "a" mode, but don't really know how to proceed:
  
  ```
  # I have the chromosome sizes for my genome of interest already in a list:
  chrom_sizes
  #[('I', 15072434),
  # ('II', 15279421),
  # ('III', 13783801),
  # ('IV', 17493829),
  # ('MtDNA', 13794),
  # ('V', 20924180),
  # ('X', 17718942)]
  bw_test = pyBigWig.open("path/to/bigwig", "a")
  bw_test.chroms()
  # {'IV': 17493829, 'V': 20924180, 'X': 17718942}
  bw_test.addHeader(chrom_sizes)
  # RuntimeError: Received an error in bwCreateHdr
  
  ```
  
  **Tags:** python, bigwig
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-10-30. Score: 3 | Accepted answer
  
  Presuming you still have your BAM file sitting around somewhere:
  
  ```
  #!/usr/bin/env python
  import pysam
  import pyBigWig
  
  bam = pysam.AlignmentFile("alignments.bam")
  ifile = pyBigWig.open("your current file.bw")
  ofile = pyBigWig.open("your new file.bw", "w")
  
  # Create/Add the header
  hdr = []
  for chrom in bam.header['SQ']: 
      hdr.append((chrom['SN'], chrom['LN']))
  bam.close()
  ofile.addHeader(hdr)
  
  # Write the bigWig
  for _ in hdr:
      try:
          ints = ifile.intervals(_[0])
          starts = [x[0] for x in ints]
          ends = [x[1] for x in ints]
          vals = [x[2] for x in ints]
          ofile.addEntries([_[0]] * len(starts), starts, ends=ends, values=vals)
      except:
          # intervals() will throw an error if the chromosome isn't present
          pass
  ofile.close()
  ifile.close()
  
  ```
  
  The reason you can't append to a bigWig file is that it has a various indices and zoom levels typically built in. You'd have to add to them without overwriting neighboring blocks of data. In theory this might sometimes be theoretically possible, but not typically and I'm not aware of tools that support this.
  
  > **Comments:**
  > **username_0**: If I understand correctly, the bam file is not necessary in my case, because I already have the `chrom_sizes` list, which should be the same as the `hdr` you obtain by parsing the bam header.  
  > **username_1**: Correct, if you already have such a list then you don’t need a BAM file.  
  > **username_0**: Just a detail: It seems strange to me to use a `_` placeholder as looping variable if you then use it to access its first element. I suppose `for (chrom, _) in hdr:` would work as well while avoiding you the `_[0]`.  
  > **username_1**: Yup that’d work too.  
  
  ---
  
  