* If the score model computes pairwise distance scores, then these are used * directly to derive the tree *
* If the score model computes similarity scores, then the range of the scores * is reversed to give a distance measure, and this is used to derive the tree * * @param sm * @param scoreOptions */ protected void computeTree(ScoreModelI sm, SimilarityParamsI scoreOptions) { this.scoreModel = sm; this.scoreParams = scoreOptions; testDistances = scoreModel.findDistances(seqData, scoreParams); distances = scoreModel.findDistances(seqData, scoreParams); makeLeaves(); noClus = clusters.size(); cluster(); } /** * Finds the node, at or below the given node, with the maximum distance, and * saves the node and the distance value * * @param nd */ void findMaxDist(SequenceNode nd) { if (nd == null) { return; } if ((nd.left() == null) && (nd.right() == null)) { double dist = nd.dist; if (dist > maxDistValue) { maxdist = nd; maxDistValue = dist; } } else { findMaxDist((SequenceNode) nd.left()); findMaxDist((SequenceNode) nd.right()); } } /** * Calculates and returns r, whatever that is * * @param i * @param j * * @return */ protected double findr(int i, int j) { double tmp = 1; for (int k = 0; k < noseqs; k++) { if ((k != i) && (k != j) && (!done.get(k))) { tmp = tmp + distances.getValue(i, k); } } if (noClus > 2) { tmp = tmp / (noClus - 2); } return tmp; } protected void init(AlignmentView seqView, int start, int end) { this.node = new Vector<>(); if (seqView != null) { this.seqData = seqView; } else { SeqCigar[] seqs = new SeqCigar[sequences.length]; for (int i = 0; i < sequences.length; i++) { seqs[i] = new SeqCigar(sequences[i], start, end); } CigarArray sdata = new CigarArray(seqs); sdata.addOperation(CigarArray.M, end - start + 1); this.seqData = new AlignmentView(sdata, start); } /* * count the non-null sequences */ noseqs = 0; done = new BitSet(); for (SequenceI seq : sequences) { if (seq != null) { noseqs++; } } } /** * Merges cluster(j) to cluster(i) and recalculates cluster and node distances * * @param i * @param j */ void joinClusters(final int i, final int j) { double dist = distances.getValue(i, j); ri = findr(i, j); rj = findr(j, i); findClusterDistance(i, j); SequenceNode sn = new SequenceNode(); sn.setLeft((node.elementAt(i))); sn.setRight((node.elementAt(j))); SequenceNode tmpi = (node.elementAt(i)); SequenceNode tmpj = (node.elementAt(j)); findNewDistances(tmpi, tmpj, dist); tmpi.setParent(sn); tmpj.setParent(sn); node.setElementAt(sn, i); /* * move the members of cluster(j) to cluster(i) * and mark cluster j as out of the game */ clusters.get(i).or(clusters.get(j)); clusters.get(j).clear(); done.set(j); } /* * Computes and stores new distances for nodei and nodej, given the previous * distance between them */ protected abstract void findNewDistances(SequenceNode nodei, SequenceNode nodej, double previousDistance); /** * Calculates and saves the distance between the combination of cluster(i) and * cluster(j) and all other clusters. The form of the calculation depends on * the tree clustering method being used. * * @param i * @param j */ protected abstract void findClusterDistance(int i, int j); /** * Start by making a cluster for each individual sequence */ void makeLeaves() { clusters = new Vector<>(); for (int i = 0; i < noseqs; i++) { SequenceNode sn = new SequenceNode(); sn.setElement(sequences[i]); sn.setName(sequences[i].getName()); node.addElement(sn); BitSet bs = new BitSet(); bs.set(i); clusters.addElement(bs); } } public AlignmentView getOriginalData() { return seqStrings; } public MatrixI getDistances() { return distances; } public AlignmentView getSeqData() { return seqData; } public ScoreModelI getScoreModel() { return scoreModel; } public SimilarityParamsI getScoreParams() { return scoreParams; } }