AlignmentAnnotation aa;
+ // 0 - normalised dot product
+ // 1 - L1 - ie (abs(v_1-v_2)/dim(v))
+ // L1 is more rational - since can reason about value of difference,
+ // normalised dot product might give cleaner clusters, but more difficult to
+ // understand.
+
+ int mode = 1;
+
/**
* compute cosine distance matrix for a given contact matrix and create a
* UPGMA tree
- *
* @param cm
+ * @param cosineOrDifference false - dot product : true - L1
*/
public AverageDistanceEngine(AlignmentViewport av, AlignmentAnnotation aa,
- ContactMatrixI cm)
+ ContactMatrixI cm, boolean cosineOrDifference)
{
this.av = av;
this.aa = aa;
this.cm = cm;
+ mode = (cosineOrDifference) ? 1 :0;
calculate(cm);
}
- // 0 - normalised dot product
- // 1 - L1 - ie (abs(v_1-v_2)/dim(v))
- // L1 is more rational - since can reason about value of difference,
- // normalised dot product might give cleaner clusters, but more difficult to
- // understand.
-
- int mode = 1;
public void calculate(ContactMatrixI cm)
{
import java.util.BitSet;
import java.util.List;
+import jalview.util.ColorUtils;
+import jalview.ws.datamodel.MappableContactMatrixI;
+
public interface ContactMatrixI
{
}
void setGroupSet(GroupSet makeGroups);
+
+ default void randomlyReColourGroups() {
+ if (hasGroupSet())
+ {
+ GroupSetI groups = getGroupSet();
+ for (BitSet group:groups.getGroups())
+ {
+ groups.setColorForGroup(group, ColorUtils.getARandomColor());
+ }
+ }
+ }
+
+ default void transferGroupColorsTo(AlignmentAnnotation aa)
+ {
+ if (hasGroupSet())
+ {
+ GroupSetI groups = getGroupSet();
+ // stash colors in linked annotation row.
+ // doesn't work yet. TESTS!
+ int sstart = aa.sequenceRef != null ? aa.sequenceRef.getStart() - 1
+ : 0;
+ Annotation ae;
+ Color gpcol = null;
+ int[] seqpos = null;
+ for (BitSet gp : groups.getGroups())
+ {
+ gpcol = groups.getColourForGroup(gp);
+ for (int p = gp.nextSetBit(0); p >= 0
+ && p < Integer.MAX_VALUE; p = gp.nextSetBit(p + 1))
+ {
+ if (this instanceof MappableContactMatrixI)
+ {
+ MappableContactMatrixI mcm = (MappableContactMatrixI) this;
+ seqpos = mcm.getMappedPositionsFor(aa.sequenceRef, p);
+ if (seqpos == null)
+ {
+ // no mapping for this column.
+ continue;
+ }
+ // TODO: handle ranges...
+ ae = aa.getAnnotationForPosition(seqpos[0]);
+ }
+ else
+ {
+ ae = aa.getAnnotationForPosition(p + sstart);
+ }
+ if (ae != null)
+ {
+ ae.colour = gpcol.brighter().darker();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * look up the colour for a column in the associated contact matrix
+ * @return Color.white or assigned colour
+ */
+ default Color getGroupColorForPosition(int column)
+ {
+ if (hasGroupSet())
+ {
+ GroupSetI groups = getGroupSet();
+ for (BitSet gp:groups.getGroups())
+ {
+ if (gp.get(column))
+ {
+ return groups.getColourForGroup(gp);
+ }
+ }
+ }
+ return Color.white;
+ }
+
}
return treeType;
}
- public static GroupSet makeGroups(ContactMatrixI matrix, float thresh,
+ public static GroupSet makeGroups(ContactMatrixI matrix, boolean autoCut)
+ {
+ return makeGroups(matrix, autoCut, 0, autoCut);
+ }
+ public static GroupSet makeGroups(ContactMatrixI matrix, boolean auto, float thresh,
boolean abs)
{
AverageDistanceEngine clusterer = new AverageDistanceEngine(null, null,
- matrix);
+ matrix, true);
double height = clusterer.findHeight(clusterer.getTopNode());
+ Console.debug("Column tree height: " + height);
String newick = new jalview.io.NewickFile(clusterer.getTopNode(), false,
true).print();
String treeType = "UPGMA";
Console.trace("Newick string\n" + newick);
List<BinaryNode> nodegroups;
- if (abs ? height > thresh : 0 < thresh && thresh < 1)
+ float cut = -1f;
+ if (auto)
{
- float cut = abs ? (float) (thresh / height) : thresh;
- Console.debug("Threshold " + cut + " for height=" + height);
-
- nodegroups = clusterer.groupNodes(cut);
+ double rootw = 0;
+ int p = 2;
+ BinaryNode bn = clusterer.getTopNode();
+ while (p-- > 0 & bn.left() != null)
+ {
+ if (bn.left() != null)
+ {
+ bn = bn.left();
+ }
+ if (bn.left() != null)
+ {
+ rootw = bn.height;
+ }
+ }
+ thresh = Math.max((float) (rootw / height) - 0.01f, 0);
+ cut = thresh;
+ nodegroups = clusterer.groupNodes(thresh);
}
else
{
- nodegroups = new ArrayList<BinaryNode>();
- nodegroups.add(clusterer.getTopNode());
+ if (abs ? (height > thresh) : (0 < thresh && thresh < 1))
+ {
+ cut = abs ? thresh : (float) (thresh * height);
+ Console.debug("Threshold " + cut + " for height=" + height);
+ nodegroups = clusterer.groupNodes(cut);
+ }
+ else
+ {
+ nodegroups = new ArrayList<BinaryNode>();
+ nodegroups.add(clusterer.getTopNode());
+ }
}
+
List<BitSet> groups = new ArrayList<>();
for (BinaryNode root : nodegroups)
{
}
groups.add(gpset);
}
- GroupSet grps = new GroupSet(abs, thresh, groups, treeType, newick);
+ GroupSet grps = new GroupSet(abs, (cut == -1f) ? thresh : cut, groups,
+ treeType, newick);
return grps;
}
public void actionPerformed(ActionEvent e)
{
sel_row.setShowGroupsForContactMatrix(chitem.getState());
- ap.getAnnotationPanel()
- .paint(ap.getAnnotationPanel().getGraphics());
+ // so any annotation colour changes are propagated - though they
+ // probably won't be unless the annotation row colours are removed
+ // too!
+ ap.alignmentChanged();
}
});
pop.add(chitem);
{
final long progBar;
ap.alignFrame.setProgressBar(MessageManager.formatMessage("action.clustering_matrix_for",cm.getAnnotDescr(),5f), progBar = System.currentTimeMillis());
- cm.setGroupSet(GroupSet.makeGroups(cm, 5f, true));
+ cm.setGroupSet(GroupSet.makeGroups(cm, true));
+ cm.randomlyReColourGroups();
+ cm.transferGroupColorsTo(alignmentAnnotation);
+ ap.alignmentChanged();
ap.alignFrame.showContactMapTree(alignmentAnnotation, cm);
ap.alignFrame.setProgressBar(null, progBar);
}
import jalview.analysis.Conservation;
import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
+import jalview.bin.Console;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.BinaryNode;
import jalview.gui.JalviewColourChooser.ColourChooserListener;
import jalview.schemes.ColourSchemeI;
import jalview.structure.SelectionSource;
+import jalview.util.ColorUtils;
import jalview.util.Format;
import jalview.util.MessageManager;
import jalview.ws.datamodel.MappableContactMatrixI;
boolean has_placeholders = false;
longestName = "";
+ AlignmentAnnotation aa = tp.getAssocAnnotation();
+ ContactMatrixI cm = (aa!=null) ? av.getContactMatrix(aa) : null;
+ if (cm!=null && cm.hasCutHeight())
+ {
+ threshold=(float) cm.getCutHeight();
+ }
+
for (int i = 0; i < leaves.size(); i++)
{
BinaryNode lf = leaves.elementAt(i);
longestName = TreeCanvas.PLACEHOLDER
+ ((Sequence) lf.element()).getName();
}
+ if (tp.isColumnWise() && cm!=null)
+ {
+ // get color from group colours, if they are set for the matrix
+ try {
+ Color col = cm.getGroupColorForPosition(parseColumnNode(lf));
+ setColor(lf,col.brighter());
+ } catch (NumberFormatException ex) {};
+ }
}
setMarkPlaceholders(has_placeholders);
* @param offy
* DOCUMENT ME!
*/
- public void drawNode(Graphics g, BinaryNode node, float chunk,
+ public void drawNode(Graphics g, BinaryNode node, double chunk,
double wscale, int width, int offx, int offy)
{
if (node == null)
+ ((BinaryNode) top.right()).count;
}
- float chunk = (float) (height - (offy)) / top.count;
+ double chunk = (double) (height - (offy)) / (double)top.count;
drawNode(g2, tree.getTopNode(), chunk, wscale, width, offx, offy);
threshold = 0f;
}
}
-
+ Console.log.debug("Tree cut threshold set at:" + threshold);
PaintRefresher.Refresh(tp,
getAssociatedPanel().av.getSequenceSetId());
repaint();
Map<BitSet, Color> colors = new HashMap();
for (int i = 0; i < groups.size(); i++)
{
- Color col = new Color((int) (Math.random() * 255),
- (int) (Math.random() * 255), (int) (Math.random() * 255));
+ Color col = ColorUtils.getARandomColor();
+
setColor(groups.get(i), col.brighter());
Vector<BinaryNode> l = tree.findLeaves(groups.get(i));
cm.setColorForGroup(gp, colors.get(gp));
}
}
- // stash colors in linked annotation row.
- // doesn't work yet. TESTS!
- int sstart = aa.sequenceRef != null ? aa.sequenceRef.getStart() - 1
- : 0;
- Annotation ae;
- Color gpcol = null;
- int[] seqpos = null;
- for (BitSet gp : colors.keySet())
- {
- gpcol = colors.get(gp);
- for (int p = gp.nextSetBit(0); p >= 0
- && p < Integer.MAX_VALUE; p = gp.nextSetBit(p + 1))
- {
- if (cm instanceof MappableContactMatrixI)
- {
- MappableContactMatrixI mcm = (MappableContactMatrixI) cm;
- seqpos = mcm.getMappedPositionsFor(aa.sequenceRef, p);
- if (seqpos == null)
- {
- // no mapping for this column.
- continue;
- }
- // TODO: handle ranges...
- ae = aa.getAnnotationForPosition(seqpos[0]);
- }
- else
- {
- ae = aa.getAnnotationForPosition(p + sstart);
- }
- if (ae != null)
- {
- ae.colour = gpcol.brighter().darker();
- }
- }
- }
+ cm.transferGroupColorsTo(aa);
}
}
}
}
}
-
+ private int parseColumnNode(BinaryNode bn) throws NumberFormatException
+ {
+ return Integer.parseInt(
+ bn.getName().substring(bn.getName().indexOf("c") + 1));
+ }
private boolean isColumnForNodeSelected(BinaryNode bn)
{
SequenceI rseq = tp.assocAnnotation.sequenceRef;
int colm = -1;
try
{
- colm = Integer.parseInt(
- bn.getName().substring(bn.getName().indexOf("c") + 1));
+ colm = parseColumnNode(bn);
} catch (Exception e)
{
return false;
// parse out from nodename
try
{
- colm = Integer.parseInt(
- bn.getName().substring(bn.getName().indexOf("c") + 1));
+ colm = parseColumnNode(bn);
} catch (Exception e)
{
continue;
if (mcm!=null)
{
int[] seqpos = mcm.getMappedPositionsFor(
- tp.assocAnnotation.sequenceRef, colm);
+ rseq, colm);
if (seqpos == null)
{
// no mapping for this column.
continue;
}
// TODO: handle ranges...
- offp = seqpos[0]-1;
+ offp = rseq.findIndex(seqpos[0])-1;
}
else
{
this.treeType = type;
this.scoreModelName = modelName;
+ treeCanvas = new TreeCanvas(this, ap, scrollPane);
+ scrollPane.setViewportView(treeCanvas);
+
if (columnWise)
{
bootstrapMenu.setVisible(false);
- placeholdersMenu.setSelected(false);
+ placeholdersMenu.setState(false);
placeholdersMenu.setVisible(false);
- fitToWindow.setSelected(false);
+ fitToWindow.setState(false);
sortAssocViews.setVisible(false);
}
- treeCanvas = new TreeCanvas(this, ap, scrollPane);
- scrollPane.setViewportView(treeCanvas);
addKeyListener(new KeyAdapter()
{
? new NJTree(av, sm, similarityParams)
: new AverageDistanceTree(av, sm, similarityParams);
tree = new TreeModel(njtree);
- showDistances(true);
+ // don't display distances for columnwise trees
}
-
+ showDistances(!columnWise);
tree.reCount(tree.getTopNode());
tree.findHeight(tree.getTopNode());
treeCanvas.setTree(tree);
return color;
}
+
+ /**
+ *
+ * @return random color
+ */
+ public static final Color getARandomColor()
+ {
+ Color col = new Color((int) (Math.random() * 255),
+ (int) (Math.random() * 255), (int) (Math.random() * 255));
+ return col;
+ }
/**
* Convert to Tk colour code format
*
+ matrix.getMin());
long start = System.currentTimeMillis();
AverageDistanceEngine clusterer = new AverageDistanceEngine(
- af.getViewport(), null, matrix);
+ af.getViewport(), null, matrix, false);
System.out.println("built a tree in "
+ (System.currentTimeMillis() - start) * 0.001 + " seconds.");
StringBuffer sb = new StringBuffer();
verifyPAEmatrix(seq, aa, 0, 0, 4);
// test clustering
- paematrix.setGroupSet(GroupSet.makeGroups(paematrix, 0.1f, false));
+ paematrix.setGroupSet(GroupSet.makeGroups(paematrix, false,0.1f, false));
// remap - test the MappableContactMatrix.liftOver method
SequenceI newseq = new Sequence("Seq", "ASDQEASDQEASDQE");
sq.getLength(), sq.getLength());
assertEquals(vals[3][4], paevals[3][4]);
assertEquals(vals[4][3], paevals[4][3]);
- dummyMat.setGroupSet(GroupSet.makeGroups(dummyMat, 0.5f, false));
+ dummyMat.setGroupSet(GroupSet.makeGroups(dummyMat, false,0.5f, false));
Assert.assertNotSame(dummyMat.getNewick(), "");
AlignmentAnnotation paeCm = sq.addContactList(dummyMat);
al.addAnnotation(paeCm);