-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7c095ac
commit 683226a
Showing
6 changed files
with
280 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
vcell-core/src/main/java/org/vcell/plotting/Results2DLinePlot.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package org.vcell.plotting; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* Stores all relevant info to create a 2D plot, and lazily builds a PDF on request | ||
*/ | ||
public class Results2DLinePlot implements ResultsLinePlot { | ||
private String plotTitle; | ||
private double[] xData, yData; | ||
private String xLabel, yLabel; | ||
|
||
public Results2DLinePlot(){ | ||
this.plotTitle = ""; | ||
this.xData = new double[0]; | ||
this.yData = new double[0]; | ||
this.xLabel = ""; | ||
this.yLabel = ""; | ||
} | ||
|
||
@Override | ||
public void setTitle(String newTitle) { | ||
this.plotTitle = newTitle; | ||
} | ||
|
||
@Override | ||
public String getTitle() { | ||
return this.plotTitle; | ||
} | ||
|
||
public void setXData(double[] newXData){ | ||
this.xData = newXData; | ||
} | ||
|
||
public double[] getXData(){ | ||
return this.xData; | ||
} | ||
|
||
public void setYData(double[] newYData){ | ||
this.yData = newYData; | ||
} | ||
|
||
public double[] getYData(){ | ||
return this.yData; | ||
} | ||
|
||
public void setXLabel(String newXLabel){ | ||
this.xLabel = newXLabel; | ||
} | ||
|
||
public String getXLabel(){ | ||
return this.xLabel; | ||
} | ||
|
||
public void setYLabel(String newYLabel){ | ||
this.yLabel = newYLabel; | ||
} | ||
|
||
public String getYLabel(){ | ||
return this.yLabel; | ||
} | ||
|
||
@Override | ||
public void generatePdf(String desiredFileName, File desiredParentDirectory) { | ||
|
||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
vcell-core/src/main/java/org/vcell/plotting/ResultsLinePlot.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.vcell.plotting; | ||
|
||
import java.io.File; | ||
|
||
/** | ||
* Describes the basic functionality all LinePlots displaying simulation results should have. | ||
*/ | ||
public interface ResultsLinePlot { | ||
|
||
/** | ||
* Generates a PDF copy of the current plot state, and exports it as PDF at the desired location. | ||
* @param desiredFileName name of the plot file; needs no file suffix: ".pdf" will be appended. | ||
* @param desiredParentDirectory directory to place the new pdf into. | ||
*/ | ||
void generatePdf(String desiredFileName, File desiredParentDirectory); | ||
|
||
/** | ||
* Setter for the title of the plot | ||
* @param newTitle the desired new title as a String | ||
*/ | ||
void setTitle(String newTitle); | ||
|
||
/** | ||
* Getter for the title of the plot | ||
* @return the title as a String | ||
*/ | ||
String getTitle(); | ||
|
||
} |
149 changes: 149 additions & 0 deletions
149
vcell-core/src/test/java/org/vcell/plotting/TestJFreeChartLibrary.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package org.vcell.plotting; | ||
|
||
import cbit.vcell.publish.PDFWriter; | ||
import com.lowagie.text.DocumentException; | ||
import org.jfree.chart.*; | ||
import org.jfree.chart.labels.StandardXYItemLabelGenerator; | ||
import org.jfree.chart.labels.XYItemLabelGenerator; | ||
import org.jfree.chart.plot.XYPlot; | ||
import org.jfree.chart.renderer.category.LineAndShapeRenderer; | ||
import org.jfree.data.*; | ||
import org.jfree.data.xy.*; | ||
import org.jfree.data.category.CategoryDataset; | ||
import org.jfree.data.general.DefaultKeyedValues2DDataset; | ||
|
||
import org.junit.jupiter.api.AfterAll; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.api.Tag; | ||
import org.junit.jupiter.api.Test; | ||
import org.vcell.sbml.BMDB_SBML_Files; | ||
import org.vcell.util.Pair; | ||
import scala.collection.immutable.Page; | ||
|
||
import java.awt.*; | ||
import java.awt.image.BufferedImage; | ||
import java.awt.print.PageFormat; | ||
import java.awt.print.Paper; | ||
import java.io.*; | ||
import java.nio.charset.StandardCharsets; | ||
import java.text.DecimalFormat; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
|
||
@Tag("Fast") | ||
public class TestJFreeChartLibrary { | ||
|
||
private static List<XYDataItem> testData = List.of( | ||
new XYDataItem(0.0, 0.0), | ||
new XYDataItem(0.5, 0.25), | ||
new XYDataItem(1.0, 1.0), | ||
new XYDataItem(1.5, 2.25), | ||
new XYDataItem(2.0, 4.0), | ||
new XYDataItem(2.5, 6.25), | ||
new XYDataItem(3.0, 9.0), | ||
new XYDataItem(3.5, 12.25), | ||
new XYDataItem(4.0, 16.0), | ||
new XYDataItem(4.5, 20.25), | ||
new XYDataItem(5.0, 25.0), | ||
new XYDataItem(5.5, 30.25) | ||
); | ||
|
||
@Test | ||
public void testDirectChartCreation() throws IOException, DocumentException { | ||
PageFormat pageFormat = TestJFreeChartLibrary.generateAlternatePageFormat(); | ||
|
||
// Build Chart | ||
XYSeries xySeries = new XYSeries("Ka+", true, false); // The "key" field is what to name the curve itself, when shown in a Legend | ||
for (XYDataItem valuePair: TestJFreeChartLibrary.testData){ | ||
xySeries.add(valuePair); | ||
} | ||
XYDataset dataset2D = new XYSeriesCollection(xySeries); | ||
this.generateChart(dataset2D, pageFormat, "Time"); | ||
} | ||
|
||
@Test | ||
public void testDirectChartCreationFromCSV() throws IOException, DocumentException { | ||
PageFormat pageFormat = TestJFreeChartLibrary.generateAlternatePageFormat(); | ||
Pair<String, XYDataset> datasetPair = TestJFreeChartLibrary.csvToXYDataset(); | ||
this.generateChart(datasetPair.two, pageFormat, datasetPair.one); | ||
} | ||
|
||
private void generateChart(XYDataset dataset2D, PageFormat pageFormat, String xAxisLabel) throws IOException, DocumentException { | ||
int AXIS_LABEL_FONT_SIZE = 15; | ||
String yAxisLabel = ""; | ||
JFreeChart chart = ChartFactory.createXYLineChart("Test Sim Results", xAxisLabel, yAxisLabel, dataset2D); | ||
|
||
// Tweak Chart so it looks better | ||
chart.setBorderVisible(true); | ||
XYPlot chartPlot = chart.getXYPlot(); | ||
chartPlot.getDomainAxis().setLabelFont(new Font(xAxisLabel, Font.PLAIN, AXIS_LABEL_FONT_SIZE)); | ||
chartPlot.getRangeAxis().setLabelFont(new Font(yAxisLabel, Font.PLAIN, AXIS_LABEL_FONT_SIZE)); | ||
if (dataset2D.getItemCount(0) <= 10) { // if it's too crowded, having data point labels is bad | ||
for (int i = 0; i < dataset2D.getSeriesCount(); i++){ | ||
//DecimalFormat decimalformat1 = new DecimalFormat("##"); | ||
chartPlot.getRenderer().setSeriesItemLabelGenerator(0, | ||
new StandardXYItemLabelGenerator("({1}, {2})")); | ||
chartPlot.getRenderer().setSeriesItemLabelFont(i, new Font(null, Font.PLAIN, 8)); | ||
chartPlot.getRenderer().setSeriesItemLabelsVisible(i, true); | ||
} | ||
} | ||
|
||
// Prepare for export | ||
PDFWriter pdfWriter = new PDFWriter(); | ||
|
||
File testfile = File.createTempFile("VCell::TestJFreeChartLibrary::testDirectChartCreation::", ".pdf"); | ||
if (!testfile.exists()) throw new IllegalArgumentException("Unable to create the testfile, somehow."); | ||
try (FileOutputStream fos = new FileOutputStream(testfile)){ | ||
BufferedImage bfi = chart.createBufferedImage((int)pageFormat.getImageableWidth(), (int)pageFormat.getImageableHeight()); | ||
pdfWriter.writePlotImageDocument("Test Document", fos, pageFormat, bfi); | ||
} | ||
} | ||
|
||
private static PageFormat generateAlternatePageFormat(){ | ||
java.awt.print.PageFormat pageFormat = java.awt.print.PrinterJob.getPrinterJob().defaultPage(); | ||
Paper alternatePaper = new Paper(); // We want to try and increase the margins | ||
double altOriginX = alternatePaper.getImageableX() / 2, altOriginY = alternatePaper.getImageableY() / 2; | ||
double altWidth = alternatePaper.getWidth() - 2 * altOriginX, altHeight = alternatePaper.getHeight() - 2 * altOriginY; | ||
alternatePaper.setImageableArea(altOriginX, altOriginY, altWidth, altHeight); | ||
pageFormat.setPaper(alternatePaper); | ||
pageFormat.setOrientation(PageFormat.LANDSCAPE); | ||
return pageFormat; | ||
} | ||
|
||
private static Pair<String, XYDataset> csvToXYDataset() throws IOException { | ||
String CSV_DATA_FILE_LOCAL_PATH = "plot2d_SimpleSimulation.csv"; | ||
InputStream inputStream = TestJFreeChartLibrary.class.getResourceAsStream(CSV_DATA_FILE_LOCAL_PATH); | ||
if (inputStream == null) | ||
throw new FileNotFoundException(String.format("can not find `%s`; maybe it moved?", CSV_DATA_FILE_LOCAL_PATH)); | ||
XYSeriesCollection dataset2D = new XYSeriesCollection(); | ||
List<String> linesOfData; | ||
try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))){ | ||
linesOfData = br.lines().toList(); | ||
} | ||
String[] indepDataParts = linesOfData.get(linesOfData.size() - 1).split(","); | ||
List<Double> xSeriesData = new ArrayList<>(); | ||
for (int partNum = 3; partNum < indepDataParts.length; partNum++){ // Skip first three; no need for them | ||
xSeriesData.add(Double.parseDouble(indepDataParts[partNum])); | ||
} | ||
|
||
for (int lineNum = 0; lineNum < linesOfData.size() - 1; lineNum++){ // Skip last line; that's our independent-var data | ||
XYSeries series = getXySeries(linesOfData, lineNum, xSeriesData); | ||
dataset2D.addSeries(series); | ||
} | ||
|
||
return new Pair<>(indepDataParts[2], dataset2D); | ||
} | ||
|
||
private static XYSeries getXySeries(List<String> linesOfData, int lineNum, List<Double> xSeriesData) { | ||
String[] parts = linesOfData.get(lineNum).split(","); | ||
String ySeriesName = parts[2]; | ||
XYSeries series = new XYSeries(ySeriesName, true); | ||
if (parts.length - 3 != xSeriesData.size()) throw new RuntimeException("Mismatched data length!"); | ||
for (int partNum = 3; partNum < parts.length; partNum++){ // Skip first two; third we've already grabbed | ||
double xData = xSeriesData.get(partNum - 3), yData = Double.parseDouble(parts[partNum]); | ||
series.add(xData, yData); | ||
} | ||
return series; | ||
} | ||
} |
Oops, something went wrong.