private int getRightBound(int i, Region w) {
   int right =
       i >= data.getCount() - 1
           ? w.getEnd()
           : Math.min(data.getPos(i) + maxJump, (data.getPos(i) + data.getPos(i + 1)) / 2);
   return right;
 }
 public String toString() {
   StringBuilder sb = new StringBuilder();
   sb.append(region.getLocationString() + "\t");
   for (Factor f : binding.keySet()) {
     sb.append(binding.get(f) > 0 ? "1" : "0");
   }
   return sb.toString();
 }
 private int getLeftBound(int i, Region w) {
   int left =
       i == 0
           ? w.getStart()
           : Math.max(
               Math.max(1, data.getPos(i) - maxJump), (data.getPos(i) + data.getPos(i - 1)) / 2);
   return left;
 }
  public Iterator<SimpleDomain> execute(Region a) {
    try {
      LinkedList<SimpleDomain> doms = new LinkedList<SimpleDomain>();
      data.window(a.getChrom(), a.getStart(), a.getEnd());
      int np = data.getCount();

      for (int pi = 0; pi < np - 1; pi++) {
        int f = findNextDomainIndex(pi, a);
        if (f != -1) {
          SimpleDomain dom = buildDomain(pi, f, a);
          doms.addLast(dom);
          pi = f;
        }
      }

      return doms.iterator();
    } catch (NotFoundException e) {
      e.printStackTrace();
      return new EmptyIterator<SimpleDomain>();
    }
  }
  private Pair<Region, Region> findProbePair(
      String primerName, Map<String, Set<Region>> primerHits) {
    String leftName = String.format("%s_left", primerName);
    String rightName = String.format("%s_right", primerName);

    if (!primerHits.containsKey(leftName) || !primerHits.containsKey(rightName)) {
      return null;
    }
    if (primerHits.get(leftName).size() != 1 || primerHits.get(rightName).size() != 1) {
      return null;
    }

    Iterator<Region> leftitr = primerHits.get(leftName).iterator();
    Iterator<Region> rightitr = primerHits.get(rightName).iterator();
    Region left = leftitr.next();
    Region right = rightitr.next();

    if (!left.getChrom().equals(right.getChrom())) {
      return null;
    }

    return new Pair<Region, Region>(left, right);
  }
  public Collection<NamedRegion> parseProbes() throws IOException {
    double ethreshold = 1.0e-3;
    Parser<BlastTabEntry> parser =
        new Parser<BlastTabEntry>(blasttab, new BlastTabEntry.ParsingMapper());
    Iterator<BlastTabEntry> itr =
        new FilterIterator<BlastTabEntry, BlastTabEntry>(
            new BlastTabEntry.ExpectedScoreFilter(ethreshold), parser);

    Map<String, Set<Region>> primerHits = new TreeMap<String, Set<Region>>();
    Set<String> primerNames = new TreeSet<String>();

    while (itr.hasNext()) {
      BlastTabEntry entry = itr.next();
      NamedRegion r = createNamedRegion(entry);
      if (!primerHits.containsKey(entry.getQuery())) {
        primerHits.put(entry.getQuery(), new HashSet<Region>());
      }
      primerHits.get(entry.getQuery()).add(r);
      primerNames.add(removePrimerLR(entry.getQuery()));
    }

    LinkedList<NamedRegion> probes = new LinkedList<NamedRegion>();

    for (String primerName : primerNames) {
      Pair<Region, Region> hits = findProbePair(primerName, primerHits);
      if (hits != null) {
        Region left = hits.getFirst(), right = hits.getLast();
        int start = Math.min(left.getStart(), right.getStart());
        int end = Math.max(left.getEnd(), right.getEnd());

        NamedRegion probe = new NamedRegion(genome, left.getChrom(), start, end, primerName);
        probes.addLast(probe);
      }
    }

    return probes;
  }
 private SimpleDomain buildDomain(int pi, int farthest, Region w) {
   int left = getLeftBound(pi, w);
   int right = getRightBound(farthest, w);
   return new SimpleDomain(w.getGenome(), w.getChrom(), left, right);
 }
  public void paintItem(Graphics2D g, int x1, int y1, int x2, int y2) {
    if (!model.isReady()) {
      return;
    }
    Set<Genome> genomes = model.getGenomes();
    if (genomes == null) {
      g.drawString("No Genomes Yet", x1 + 40, y1 + 40);
      return;
    }
    Genome currentGenome = model.getCurrentGenome();
    if (currentGenome == null) {
      g.drawString("Haven't moved", x1 + 40, y1 + 40);
      return;
    }
    genomes.remove(currentGenome);
    if (genomes.size() == 0) {
      g.drawString("Single genome isn't very interesting", x1 + 40, y1 + 40);
      return;
    }
    cs.reset();
    int h = y2 - y1;
    int midY = y1 + h / 2;
    int rstart = getRegion().getStart();
    int rend = getRegion().getEnd();
    Stroke old = g.getStroke();
    Stroke thin = new BasicStroke(1);
    Stroke medium = new BasicStroke(3);
    Stroke thick = new BasicStroke(6);
    for (Genome genome : genomes) {
      Region best = model.getBestRegion(genome);
      if (best == null) {
        continue;
      }
      String bestc = best.getChrom();
      int ostart = best.getStart();
      int oend = best.getEnd();
      java.util.List<MultiZAlignRegion> alignedRegions = model.getAlignedRegions(genome);
      for (MultiZAlignRegion align : alignedRegions) {
        if (align.getOtherChrom().equals(bestc)) {
          g.setColor(
              cs.colorAt(
                  hashPosPair(
                      align.getStart(),
                      align.getEnd(),
                      align.getOtherStart(),
                      align.getOtherEnd(),
                      cs.colorCount())));
          int rsx = getXPos(align.getStart(), rstart, rend, x1, x2);
          int osx = getXPos(align.getOtherStart(), ostart, oend, x1, x2);
          int rex = getXPos(align.getEnd(), rstart, rend, x1, x2);
          int oex = getXPos(align.getOtherEnd(), ostart, oend, x1, x2);

          g.setStroke(medium);
          if (myGenome == currentGenome) {
            g.drawLine(rsx, midY, rex, midY);
            g.drawLine(rsx, y1, rsx, y2);
            g.drawLine(rex, y1, rex, y2);
            addLabel(rsx, y1, rex - rsx, y2, align.toString());
          } else {
            g.drawLine(osx, midY, oex, midY);
            g.drawLine(osx, y1, osx, y2);
            g.drawLine(oex, y1, oex, y2);
            addLabel(osx, y1, oex - osx, y2, align.toString());
          }
        }
      }
    }
    g.setStroke(old);
    g.setColor(Color.BLACK);
    g.drawString(model.getAlignment(), x1 + 5, y2);
  }