annotate java-genomics-toolkit/src/edu/unc/genomics/visualization/KMeans.java @ 0:1daf3026d231

Upload alpha version
author timpalpant
date Mon, 13 Feb 2012 21:55:55 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
1 package edu.unc.genomics.visualization;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
2
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
3 import java.io.BufferedReader;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
4 import java.io.BufferedWriter;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
5 import java.io.IOException;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
6 import java.nio.charset.Charset;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
7 import java.nio.file.Files;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
8 import java.nio.file.Path;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
9 import java.util.ArrayList;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
10 import java.util.Arrays;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
11 import java.util.HashMap;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
12 import java.util.List;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
13 import java.util.Map;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
14 import java.util.Random;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
15
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
16 import org.apache.commons.lang3.StringUtils;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
17 import org.apache.commons.math.stat.clustering.Cluster;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
18 import org.apache.commons.math.stat.clustering.KMeansPlusPlusClusterer;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
19 import org.apache.log4j.Logger;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
20
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
21 import com.beust.jcommander.Parameter;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
22
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
23 import edu.unc.genomics.CommandLineTool;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
24 import edu.unc.genomics.ReadablePathValidator;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
25 import edu.unc.genomics.io.IntervalFileSnifferException;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
26 import edu.unc.genomics.io.WigFileException;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
27
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
28 public class KMeans extends CommandLineTool {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
29
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
30 private static final Logger log = Logger.getLogger(KMeans.class);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
31
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
32 @Parameter(names = {"-i", "--input"}, description = "Input file (matrix2png format)", required = true, validateWith = ReadablePathValidator.class)
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
33 public Path inputFile;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
34 @Parameter(names = {"-k", "--clusters"}, description = "Number of clusters")
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
35 public int k = 10;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
36 @Parameter(names = {"-1", "--min"}, description = "Minimum column to use for clustering")
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
37 public int minCol = 1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
38 @Parameter(names = {"-2", "--max"}, description = "Maximum column to use for clustering")
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
39 public Integer maxCol;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
40 @Parameter(names = {"-o", "--output"}, description = "Output file (clustered matrix2png format)", required = true)
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
41 public Path outputFile;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
42
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
43 private Map<String, String> rows = new HashMap<String, String>();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
44 private List<KMeansRow> data = new ArrayList<KMeansRow>();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
45
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
46 @Override
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
47 public void run() throws IOException {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
48 log.debug("Loading data from the input matrix");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
49 String headerLine = "";
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
50 try (BufferedReader reader = Files.newBufferedReader(inputFile, Charset.defaultCharset())) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
51 // Header line
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
52 int lineNum = 1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
53 headerLine = reader.readLine();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
54 int numColsInMatrix = StringUtils.countMatches(headerLine, "\t");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
55
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
56 // Validate the range info
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
57 if (maxCol != null) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
58 if (maxCol > numColsInMatrix) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
59 throw new RuntimeException("Invalid range of data specified for clustering ("+maxCol+" > "+numColsInMatrix+")");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
60 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
61 } else {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
62 maxCol = numColsInMatrix;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
63 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
64
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
65 // Loop over the rows and load the data
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
66 String line;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
67 while ((line = reader.readLine()) != null) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
68 lineNum++;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
69 if (StringUtils.countMatches(line, "\t") != numColsInMatrix) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
70 throw new RuntimeException("Irregular input matrix does not have same number of columns on line " + lineNum);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
71 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
72
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
73 int delim = line.indexOf('\t');
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
74 String id = line.substring(0, delim);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
75 String[] row = line.substring(delim+1).split("\t");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
76 String[] subset = Arrays.copyOfRange(row, minCol, maxCol);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
77 float[] rowData = new float[subset.length];
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
78 for (int i = 0; i < subset.length; i++) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
79 try {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
80 rowData[i] = Float.parseFloat(subset[i]);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
81 } catch (NumberFormatException e) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
82 rowData[i] = Float.NaN;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
83 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
84 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
85 data.add(new KMeansRow(id, rowData));
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
86 rows.put(id, line);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
87 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
88 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
89
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
90 // Perform the clustering
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
91 log.debug("Clustering the data");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
92 Random rng = new Random();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
93 KMeansPlusPlusClusterer<KMeansRow> clusterer = new KMeansPlusPlusClusterer<KMeansRow>(rng);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
94 List<Cluster<KMeansRow>> clusters = clusterer.cluster(data, k, 50);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
95
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
96 // Write to output
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
97 log.debug("Writing clustered data to output file");
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
98 try (BufferedWriter writer = Files.newBufferedWriter(outputFile, Charset.defaultCharset())) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
99 writer.write(headerLine);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
100 writer.newLine();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
101 int n = 1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
102 int count = 1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
103 for (Cluster<KMeansRow> cluster : clusters) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
104 int numRowsInCluster = cluster.getPoints().size();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
105 int stop = count + numRowsInCluster - 1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
106 log.info("Cluster "+(n++)+": rows "+count+"-"+stop);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
107 count = stop+1;
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
108 for (KMeansRow row : cluster.getPoints()) {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
109 writer.write(rows.get(row.getId()));
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
110 writer.newLine();
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
111 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
112 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
113 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
114 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
115
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
116 public static void main(String[] args) throws IOException, WigFileException, IntervalFileSnifferException {
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
117 new KMeans().instanceMain(args);
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
118 }
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
119
1daf3026d231 Upload alpha version
timpalpant
parents:
diff changeset
120 }