I am using TimeSeries jfreechart to show network performance.I want to show total time passed in seconds but it showing only seconds from 0 to 59 and then reset seconds to 0 again.I have to show data for last 120 seconds.
Here is the code :
This function is used to create chart:
private JFreeChart createChart(XYDataset xydataset) {
result = ChartFactory.createTimeSeriesChart("admin0", "", "MBytes/S", xydataset, true, true, true);
TextTitle objTitle = new TextTitle("admin0", new Font("Verdana", Font.BOLD, 12));
result.setTitle(objTitle);
final XYPlot plot = result.getXYPlot();
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinesVisible(true);
plot.setBackgroundPaint(Color.WHITE);
plot.setRangeGridlinePaint(Color.GRAY);
plot.setDomainGridlinePaint(Color.GRAY);
DateAxis xaxis = (DateAxis)plot.getDomainAxis();
xaxis.setAutoRange(true); ////set true to move graph with time.
xaxis.setFixedAutoRange(120000.0);
xaxis.setTickUnit(new DateTickUnit(DateTickUnit.SECOND, 15, new SimpleDateFormat("ss")));
NumberAxis range = (NumberAxis) plot.getRangeAxis();///y-Axis
range.setRange(0.0, 1.0);
range.setTickUnit(new NumberTickUnit(0.2));
XYItemRenderer renderer = plot.getRenderer();
renderer.setSeriesPaint(0, Color.RED);
renderer.setSeriesPaint(1, Color.GREEN);
return result;
}
And here is the code for creating dataset:
private XYDataset createAdmin0DatasetTest() {
TimeSeriesCollection dataset = new TimeSeriesCollection();
try
{
if(performanceData != null)
{
long speed = 0;
double recieveRate = 0;
double sendRate = 0;
long timeinMilli = 0;
long devider = 4294967296l;
long snapTime = 0;
Vector admin0Vec = (Vector)this.performanceData.get("admin0");
if(admin0Vec != null && admin0Vec.size() > 0)
{
Vector innerVec = (Vector)admin0Vec.get(0);
recieveRate = Long.parseLong(innerVec.get(2).toString());
sendRate = Long.parseLong(innerVec.get(1).toString());
timeinMilli = Long.parseLong(innerVec.get(0).toString());
}catch(Exception ex)
{
System.out.println("Exception in adding same values");
}
for(int i = 1 ; i < admin0Vec.size() ; i++)
{
innerVec = (Vector)admin0Vec.get(i);
recieveRate = Long.parseLong(innerVec.get(2).toString());
sendRate = Long.parseLong(innerVec.get(1).toString());
timeinMilli = Long.parseLong(innerVec.get(0).toString());
try
{
this.adminRecieve.addOrUpdate(new Second(new Date(timeinMilli)), recieveRate);
this.adminSend.addOrUpdate(new Second(new Date(timeinMilli)), sendRate);
}catch(Exception ex)
{
System.out.println("Exception in adding same values");
//ex.printStackTrace();
}
}
dataset = new TimeSeriesCollection(this.adminRecieve);
dataset.addSeries(adminSend);
}
}
}catch(Exception ex)
{
ex.printStackTrace();
}
return dataset;
}
Please help me out
Hint:
You are using DateAxis for your domain axis and render it as seconds, so surely it will only display the seconds-part of the data without computing any totals. Moreover, it does not have to start at zero and will only display 120 seconds worth of data.
What you want is not a time series, i.e. numbers vs. time, but a data series of numbers vs. numbers (elapsed seconds). So construct it in that way and use NumberAxis for the domain.
Note: The above is for really showing the total elapsed time, e.g. for data between seconds 480 and 600 the labels will be for example 480, 500, 520, 540, 560, 580, 600 (i.e. total, as asked in the title, since some moment). If the question is to have static labels, e.g. -120, -100, -80, -60, -40, -20, 0, with moving data then setting ticks and labels on the axis needs to be done differently.
Related
I want to plot a sine wave, but instead my application generates a flat line. When I use series with random from jchartfree example everything works fine. I also use debugger to check if values are good. Values are different than zero
public void createDataset() {
XYSeriesCollection dataset = new XYSeriesCollection();
XYSeries series1 = new XYSeries("Object 1");
double A = 1;
double T = 1;
double Fs = 10;
double f = 200;
int rozmiar = (int) (T*Fs);
double[] x = new double[rozmiar];
for (int i = 0; i < rozmiar; i++)
{
x[i] = A * Math.sin(2 * Math.PI * f * i / Fs);
series1.add(i, x[i]);
}
dataset.addSeries(series1);
data = dataset;
}
//...
public void createChartPanel() {
//pWykres = new JPanel();
//if(java.util.Arrays.asList(getComponents()).contains(pWykres)){
//getContentPane().remove(pWykres);
//}
if(pWykres != null){
pWykres.removeAll();
pWykres.revalidate();
}
String chartTitle = "Objects Movement Chart";
String xAxisLabel = "X";
String yAxisLabel = "Y";
JFreeChart chart = ChartFactory.createXYLineChart(chartTitle,
xAxisLabel, yAxisLabel, dataset);
customizeChart(chart);
pWykres = new ChartPanel(chart);
getContentPane().add(pWykres, BorderLayout.CENTER);
setSize(620, 460);
//validate();
pWykres.repaint();
}
//endregion
//...
//region
private void customizeChart(JFreeChart chart) {
XYPlot plot = chart.getXYPlot();
XYSplineRenderer renderer;
renderer = new XYSplineRenderer();
renderer.setSeriesShapesVisible(0, false);
// sets paint color for each series
renderer.setSeriesPaint(0, Color.RED);
// sets thickness for series (using strokes)
renderer.setSeriesStroke(0, new BasicStroke(1.0f));
// sets paint color for plot outlines
//plot.setOutlinePaint(Color.BLUE);
//plot.setOutlineStroke(new BasicStroke(2.0f));
// sets renderer for lines
plot.setRenderer(renderer);
// sets plot background
plot.setBackgroundPaint(Color.WHITE);
// sets paint color for the grid lines
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.BLACK);
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.BLACK);
}
You are taking the sine of values that are always whole multiples of 2 * PI, so all of these values will be (approximately) zero, hence your graph will end up appearing flat unless it is scaled to show up these tiny values (which are just floating point errors).
x[i] = A * Math.sin(2 * Math.PI * f * i / Fs);
where A = 1 and f/Fs = 20 and i is integer
For example:
Math.sin(0) // 0.0
Math.sin(2 * Math.PI) // -2.4492935982947064E-16 (approximately zero)
Math.sin(4 * Math.PI) // -4.898587196589413E-16 (approximately zero)
To see the characteristic shape of a sine wave, you need to vary the input to the sin function by much smaller increments, e.g. pi/10 or less.
I am trying to make a normal distribution graph using the JFreeChart library. I am successful if I try to get one area under the graph. However I did not find a way on how get 2 areas under the graph.
Here is the code for one side :
public GrafHujungKanan() {
Function2D normal = new NormalDistributionFunction2D(0.0, 1.0);
dataset = DatasetUtilities.sampleFunction2D(normal, -4, 4, 100,
"Normal");
XYSeries fLine = new XYSeries("fLine");
fLine.add(nilaiKritikal, 0);
fLine.add(4, 0);
((XYSeriesCollection) dataset).addSeries(fLine);
NumberAxis xAxis = new NumberAxis(null);
NumberAxis yAxis = new NumberAxis(null);
XYDifferenceRenderer renderer = new XYDifferenceRenderer();
xAxis.setRange(0, 5);
plot = new XYPlot(dataset, xAxis, yAxis, renderer);
chart = new JFreeChart(plot);
chart.removeLegend();
ChartPanel cp = new ChartPanel(chart);
this.add(cp);
}
Here is how it looks with the above code
And here is how I need it to look :
I already tried flipping the values with positive and negative. But instead the line of the graph turns green.
This is what I tried
public GrafDuaHujung() {
Function2D normal = new NormalDistributionFunction2D(0.0, 1.0);
dataset = DatasetUtilities.sampleFunction2D(normal, -4, 4, 100,
"Normal");
// line on right side
XYSeries fLine = new XYSeries("fLine");
fLine.add(2, 0);
fLine.add(4, 0);
((XYSeriesCollection) dataset).addSeries(fLine);
// line on left side
XYSeries dLine = new XYSeries("dLine");
dLine.add(-2, 0);
dLine.add(-4, 0);
((XYSeriesCollection) dataset).addSeries(dLine);
NumberAxis xAxis = new NumberAxis(null);
NumberAxis yAxis = new NumberAxis(null);
XYDifferenceRenderer renderer = new XYDifferenceRenderer();
xAxis.setRange(0, 5);
plot = new XYPlot(dataset, xAxis, yAxis, renderer);
chart = new JFreeChart(plot);
chart.removeLegend();
ChartPanel cp = new ChartPanel(chart);
this.add(cp);
}
Thank you for your answer.
You can use multiple datasets.
public GrafDuaHujung() {
Function2D normal = new NormalDistributionFunction2D(0.0, 1.0);
dataset = DatasetUtilities.sampleFunction2D(normal, -4, 4, 100, "Normal");
dataset2 = DatasetUtilities.sampleFunction2D(normal, -4, 4, 100, "Normal"); //New
// line on right side
XYSeries fLine = new XYSeries("fLine");
fLine.add(2, 0);
fLine.add(4, 0);
((XYSeriesCollection) dataset).addSeries(fLine);
// line on left side
XYSeries dLine = new XYSeries("dLine");
dLine.add(-2, 0);
dLine.add(-4, 0);
((XYSeriesCollection) dataset2).addSeries(dLine); //Changed
XYDifferenceRenderer renderer = new XYDifferenceRenderer();
plot = new XYPlot(); //New
plot.setDataset(0, dataset); //New
plot.setDataset(1, dataset2); //New
plot.setRenderer(renderer); //New
chart = new JFreeChart(plot);
chart.removeLegend();
ChartPanel cp = new ChartPanel(chart);
this.add(cp);
}
.csv file 1 data:
sampler_label,aggregate_report_count,average,aggregate_report_median,aggregate_report_90%_line
HTTP Request1, 750 ,26339 ,22644 , 40210
HTTP Request2, 750 ,8280 ,4781 ,21016
.csv file 2 data:
sampler_label,aggregate_report_count,average,aggregate_report_median,aggregate_report_90%_line
HTTP Request1, 350 ,2539 ,2224 , 48410
HTTP Request4, 350 ,8736 ,9285 ,38217
I want to display bar graph, which should depict values of average from both files for each sampler label.
Here there are 2 average values in each file. there may be n number of values. in bar graph i want to display values of file 1 and file 2 in one graph only.
Please help me....
public JFreeChart createBarChartFromCSV() {
csv csvReader = new csv();
List<String[]> csvData1 = null;
List<String[]> csvData2 = null;
int indexOfAverage1 = 0;
int indexOfAverage2 = 0;
csvData1 = csvReader.getDataFromCSV1(csv.CSVFILENAME1);
csvData2 = csvReader.getDataFromCSV2(csv.CSVFILENAME2);
for(String[] columnArray : csvData1)
for(int i = 0; i< columnArray.length; i++)
if(columnArray[i].equalsIgnoreCase("average")){
enter code here
indexOfAverage1 = i;
break;
}
if(indexOfAverage1 == 0){
System.err.println("Error retrieving data from CSV File1 !!");
System.exit(0);
}
for(String[] columnArray : csvData2)
for(int j = 0; j< columnArray.length; j++)
if(columnArray[j].equalsIgnoreCase("average")){
indexOfAverage2 = j;
break;
}
if(indexOfAverage2 == 0){
System.err.println("Error retrieving data from CSV File2 !!");
System.exit(0);
}
JFreeChart barChart = generateBarChart(csvData1,csvData2, indexOfAverage1,indexOfAverage2);
return barChart;
}
private JFreeChart generateBarChart(List<String[]> csvData1,List<String[]> csvData2, int columnIndex1, int columnIndex2){
DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
final String YAXIS_NAME = csvData1.get(0)[columnIndex1]; //value returned is "average"
final String XAXIS_NAME = csvData1.get(0)[0]; //value returned is "sampler_label"
for(int i = 1; i < csvData1.size() - 1; i++){
long averageValue1 = Long.parseLong(csvData1.get(i)[columnIndex1]);
String columnKey1 = csvData1.get(i)[0];
dataSet.setValue(averageValue1, YAXIS_NAME, columnKey1); // plot the graph
}
for(int j = 1; j< csvData2.size() - 1; j++){
long averageValue2 = Long.parseLong(csvData2.get(j)[columnIndex2]);
String columnKey2 = csvData2.get(j)[0];
dataSet.setValue(averageValue2, YAXIS_NAME, columnKey2); // plot the graph
}
System.out.println("created");
JFreeChart chart = ChartFactory.createBarChart("Comparison between the average of 2 values", XAXIS_NAME, YAXIS_NAME, dataSet, PlotOrientation.VERTICAL, true, true, false);
final CategoryPlot plot = chart.getCategoryPlot();
chart.setBackgroundPaint(Color.white);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setRangeGridlinePaint(Color.white);
BarRenderer renderer=new BarRenderer();
System.out.print( "set the range axis to display integers only...");
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
System.out.print( "disable bar outlines...");
renderer = (BarRenderer) plot.getRenderer();
renderer.setDrawBarOutline(false);
renderer.setMaximumBarWidth(0.10);
System.out.print( "set up gradient paints for series...");
final GradientPaint gp0 = new GradientPaint(
0.0f, 0.0f, Color.blue,
0.0f, 0.0f, Color.lightGray
);
final GradientPaint gp1 = new GradientPaint(
0.0f, 0.0f, Color.green,
0.0f, 0.0f, Color.lightGray
);
renderer.setSeriesPaint(0, gp0);
renderer.setSeriesPaint(1, gp1);
return chart;
}
I am trying to make a plot of weight of an animal stored with soem specific date. I have Weight Class with two vars , Date and Weight.
Here is the code I am using.
else if (str.equals("Weight"))
{
mDbHelper.open();
wtArray = mDbHelper.getWeight();
mDbHelper.close();
TimeSeries diaSeries = new TimeSeries("Weight");
for ( int i =0; i <wtArray.size(); i++)
{
Weight wt = wtArray.get(i);
diaSeries.add(wt.date, wt.weight);
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(diaSeries);
XYMultipleSeriesRenderer mrenderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.DIAMOND);
renderer.setFillPoints(true);
mrenderer.addSeriesRenderer(renderer);
graphLayout.addView(ChartFactory.getTimeChartView(this, dataset, mrenderer, "MM/dd/yyyy"));
}
The problem with this code is, it never shows anything on x Axis and no graph line is also displayed.
Secondly, What If I want to show data from specific date to another date? Like from Feb to March etc.?
I have used your code to build an example to compile and run for me. Please see the code below that displays a chart correctly. The code builds an Intent, so you will have to change the last line to build a View.
So, if you are really sure that you really put data into the model than you should check the layout. You are probably not adding the chart view to your layout correctly.
List<Date> wtArray = new ArrayList<Date>();
double[] weight = new double[] { 70, 71, 74, 73, 70, 71, 75, 76, 75, 73, 75, 73 };
for (int i = 0; i < 12; i++) {
wtArray.add(new Date(108, i, 1));
}
TimeSeries diaSeries = new TimeSeries("Weight");
for (int i = 0; i < wtArray.size(); i++) {
diaSeries.add(wtArray.get(i), weight[i]);
}
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(diaSeries);
XYMultipleSeriesRenderer mrenderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.DIAMOND);
renderer.setFillPoints(true);
mrenderer.addSeriesRenderer(renderer);
return ChartFactory.getTimeChartIntent(context, dataset, mrenderer, "MM/dd/yyyy");
I have a method for generating dataset:
private CategoryDataset createDataset(double[] arr,
String seriesName) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 0; i < arr.length; i++) {
dataset.addValue(arr[i], "mySeries", new Integer(i));
}
return dataset;
}
and create BarChart:
JFreeChart chart = ChartFactory.createBarChart(chartTitle,
xaxis, // domain axis label
yaxis, // range axis label
dataset, // data
orientation, // orientation
true, // include legend
true, // tooltips?
false // URLs?
);
Array of doubles hold histogram data, so there are 255 values.
When I display chart there are labels for
all values from 0 - 255 on x axis. I want display only labels for several indexes (for example: 0, 10, 20, 30). I saw that in RangeAxis there is setStandardTickUnits method. But in CategoryAxis:
CategoryAxis domainAxis = plot.getDomainAxis();
I didn't find this.
Any help?
You can try as follows,
NumberAxis vn = (NumberAxis) plot.getRangeAxis();
vn.setTickUnit(new NumberTickUnit(10d));
vn.setRange(0D, Math.ceil(factor * MAX_VALUE));
--that is you just need cast plot.getRangeAxis() to NumberAxis type.
I had same problem. I created new class implementing 'Comparable', and use it as last parameter in addValue(...). You can create something like
class MyCategory implements Comparable<MyCategory> {
Integer value;
String stValue;
MyCategory(int val) {
value = val;
stValue = val%10==0?""+val:"";}
public int compareTo(MyCategory key) { return value.compareTo(key.value); }
public String toString() { return stValue; }
}
And then instead of
dataset.addValue(arr[i], "mySeries", new Integer(i));
use
dataset.addValue(arr[i], "mySeries", new MyCategory(i));