UPDATE 25-09-2018
In a bid to create a simpler demo (posted here: http://jsfiddle.net/bLgj4vc7/3/) for this question, I finally discovered the root cause of the problem. I have also managed to work around it, which I have posted as an answer.
I am using standalone bokehjs in my webapp. My problem is that the renderer is not updating its line glyph with updated datasource (or at least this is what the problem looks like to me).
This jsfiddle: http://jsfiddle.net/uwnqcotg/8/ demonstrates the problem. Please ignore any bad coding conventions in it; its a quick, one-off demo.
In the fiddle, the plot is loaded with a dataseries which is rendered fine and dandy. The plot can be updated in two ways:
Update Plot Once By Overwriting CDS.data Object overwrites the ColumnDataSource.data object at one-go, thus adhering to the bokeh principle of maintaining same column lengths.
Start Stream With CDS.stream employs the ColumnDataSource.stream() and updates the plot at a regular interval with randomly generated, but incremental dataseries.
In the first approach, it looks like the glyph is being updated - the axes sure are updated in accordance with the dataseries printed in the console for reference. But, the plotted glyph and the dataseries show a mismatch. To me, it looks like the glyph plotted when the plot initialized simply re-adjusted to the new axes, though I cannot be sure.
In the second approach, again, the axes are updated, but the glyph isn't. Again, the originally plotted glyph seem to re-adjust to the new axes ranges. Moreover, the rollover attr seems to be ignored as the renderer simply keeps accumulating data.
Overall, my observation is that any data provided to the renderer during its initialization is plotted correctly, but any subsequent streamed update or even an overwrite are not. Though I may be wrong here.
On the other hand, between me and bokeh, I am inclined to believe I am doing something wrong or am missing something. So what is it?
As updated in the question, in a bid to create a simpler demo posted here http://jsfiddle.net/bLgj4vc7/3/, I ran across the root cause of this problem:
It looks like bokehjs has a bug where a renderer, once initialized with a certain length of dataset, sticks to that length even for subsequent updates in dataset. In other words,
If a renderer was initialized with an empty dataset {x:[], y:[]}, even if the renderer.data_source is updated with a populated dataset later on, the renderer sticks to the zero length and nothing is drawn on the plot.
For an initial dataset of length 5, only first 5 points will be read from any subsequent updates and the glyph will be updated accordinly. Rest of the points are not acknowledged.
I don't know whether the problem is whether renderer doesn't read beyond the initial length or whether it does but fails to redraw the glyph on the plot. The ColumnDataSource sure is updated correctly.
The fiddle linked in this answer best demonstrates the problem.
So what is the solution? At the moment, this workaround: initialize the renderer with a dataset filled with NaNs, which has a length equal or more than the maximum number of datapoints you want to plot for a single dataseries.
So, if in a line glyph, I wish to plot maximum 100 datapoints, then:
const plot = Bokeh.Plotting.figure()
const maxDataPoints = 100 // maximum number of points I want for this glyph
const emptyData = Array().fill().map(_ => NaN)
const cds = new Bokeh.ColumnDataSource({x: emptyData, y: emptyData})
const renderer = plot.line({field: 'x'}, {field: 'y'}, {source: cds, line_width: 2})
// now any subsequent updates to datasource of renderer will update its glyph on the plot.
renderer.data_source.data = {
x: dataLengthLessOrEqualToMaxDataPoints.x,
y: dataLengthLessOrEqualToMaxDataPoints.y
}
Of course, I think this behaviour of bokehjs is either a bug or I am missing an undocumented step in initialization. Either way, its worth creating an issue on github: https://github.com/bokeh/bokeh/issues/8277
Related
I have an application that dumps statistics once every minute into ElasticSearch. Using Kibana, I've created a lens to visualize the values over time. All good.
Occasionally, the application skips a dump (which is a separate issue I'll be working on), so I may have occasional missing values. In the Lens, the Line chart breaks the line when a value is missing for a certain time (see screenshot).
How can I interpolate between the available values and show a continuous line instead?
EDIT
To make it clear, I'm asking how to fix the chart in the Lens. The issue of skipped dumps is a separate one and needs to be addressed separately. I may still have some missing values (unlikely but not impossible), and I would like my Lens to show a continuous chart anyway.
UPDATE
While I found the "Missing values" setting in "Visual Options" and I set it to "Linear", the interpolation is rendered with a dashed line. How can I make it the same as the main line?
This is a follow up to this question which has to that day still 0 answers.
What I really want to do is having in a tableview, a column that has the symbol for the plotted data corresponding to the objects in the table view row. I have managed to generate the colours supposedly followed by the JavaFX chart. The issue I have of course is that my own colour generation works (it goes back to the first colour without fail after 8 elements), when the one from the chart has the issue outlined in my unanswered question.
So.
I would like now to try to pick up the style actually applied to each series of the chart independently from pre-supposed rule about the default order of colours. How do I do that?
This way I could apply those to my table view and even if the colours randomly change upon reloading then at least I will know what I am looking at.
Thanks in advance for your help.
After a bit of research I found that the following code allows me to get what I want, supposing I am interested in the series at index intitem:
plotswingschart.getData().get(intitem).getNode().getStyleClass();
This will produce a ObservableList containing the following string values (here example for the series at index 8 (9th series)):
chart-series-line
series8
default-color2
From this I can then get the information that I need. that is the colour actually applied to that curve. I can then generate a symbol to be used in my tableview.
I would still be interested in an answer to the question linked, which prompted the present question...
I'm working with a lot of rank data that would benefit from a way to simultaneously display its respective year on the x-axis. For example, I want to create the following graph adapted from the dygraph gallery:
Note how the rank information (red arrow) for a particular weekend (green arrow) are both displayed on the x axis.
I know this might not be possible with dygraphs now, at least it wasn't available in these demos, so I guess my follow up question would be are there any plans to make this possible (how about in the [r] {dygraph} package)? Apparently a plotter called flot can do this.
UPDATE 1
If indeed this feature does not exist yet, then the following, although potentially obvious to Dygraph developers, is a thought for accomplishing the task easily (perhaps I'm wrong). At first I thought it would be necessary to provide input data of the form shown in Table A
However such input is a major deviation from the existing Dygraph parser model who expects one abscissa. Such suggests that a modification to the parser to accept a "Dual Label" option, requiring that both labels be contained in a single abscissa element as in Table B, would be easier. Thereafter, with the option specified, the parser would manage CSV as it usually would with the exception that it is now "bin cognizant" and detects division between labels 1 and 2 by use of an acceptable delimiter (in this case a single quotation mark - maybe not the best choice) and divisions between label 1 abscissa elements by name change. Behind the scenes each point gets its unique x coordinate and the "Dual Label" option causes the dygraph to visually scoot up a couple pixels to accommodate an extra label. Not sure how to handle full zoomed scrolling put simply leaving a label 1 element centered until an adjacent label 1 element comes on screen is an option.
Dygraphs rule!
There's no simple way to do this with dygraphs now. As you say, there's a fairly deep assumption that there's only a single x-axis.
Your best bet would be to either modify the existing legend plugin to do this, or to create a new plugin which renders just the "Weekend 1", "Weekend 2" line. While the plugins API isn't official yet, it is at least somewhat documented.
If you get this to work, please share your code!
I have a crossfilter.dimension. How do I get the current filter set on it (for example if it was set by a brush from a chart)?
Example:
dimension.filterRange([1,15]) // returns dimension
Given this filtered dimension, how do I get the values 1 and 15 out?
Stumbled on this old question because it is the top-voted unanswered crossfilter question, with 1k views!
This feature was contributed by Thomas Gillet in 1.4.5 as dimension.currentFilter()
The tough remaining problem: when you get beyond filterExact and filterRange, the more complex filters use filterFunction. You might be able to retrieve the function but functions are essentially opaque.
For example, if you are using dc.js, it will generate a filter function when
multiple items are selected in pie chart, row chart, or bar chart with ordinal dimension
the chart has a two-dimensional filter, like the scatter plot or the heatmap
For this reason, if you're using dc.js, you should use chart.filters() instead.
Thank you, Gordon. This was really helpful to me! One note - your link is correct -- it goes to filters(), but the text displays as chart.filter() which is in the API, but doesn't return multiple filters on a chart. I tried to edit your answer, but it won't allow single character changes!
I have a list of data that I want to be animated on the plot, I'm currently using:
graph1=gdots(pos = pvalues) #pvalues is list of points
while t <= t_max:
rate(200)
... #pvalues is updated to new contain the new points
graph1=gdots(pos = pvalues)
What happens here is the old points remain on the plot, so lines are traced out when I want the points to just move. I've tried deleting the graph, making it invisible, but none of it works.
graph1.visible = False
del graph1
Including the above makes no noticeable difference to the display. I've searched a lot about this, but the VPython documentation seems to be annoyingly incomplete.
I realise this is a very old question, however I had the same issue with vpython 7. For me, graph1.delete() removed the associated data points from the graph, and rescaled the axes based on the remaining data (if any). I haven't yet found a way to remove the graph axes themselves (i.e. delete the figure).