private AbstractSequence cutRegion(
     AbstractSequence s, BlastAnalysis.Result blastResult, BlastAnalysis.Region region) {
   int rs = Math.max(0, region.getBegin() - blastResult.getStart());
   int re = Math.min(s.getLength(), s.getLength() - (blastResult.getEnd() - region.getEnd()));
   AbstractSequence s2 = re > rs ? new SubSequence(s.getName(), s.getDescription(), s, rs, re) : s;
   return s2;
 }
  @Override
  public void analyze(AbstractSequence s) throws AnalysisException {
    /*
     * First perform the blast analysis.
     */
    BlastAnalysis.Result blastResult = blastAnalysis.run(s);

    if (blastResult.haveSupport()) {
      Cluster c = blastResult.getConcludedCluster();

      analyseClaster(c, s);

      /*
       * Reverse complement the sequence for subsequent analyses.
       */
      if (blastResult.isReverseComplement()) s = s.reverseCompliment();

      boolean haveConclusion = false;

      try {
        /*
         * Perhaps we have a full-genome analysis?
         */
        PhyloClusterAnalysis pca = getPhyloAnalysis(c.getId(), null, null);
        if (pca != null) {
          phyloAnalysis(pca, s, blastResult, null);
          haveConclusion = true;
        }

        List<Region> regions = Collections.emptyList();

        if (blastResult.getReference() != null)
          /*
           * Perhaps we have an analysis for the region covered by the input sequence ?
           */
          regions = findOverlappingRegions(blastResult);

        if (!regions.isEmpty()) {
          for (Region region : regions) {
            pca = getPhyloAnalysis(c.getId(), null, region);
            if (pca != null) {
              AbstractSequence s2 = cutRegion(s, blastResult, region);
              phyloAnalysis(pca, s2, blastResult, region);
              haveConclusion = true;
            }
          }
        }
      } catch (IOException e) {
        throw new AnalysisException("", s, e);
      } catch (ParameterProblemException e) {
        throw new AnalysisException("", s, e);
      } catch (FileFormatException e) {
        throw new AnalysisException("", s, e);
      }

      /*
       * If no conclusion: conclude the blast result
       */
      if (!haveConclusion)
        if (blastAnalysis.getAbsCutoff() != null && blastAnalysis.getRelativeCutoff() != null)
          conclude(
              blastResult,
              "Assigned based on BLAST absolute score &gt;= "
                  + blastAnalysis.getAbsCutoff()
                  + " and relative score &gt;= "
                  + blastAnalysis.getRelativeCutoff(),
              null);
        else if (blastAnalysis.getAbsCutoff() != null)
          conclude(
              blastResult,
              "Assigned based on BLAST absolute score &gt;= " + blastAnalysis.getAbsCutoff(),
              null);
        else if (blastAnalysis.getRelativeCutoff() != null)
          conclude(
              blastResult,
              "Assigned based on BLAST relative score &gt;= " + blastAnalysis.getAbsCutoff(),
              null);
    } else {
      if (blastAnalysis.getAbsCutoff() != null && blastAnalysis.getRelativeCutoff() != null)
        conclude(
            "Unassigned",
            "Unassigned based on BLAST absolute score &gt;= "
                + blastAnalysis.getAbsCutoff()
                + " and relative score &gt;= "
                + blastAnalysis.getRelativeCutoff(),
            null);
      else if (blastAnalysis.getAbsCutoff() != null)
        conclude(
            "Unassigned",
            "Unassigned based on BLAST absolute score &gt;= " + blastAnalysis.getAbsCutoff(),
            null);
      else if (blastAnalysis.getRelativeCutoff() != null)
        conclude(
            "Unassigned",
            "Unassigned based on BLAST relative score &gt;= " + blastAnalysis.getAbsCutoff(),
            null);
    }
  }