Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
77f136a
Fixing class name ambiguity
danv61 Feb 24, 2026
48a71c4
Clusters panel
danv61 Feb 25, 2026
ff17e3a
implementing the cluster specifications panel
danv61 Feb 27, 2026
1d6b2e4
separating the cluster results panel
danv61 Mar 3, 2026
41840ee
decoupling the pannels, one way communication between panels
danv61 Mar 4, 2026
f1b028d
graceful behavior if no data
danv61 Mar 6, 2026
1b3548d
standard color tables - tableau20, color blind, etc
danv61 Mar 9, 2026
ca84714
color management, legend panel
danv61 Mar 9, 2026
793b531
plot panel, multithreaded. scaling fails during initial display
danv61 Mar 10, 2026
1937433
plot panel, nice working implementation
danv61 Mar 10, 2026
ed998b0
cluster analyze panel, testing JFreeChart
danv61 Mar 12, 2026
de35730
cluster data panel - table view
danv61 Mar 12, 2026
7df9594
cluster specification and visualization panel - visual refinements
danv61 Mar 13, 2026
7f2fbf3
cluster specification and visualization panel - more visual refinemen…
danv61 Mar 17, 2026
7ef9705
cluster specification and visualization panel, SD of ACS
danv61 Mar 19, 2026
bf990ea
cluster visualization panel: copy to clipboard, renderting, bug fixing
danv61 Mar 19, 2026
f6d4a65
cluster plot panel: rendering y-axis ticks
danv61 Mar 23, 2026
9e4cc0a
molecule specification and visualization panels - the basics
danv61 Mar 24, 2026
a6c3f49
various results panels: generalized class name
danv61 Mar 24, 2026
36e069a
proper management and selection of tabbed panels for batch results
danv61 Mar 24, 2026
8e19ef1
stubs for left and right panels
danv61 Mar 24, 2026
ff9e446
Implementation for specification panels base class and molecule speci…
danv61 Mar 26, 2026
d7f9f51
Implementation for specification panels base class and molecule speci…
danv61 Mar 30, 2026
fe4ecd4
Implementation for specification panels base class and molecule speci…
danv61 Apr 1, 2026
13a9efb
Standalone MoleculeDataPanel
danv61 Apr 7, 2026
e4a780e
Symmetrical class hierarchy for all components
danv61 Apr 7, 2026
0723371
batch simulation results visualization, alpha candidate
danv61 Apr 10, 2026
a1f6bf0
replaces system.out with logger.debug
danv61 Apr 13, 2026
ca32b38
replaces system.out with logger.debug
danv61 Apr 13, 2026
178039e
typos
danv61 Apr 14, 2026
eb6529d
Eliminating all references to JFreeChart
danv61 Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
import com.lowagie.text.DocumentException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.labels.StandardXYItemLabelGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYDifferenceRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
Expand All @@ -16,7 +22,9 @@
import org.apache.logging.log4j.Logger;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
Expand Down Expand Up @@ -319,4 +327,246 @@ private static PageFormat generateAlternatePageFormat(){
pageFormat.setOrientation(PageFormat.LANDSCAPE);
return pageFormat;
}


Comment thread
danv61 marked this conversation as resolved.
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {

Random rand = new Random();

int n = 50;
double xMin = 0.0;
double xMax = 7.0;
double dx = (xMax - xMin) / (n - 1);

double xLower = 0.0; // these are the limits for the x values of the axis
double xUpper = 7.5;

Color sinColor = new Color(31, 119, 180); // blue
Color tanColor = new Color(255, 127, 14); // orange

// --- SIN series ---
XYSeries sinMin = new XYSeries("sin-min");
XYSeries sinMax = new XYSeries("sin-max");
XYSeries sinMain = new XYSeries("sin");
XYSeries sinStd = new XYSeries("sin-std");

for (int i = 0; i < n; i++) {
double x = xMin + i * dx;
double y = Math.sin(x);

double delta = 0.2 + rand.nextDouble() * 0.2;
double yMin = y - delta;
double yMax = y + delta;

double std = 0.08 + rand.nextDouble() * 0.08;

sinMin.add(x, yMin);
sinMax.add(x, yMax);
sinMain.add(x, y);
sinStd.add(x, y + std);
}

// --- TAN series ---
XYSeries tanMin = new XYSeries("tan-min");
XYSeries tanMax = new XYSeries("tan-max");
XYSeries tanMain = new XYSeries("tan");
XYSeries tanStd = new XYSeries("tan-std");

for (int i = 0; i < n; i++) {
double x = xMin + i * dx;
double y = Math.tan(x);

if (y > 3) y = 3;
if (y < -3) y = -3;

double delta = 0.3 + rand.nextDouble() * 0.3;
double yMin = y - delta;
double yMax = y + delta;

double std = 0.2 + rand.nextDouble() * 0.2;

tanMin.add(x, yMin);
tanMax.add(x, yMax);
tanMain.add(x, y);
tanStd.add(x, y + std);
}

double globalMin = Double.POSITIVE_INFINITY;
double globalMax = Double.NEGATIVE_INFINITY;
for (int i = 0; i < n; i++) {
globalMin = Math.min(globalMin, sinMin.getY(i).doubleValue());
globalMin = Math.min(globalMin, tanMin.getY(i).doubleValue());
globalMax = Math.max(globalMax, sinMax.getY(i).doubleValue());
globalMax = Math.max(globalMax, tanMax.getY(i).doubleValue());
}
// Add padding
double pad = 0.1 * (globalMax - globalMin);
globalMin -= pad;
globalMax += pad;

// --- Datasets ---

// Dataset 0: sin min/max (for band)
XYSeriesCollection sinMinMaxDataset = new XYSeriesCollection();
sinMinMaxDataset.addSeries(sinMax); // upper
sinMinMaxDataset.addSeries(sinMin); // lower

// Dataset 1: tan min/max (for band)
XYSeriesCollection tanMinMaxDataset = new XYSeriesCollection();
tanMinMaxDataset.addSeries(tanMax); // upper
tanMinMaxDataset.addSeries(tanMin); // lower

// Dataset 2: main curves
XYSeriesCollection mainDataset = new XYSeriesCollection();
mainDataset.addSeries(sinMain);
mainDataset.addSeries(tanMain);

// Dataset 3: std diamonds
XYSeriesCollection stdDataset = new XYSeriesCollection();
stdDataset.addSeries(sinStd);
stdDataset.addSeries(tanStd);

// --- Chart skeleton ---
JFreeChart chart = ChartFactory.createXYLineChart(
"Min/Max Bands + STD Demo",
"x",
"y",
null,
PlotOrientation.VERTICAL,
true,
true,
false
);
XYPlot plot = chart.getXYPlot();

// Transparent backgrounds
chart.setBackgroundPaint(Color.WHITE);
plot.setBackgroundPaint(Color.WHITE);
plot.setOutlinePaint(null);
plot.setDomainGridlinePaint(new Color(180, 180, 180)); // very light
plot.setRangeGridlinePaint(new Color(180, 180, 180));

plot.getDomainAxis().setAutoRange(false); // lock the axis so that they never resize
plot.getRangeAxis().setAutoRange(false);
plot.getDomainAxis().setRange(xLower, xUpper);
plot.getRangeAxis().setRange(globalMin, globalMax);

// --- Legend to the right
chart.getLegend().setPosition(RectangleEdge.RIGHT);
chart.getLegend().setBackgroundPaint(Color.WHITE);
// chart.getLegend().setFrame(BlockBorder.NONE);

// --- Renderer 0: sin band ---
XYDifferenceRenderer sinBandRenderer = new XYDifferenceRenderer();
Color sinBandColor = new Color(sinColor.getRed(), sinColor.getGreen(), sinColor.getBlue(), 40);
sinBandRenderer.setPositivePaint(sinBandColor);
sinBandRenderer.setNegativePaint(sinBandColor);
sinBandRenderer.setSeriesStroke(0, new BasicStroke(0f));
sinBandRenderer.setSeriesStroke(1, new BasicStroke(0f));
// sinBandRenderer.setOutlinePaint(null);
sinBandRenderer.setSeriesVisibleInLegend(0, false); // hide sin-max legend entries
sinBandRenderer.setSeriesVisibleInLegend(1, false);

plot.setDataset(0, sinMinMaxDataset);
plot.setRenderer(0, sinBandRenderer);

// --- Renderer 1: tan band ---
XYDifferenceRenderer tanBandRenderer = new XYDifferenceRenderer();
Color tanBandColor = new Color(tanColor.getRed(), tanColor.getGreen(), tanColor.getBlue(), 40);
tanBandRenderer.setPositivePaint(tanBandColor);
tanBandRenderer.setNegativePaint(tanBandColor);
tanBandRenderer.setSeriesStroke(0, new BasicStroke(0f));
tanBandRenderer.setSeriesStroke(1, new BasicStroke(0f));
// tanBandRenderer.setOutlinePaint(null);
tanBandRenderer.setSeriesVisibleInLegend(0, false);
tanBandRenderer.setSeriesVisibleInLegend(1, false);

plot.setDataset(1, tanMinMaxDataset);
plot.setRenderer(1, tanBandRenderer);

// --- Renderer 2: main curves ---
XYLineAndShapeRenderer lineRenderer = new XYLineAndShapeRenderer(true, false);
lineRenderer.setSeriesPaint(0, sinColor);
lineRenderer.setSeriesPaint(1, tanColor);
lineRenderer.setSeriesStroke(0, new BasicStroke(2f));
lineRenderer.setSeriesStroke(1, new BasicStroke(2f));
lineRenderer.setSeriesVisibleInLegend(0, true); // keep the main curves visible in Legend
lineRenderer.setSeriesVisibleInLegend(1, true);

plot.setDataset(2, mainDataset);
plot.setRenderer(2, lineRenderer);

// --- Renderer 3: STD diamonds ---
XYLineAndShapeRenderer stdRenderer = new XYLineAndShapeRenderer(false, true);
Shape diamond = createDiamondShape(4);

stdRenderer.setSeriesShape(0, diamond);
stdRenderer.setSeriesShape(1, diamond);
stdRenderer.setSeriesPaint(0, sinColor.darker());
stdRenderer.setSeriesPaint(1, tanColor.darker());
stdRenderer.setSeriesVisibleInLegend(0, false);
stdRenderer.setSeriesVisibleInLegend(1, false);

plot.setDataset(3, stdDataset);
plot.setRenderer(3, stdRenderer);

// --- ChartPanel ---
ChartPanel panel = new ChartPanel(chart);
panel.setOpaque(true); // must be opaque for white to show
panel.setBackground(Color.WHITE);

// --- checkboxes to control display
JPanel controls = new JPanel();
JCheckBox cbAvg = new JCheckBox("Averages", true);
JCheckBox cbMinMax = new JCheckBox("Min-Max", false);
JCheckBox cbStd = new JCheckBox("STD", false);
controls.add(cbAvg);
controls.add(cbMinMax);
controls.add(cbStd);

// Averages (dataset 2)
cbAvg.addActionListener(e -> {
boolean on = cbAvg.isSelected();
plot.getRenderer(2).setSeriesVisible(0, on);
plot.getRenderer(2).setSeriesVisible(1, on);
lineRenderer.setSeriesVisibleInLegend(0, true); // force legend visible
lineRenderer.setSeriesVisibleInLegend(1, true);
});

// Min-Max (datasets 0 and 1)
cbMinMax.addActionListener(e -> {
boolean on = cbMinMax.isSelected();
plot.setRenderer(0, on ? sinBandRenderer : null);
plot.setRenderer(1, on ? tanBandRenderer : null);
});

// STD (dataset 3)
cbStd.addActionListener(e -> {
boolean on = cbStd.isSelected();
stdRenderer.setSeriesVisible(0, on);
stdRenderer.setSeriesVisible(1, on);
});

// --- Frame ---
JFrame frame = new JFrame("JFreeChart Min/Max/STD Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel, BorderLayout.CENTER);
frame.add(controls, BorderLayout.SOUTH);
frame.setSize(900, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}

private static Shape createDiamondShape(int size) {
Path2D.Double p = new Path2D.Double();
p.moveTo(0, -size);
p.lineTo(size, 0);
p.lineTo(0, size);
p.lineTo(-size, 0);
p.closePath();
return p;
}

}
Loading
Loading