/* * Created on Jan 11, 2008 * * TODO * * To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package org.seqcode.projects.seqview.model; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.ArrayList; import java.util.TreeMap; import java.util.Collection; import org.seqcode.data.readdb.*; import org.seqcode.data.seqdata.SeqAlignment; import org.seqcode.data.seqdata.SeqHit; import org.seqcode.genome.location.Region; import org.seqcode.gsebricks.verbs.WeightedRunningOverlapSum; /** * SeqDataModel: * SeqView data model for SeqHits. * If an extension is specified, then each return hit will * be extended by that many bp. */ public class SeqDataModel extends SeqViewModel implements RegionModel, Runnable { private Client client; private Collection<String> alignids; private Collection<SeqAlignment> alignments; private SeqAlignment align; private WeightedRunningOverlapSum totalSum; private WeightedRunningOverlapSum watsonSum; private WeightedRunningOverlapSum crickSum; private int extension; private int shift; private Region region; private boolean newinput, reloadInput, doSums, doHits; private ArrayList<SeqHit> results; private SeqDataProperties props; public SeqDataModel(Client c, Collection<SeqAlignment> alignments) throws IOException { client = c; extension = 0; totalSum = null; watsonSum = null; crickSum = null; shift=0; newinput = false; reloadInput = false; doSums = true; doHits = true; alignids = new ArrayList<String>(); this.alignments = alignments; align = null; for (SeqAlignment a : alignments) { alignids.add(Integer.toString(a.getDBID())); if (align == null) { align = a; } if(!client.exists(Integer.toString(a.getDBID()))){ System.err.println("SeqHistogramModel: Error: "+a.getExpt().getName()+";"+a.getExpt().getReplicate()+";"+a.getName()+"\tRDBID:"+a.getDBID()+" does not exist in ReadDB."); dataError=true; } } results = new ArrayList<SeqHit>(); props = new SeqDataProperties(); } public SeqDataProperties getProperties() {return props;} public WeightedRunningOverlapSum getTotalRunningOverlap() { return totalSum; } public WeightedRunningOverlapSum getWatsonRunningOverlap() { return watsonSum; } public WeightedRunningOverlapSum getCrickRunningOverlap() { return crickSum; } public double getTotalMaxOverlap() { return totalSum.getMaxOverlap(); } public double getWatsonMaxOverlap() { return watsonSum.getMaxOverlap(); } public double getCrickMaxOverlap() { return crickSum.getMaxOverlap(); } public void setExtensionAndShift(int extension, int shift) { if (this.extension == extension && this.shift == shift) { return; } this.extension = extension; this.shift = shift; } protected void clearValues() { Region r = getRegion(); totalSum = new WeightedRunningOverlapSum(r.getGenome(), r.getChrom()); watsonSum = new WeightedRunningOverlapSum(r.getGenome(), r.getChrom()); crickSum = new WeightedRunningOverlapSum(r.getGenome(), r.getChrom()); } public Region getRegion() {return region;} public void setRegion(Region r) { if (newinput == false) { if (!r.equals(region)) { region = r; newinput = true; } else { notifyListeners(); } } } public void resetRegion(Region r) { if (newinput == false) { region = r; newinput = true; } } public boolean isReady() {return !newinput;} public synchronized void run() { while(keepRunning()) { try { if (!newinput) { wait(); } } catch (InterruptedException ex) { } if (newinput) { try { setExtensionAndShift(getProperties().ExtendRead,getProperties().ShiftRead); if (doSums) { if(props.ShowType1Reads){ mapToSum(totalSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), false, //type1 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, null)); mapToSum(watsonSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), false, //type1 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, true)); mapToSum(crickSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), false, //type1 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, false)); } if(props.ShowType2Reads){ mapToSum(totalSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), true, //type2 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, null)); mapToSum(watsonSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), true, //type2 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, true)); mapToSum(crickSum, client.getWeightHistogram(alignids, region.getGenome().getChromID(region.getChrom()), true, //type2 false, // paired extension, 1, // binsize props.DeDuplicate, region.getStart(), region.getEnd(), null, false)); } } if (doHits) { results.clear(); for (String aid : alignids) { if(props.ShowType1Reads){ for (SingleHit hit : client.getSingleHits(aid, region.getGenome().getChromID(region.getChrom()), false, region.getStart(), region.getEnd(), null, null)) { results.add(convert(hit)); } } if(props.ShowType2Reads){ for (SingleHit hit : client.getSingleHits(aid, region.getGenome().getChromID(region.getChrom()), true, region.getStart(), region.getEnd(), null, null)) { results.add(convert(hit)); } } } if(props.DeDuplicate>0) results = deDuplicateSingleHits(results, props.DeDuplicate); } } catch (Exception ex) { ex.printStackTrace(); } newinput = false; notifyListeners(); } } } public void setDoSums(boolean b) {doSums = b;} public void setDoHits(boolean b) {doHits = b;} public Iterator<SeqHit> getResults() { return results.iterator(); } private void mapToSum(WeightedRunningOverlapSum sum, TreeMap<Integer,Float> map) { for (Integer i : map.keySet()) { sum.addWeightedInterval(i, i, map.get(i)); } } private SeqHit convert(SingleHit hit) { hit.length += extension; hit.pos += shift * (hit.strand ? 1 : -1); SeqHit out = new SeqHit(region.getGenome(), region.getChrom(), hit.strand ? hit.pos : hit.pos - hit.length + 1, hit.strand ? hit.pos + hit.length + 1 : hit.pos, hit.strand ? '+' : '-', hit.weight); return out; } //Hack to allow de-duplication of reads when drawing all reads private ArrayList<SeqHit> deDuplicateSingleHits(ArrayList<SeqHit> res, int deDup) { ArrayList<SeqHit> out = new ArrayList<SeqHit>(); HashMap<String, Integer> hitCounts = new HashMap<String, Integer>(); for(SeqHit h : res){ if(hitCounts.containsKey(h.getLocationString())){ int c = hitCounts.get(h.getLocationString()); hitCounts.put(h.getLocationString(), c+1); if(c <= deDup){ out.add(h); } }else{ hitCounts.put(h.getLocationString(), 1); out.add(h); } } return out; } protected void doReload() { synchronized(this) { reloadInput = true; this.notifyAll(); } } }