Re: Highlight plotted data
This question is over because I have found help to solve.
susie
Re: Highlight plotted data
If you think that the solution may helpful to someone else and interesting, please post it here. :)
Re: Highlight plotted data
Hi Eranga,
here is a good solution to my question: would love to have help for the other my questions left, I still have problem also with Y Log scale, I can't solve.
Susie
Code:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.effect.DropShadow;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class HighlightBaseXYChart extends Application {
private DropShadow ds = new DropShadow();
private ContextMenu contextMenu;
private XYChart.Series selectedSeries;
@Override
public void start(Stage stage) {
stage.setTitle("Linear plot");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis(0, 22, 0.5);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
@Override
public String toString(Number object) {
return String.format("%7.2f", object);
}
});
final LineChart<String, Number> lineChart = new LineChart<String, Number>(xAxis, yAxis);
lineChart.setCreateSymbols(false);
lineChart.setAlternativeRowFillVisible(false);
lineChart.setLegendVisible(false);
final XYChart.Series series1 = new XYChart.Series();
series1.getData().add(new XYChart.Data("Jan", 1));
series1.getData().add(new XYChart.Data("Feb", 1.5));
series1.getData().add(new XYChart.Data("Mar", 2));
series1.getData().add(new XYChart.Data("Apr", 2.5));
series1.getData().add(new XYChart.Data("May", 3));
series1.getData().add(new XYChart.Data("Jun", 4));
series1.getData().add(new XYChart.Data("Jul", 6));
series1.getData().add(new XYChart.Data("Aug", 9));
series1.getData().add(new XYChart.Data("Sep", 12));
series1.getData().add(new XYChart.Data("Oct", 15));
series1.getData().add(new XYChart.Data("Nov", 20));
series1.getData().add(new XYChart.Data("Dec", 22));
BorderPane pane = new BorderPane();
pane.setCenter(lineChart);
Scene scene = new Scene(pane, 800, 600);
lineChart.getData().addAll(series1);
contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Save data");
contextMenu.getItems().add(menuItem);
menuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
if (selectedSeries != null) {
System.out.println("Save data of " + selectedSeries.getData());
// Saving logic here
}
}
});
// for every series in linechart
applyMouseEvents(series1);
stage.setScene(scene);
stage.show();
}
private void applyMouseEvents(final XYChart.Series series) {
final Node node = series.getNode();
// We need set userdata to obtain it later through the node.
node.setUserData(series);
node.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
node.setEffect(ds);
node.setCursor(Cursor.HAND);
}
});
node.setOnMouseExited(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent arg0) {
node.setEffect(null);
node.setCursor(Cursor.DEFAULT);
}
});
node.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
contextMenu.show(node, mouseEvent.getScreenX() + 1, mouseEvent.getScreenY() + 1);
// Set as selected
selectedSeries = (XYChart.Series) node.getUserData();
System.out.println("Selected Series data " + selectedSeries.getData());
}
}
});
}
public static void main(String[] args) {
launch(args);
}
}
Quote:
Originally Posted by
Eranga
If you think that the solution may helpful to someone else and interesting, please post it here. :)
Re: Highlight plotted data
If you could specifically explain questions left with you I can help you to sort out them. And other members in the community too. :)
Re: Highlight plotted data
Thanks Eranga,
my questions left are the following:
1) I am not able to set YAxis as logarithmic: I have found the only example on the net and Darryl Burke kindly recode the JavaScript in FX but after all this time I still am not able to implement correctly
Topic is here:
http://www.java-forums.org/javafx/60...s-xychart.html
2) Compress / Expand data visualisation : thread is here
http://www.java-forums.org/javafx/61...alization.html
Haven't had any reply for this
Thank you very much
Quote:
Originally Posted by
Eranga
If you could specifically explain questions left with you I can help you to sort out them. And other members in the community too. :)
Re: Highlight plotted data
Any help still really very much appreciated!
Susie
Re: Highlight plotted data
Let me try :-)
Quote:
1) I am not able to set YAxis as logarithmic: I have found the only example on the net and Darryl Burke kindly recode the JavaScript in FX but after all this time I still am not able to implement correctly
Topic is here:
http://www.java-forums.org/javafx/60...s-xychart.html
Code:
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis(1, 22, 0.5);
Maybe you should change your code for yAxis with something like this:
Code:
final NumberAxis yAxis = new NumberAxis(Math.log10(1), Math.log10(22), Math.log10(0.5));
Re: Highlight plotted data
Hi cselic,
thanks for your reply but your suggestion doesn't work, I've aleady tried this solution before.
I think the task is in replacing the standard object chart with a log version, not just set lower and upper bound Y scale as log.
Susie
Re: Highlight plotted data
^I think that I've found solution:
Change you existing code:
Code:
series1.getData().add(new XYChart.Data("Jan", 1));
series1.getData().add(new XYChart.Data("Feb", 1.5));
series1.getData().add(new XYChart.Data("Mar", 2));
series1.getData().add(new XYChart.Data("Apr", 2.5));
series1.getData().add(new XYChart.Data("May", 3));
series1.getData().add(new XYChart.Data("Jun", 4));
series1.getData().add(new XYChart.Data("Jul", 6));
series1.getData().add(new XYChart.Data("Aug", 9));
series1.getData().add(new XYChart.Data("Sep", 12));
series1.getData().add(new XYChart.Data("Oct", 15));
series1.getData().add(new XYChart.Data("Nov", 20));
series1.getData().add(new XYChart.Data("Dec", 22));
with:
Code:
series1.getData().add(new XYChart.Data("Jan", Math.log(1)));
series1.getData().add(new XYChart.Data("Feb", Math.log(1.5)));
series1.getData().add(new XYChart.Data("Mar", Math.log(2)));
series1.getData().add(new XYChart.Data("Apr", Math.log(2.5)));
series1.getData().add(new XYChart.Data("May", Math.log(3)));
series1.getData().add(new XYChart.Data("Jun", Math.log(4)));
series1.getData().add(new XYChart.Data("Jul", Math.log(6)));
series1.getData().add(new XYChart.Data("Aug", Math.log(9)));
series1.getData().add(new XYChart.Data("Sep", Math.log(12)));
series1.getData().add(new XYChart.Data("Oct", Math.log(15)));
series1.getData().add(new XYChart.Data("Nov", Math.log(20)));
series1.getData().add(new XYChart.Data("Dec", Math.log(22)));
Re: Highlight plotted data
Yes this is an alternative way to have data as log, but it is not the best one: I have to load and display thousands of data and the right solution would be in having a Value Axis as log.
What it seems an easy task reveals to be one of the hardest issues in FX 2.x : it doesn't esist any native Java FX method to have log axis, and even searching through the web there are only one solution, written in JavaScript that I am not able to use, and it is here
JavaFX chart API and logarithmic scale - dooApp technical blog
It seems one developer has just been able to solve this problem, I have found his tweet here
@jasperpotts Been playing with JavaFX charts. Nice! Are logarithmic scale axes possible - see x-axis on this image?
where he set X Axis as log.
Susie
Re: Highlight plotted data
Quote:
Originally Posted by
susieferrari
Yes this is an alternative way to have data as log, but it is not the best one: I have to load and display thousands of data and the right solution would be in having a Value Axis as log.
Then the best way for doing that is in some loop where you are going to change Data values in every step. For example change this line of code so that it can be used in loop for changing values of Data.
Code:
series1.getData().add(new XYChart.Data("Jan", Math.log(1)));
.
You can also put your String and Double values into Collection, maybe HashMap or something else.
There are other ways, but they not good as previous one. For example:
Code:
MyLogClass number = new MyLogClass(5);
XYChart.Series<String, MyLogClass> series2 = new XYChart.Series<>();
XYChart.Data<String, MyLogClass> chart = new XYChart.Data<>();
series2.getData().add(new XYChart.Data<>("Jan", number));
and you should write private class inside your public class BaseXYChart. It could be something like this:
Code:
private class MyLogClass {
public MyLogClass(int number) {
Math.log(number);
}
}
Re: Highlight plotted data
Thank you very much cselic,
I will try to follow your suggestions: I have just had some chat on Skype with Jonathan Giles and he gave me this link
Login Required - JavaFX
Regards,
Susie
Re: Highlight plotted data
^Can you please copy+paste content from that link, because login is required for that link.
2 Attachment(s)
Re: Highlight plotted data
The page should open without a login, but here are two picture from this link
Attachment 3964Attachment 3965
Quote:
Originally Posted by
cselic
^Can you please copy+paste content from that link, because login is required for that link.
Re: Highlight plotted data
Re: Highlight plotted data
Well what I want to plot is not a log(number); I want to plot that number but charted in log scale, and this is the reason:
when dealing with financial time serie, linear scale is not the right choice because it is far more important to graphically visualize data as percentage move.
Just an example: let's suppose we have a time serie at point x=1,y=10 and point x=2,y=20. At point x=n,y=100 and point x=n+1,y=110.
If we plot these data as linear Y axis, the rate of change from point x=n+1 to point x=n is = 10, just as from point x=2 to point x=1, BUT the percentage move from point x=1 to point x=2 is 100% increase while from point x=n to point x=n+1 is only 10%.
The 100% increase get the same height as 10% increase, and this is incorrect for financial data plot and analysis.
If we plot as log, we would see a great Y increase from point 1 to point 2 (100%), and we will have the appropriate 10% Y increase later.
Susie
Re: Highlight plotted data
Quote:
Originally Posted by
susieferrari
Well what I want to plot is not a log(number); I want to plot that number but charted in log scale ...
Then you should change this line of your code:
Code:
final NumberAxis yAxis = new NumberAxis(1, 22, 0.5);
you should change it to something like this:
Code:
final NumberAxis yAxis = new NumberAxis(Math.log10(1), Math.log10(100), Math.log10(1.12202);
or maybe to something like this (same values like calculated with logs but without logs):
Code:
final NumberAxis yAxis = new NumberAxis(0, 2, 0.05);
1 Attachment(s)
Re: Highlight plotted data
Well let me do another example to better clarify the Y log axis:
I have changed a little my code in this way:
Code:
final NumberAxis yAxis = new NumberAxis(0.5, 20.5, 0.5);
and
Code:
series1.getData().add(new XYChart.Data("Jan", 1));
series1.getData().add(new XYChart.Data("Feb", 2));
series1.getData().add(new XYChart.Data("Mar", 1.5));
series1.getData().add(new XYChart.Data("Apr", 3));
series1.getData().add(new XYChart.Data("May", 2.5));
series1.getData().add(new XYChart.Data("Jun", 5));
series1.getData().add(new XYChart.Data("Jul", 4));
series1.getData().add(new XYChart.Data("Aug", 8));
series1.getData().add(new XYChart.Data("Sep", 6.5));
series1.getData().add(new XYChart.Data("Oct", 13));
series1.getData().add(new XYChart.Data("Nov", 10));
series1.getData().add(new XYChart.Data("Dec", 20));
The series is now modified to show each up swing is 100% up move, I have highlited in green lines below each swing
Attachment 3966
We can immediately note that these up swing are not the same Y height: move from 1 to 2 takes only 1 point on Y scale, while the swing from 10 to 20 takes 10 point on Y scale.
This is not correct for financial data series analysis: all of these up swings MUST have the same Y values on Y scale, because all of these are 100% moves.
So, if I set my upper Y bound as Math.log10(20) I will not have the upper value plotted because that values is = 2!
I need to display 20 as upper bound ( to be accurate, here I have set 20,5 as upper value bound) but the Y scale must be setted differently from this linear Y.
In other words, the distance for each ticks in Y scale should not be linear as now, but dislayed differently, in logarithmic display, so that the charting Y distance from 1 to 2 is the same charting y distance from 10 to 20.
Thanks for your patience.
Susie
Re: Highlight plotted data
^Lets try this:
Write this code (from my previous post):
Code:
final NumberAxis yAxis = new NumberAxis(Math.log10(1), Math.log10(100), Math.log10(1.12202);
or maybe to something like this (same values like calculated with logs but without logs):
Code:
final NumberAxis yAxis = new NumberAxis(0, 2, 0.05);
So, next idea is that we are going to work with log10, but we are going to show results on a graph from 0 to 20. So we should change this part of code:
Code:
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
@Override
public String toString(Number object) {
return String.format("%7.2f", object);
}
});
with something like this:
Code:
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
@Override
public String toString(Number object) {
return String.format("%7.2f", Math.pow(10.0, object.doubleValue()));
}
});