04-21-2015 11:34 AM
I'm trying to solve following issue. Let's say I'm sampling data once per second and showing it on the graph. I want to show history of the data, say last 20 plots using the same color with fading. What I do now:
- create 21 plots, say Plots[0]..Plots[20]
- at meas 1, set Data[0] = data
- set Plots[0] opacity to 1
- at meas 2, set Data[1] = data
- set Plots[1] opacity to 1, Plots[0] opacity to 0.5
- at meas 3, set Data[2] = data
- set Plots[2] opacity to 1, Plots[1] opacity to 0.6, Plots[0] opacity to 0.3
...
- at meas 21, set Data[20] = data
- set opacity to 0.1..1
// we're fine as of now, here comes the tricky part
- at meas 22 I need to remove the data of meas 0 (stored at Data[0]) and replace it with the new data
- so I set Data[0] = data
- set Plots[0] opacity to 1 (it's the newest result)
- set other plots opacity 0.1..0.9
// and here is the problem: Plots[0] is now at the bottom of the plot stack and is covered by 20 other plots, thus is barely visible
so I somehow need to move Plots[0] to the top of the stack
I've tried removing Plot and Data of the farthest plot and adding creating plot with the most recent data, but it leads to incorrect indices (Plot.Index grows all the time, but Data array stays the same)
Another option would be to fix plots order and opacity in advance, and change data for all plots all the time. But I assume this would be very slow (think of 20-50 copies of the plot with say 1000 points).
So, any bright ideas here?
04-21-2015 03:37 PM
Idea 1) Pre-allocate all of the fade plots, use BeginInit
/EndInit
when updating the Data
collection, and always apply the newest data to the last plot. In pseudo-code:
// initial setup
for( opacity = 0..1 )
var renderer = new Renderer( opacity )
graph.Plots.Add( new Plot { Renderer = renderer } )
// on data update
graph.BeginInit()
for( i = 1..graph.Data.Count )
graph.Data[i - 1] = graph.Data[i] /* shift old data down */
graph.Data[20] = /* assign new data to the last plot */
graph.EndInit()
Idea 2) If you just want the historic data visible in the graph (i.e. you do not need to query or interact with the old data through the graph), and if your range is stable, then you could have one plot in the graph and use a PhosphorColorRamp
to get the visual fade effect. In pseudo-code:
// initial setup
var brush = new SolidColorBrush( C )
Graph.SetPhosphorMode( brush, Immediate )
graph.Plots.Add( new Plot { Renderer = new Renderer( brush ) } )
graph.RenderMode = Raster
graph.PhosphorColorRamp = new FadeRamp { Color = C, Duration = 20, DurationKind = Frames }
// on data update
graph.Data[0] = /* assign new data to first plot */
(Note that the phosphor effect is one of the areas being updated, so the syntax will be changing in the next release of Measurement Studio.)
04-27-2015 09:15 AM
Wow, that's a killer feature!
2 questions:
1. I don't succeed to disable this effect:
if(enabled)
{
Color plotColor = getPlotColor(Plot);
var brush = new SolidColorBrush(plotColor);
Graph.SetPhosphorMode(brush, GraphPhosphorMode.Deferred);
graph.RenderMode = RenderMode.Raster;
Plot.Renderer = new LinePlotRenderer() { Stroke = brush };
var ramp = BrushRamp.CreateSingleGradientBrushRamp(plotColor, Colors.Red);
ramp.Duration = 20;
ramp.DurationKind = NationalInstruments.Controls.Rendering.DurationKind.Frames;
graph.PhosphorColorRamp = ramp;
// this works
}
else
{
Color plotColor = getPlotColor(Plot);
var brush = new SolidColorBrush(plotColor);
Graph.SetPhosphorMode(brush, GraphPhosphorMode.None);
Plot.Renderer = new LinePlotRenderer() { Stroke = brush };
graph.PhosphorColorRamp = null;
// after this I see the effect still
}
2. my renderes are quite complex:
plot.Renderer = new PlotRendererGroup
{
PlotRenderers = {
new NoDecimationRenderer( ),
makeLineRenderer( GraphLineStyle.SOLID, HLResultsDisplayContainer.colorMap[GraphPlotColor.PLOT_COLOR_LIMIT_1], 2),
makePointRenderer( GraphPointStyle.SOLID_CIRCLE, HLResultsDisplayContainer.colorMap[GraphPlotColor.PLOT_COLOR_LIMIT_1], 3),
}
};
how do I enable the effect for such renderer?
04-27-2015 09:52 AM
1) To disable the effect, set PhosphorColorRamp
to null and then call the Refresh
method.
2) Phosphor is enabled or disabled at the brush level, so if your renderers use a brush with PhosphorMode
set they should display with the effect.
04-29-2015 03:38 AM
another strange thing: I made ramp from yellow to red, but when I pan/zoom the graph, one plot goes blue. after all history frames are reset, blue one disapears
04-29-2015 05:28 AM
well, this is even worse: zooming doesn't update history plots at all. so we see both new zoomed in plots and old zoomed-out ones
04-29-2015 08:08 AM
another issue with colors: I define ramp from Orange to Red, and plot itself is Yellow. Look at movie and see what happens when I increase ramp duration (in frames).
When duration is 1, we get Yellow and Blue (instead of Orange and Red)
when 2, we get Yellow, Orange and Blue
when 3: Yellow, Orange, Red and Blue
http://screencast.com/t/5uahyibWeK
Where the Blue is coming from?
Why first history color is Yellow instead of Orange?
btw, this does explain why we see Blue after moving the graph. our demo plot periodicity is about 25, so when history depth is 30, we don't see the last blue history, as it's overridden by the new yellow plot.
04-29-2015 11:06 AM
Regarding the color issue, after some investigation this looks like a known issue that has been fixed for the next release. Unfortunately, the problem is in the internal blending code, and I could not come up with a successful workaround.
Regarding the zoom behavior, phosphor is a purely bitmap effect, and we do not interpolate historic pixels when you do a zoom operation. To avoid the old history, you can temporarily clear and restore the phosphor setting on the graph after a zoom to clear the phosphor state.
05-01-2015 05:36 PM
Is there a release date for the next version?
05-01-2015 05:41 PM
I do not know of another date beyond the announcement of a 2015 release.