bool GaussianEdgeCalculator::edgeBetween(const AlignmentRecord & ap1, const AlignmentRecord & ap2, int numGCAllowedPos, int ct) const {
	if (ap1.isSingleEnd() || ap2.isSingleEnd()) {
		throw runtime_error("Cannot process single-end reads in GaussianEdgeCalculator!");
	}
	double insert_length_diff = abs(((int)ap1.getInsertLength()) - ((int)ap2.getInsertLength()));
	// double meanedge = 2.0 * sf( insert_length_diff / (sqrt2*insert_size_popstddev) );
	if (insert_length_diff > allowable_insert_size_diff) {
		return false;
	}
	size_t intersection_length = ap1.internalSegmentIntersectionLength(ap2);
	if (intersection_length == 0) return false;
	double mean_insert_length = (ap1.getInsertLength() + ap2.getInsertLength()) / 2.0;
	double interedge = min(1.0, 2.0 * sf(sqrt2*(mean_insert_length - intersection_length - insert_size_popmean) / insert_size_popstddev) );
	return interedge >= significance_level;
}
double QuasispeciesEdgeCalculator::computeOverlap(const AlignmentRecord & ap1, const AlignmentRecord & ap2, const double cutoff) const {

    double MIN_OVERLAP = 0;
    if (ap1.getName().find("Clique") != string::npos
        && ap2.getName().find("Clique") != string::npos) {
        MIN_OVERLAP = MIN_OVERLAP_CLIQUES;
    } else {
        MIN_OVERLAP = MIN_OVERLAP_SINGLE;
    }

    if (ap1.isSingleEnd() && ap2.isSingleEnd()) {
        int read_size1 = min(ap1.getEnd1() - ap1.getStart1(), ap2.getEnd1() - ap2.getStart1());
        float overlap_size1 = overlapSize(ap1.getEnd1(), ap2.getEnd1(), ap1.getStart1(), ap2.getStart1());
        if (MIN_OVERLAP <= 1) overlap_size1 /= (float) read_size1;
        if (overlap_size1 < MIN_OVERLAP) return 0;
        // if (!is_disjoint(ap1.getReadNames(),ap2.getReadNames())) return 1;
        return singleOverlap(ap1, ap2, 1, 1, MIN_OVERLAP, cutoff);
    } else if (ap1.isSingleEnd() || ap2.isSingleEnd()) {
        if (ap1.isSingleEnd()) {
            int read_size1 = min(ap1.getEnd1() - ap1.getStart1(), ap2.getEnd1() - ap2.getStart1());
            int read_size2 = min(ap1.getEnd1() - ap1.getStart1(), ap2.getEnd2() - ap2.getStart2());
            float overlap_size1 = overlapSize(ap1.getEnd1(), ap2.getEnd1(), ap1.getStart1(), ap2.getStart1());
            float overlap_size2 = overlapSize(ap1.getEnd1(), ap2.getEnd2(), ap1.getStart1(), ap2.getStart2());

            if (MIN_OVERLAP <= 1) {
                overlap_size1 /= (float) read_size1;
                overlap_size2 /= (float) read_size2;
            }
            if ((overlap_size1 >= MIN_OVERLAP && overlap_size2 >= MIN_OVERLAP) || (overlap_size1+overlap_size2 >= MIN_OVERLAP && overlap_size1 > 0 && overlap_size2 > 0)) {
                // if (!is_disjoint(ap1.getReadNames(),ap2.getReadNames())) return 1;
                return singleOverlap(ap1, ap2, 1, 1, MIN_OVERLAP, cutoff)*singleOverlap(ap1, ap2, 1, 2, MIN_OVERLAP, cutoff);
            }
            return 0;
        } else {
            int read_size1 = min(ap1.getEnd1() - ap1.getStart1(), ap2.getEnd1() - ap2.getStart1());
            int read_size2 = min(ap1.getEnd2() - ap1.getStart2(), ap2.getEnd1() - ap2.getStart1());

            float overlap_size1 = overlapSize(ap1.getEnd1(), ap2.getEnd1(), ap1.getStart1(), ap2.getStart1());
            float overlap_size2 = overlapSize(ap1.getEnd2(), ap2.getEnd1(), ap1.getStart2(), ap2.getStart1());
            if (MIN_OVERLAP <= 1) {
                overlap_size1 /= (float) read_size1;
                overlap_size2 /= (float) read_size2;
            }
            if ((overlap_size1 >= MIN_OVERLAP && overlap_size2 >= MIN_OVERLAP) || (overlap_size1+overlap_size2 >= MIN_OVERLAP && overlap_size1 > 0 && overlap_size2 > 0)) {
                // if (!is_disjoint(ap1.getReadNames(),ap2.getReadNames())) return 1;
                return singleOverlap(ap1, ap2, 1, 1, MIN_OVERLAP, cutoff)*singleOverlap(ap1, ap2, 2, 1, MIN_OVERLAP, cutoff);
            }
            return 0;
        }
    } else {
        int read_size1 = min(ap1.getEnd1() - ap1.getStart1(), ap2.getEnd1() - ap2.getStart1());
        float overlap_size1 = overlapSize(ap1.getEnd1(), ap2.getEnd1(), ap1.getStart1(), ap2.getStart1());
        if (MIN_OVERLAP <= 1) overlap_size1 /= (float) read_size1;
        if (overlap_size1 < MIN_OVERLAP) return 0;

        int read_size2 = min(ap1.getEnd2() - ap1.getStart2(), ap2.getEnd2() - ap2.getStart2());
        float overlap_size2 = overlapSize(ap1.getEnd2(), ap2.getEnd2(), ap1.getStart2(), ap2.getStart2());
        if (MIN_OVERLAP <= 1) overlap_size2 /= (float) read_size2;
        if (overlap_size2 < MIN_OVERLAP) return 0;

        // if (!is_disjoint(ap1.getReadNames(),ap2.getReadNames())) return 1;
        return singleOverlap(ap1, ap2, 1, 1, MIN_OVERLAP, cutoff)*singleOverlap(ap1, ap2, 2, 2, MIN_OVERLAP, cutoff);
    }

    return 0;
}