/* * #%L * gitools-ui-app * %% * Copyright (C) 2013 Universitat Pompeu Fabra - Biomedical Genomics group * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ package org.gitools.ui.app.actions.analysis; import org.gitools.analysis.clustering.ClusteringMethod; import org.gitools.analysis.clustering.hierarchical.HierarchicalMethod; import org.gitools.analysis.clustering.kmeans.KMeansPlusPlusMethod; import org.gitools.api.analysis.Clusters; import org.gitools.api.analysis.IProgressMonitor; import org.gitools.api.matrix.MatrixDimensionKey; import org.gitools.api.matrix.SortDirection; import org.gitools.heatmap.Bookmark; import org.gitools.heatmap.Bookmarks; import org.gitools.heatmap.Heatmap; import org.gitools.heatmap.HeatmapDimension; import org.gitools.heatmap.header.HeatmapColoredLabelsHeader; import org.gitools.heatmap.header.HierarchicalCluster; import org.gitools.heatmap.header.HierarchicalClusterHeatmapHeader; import org.gitools.matrix.filter.PatternFunction; import org.gitools.matrix.model.matrix.AnnotationMatrix; import org.gitools.matrix.sort.SortByLabelComparator; import org.gitools.ui.app.actions.data.analysis.SortByHierarchicalClusteringCommand; import org.gitools.ui.app.analysis.clustering.ClusteringWizard; import org.gitools.ui.app.analysis.clustering.visualization.DendrogramEditor; import org.gitools.ui.app.commands.AddHeaderColoredLabelsCommand; import org.gitools.ui.core.Application; import org.gitools.ui.core.actions.HeatmapAction; import org.gitools.ui.platform.progress.JobRunnable; import org.gitools.ui.platform.progress.JobThread; import org.gitools.ui.platform.wizard.WizardDialog; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.*; public class ClusteringAction extends HeatmapAction { public ClusteringAction() { super("Clustering..."); setDesc("Cluster by values"); setMnemonic(KeyEvent.VK_L); } @Override public void actionPerformed(ActionEvent e) { final Heatmap heatmap = getHeatmap(); final ClusteringWizard wiz = new ClusteringWizard(heatmap); WizardDialog wdlg = new WizardDialog(Application.get(), wiz); wdlg.open(); if (wdlg.isCancelled()) { return; } final ClusteringMethod method = wiz.getMethod(); JobThread.execute(Application.get(), new JobRunnable() { @Override public void run(IProgressMonitor monitor) { // Cluster data Clusters results = method.cluster(wiz.getClusterData(), monitor); // Target dimension HeatmapDimension clusteringDimension = heatmap.getDimension(wiz.getClusteringDimension()); // Annotations AnnotationMatrix annotationMatrix = clusteringDimension.getAnnotations(); if (method instanceof HierarchicalMethod) { processHierarchical(results, clusteringDimension, annotationMatrix, wiz.getClusteringLayer(), (HierarchicalMethod) method, heatmap, monitor); } else { processKMeans(results, clusteringDimension, annotationMatrix, wiz.getClusteringLayer(), method, heatmap); } } }); Application.get().showNotificationPermanent("Clusters and bookmarks created and applied"); } private static void processKMeans(Clusters results, HeatmapDimension clusteringDimension, AnnotationMatrix annotationMatrix, String layerId, ClusteringMethod method, Heatmap heatmap) { String annotationLabel = "Cluster " + layerId; if (method instanceof KMeansPlusPlusMethod) { annotationLabel = annotationLabel + " #" + ((KMeansPlusPlusMethod) method).getNumClusters(); } // Save annotations Collection<String> clusters = results.getClusters(); for (String cluster : clusters) { for (String item : results.getItems(cluster)) { annotationMatrix.setAnnotation(item, annotationLabel, cluster); } } String sortLabel = "${" + annotationLabel + "}"; HeatmapColoredLabelsHeader header = new HeatmapColoredLabelsHeader(clusteringDimension); AddHeaderColoredLabelsCommand.updateFromClusterResults(header, results.getClusters()); header.setTitle(annotationLabel); header.setAnnotationPattern(sortLabel); clusteringDimension.addHeader(header); // Sort the header clusteringDimension.sort(new SortByLabelComparator(clusteringDimension, SortDirection.ASCENDING, new PatternFunction(sortLabel, clusteringDimension.getAnnotations()), -1, false)); // Bookmark current sort addBookmarkKMeans(clusteringDimension, layerId, heatmap, (KMeansPlusPlusMethod) method); } private static void processHierarchical(Clusters results, HeatmapDimension clusteringDimension, AnnotationMatrix annotationMatrix, String layerId, HierarchicalMethod method, Heatmap heatmap, IProgressMonitor monitor) { HierarchicalCluster rootCluster = (HierarchicalCluster) results; rootCluster.setName(""); // Sort new SortByHierarchicalClusteringCommand(clusteringDimension, rootCluster).execute(monitor); // Bookmark current sort String clusterDesc = "hierarchical clustering of " + clusteringDimension.getId().getLabel() + "s using the data values \"" + layerId + "\"." + " Distance used: " + method.getDistanceMeasure().toString() + ", Link type used: " + method.getLinkageStrategy().toString() + "."; Bookmark b = addBookmarkHierarchical(clusteringDimension, layerId, heatmap, method, clusterDesc); // Hierarchical cluster header int maxLevels = 20; rootCluster.setName(b.getName()); HierarchicalClusterHeatmapHeader hierarchicalHeader = new HierarchicalClusterHeatmapHeader(clusteringDimension); hierarchicalHeader.setDescription(clusterDesc); hierarchicalHeader.setTitle("Clust. " + layerId); hierarchicalHeader.setHierarchicalCluster(rootCluster); // Add to annotations String annotationPrefix = b.getName() + " L"; HierarchicalClusterHeatmapHeader.createHierarchicalLevelsHeaders(hierarchicalHeader, maxLevels, annotationPrefix); clusteringDimension.addHeader(hierarchicalHeader); // Open a tree editor Application.get().getEditorsPanel().addEditor(new DendrogramEditor(rootCluster)); } private static Bookmark addBookmarkHierarchical(HeatmapDimension clusteringDimension, String layerId, Heatmap heatmap, HierarchicalMethod method, String clusterDesc) { boolean rowsUsed = clusteringDimension.getId().equals(MatrixDimensionKey.ROWS); String bookmarkName = method.getName() + "-" + clusteringDimension.getId().toString().substring(0, 3).toLowerCase() + "s-" + layerId; int[] include = new int[]{rowsUsed ? Bookmarks.ROWS : Bookmarks.COLUMNS, Bookmarks.LAYER}; String description = "Automatically generated bookmark for " + clusterDesc; return heatmap.getBookmarks().createNew(heatmap, bookmarkName, description, include); } private static Bookmark addBookmarkKMeans(HeatmapDimension clusteringDimension, String layerId, Heatmap heatmap, KMeansPlusPlusMethod method) { boolean rowsUsed = clusteringDimension.getId().equals(MatrixDimensionKey.ROWS); String bookmarkName = method.getName() + "-" + clusteringDimension.getId().toString().substring(0, 3) + "-" + layerId; int[] include = new int[]{rowsUsed ? Bookmarks.ROWS : Bookmarks.COLUMNS, Bookmarks.LAYER}; String description = "Automatically generated bookmark for K-Means clustering of " + clusteringDimension.getId().toString() + " using the data values \"" + layerId + "\"." + " Clusters: " + method.getNumClusters().toString() + ", Distance used: " + method.getDistance().toString() + ", Iterations made: " + method.getIterations().toString() + "."; return heatmap.getBookmarks().createNew(heatmap, bookmarkName, description, include); } }