I need to set minimum X-tick interval in the chart. I have a dataset that contains 1000 entries, i.e. <0,12>,<5,22>,<10,23>,...,<1000,20>. In dataset, the interval between X-values is equal to 5. In the chart I want to set X-tick interval equal to 100.
I use this code, but it does not work:
NumberAxis range = (NumberAxis)plot.getRangeAxis();
range.setTickUnit(new NumberTickUnit(100));
Here is my code snippet:
private JFreeChart createChart(CategoryDataset dataset)
{
final JFreeChart chart = ChartFactory.createAreaChart(
this.title,
"Time",
"Net demand",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
Title t = new TextTitle(this.subtitle);
chart.addSubtitle(t);
int transparency = 95;
Color c = new Color(1, 158, 115, transparency);
final CategoryPlot plot = chart.getCategoryPlot();
CategoryItemRenderer renderer = new CustomRenderer(c);
renderer.setSeriesOutlinePaint(0, Color.black);
renderer.setSeriesOutlineStroke(0, new BasicStroke(0.5f));
renderer.setSeriesPaint(0,c);
plot.setRenderer(renderer);
NumberAxis range = (NumberAxis)plot.getRangeAxis();
range.setTickUnit(new NumberTickUnit(60));
return chart;
}
You've set the tick unit for the range axis, which is the y-axis in JFreeChart. For the x-axis, you want the domain axis.
NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
xAxis.setTickUnit(new NumberTickUnit(60));
The domain and range terms come from a function mapping a set of domain values to a set of range values. With hindsight, using getXAxis() and getYAxis() for the method names would have been clearer for most people...for JFreeChart 2 I'll probably change it.
Related
I have an app and I somehow successfully managed to get a candlestick chart visible. However, once the chart is displayed, it shows all the candles (can be several hundred) which causes the chart to be very tiny and zoomed out. What I actually want is, the chart to be zoomed into the range of the last N candles so it looks more visible to the eye.
Here is how my charts look once they get created
I tried working with setRange, the Range on the Date Axis returns values in the format of [09.02.2023, 23:21:02 --> 10.02.2023, 08:29:56]
I dont seem to get how to make the chart like zoom in to a range of for example range.length-100 -> range.length. Whatever I tried, I always end up somewhere randomly without any data really shown.
Is there a way to define the last n entries on the range and set the dateAxis to start showing this range?
What I actually want to see after creation is something like this
private void displayChart(String title, String quoteMarket, BarSeries series) {
OHLCDataset dataSet = createOHLCDataset(title,series);
JFreeChart chart = ChartFactory.createCandlestickChart(
title,
"Time",
quoteMarket,
dataSet,
false);
chart.setBackgroundPaint(new Color(28, 39, 57));
chart.setBorderVisible(false);
chart.getTitle().setPaint(Color.WHITE);
// Candlestick rendering
CandlestickRenderer renderer = new CandlestickRenderer();
renderer.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_INTERVALDATA);
renderer.setUpPaint(new Color(0, 214, 110));
renderer.setDownPaint(new Color(196, 19, 30));
renderer.setSeriesPaint(0,new Color(211, 211, 211));
renderer.setCandleWidth(3.0);
XYPlot plot = chart.getXYPlot();
plot.setRenderer(renderer);
plot.setRangeGridlinePaint(Color.lightGray);
plot.setBackgroundPaint(new Color(28, 39, 57));
plot.setDomainGridlinesVisible( false );
plot.setRangeGridlinesVisible( false );
NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
numberAxis.setAutoRangeIncludesZero(false);
numberAxis.setLabelPaint(Color.WHITE);
numberAxis.setTickLabelPaint(Color.WHITE);
numberAxis.setAutoRangeIncludesZero(false);
DateAxis dateAxis = (DateAxis) plot.getDomainAxis();
dateAxis.setAutoRange(true);
dateAxis.setLabelPaint(Color.WHITE);
dateAxis.setTickLabelPaint(Color.WHITE);
dateAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
ChartPanel panel = new ChartPanel(chart);
panel.setMouseWheelEnabled(true);
panel.setMouseZoomable(true);
panel.setRangeZoomable(true);
panel.setDomainZoomable(true);
this.add(panel);
System.out.println(dateAxis.getRange());
}
I am creating a graph with contain x and y value. The y axis in normal but x is with the logarithmic value. I used the library (jfreechart.jar) for making this logarithmic graph.
My question is how can in fine the exact value of x if for example y is 10? (the value of x is in logarithmic number)
private void interActionPerformed(java.awt.event.ActionEvent evt) {
final XYSeries s1 = new XYSeries("Series 1");
s1.add(0.075,4.8);
s1.add(0.15,13.9);
s1.add(0.425,19.5);
s1.add(0.6,22.1);
s1.add(1.18,26.6);
s1.add(2,29.5);
s1.add(2.36,31.2);
s1.add(4.75,38.6);
s1.add(9.5,46.2);
s1.add(19,62.4);
s1.add(25,76.);
s1.add(37.5,86.2);
s1.add(50,100);
final XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(s1);
final JFreeChart chart = ChartFactory.createXYLineChart(
"sieve analyese", // chart title
"sieve size", // domain axis label
"passing", // range axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true,
false
);
final XYPlot plot = chart.getXYPlot();
final LogarithmicAxis domainAxis = new LogarithmicAxis("particle size in milimeters");
final NumberAxis rangeAxis = new NumberAxis("percent passing");
plot.setDomainAxis(domainAxis);
plot.setRangeAxis(rangeAxis);
BarRenderer renderer = null;
ChartFrame frame = new ChartFrame("sive chart", chart);
frame.setVisible(true);
frame.setSize(1000,600);
chart.setBackgroundPaint(Color.lightGray);
plot.setOutlinePaint(Color.RED);
} [chart of x and y value][1]
Use the below function to get the value of x from y
x = Math.log(y)
For exact value of X you should know exact dependence (function) of Y(X) or X(Y). For real-life data the kind of this function often is unknown, and one have to apply some approximation method.
Considering that your data are monotone (increasing), you can find an index of interval where given Y lie using binary search. For sample data you'll find 0-th interval between (0.075,4.8) and (0.15,13.9)
Then apply some interpolation method. The simplest approach - linear interpolation.
For you data set you might use quadratic interpolation with better accuracy - use 3 closest points to build parabola equation, and from this equation get X for given Y.
I am new to JFreeChart. My requirement is to display the X axis (time-axis) as following (time ranges will be configurable as per user input) for a line chart with suppose 3 variables:
3rdAug-8thAug..10thAug-15thAug.. [ and so on ]
Currently my graph's X axis is like this :
1..2..3..4..5 ..
[Unable to attach screenshots]
My demo code is as follows :
private JFreeChart createChart(final XYDataset dataset) {
// create the chart...
final JFreeChart chart = ChartFactory.createXYLineChart(
"Line Chart Demo ", // chart title
"X", // x axis label
"Y", // y axis label
dataset, // data
PlotOrientation.VERTICAL,
true, // include legend
true, // tooltips
false // urls
);
// OPTIONAL CUSTOMISATION OF THE CHART...
chart.setBackgroundPaint(Color.white);
// get a reference to the plot for further customisation...
final XYPlot plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesLinesVisible(0, true); //for line visibility
renderer.setSeriesShapesVisible(1, false);
plot.setRenderer(renderer);
// change the auto tick unit selection to integer units only...
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
// final Axis range = plot.get
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
// OPTIONAL CUSTOMISATION COMPLETED.
return chart;
}
Can anyone point me in the right direction here?
How do I get only the required values shown on the X axis?
XYPlot differ between domain axes and range axes. In your case the X axis is the domain axis whereas the Y axis is the range axis.
Valuexis domainAxis = plot.getDomainAxis();
You can also set a different domain axis:
ValueAxis dAxis = new ...
plot.setDomainAxis(dAxis);
You want to use JFreeChart's TimeLine interface to limit the shown dates on the DateAxis (which is actually the domain-axis in your case, as already pointed out by #Uli). For your requirement the default implementation SegmentedTimeline should fulfill your requirements. Just configure it and pass it on to your axis:
SegmentedTimeline timeline = new SegmentedTimeline(
86400000l, // segment size = one day in ms (24*3600*1000)
5, // include 5 segments (days)
2); // exclude 2 segments (days)
DateAxis axis = new DateAxis();
axis.setTimeline(timeline);
And don't forget to configure the plot to use the new DateAxis, as XYPlot uses NumberAxis by default:
plot.setDomainAxis(axis);
hth,
- martin
I have a single series XYAreaChart
final JFreeChart chart = ChartFactory.createXYAreaChart(
"",
"", "Rolling",
dataset,
PlotOrientation.VERTICAL,
false, // legend
true, // tool tips
false // URLs
);
final XYPlot plot = chart.getXYPlot();
I want to set paint color to Red when RangeValue >0 otherwise set it to Green. This is the nearest bit of code I can find BUT I think it is for two series:
plot.setRenderer(new XYDifferenceRenderer(Color.green, Color.red, false));
Which renderer do I need for a single series?
This may be able to help you. Below is an example showing a basic chart from a JFreechart tutorial. I have added the renderer in your example to it, my theory is that when you have 1 series the 'second series' as it were is effectively 0. Therefore when you apply the two series renderer, if the first series dips below 0 it becomes the negative color, and when it is above 0 becomes the positive colour.
When I opened my saved chart it had red on the minus points, and green on the posotive. See if it helps:
public class SO{
public static void main(String[] args) {
// Create a simple XY chart
XYSeries series = new XYSeries("Gradient logs chopped");
series.add(1, -7);
series.add(2, -2);
series.add(3, 4);
series.add(4, 7);
series.add(5, 10);
// Add the series to your data set
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
// Generate the graph
JFreeChart chart = ChartFactory.createXYLineChart(
"Logs chopped", // Title
"Week", // x-axis Label
"Logs", // y-axis Label
dataset, // Dataset
PlotOrientation.VERTICAL, // Plot Orientation
true, // Show Legend
true, // Use tooltips
false // Configure chart to generate URLs?
);
//The renderer part
XYPlot plot = chart.getXYPlot();
XYDifferenceRenderer rend = new XYDifferenceRenderer(Color.GREEN, Color.RED, false);
rend.setSeriesFillPaint(0, Color.DARK_GRAY);
rend.setRoundXCoordinates(true);
plot.setRenderer(rend);
//The renderer part
try {
ChartUtilities.saveChartAsJPEG(new File("D:\\Users\\user2777005\\Desktop\\XYchart.jpg"), chart, 500, 300);
} catch (IOException e) {
System.err.println("Problem occurred creating chart.");
}
}
}
Good luck!
I'm building multiple stacked bar charts (subplots) that are combined through a CombinedRangeCategoryPlot.
As the subplots datasets do not have the same number of items and since JFreeChart decides to allocate the same space for each subplot, I have different widths of bars.
Is there any way I can align their width (even if it means that the subplots have different widths)?
Please see below for the result and the code I have so far.
Many thanks,
Thomas
//Builds commong range axis
NumberAxis rangeAxis = new NumberAxis("%");
rangeAxis.setRange(0, 1.0);
rangeAxis.setNumberFormatOverride(NumberFormat.getPercentInstance());
//Builds common data set
CombinedRangeCategoryPlot combinedPlots = new CombinedRangeCategoryPlot(rangeAxis);
for (int groupIndex=0; groupIndex<LeakGroups.values().length; ++groupIndex){
//Builds category axis
CategoryAxis categoryAxis = new CategoryAxis(GuiConstants.LEAK_GROUPS_LABELS[groupIndex]);
//Sets margins between bars
categoryAxis.setCategoryMargin(0.5f);
//Builds bar renderer
StackedBarRenderer barRenderer = new StackedBarRenderer();
barRenderer.setRenderAsPercentages(true);
//Builds dot/level renderer
LineAndShapeRenderer dotRenderer = new LineAndShapeRenderer();
//dotRenderer.setSeriesLinesVisible(0, false);
//dotRenderer.setSeriesShapesVisible(0, false);
//dotRenderer.setSeriesLinesVisible(1, false);
//Defines level shape height (depends on chart size): nominal values are for a height of 1000px
int shapeHeightPx = (int) Math.round(20 * (this.getHeight() / 1000.0));
dotRenderer.setSeriesShape(1, new Rectangle(-1, -shapeHeightPx/2, 2, shapeHeightPx));
//Builds plot
CategoryPlot plot = new CategoryPlot();
plot.setDomainAxis(categoryAxis);
plot.setDataset(0, data[groupIndex].bars);
plot.setRenderer(0, barRenderer);
plot.setDataset(1, data[groupIndex].dots);
plot.setRenderer(1, dotRenderer);
//Adds to combined
combinedPlots.add(plot);
}
combinedPlots.setOrientation(PlotOrientation.HORIZONTAL);
//Puts range axis at the bottom
combinedPlots.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
//Changes plot render sequence so that bars are in the background and shapes in front
combinedPlots.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
//Shows gridlines for categories and not for values
combinedPlots.setDomainGridlinesVisible(true);
combinedPlots.setRangeGridlinesVisible(false);
//Creates chart
JFreeChart chart = new JFreeChart("Leaks", combinedPlots);
//Sets a margin right to allow space for last catergory label ("100%")
chart.setPadding(new RectangleInsets(0, 0, 0, 20));
return chart;
For some reason, the weight gets reset to value 1 when adding the plot.
By way of explanation,
The add(CategoryPlot subplot) method specifies a default weight of 1,
The add(CategoryPlot subplot, int weight) method lets you specify a weight value.
After a few hours of search, found the solution: use plot.setWeight().
For some reason, the weight gets reset to value 1 when adding the plot to the CombinedRangeCategoryPlot, hence it has to be set after.
Hope this helps.