Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package web.diva.server.model.pca; import java.awt.Color; import java.awt.Dimension; import java.awt.LayoutManager; import java.awt.Point; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Serializable; import java.io.Writer; import java.util.ArrayList; import java.util.HashSet; import java.util.Vector; import javax.swing.border.Border; import no.uib.jexpress_modularized.pca.computation.PcaResults; import no.uib.jexpress_modularized.pca.model.ArrayUtils; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.svggen.SVGGraphics2D; import org.apache.batik.transcoder.Transcoder; import org.apache.batik.transcoder.TranscoderInput; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.commons.codec.binary.Base64; import org.apache.fop.svg.PDFTranscoder; import org.jfree.chart.ChartUtilities; import org.w3c.dom.DOMImplementation; import org.w3c.dom.svg.SVGDocument; import web.diva.server.model.beans.DivaDataset; import web.diva.shared.beans.UpdatedTooltip; /** * * @author Yehia Farag */ public class PCAImageGenerator implements Serializable { //For speeding lookup private final DivaDataset divaDataset; private final PcaPlot plot; private final no.uib.jexpress_modularized.pca.computation.PcaResults pcaResults; private boolean zoom = false; private double[] zoomedRect = new double[4]; private UpdatedTooltip tooltips; private int pcax = 0; private int pcay = 1; private int pcaz = 2; private boolean shadowUnselected = false; private int[] notshadIndex; public boolean[] zoomedSelectionChange(int[] sel) { ArrayList<Integer> reIndexSel = new ArrayList<Integer>(); for (int x : sel) { if (indexToZoomed[x] != -100) { reIndexSel.add(indexToZoomed[x]); } } int[] zoomSel = new int[reIndexSel.size()]; for (int x = 0; x < zoomSel.length; x++) { zoomSel[x] = reIndexSel.get(x); } boolean[] notShaded = getSelectedIndexes(zoomSel); return notShaded; } public void selectionChanged(int[] sel) { notshadIndex = sel; boolean[] notShaded = getSelectedIndexes(sel); plot.setNotShaded(notShaded); if (shadowUnselected == false) { plot.forceFullRepaint(); } } public boolean isShadowUnselected() { return shadowUnselected; } public void setShadowUnselected(boolean shadowUnselected) { this.shadowUnselected = shadowUnselected; } private final String[] pcaLabelData; private final String totalvarStr; public PCAImageGenerator(PcaResults pcaResults, DivaDataset divaDataset, int pcax, int pcay) { this.divaDataset = divaDataset; this.pcaResults = pcaResults; this.pcax = pcax; this.pcay = pcay; this.plot = new PcaPlot(); plot.setMaximumSize(new Dimension(32767, 32767)); plot.setMinimumSize(new Dimension(900, 900)); plot.setPreferredSize(new Dimension(900, 900)); plot.setBorder(javax.swing.BorderFactory.createLineBorder(Color.BLUE)); plot.setLayout(new java.awt.FlowLayout(0, 5, 1)); plot.setSize(900, 900); plot.setBackground(Color.WHITE); indexToZoomed = new int[divaDataset.getDataLength()];// updatePlot(); pcaLabelData = new String[pcaResults.eigenvalues.length]; for (int i = 0; i < pcaResults.eigenvalues.length; i++) { pcaLabelData[i] = ("Principal Component nr." + String.valueOf(i + 1) + " - " + pcaResults.varianceastr(i) + "% var."); } double totalvar = 0.0; java.text.NumberFormat numformat = java.text.NumberFormat.getNumberInstance(java.util.Locale.US); numformat.setMaximumFractionDigits(1); if (pcax != pcay) { totalvar = pcaResults.varianceaccounted(pcax) + pcaResults.varianceaccounted(pcay); } else { totalvar = pcaResults.varianceaccounted(pcax); } totalvarStr = ("Total variance retained: " + numformat.format(totalvar) + "% var."); } /** * If this is a som representation, light up the neuron at point p. * * @param p The neuron to be lit. */ public void setSelected(java.awt.Point p) { plot.setHighLightedNeuron(p); } public void forceFullRepaint() { plot.setFullRepaint(true); // plot.repaint(); plot.forceFullRepaint(); } public void zoomOut() { zoom = false; updatePlot(); } public Vector getIndexesAtPoint(Point point, int radius) { return plot.getIndexesAtPoint(point, radius); } public boolean isZoompca() { return plot.isZoompca(); } public boolean isPaintNamesonClick() { return plot.isPaintNamesonClick(); } public boolean[] getFramedIndexes() { return plot.getFramedIndexes(); } public double[] getZoomedArea() { return plot.getZoomedArea(); } public void setSpotNames(String[][] SpotNames) { plot.setSpotNames(SpotNames); } public void setBorder(Border border) { plot.setBorder(border); } public void setLayout(LayoutManager loutManager) { plot.setLayout(loutManager); } public void setNotShaded(boolean[] notShaded) { plot.setNotShaded(notShaded); } /** * @param sel selection indexes * @return an array where the selected indexes are flagged as true. If there * are no indexes that are currently selected, or if the current Selection * from the SelectionManager is null, then an array of only false values are * returned. */ private boolean[] getSelectedIndexes(int[] sel) { if (sel == null) { return new boolean[divaDataset.getDataLength()]; } boolean[] ret = ArrayUtils.toBooleanArray(divaDataset.getDataLength(), sel); return ret; } private double[][] points; private int[] zoomedToNormalIndex; private final int[] indexToZoomed; private String[] rowIds; public double[][] getPoints() { return points; } private void updatePlot() { if (pcaResults == null) { return; } points = new double[2][(int) pcaResults.nrPoints()]; for (int i = 0; i < pcaResults.nrPoints(); i++) { points[0][i] = pcaResults.ElementAt(i, pcax); points[1][i] = pcaResults.ElementAt(i, pcay); } plot.setData(divaDataset); rowIds = divaDataset.getRowIds(); if (zoom) { plot.setPropsAndData(points[0], points[1], zoomedRect); } else { plot.zoomout(); plot.setForceEndLabel(true); plot.setPropsAndData(points[0], points[1]); } plot.setXaxisTitle("Principal Component " + (pcax + 1)); plot.setYaxisTitle("Principal Component " + (pcay + 1)); plot.setFullRepaint(true); plot.forceFullRepaint(); } private BufferedImage image; public BufferedImage getImage() { return image; } public int getImageHeight() { return image.getHeight(); } public int getImageWidth() { return image.getWidth(); } @SuppressWarnings("CallToPrintStackTrace") public String toImage() { image = (BufferedImage) plot.getImage(); byte[] imageData = null; try { imageData = ChartUtilities.encodeAsPNG(image); } catch (Exception e) { e.printStackTrace(); } String base64 = Base64.encodeBase64String(imageData); base64 = "data:image/png;base64," + base64; return base64; } public void setZoomPca(boolean zoom) { plot.setZoompca(zoom); } public void setZoom(boolean zoom, int startX, int startY, int endX, int endY) { this.zoom = zoom; this.zoomedRect = this.getSelectionRecatangle(startX, startY, endX, endY); this.updatePlot(); } public void setPaintNamesonClick(boolean paint) { plot.setPaintNamesonClick(paint); } public int getPcax() { return pcax; } public void setPcax(int pcax) { this.pcax = pcax; } public int getPcay() { return pcay; } public void setPcay(int pcay) { this.pcay = pcay; } public int getPcaz() { return pcaz; } public void setPcaz(int pcaz) { this.pcaz = pcaz; } public PcaPlot getPlot() { return plot; } @SuppressWarnings("CallToPrintStackTrace") public String toPdfFile(File userFolder, String url) { try { BufferedImage pdfImage = image; DOMImplementation domImpl = new SVGDOMImplementation(); String svgNS = "http://www.w3.org/2000/svg"; SVGDocument svgDocument = (SVGDocument) domImpl.createDocument(svgNS, "svg", null); SVGGraphics2D svgGenerator = new SVGGraphics2D(svgDocument); svgGenerator.setSVGCanvasSize(new Dimension(pdfImage.getWidth(), pdfImage.getHeight())); svgGenerator.setPaint(Color.WHITE); svgGenerator.drawImage(pdfImage, 0, 0, null); File pdfFile = new File(userFolder, divaDataset.getName() + "_PCA_PLOT" + ".pdf"); if (!pdfFile.exists()) { pdfFile.createNewFile(); } else { pdfFile.delete(); pdfFile.createNewFile(); } // write the svg file File svgFile = new File(pdfFile.getAbsolutePath() + ".temp"); OutputStream outputStream = new FileOutputStream(svgFile); BufferedOutputStream bos = new BufferedOutputStream(outputStream); Writer out = new OutputStreamWriter(bos, "UTF-8"); svgGenerator.stream(out, true /* use css */); outputStream.flush(); outputStream.close(); bos.close(); System.gc(); String svgURI = svgFile.toURI().toString(); TranscoderInput svgInputFile = new TranscoderInput(svgURI); OutputStream outstream = new FileOutputStream(pdfFile); bos = new BufferedOutputStream(outstream); TranscoderOutput output = new TranscoderOutput(bos); // write as pdf Transcoder pdfTranscoder = new PDFTranscoder(); pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER, 0.084666f); pdfTranscoder.transcode(svgInputFile, output); outstream.flush(); outstream.close(); bos.close(); System.gc(); return url + userFolder.getName() + "/" + pdfFile.getName(); } catch (Exception e) { e.printStackTrace(); } return ""; } @SuppressWarnings("CallToPrintStackTrace") public UpdatedTooltip getTooltipsInformationData() { tooltips = new UpdatedTooltip(); if (zoom) { try { int plotWidthArea = (plot.getWidth() - plot.left - plot.right); int plotHeightArea = plot.getHeight() - plot.top - plot.bottom; double xDataArea = plot.getZoomedArea()[1] - plot.getZoomedArea()[0]; double xUnitPix = xDataArea / (double) plotWidthArea; tooltips.setPlotWidth(plot.getWidth()); tooltips.setPlotHeight(plot.getHeight()); tooltips.setPlotHeightArea(plotHeightArea); tooltips.setPlotWidthArea(plotWidthArea); tooltips.setPlotRight(plot.right); tooltips.setPlotTop(plot.top); tooltips.setPlotBottom(plot.bottom); tooltips.setPlotLeft(plot.left); tooltips.setyAxisFactor(0); tooltips.setxAxisFactor(0); tooltips.setxUnitPix(xUnitPix); double yDataArea = plot.getZoomedArea()[3] - plot.getZoomedArea()[2]; double yUnitPix = yDataArea / (double) plotHeightArea; tooltips.setyUnitPix(yUnitPix); tooltips.setMinX(plot.getZoomedArea()[0]); tooltips.setMaxY(plot.getZoomedArea()[3]); tooltips.setPoints(points); tooltips.setRowIds(rowIds); } catch (Exception exp) { exp.printStackTrace(); } } else {//step 1 int yAxisFactor = plot.left - plot.yaxis.predictWidth(); int xAxisFactor = plot.bottom - plot.xaxis.predictWidth(); int plotWidthArea = plot.Width() - (plot.left) - plot.right + yAxisFactor; int plotHeightArea = plot.getHeight() - plot.top - plot.bottom + xAxisFactor; tooltips.setPlotWidth(plot.getWidth()); tooltips.setPlotHeight(plot.getHeight()); tooltips.setPlotHeightArea(plotHeightArea); tooltips.setPlotWidthArea(plotWidthArea); tooltips.setPlotRight(plot.right); tooltips.setPlotTop(plot.top); tooltips.setPlotBottom(plot.bottom); tooltips.setPlotLeft(plot.left); tooltips.setyAxisFactor(yAxisFactor); tooltips.setxAxisFactor(xAxisFactor); double xDataArea = plot.xaxis.maximum - plot.xaxis.minimum; double xUnitPix = xDataArea / (double) plotWidthArea; tooltips.setxUnitPix(xUnitPix); double yDataArea = plot.yaxis.maximum - plot.yaxis.minimum; double yUnitPix = yDataArea / (double) plotHeightArea; tooltips.setyUnitPix(yUnitPix); tooltips.setMinX(plot.xaxis.minimum); tooltips.setMaxY(plot.yaxis.maximum); tooltips.setPoints(points); tooltips.setRowIds(rowIds); } return tooltips; } @SuppressWarnings("CallToPrintStackTrace") public int[] getPCASelection(int startX, int startY, int endX, int endY) { double[] selectRect = null; if (zoom) { try { selectRect = getZoomedSelectionRecatangle(startX, startY, endX, endY); } catch (Exception exp) { exp.printStackTrace(); } } else { selectRect = this.getSelectionRecatangle(startX, startY, endX, endY); } if (selectRect == null) return new int[] {}; HashSet<Integer> selectedPoints = new HashSet<Integer>(); for (int x = 0; x < points[0].length; x++) { double pointX = points[0][x]; double pointY = points[1][x]; if (pointX >= selectRect[0] && pointX <= selectRect[1] && pointY >= selectRect[2] && pointY <= selectRect[3]) { selectedPoints.add(x); } } if (selectedPoints.size() > 0) { Integer[] selectedIndexes = new Integer[selectedPoints.size()]; System.arraycopy(selectedPoints.toArray(), 0, selectedIndexes, 0, selectedIndexes.length); int[] arr = new int[selectedIndexes.length]; arr = org.apache.commons.lang3.ArrayUtils.toPrimitive(selectedIndexes, selectedIndexes.length); return arr; } return new int[] {}; } private double[] getZoomedSelectionRecatangle(int startX, int startY, int endX, int endY) { double[] selectionRect = new double[4]; int maxXM = Math.max(startX, endX); int minXM = Math.min(startX, endX); int maxYM = Math.max(startY, endY); int minYM = Math.min(startY, endY); // int plotWidthArea = (plot.getWidth() - plot.left - plot.right); int plotHeightArea = plot.getHeight() - plot.top - plot.bottom; if ((minXM < (plot.left) && maxXM < (plot.left)) || (minXM > (plot.left + plotWidthArea))) { return null; } if ((minYM < plot.top && maxXM < plot.left) || (minYM > plot.top + plotHeightArea)) { return null; } minXM = minXM - plot.left; maxXM = maxXM - plot.left; minYM -= plot.top; maxYM -= plot.top; if ((minXM < 0 && maxXM >= 0)) minXM = 0;// plot.left; if (maxXM > plotWidthArea && minXM >= 0) maxXM = plotWidthArea; if ((minYM <= 0 && maxYM > 0))//plot.top)) minYM = 0;//plot.top; if (maxYM > plotHeightArea && minYM >= 0) maxXM = plotHeightArea; double xDataArea = plot.getZoomedArea()[1] - plot.getZoomedArea()[0]; double xUnitPix = xDataArea / (double) plotWidthArea; double modStartX = (minXM * xUnitPix) + plot.getZoomedArea()[0];//xstart units from min selectionRect[0] = modStartX; double modEndX = (maxXM * xUnitPix) + plot.getZoomedArea()[0]; selectionRect[1] = modEndX; double yDataArea = plot.getZoomedArea()[3] - plot.getZoomedArea()[2]; double yUnitPix = yDataArea / (double) plotHeightArea; double modStartY = plot.getZoomedArea()[3] - (maxYM * yUnitPix); selectionRect[2] = modStartY; double modEndY = plot.getZoomedArea()[3] - (minYM * yUnitPix); selectionRect[3] = modEndY; return selectionRect; } private double[] getSelectionRecatangle(int startX, int startY, int endX, int endY) { double[] selectionRect = new double[4]; int maxXM = Math.max(startX, endX); int minXM = Math.min(startX, endX); int maxYM = Math.max(startY, endY); int minYM = Math.min(startY, endY); int yAxisFactor = plot.left - plot.yaxis.predictWidth(); int xAxixFactor = plot.bottom - plot.xaxis.predictWidth(); int plotWidthArea = (plot.getWidth() - plot.left - plot.right) + (yAxisFactor); int plotHeightArea = plot.getHeight() - plot.top - plot.bottom + xAxixFactor; if ((minXM < (plot.left - yAxisFactor) && maxXM < (plot.left - yAxisFactor)) || (minXM > (plot.left + plotWidthArea))) { return null; } if ((minYM < plot.top && maxXM < plot.left) || (minYM > plot.top + plotHeightArea)) { return null; } minXM = minXM - plot.left + yAxisFactor; maxXM = maxXM - plot.left + yAxisFactor; minYM -= plot.top; maxYM -= plot.top; if ((minXM < 0 && maxXM >= 0)) minXM = 0; if (maxXM > plotWidthArea && minXM >= 0) maxXM = plotWidthArea; if ((minYM <= 0 && maxYM > 0)) minYM = 0; if (maxYM > plotHeightArea && minYM >= 0) maxXM = plotHeightArea; double xDataArea = plot.xaxis.maximum - plot.xaxis.minimum; double xUnitPix = xDataArea / (double) plotWidthArea; double modStartX = (minXM * xUnitPix) + plot.xaxis.minimum;//xstart units from min selectionRect[0] = modStartX; double modEndX = (maxXM * xUnitPix) + plot.xaxis.minimum; selectionRect[1] = modEndX; double yDataArea = plot.yaxis.maximum - plot.yaxis.minimum; double yUnitPix = yDataArea / (double) plotHeightArea; double modStartY = plot.yaxis.maximum - (maxYM * yUnitPix); selectionRect[2] = modStartY; double modEndY = plot.yaxis.maximum - (minYM * yUnitPix); selectionRect[3] = modEndY; return selectionRect; } public void initZoomInteraction(int[] selection) { zoomedToNormalIndex = selection; for (int x = 0; x < indexToZoomed.length; x++) { indexToZoomed[x] = -100; } for (int i = 0; i < selection.length; i++) { indexToZoomed[selection[i]] = i; } } public boolean[] getZoomedNotshadIndex() { if (notshadIndex != null) { return zoomedSelectionChange(notshadIndex);//notshadIndex } else { return null; } } public int[] reindexZoomedSelectionIndexes(int[] zoomedSelection) { int[] reindexSelection = new int[zoomedSelection.length]; for (int z = 0; z < zoomedSelection.length; z++) { reindexSelection[z] = zoomedToNormalIndex[zoomedSelection[z]]; } return reindexSelection; } public String[] getPcaLabelData() { return pcaLabelData; } public String getTotalvarStr() { return totalvarStr; } }