gt: 			int[] depth = regionCoverReport.getDepthArray();
context: /*******************************************************************************
   * Copyright (c) 2017, BGI-Shenzhen
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>
   *******************************************************************************/
  package org.bgi.flexlab.gaea.tools.bamqualtiycontrol.report;
  
  import org.apache.hadoop.fs.FSDataOutputStream;
  import org.apache.hadoop.fs.FileSystem;
  import org.apache.hadoop.fs.Path;
  import org.apache.hadoop.io.Text;
  import org.apache.hadoop.mapreduce.Reducer.Context;
  import org.apache.hadoop.util.LineReader;
  import org.bgi.flexlab.gaea.data.structure.positioninformation.depth.PositionDepth;
  import org.bgi.flexlab.gaea.data.structure.reference.ReferenceShare;
  import org.bgi.flexlab.gaea.data.structure.region.SingleRegion;
  import org.bgi.flexlab.gaea.data.structure.region.SingleRegion.Regiondata;
  import org.bgi.flexlab.gaea.data.structure.region.statistic.CNVSingleRegionStatistic;
  import org.bgi.flexlab.gaea.tools.mapreduce.bamqualitycontrol.BamQualityControlOptions;
  import org.bgi.flexlab.gaea.util.SamRecordDatum;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Map;
  
  public abstract class ResultReport {
  	
  	private SingleRegion singleRegion;
  	
  	protected BasicReport basicReport;
  	
  	protected BamQualityControlOptions options;
  	
  	protected RegionCoverReport regionCoverReport;
  	
  	protected RegionCoverReport rmdupRegionCoverReport;
  	
  	protected CNVSingleRegionReport cnvSingleRegionReport;
  	
  	protected UnmappedReport unmappedReport;
  	
  	protected int[] insertSize;
  	
  	protected int[] insertSizeWithoutDup;
  	
  	protected ReferenceShare genome;
  	
  	public ResultReport(BamQualityControlOptions options) throws IOException {
  		this.options = options;
  		if(options.getSingleRegion() != null) {
  			singleRegion = new SingleRegion();
  			singleRegion.parseRegionsFileFromHDFS(options.getSingleRegion(), false, 0);
  		}
  		loadReference();
  	}
  	
  	private void loadReference() {
  		genome = new ReferenceShare();
  		if(options.isDistributeCache()) {
  			genome.loadChromosomeList();
  		} else {
  			genome.loadChromosomeList(options.getReferenceSequencePath());
  		}
  	}
  	
  	public void initReports() throws IOException {
  		basicReport = new BasicReport();
  		unmappedReport = new UnmappedReport();
  		regionCoverReport = new RegionCoverReport(1000);
  		rmdupRegionCoverReport = new RegionCoverReport(1000);
  		
  		if(options.getSingleRegion() != null) {
  			cnvSingleRegionReport = new CNVSingleRegionReport(singleRegion);
  		}
  		insertSize = new int[options.getInsertSzie()];
  		insertSizeWithoutDup = new int[options.getInsertSzieWithoutDup()];
  		Arrays.fill(insertSize, 0);
  		Arrays.fill(insertSizeWithoutDup, 0);
  	}
  	
  	public boolean unmappedReport(long winNum, String chrName, Iterable<Text> values) {
  		return unmappedReport.constructMapReport(winNum, chrName, values, basicReport);
  	}
  	
  	public boolean mappedReport(SamRecordDatum datum, String chrName, Context context) {
  		return basicReport.constructMapReport(datum, genome, chrName, context);
  	}
  	
  	public void regionCoverReport(int depth, int noPCRdepth) {
  		regionCoverReport.add(depth);
  		rmdupRegionCoverReport.add(noPCRdepth);
  	}
  	
  	public void finalizeUnmappedReport(String chrName) {
  		if(options.isOutputUnmapped()) {
  			unmappedReport.finalize(unmappedReport.getUnmappedSites(chrName));
  		}
  	}
  	
  	public void singleRegionReports(String chrName, long winStart, int winSize , PositionDepth pd) {
  		if(options.getSingleRegion() != null)
  			cnvSingleRegionReport.getStatisticString(chrName, (int) winStart, winSize, pd.getRMDupPosDepth(), "cnv");
  	}
  	
  	public void insertReport(SamRecordDatum datum) {
  		if((datum.getFlag() & 0x40) != 0) {
  			int insert = datum.getInsertSize();
  			if(Math.abs(insert) < 2000) {
  				insertSize[Math.abs(insert)]++;
  				if(!datum.isDup()) {
  					insertSizeWithoutDup[Math.abs(insert)]++;
  				}
  			}
  		}
  	}
  	
  	protected void insertSizeReportReducerString(StringBuffer info, int[] insertSize) {
  		for(int i = 0; i < insertSize.length; i++) {
  			if(insertSize[i] != 0) {
  				info.append(i);
  				info.append("\t");
  				info.append(insertSize[i]);
  				info.append("\n");
  			}
  		}
  	}
  	
  	public abstract void constructDepthReport(PositionDepth pd, int i, String chrName, long pos);
  
  	public abstract String toReducerString(String sample, String chrName, boolean unmappedRegion);
  
  	public void parseReport(LineReader lineReader, Text line, ReferenceShare genome) throws IOException {
  		String lineString = line.toString();
  		String chrName = "";
  		if(lineString.contains("chrName:")) {
  			String[] sampleSplit = line.toString().split(":");
  			chrName = sampleSplit[1];
  		}
  		
  		if(lineString.contains("Basic Information")) {
  			if(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				basicReport.parse(line.toString());
  			}
  		}
  		
  		if(lineString.startsWith("cnv part single Region Statistic")) {
  			if(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				cnvSingleRegionReport.parseReducerOutput(line.toString(), true);
  			}
  		}
  		if(lineString.startsWith("cnv single Region Statistic")) {
  			if(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				cnvSingleRegionReport.parseReducerOutput(line.toString(), false);
  			}
  		}
  		if(lineString.startsWith("Region Depth")) {
  			if(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				regionCoverReport.parseReducerOutput(line.toString());
  			}
  		}
  		if(lineString.startsWith("RMDUP Region Depth")) {
  			if(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				rmdupRegionCoverReport.parseReducerOutput(line.toString());
  			}
  		}
  		
  		if(lineString.contains("insert size information")) {
  			fillInsertSize(lineReader, line, insertSize);
  		}
  		
  		if(lineString.contains("insert size without dup information")) {
  			fillInsertSize(lineReader, line, insertSizeWithoutDup);
  		}
  		
  		if(lineString.contains("unmapped site information") && options.isOutputUnmapped()) {
  			String[] splitArray = null;
  			ArrayList<Long> unmappedSites =  unmappedReport.getUnmappedSites(chrName);
  			while(lineReader.readLine(line) > 0 && line.getLength() != 0) {
  				if(line.toString().contains("unmapped site information")) {
  					break;
  				}
  				splitArray = line.toString().split("\t");
  				
  				unmappedSites.add(Long.parseLong(splitArray[0]));
  				unmappedSites.add(Long.parseLong(splitArray[1]));
  			}
  		}
  	}
  	
  	public void write(FileSystem fs, String sampleName) throws IOException {
  		if(cnvSingleRegionReport != null) {
  			StringBuffer singleRegionFilePath = new StringBuffer();
  			singleRegionFilePath.append(options.getOutputPath());
  			singleRegionFilePath.append("/");
  			singleRegionFilePath.append(sampleName);
  			singleRegionFilePath.append(".anno_region.txt");
  			Path singleRegionPath = new Path(singleRegionFilePath.toString());
  			FSDataOutputStream singleRegionwriter = fs.create(singleRegionPath);
  			
  			StringBuffer unsingleRegionFilePath = new StringBuffer();
  			unsingleRegionFilePath.append(options.getOutputPath());
  			unsingleRegionFilePath.append("/");
  			unsingleRegionFilePath.append(sampleName);
  			unsingleRegionFilePath.append(".anno_region_low_depth.txt");
  			Path unsingleRegionPath = new Path(unsingleRegionFilePath.toString());
  			FSDataOutputStream unsingleRegionwriter = fs.create(unsingleRegionPath);
  			
  			Map<Regiondata, CNVSingleRegionStatistic> result = cnvSingleRegionReport.getResult();
  			cnvSingleRegionReport.updateAllRegionAverageDeepth();
  			for(Regiondata regionData : result.keySet()) {
  				if(result.get(regionData).getDepth(regionData) > options.getMinSingleRegionDepth())
  					singleRegionwriter.write(result.get(regionData).toString(regionData, false, cnvSingleRegionReport.getAllRegionAverageDeepth()).getBytes());
  				else {
  					singleRegionwriter.write(result.get(regionData).toString(regionData, false, cnvSingleRegionReport.getAllRegionAverageDeepth()).getBytes());
  					unsingleRegionwriter.write(result.get(regionData).toString(regionData, false, cnvSingleRegionReport.getAllRegionAverageDeepth()).getBytes());
  				}
  			}
  			singleRegionwriter.close();
  			unsingleRegionwriter.close();
  		}
  		
  		if(regionCoverReport != null) {
  			StringBuffer RegionDepthFilePath = new StringBuffer();
  			RegionDepthFilePath.append(options.getOutputPath());
  			RegionDepthFilePath.append("/");
  			RegionDepthFilePath.append(sampleName);
  			RegionDepthFilePath.append(".depth.txt");
  			Path regionDepthPath = new Path(RegionDepthFilePath.toString());
  			FSDataOutputStream regionDepthWriter = fs.create(regionDepthPath);
  