package org.seqcode.gsebricks.verbs.location;
import java.io.PrintStream;
import java.util.*;
import org.seqcode.data.core.*;
import org.seqcode.genome.Genome;
import org.seqcode.genome.Species;
import org.seqcode.genome.location.Point;
import org.seqcode.genome.location.Region;
import org.seqcode.genome.location.StrandedRegion;
import org.seqcode.gsebricks.verbs.Expander;
import org.seqcode.gsebricks.verbs.ExpanderIterator;
import org.seqcode.gsebricks.verbs.Mapper;
import org.seqcode.gsebricks.verbs.MapperIterator;
import org.seqcode.gseutils.Coverage;
import org.seqcode.gseutils.NotFoundException;
import org.seqcode.gseutils.Pair;
public class RegionCoverage extends Coverage {
private Genome genome;
public RegionCoverage(Genome g) {
super();
genome = g;
}
public RegionCoverage(RegionCoverageModel m) {
this(null, m);
}
public RegionCoverage(Genome g, RegionCoverageModel m) {
super(m);
genome = g == null ? m.loadGenome() : g;
}
public RegionCoverage(Genome g, Coverage c) {
super(c);
genome = g;
}
public RegionCoverage(Genome g, Collection<? extends Region> rs) {
this(g, rs, null);
}
public RegionCoverage(Genome g, Collection<? extends Region> rs, PrintStream ps) {
this(g);
int i = 0;
for(Region r : rs) {
addRegion(r);
i += 1;
if(ps != null) {
if(i % 100 == 0) {
System.out.print("."); System.out.flush();
}
if(i % 1000 == 0) {
System.out.println(String.format("(%dk)", i/1000));
}
}
}
if(ps != null) { ps.println(); }
}
public RegionCoverage(Genome g, Iterator<? extends Region> rs) {
this(g, rs, null);
}
public RegionCoverage(Genome g, Iterator<? extends Region> rs, PrintStream ps) {
this(g);
int i = 0;
while(rs.hasNext()) {
addRegion(rs.next());
i += 1;
if(ps != null) {
if(i % 100 == 0) {
System.out.print("."); System.out.flush();
}
if(i % 1000 == 0) {
System.out.println(String.format("(%dk)", i/1000));
}
}
}
if(ps != null) { ps.println(); }
}
public Iterator<Region> regions() {
Expander<String,Region> regExp = new Expander<String,Region>() {
public Iterator<Region> execute(String key) {
Iterator<Integer[]> units = units(key);
return new MapperIterator<Integer[],Region>(new UnitMapper(key), units);
}
};
return new ExpanderIterator<String,Region>(regExp, keys());
}
private class UnitMapper implements Mapper<Integer[],Region> {
private String key;
public UnitMapper(String k) { key = k; }
public Region execute(Integer[] a) {
return new Region(genome, key, a[0], a[1]);
}
}
public Region rightNearest(Point p) {
Integer[] bounds = super.rightNearest(p.getChrom(), p.getLocation());
if(bounds != null) {
return new Region(p.getGenome(), p.getChrom(), bounds[0], bounds[1]);
} else {
return null;
}
}
public Region leftNearest(Point p) {
Integer[] bounds = super.leftNearest(p.getChrom(), p.getLocation());
if(bounds != null) {
return new Region(p.getGenome(), p.getChrom(), bounds[0], bounds[1]);
} else {
return null;
}
}
public RegionCoverage subtract(Coverage c) {
return new RegionCoverage(genome, super.subtract(c));
}
public RegionCoverage intersection(Coverage c) {
return new RegionCoverage(genome, super.intersection(c));
}
public RegionCoverage union(Coverage c) {
return new RegionCoverage(genome, super.union(c));
}
public void addRegion(Region r) {
if(!r.getGenome().equals(genome)) {
throw new IllegalArgumentException();
}
addInterval(r.getChrom(), r.getStart(), r.getEnd());
}
public int coverage(Region r) {
return super.coverage(r.getChrom(), r.getStart(), r.getEnd());
}
public Collection<Region> coveredRegions(Region r) {
Collection<Integer[]> cov = covered(r.getChrom(), r.getStart(), r.getEnd());
ArrayList<Region> regs = new ArrayList<Region>();
for(Integer[] c : cov) {
regs.add(new Region(genome, r.getChrom(), c[0], c[1]));
}
return regs;
}
public boolean hasCoverage(Region r) {
return hasCoverage(r.getChrom(), r.getStart(), r.getEnd());
}
public RegionCoverageModel asModel() {
return new RegionCoverageModel(this, super.asModel());
}
public static class RegionCoverageModel extends CoverageModel {
public String species, version;
public RegionCoverageModel() {}
public RegionCoverageModel(RegionCoverage c, CoverageModel m) {
keys = m.keys.clone();
coverages = m.coverages.clone();
species = c.genome.getSpeciesName();
version = c.genome.getVersion();
}
public Genome loadGenome() {
try {
Species org = Species.getSpecies(species);
return new Genome(org, version);
} catch (NotFoundException e) {
e.printStackTrace();
return null;
}
}
}
public boolean isContained(StrandedRegion r) {
return isContained(r.getChrom(), r.getStart(), r.getEnd());
}
public Region findNearestRight(Point p) {
Integer[] bounds = super.findNearestRight(p.getChrom(), p.getLocation());
if(bounds == null) { return null; }
return new Region(p.getGenome(), p.getChrom(), bounds[0], bounds[1]);
}
public Region findNearestLeft(Point p) {
Integer[] bounds = super.findNearestLeft(p.getChrom(), p.getLocation());
if(bounds == null) { return null; }
return new Region(p.getGenome(), p.getChrom(), bounds[0], bounds[1]);
}
public Collection<Pair<Region, Region>>
findPairs(int maxDist, RegionCoverage coverage, boolean right) {
ArrayList<Pair<Region,Region>> lst = new ArrayList<Pair<Region,Region>>();
Iterator<String> chroms = keys();
while(chroms.hasNext()) {
String chrom = chroms.next();
Collection<Pair<Integer[],Integer[]>>
pairs = right ? super.findRightPairs(chrom, maxDist, coverage)
: super.findLeftPairs(chrom, maxDist, coverage);
for(Pair<Integer[],Integer[]> p : pairs) {
Integer[] p1 = p.getFirst(), p2 = p.getLast();
System.out.println(String.format("%d,%d vs. %d,%d", p1[0], p1[1], p2[0], p2[1]));
Region r1 = new Region(genome, chrom, p1[0], p1[1]);
Region r2 = new Region(genome, chrom, p2[0], p2[1]);
lst.add(new Pair<Region,Region>(r1, r2));
}
}
return lst;
}
}