import java.sql.*; import java.io.*; import java.util.Properties; import java.util.Scanner; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.ImageProducer; import java.awt.image.RenderedImage; import javax.imageio.ImageIO; //import org.tc33.jheatchart.HeatChart; /** * @author miles * */ public class Heatmap { String[] species; static int[] allClusterIDs; static int maxCount = 0; static String option = "webpage"; public static void main(String[] args) { String[] geneIDs = new String[] {"mgf009407m", "GRMZM2G457201_T02", "LOC_Os03g53530.1", "Bradi3g44220.1"}; Species[] species = getHeatChartData(args); // IF asked for table if (option.equals("table")) { generateDelimitedTable(species); } // IF asked for image if (option.equals("image")) { generateHeatMapImage(species); } // IF asked for webpage if (option.equals("webpage")) { for (int c = 0; c < allClusterIDs.length; c ++) { String endChar = ""; if (c + 1 < allClusterIDs.length) { endChar = ","; } System.out.print(allClusterIDs[c] + endChar); } System.out.println(); System.out.println(maxCount); } //return null; } private static void generateHeatMapImage(Species[] species) { File output = new File("heatMap.gif"); int heatMapHeight = 25*allClusterIDs.length; int heatMapWidth = 25*species.length; int imageType = (BufferedImage.TYPE_3BYTE_BGR); BufferedImage heatMapImage = new BufferedImage(heatMapWidth, heatMapHeight, imageType); Graphics2D heatMapGraphics = heatMapImage.createGraphics(); for (int s = 0; s < species.length; s ++) { for (int c = 0; c < allClusterIDs.length; c ++) { int frequency = species[s].findClusterFrequency(allClusterIDs[c]); // -1 means that species contains no genes in the specified cluster, but can't have negative color // ensure that frequency is never negative if (frequency == -1) { frequency = 0; } Color cellColor = new Color((255/maxCount) * frequency, 0, 0); heatMapGraphics.setColor(cellColor); heatMapGraphics.fillRect(s*25, c*25, 25, 25); } } int speciesNameLength = 200; int chartWidth = heatMapWidth + 50; int chartHeight = heatMapHeight + speciesNameLength; BufferedImage chartImage = new BufferedImage(chartWidth, chartHeight, imageType); Graphics2D chartGraphics = chartImage.createGraphics(); Color background = new Color(255, 255, 255); chartGraphics.setColor(background); chartGraphics.fillRect(0, 0, chartWidth, chartHeight); chartGraphics.drawImage(heatMapImage, 50, speciesNameLength, null); chartGraphics.setColor(Color.black); chartGraphics.drawString("Heat Map", 25, 25); for (int c = 0; c < allClusterIDs.length; c ++) { String clusterID = Integer.toString(allClusterIDs[c] + 1); System.out.println(allClusterIDs[c]); chartGraphics.drawString(clusterID, 5, (speciesNameLength + 15 + c*25)); } for (int s = 0; s < species.length; s ++) { int valueXPos = 70 + (s * 25); int valueYPos = speciesNameLength - 5; // Create 270 degree rotated transform. AffineTransform transform = chartGraphics.getTransform(); AffineTransform originalTransform = (AffineTransform) transform.clone(); transform.rotate(Math.toRadians(270), valueXPos, valueYPos); chartGraphics.setTransform(transform); // Draw the string. chartGraphics.drawString(species[s].name, valueXPos, valueYPos); // Revert to original transform before rotation. chartGraphics.setTransform(originalTransform); } try { ImageIO.write((RenderedImage) chartImage, "gif", output); } catch (IOException e) { System.out.println("Unable to write Heat Map Image"); } /* double[][] heatMapVals = new double[allClusterIDs.length][species.length]; for (int s = 0; s < species.length; s ++) { for (int c = 0; c < allClusterIDs.length; c ++) { int frequency = species[s].findClusterFrequency(allClusterIDs[c]); // -1 means that species contains no genes in the specified cluster, but can't have negative color // ensure that frequency is never negative if (frequency == -1) { frequency = 0; } heatMapVals[c][s] = frequency; } } String[] names = new String[species.length]; for (int s = 0; s < species.length; s ++) { names[s] = species[s].name; } HeatChart heatChart = new HeatChart(heatMapVals); Color axisColor = new Color(0, 0, 0); Color background = new Color(255, 255, 255); Dimension cellSize = new Dimension(20, 20); heatChart.setAxisColour(axisColor); heatChart.setBackgroundColour(background); heatChart.setCellSize(cellSize); heatChart.setXValues(names); heatChart.setTitle("Heat Map"); heatChart.setYAxisLabel("Cluster ID"); heatChart.setXAxisLabel("Species"); heatChart.setHighValueColour(Color.red); heatChart.setLowValueColour(Color.blue); heatChart.setAxisThickness(1); heatChart.setColourScale(0.8); heatChart.setHighValueColour(Color.red); heatChart.setLowValueColour(Color.blue); heatChart.setAxisThickness(1); heatChart.setColourScale(0.8); Image heatMap = heatChart.getChartImage(); File output = new File("heatMap.gif"); try { ImageIO.write((RenderedImage) heatMap, "gif", output); } catch (IOException e) { System.out.println("Unable to write image to file"); } */ } private static void generateDelimitedTable(Species[] species) { System.out.println("About to create a new tab delimited file with data requested." + "\n" + "Please name new file:"); Scanner in = new Scanner(System.in); String filename = in.next(); in.close(); FileWriter fileWriter = null; try { fileWriter = new FileWriter(filename); } catch (IOException e) { System.out.println("File failed to create"); } PrintWriter printWriter = new PrintWriter(fileWriter); printWriter.print("Cluster id"); for (int s = 0; s< species.length; s++) { printWriter.print("\t" + species[s].name); } for (int c = 0; c < allClusterIDs.length; c ++) { printWriter.print("\n" + c); for (int s = 0; s < species.length; s ++) { int frequency = species[s].findClusterFrequency(allClusterIDs[c]); if (frequency == -1) { frequency = 0; } printWriter.print("\t" + frequency); } } printWriter.close(); } // creates a connection, distributes work and information to the various helper functions // gathers the final list of species and their geneMaps in one place public static Species[] getHeatChartData(String[] geneIDs) { // TODO make error messages more helpful int[] clusterIDs; Connection connection = openConnection(); Statement statement = null; connection = selectDatabase(statement, connection); clusterIDs = getAllClusters(geneIDs, connection); allClusterIDs = clusterIDs; Species[] species = findAllSpecies(clusterIDs, connection); //System.out.println(species.length); for(int s = 0; s < species.length; s ++) { System.out.print(species[s].name + ","); for (int c = 0; c < allClusterIDs.length; c ++) { String endChar = ""; if (c + 1 < allClusterIDs.length) { endChar = ","; } System.out.print(species[s].findClusterFrequency(allClusterIDs[c]) + endChar); } System.out.println(""); } return species; } // prints out the heatMap public static void displayHeatChart(Species[] species) { Frame f = new Frame("heatMapFrame"); ImageProducer imgProd = null; Image i = f.createImage(imgProd); Graphics g; g = i.getGraphics(); for (int s = 0; s < species.length; s ++) { for (int c = 0; c < allClusterIDs.length; c ++) { int frequency = species[s].findClusterFrequency(allClusterIDs[c]); // -1 means that species contains no genes in the specified cluster, but can't have negative color // ensure that frequency is never negative if (frequency == -1) { frequency = 0; } Color color = new Color(frequency * 5, 50, 50); // TODO adjust based on maximum number of hits per species/cluster pair g.setColor(color); g.drawRect((s*25), (c*25), 25, 25); //TODO how do I create a graphics object? I can't manipulate it if I don't have it but I can't seem to create one either. } } } // generates the logic to gather the list of all species that fall into the given cluster ID's // generates a list of unique species objects and their geneMaps private static Species[] findAllSpecies(int[] clusterIDs, Connection connection) { Species[] rawSpecies; int speciesCount = 0; String currentSpecies = null; String inStatement = getInStatement(clusterIDs, connection); PreparedStatement findSpecies = null; ResultSet rs = null; try { findSpecies = connection.prepareStatement( "select super_id, species, count(species) from super_clust where super_id " + inStatement + "group by species, super_id order by species"); } catch (SQLException e) { System.out.println("Statement failed to prepare"); System.err.println("SQLException: " + e.getMessage()); } try { rs = findSpecies.executeQuery(); } catch (SQLException e) { System.out.println("Could not execute Query, possible error in statement"); System.err.println("SQLException: " + e.getMessage()); } try { rs.last(); speciesCount = rs.getRow(); rs.beforeFirst(); rs.next(); currentSpecies = rs.getString(2); } catch (SQLException e) { System.out.println("Error in returned data - check database"); System.err.println("SQLException: " + e.getMessage()); } rawSpecies = new Species[speciesCount]; // initialize it to the correct size speciesCount = 0; // reusing the species count variable for other purposes try { rawSpecies[speciesCount] = new Species(); rawSpecies[speciesCount].setName(currentSpecies); rawSpecies[speciesCount].addCluster(rs.getInt(1), rs.getInt(3)); while(rs.next()) { if(rs.getInt(3) > maxCount) { maxCount = rs.getInt(3); } String name = rs.getString(2); if (name == currentSpecies) { rawSpecies[speciesCount].addCluster(rs.getInt(1), rs.getInt(3)); } else { currentSpecies = name; speciesCount ++; rawSpecies[speciesCount] = new Species(); rawSpecies[speciesCount].setName(currentSpecies); rawSpecies[speciesCount].addCluster(rs.getInt(1), rs.getInt(3)); } } } catch (SQLException e) { System.out.println("Unexpected Error"); System.err.println("SQLException: " + e.getMessage()); } Species[] finalSpecies = groupSpecies(rawSpecies); return finalSpecies; } private static Species[] groupSpecies(Species[] rawSpecies) { Species[] species = new Species[rawSpecies.length]; int cs = 0; species[0] = rawSpecies[0]; Species lastSpecies = species[0]; String currentSpecies; for(int count = 0; count < rawSpecies.length; count ++) { currentSpecies = rawSpecies[count].name; if (currentSpecies.equals(lastSpecies.name)) { lastSpecies.addCluster(rawSpecies[count].geneMap[0][0], rawSpecies[count].geneMap[0][1]); } else { species[cs] = lastSpecies; cs ++; lastSpecies = rawSpecies[count]; } if (count + 1 == rawSpecies.length) { species[cs] = lastSpecies; } } int unique = 0; for(int count = 0; (count < species.length && species[count] != null); count ++) { unique = count + 1; } //System.out.println(unique + "unique"); Species[] finalSpecies = new Species[unique]; for (int count = 0; count < unique; count ++) { finalSpecies[count] = species[count]; } return finalSpecies; } private static String getInStatement(int[] clusterIDs, Connection connection) { String inStatement = "IN ("; for (int i = 0; i < clusterIDs.length; i ++) { inStatement = inStatement + clusterIDs[i]; if(i+1 < clusterIDs.length) { inStatement = inStatement + ","; } else { inStatement = inStatement + ")"; } } return inStatement; } // finds ALL clusters that the given geneID's fall into private static int[] getAllClusters(String[] geneIDs, Connection connection) { ResultSet rs = null; int[] allClusters; String logicStatement = "gene LIKE '"; for (int i = 0; i < geneIDs.length; i ++) { logicStatement = logicStatement + geneIDs[i]; if(i+1 < geneIDs.length) { logicStatement = logicStatement + "%' OR gene LIKE '"; } else { logicStatement = logicStatement + "%'"; } } //System.out.println(geneIDs.length); //System.out.println(logicStatement); // finds the clusters that the genes are in PreparedStatement findCluster; try { findCluster = connection.prepareStatement("SELECT DISTINCT super_id FROM super_clust WHERE " + logicStatement); } catch (SQLException e1) { System.out.println("Statment failed to prepare"); System.err.println("SQLException: " + e1.getMessage()); findCluster = null; } try { rs = findCluster.executeQuery(); } catch (SQLException e) { System.out.println("Unable to execute Query"); System.err.println("SQLException: " + e.getMessage()); } int totalClusters = 0; try { rs.last(); totalClusters = rs.getRow(); rs.beforeFirst(); } catch (SQLException e) { System.out.println("Error in data, unable to parse"); System.err.println("SQLException: " + e.getMessage()); } allClusters = new int[totalClusters]; for (int i = 0; i < geneIDs.length; i ++) { try { rs.next(); allClusters[i] = rs.getInt(1); } catch (SQLException e) { //System.out.println("Genes overlap"); //System.err.println("SQLException: " + e.getMessage()); } } return allClusters; } // selects the database to use private static Connection selectDatabase(Statement statement, Connection connection) { PreparedStatement useDatabase; try { useDatabase = connection.prepareStatement("USE inparanoid_data"); } catch (SQLException e2) { System.out.println("Unexpected Error"); System.err.println("SQLException: " + e2.getMessage()); useDatabase = null; } try { useDatabase.execute(); } catch (SQLException e) { System.out.println("Unexpected Error"); System.err.println("SQLException: " + e.getMessage()); } return connection; } private static Connection openConnection() { Properties properties = new Properties(); properties.setProperty("user", "inparanoid-read-user"); properties.setProperty("password", "inparanoid-read-user_pw"); properties.setProperty("autoReconnect", "true"); properties.setProperty("useOldUTF8Behavior", "true"); properties.setProperty("zeroDateTimeBehavior", "convertToNull"); properties.setProperty("dontTrackOpenResources", "true"); String url = "jdbc:mysql://floret.cgrb.oregonstate.edu:3306/inparanoid_data"; try { Class.forName("com.mysql.jdbc.Driver").newInstance(); //Or any other driver } catch(Exception x){ System.out.println( "Unable to load the driver class!" ); } try { Connection c = DriverManager.getConnection(url, properties); return c; } catch(SQLException x) { System.out.println("Couldn’t get connection!"); System.err.println("SQLException: " + x.getMessage()); } return null; } }