/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.bbfile; import htsjdk.samtools.seekablestream.SeekableStream; import org.apache.log4j.Logger; import org.broad.igv.util.CompressionUtils; import java.util.ArrayList; import java.io.IOException; import java.util.HashMap; /** * Created by IntelliJ IDEA. * User: martind * Date: Apr 16, 2010 * Time: 10:32:51 AM * To change this template use File | Settings | File Templates. */ public class BigWigDataBlock { private static Logger log = Logger.getLogger(BigWigDataBlock.class); // BigWig data types sizes final int FIXED_STEP_ITEM_SIZE = 4; final int VAR_STEP_ITEM_SIZE = 8; final int BED_GRAPH_ITEM_SIZE = 12; // Bed data block access variables - for reading in bed records from a file private long fileOffset; // Wig data block file offset private long leafDataSize; // byte size for data block specified in the R+ leaf private boolean isLowToHigh; // if true, data is low to high byte order; else high to low // defines the bigWig data source private HashMap<Integer, String> chromosomeMap; // map of chromosome ID's and corresponding names private RPTreeLeafNodeItem leafHitItem; // R+ leaf item containing data block location // uncompressed byte stream buffer and readers private byte[] wigBuffer; // buffer containing leaf block data uncompressed private int remDataSize; // number of uncompressed data bytes not extracted // Wig data extraction members private ArrayList<WigItem> wigItemList; // array of Wig section items /* * Constructor for Wig data block reader. * * Parameters: * fis - file input stream handle * leafHitItem - R+ tree leaf hit item containing data block file location and hit status * chromIDTree - B+ chromosome index tree returns chromosome ID's for names * isLowToHigh - byte order is low to high if true; else high to low * uncompressBufSize - byte size for decompression buffer; else 0 for uncompressed * * */ public BigWigDataBlock(SeekableStream fis, RPTreeLeafNodeItem leafHitItem, HashMap<Integer, String> chromosomeMap, boolean isLowToHigh, int uncompressBufSize){ this.leafHitItem = leafHitItem; this.chromosomeMap = chromosomeMap; this.isLowToHigh = isLowToHigh; fileOffset = this.leafHitItem.getDataOffset(); leafDataSize = this.leafHitItem.geDataSize(); byte[] buffer = new byte[(int) leafDataSize]; // read Wig data block into a buffer try { fis.seek(fileOffset); fis.readFully(buffer); // decompress if necessary - the buffer size is 0 for uncompressed data // Note: BBFile Table C specifies a decompression buffer size if(uncompressBufSize > 0) wigBuffer = (new CompressionUtils()).decompress(buffer, uncompressBufSize); else wigBuffer = buffer; // use uncompressed read buffer directly }catch(IOException ex) { log.error("Error reading Wig section for leaf item ", ex); String error = String.format("Error reading Wig section for leaf item %d\n"); throw new RuntimeException(error, ex); } // initialize unread data size remDataSize = wigBuffer.length; // use getWigData to extract data block items } /* * Method reads all Wig data sections within the decompressed block buffer * and returns those items in the chromosome selection region. * * Parameters: * selectionRegion - chromosome region for selecting Wig values * contained - indicates selected data must be contained in selection region * if true, else may intersect selection region * * Returns: * Wig sections in selected from the data block; else null for none selected. * * */ public ArrayList<WigItem> getWigData(RPChromosomeRegion selectionRegion, boolean contained){ wigItemList = new ArrayList<WigItem>(); for(int index = 0; remDataSize > 0; ++index) { // extract items in the Wig data section // Note: A RuntimeException is thrown if wig section is not read properly BigWigSection wigSection = new BigWigSection(wigBuffer, chromosomeMap, isLowToHigh, leafHitItem); // get wig section items and section bytes read int sectionBytes = wigSection.getSectionData(selectionRegion, contained, wigItemList); // adjust remaining data block size remDataSize -= sectionBytes; } return wigItemList; } public void print() { log.debug("Wig section data referenced by leaf item "); for(int index = 0; index <= wigItemList.size(); ++index) { // BigWig sections print themselves wigItemList.get(index).print(); } } }