Skip to content

Make PlottableSignalConst generic#100

Merged
swharden merged 13 commits intoScottPlot:masterfrom
StendProg:GenericSignal
Aug 17, 2019
Merged

Make PlottableSignalConst generic#100
swharden merged 13 commits intoScottPlot:masterfrom
StendProg:GenericSignal

Conversation

@StendProg
Copy link
Contributor

Signal and SignalConst maked generic, thats allow plot different types of struct data types (float, int, byte etc). This types must be convertable to Double.
With generic data types all comparation calculation goes slower by 30-40%.
SignalConst overall render not visibly affected by this.
PlottableSignal Render slower by 10-20% for 10M points at high resolution chart. Posible improvement commented in MinMaxRangeQuery(), but it will give lots of code duplicates for all posible data types.

@swharden
Copy link
Member

Hi @StendProg, thank you for working on this!

This pull request improves PlottableSignalConst since it can now accept many different data types at the cost of slower speed. Since using PlottableSignalConst on fixed data is so fast already, the reduced speed doesn't hurt much.

However, this change also makes PlottableSignal slower, and since this function can already be slow this could noticeably reduce frame rate. One of my most common uses for ScottPlot is using PlottableSignal to display live data in real time, and I would prefer not to slow it down by making it generic. I also noticed that this pull request broke the FFT display in the audio monitor demo (though I haven't figured out why).

At first I thought we could keep PlottableSignalConst generic but revert PlottableSignal to only accept a double array. I started to change this myself, but I now see that because of the inheritance structure this is probably not possible. I think we should consider separating PlottableSignal from PlottableSignalConst. They're both signals, but they serve different purposes (one is for live data and one is for fixed data) so it may not make sense to inherit one from another. Perhaps we could have a Signal class (which handles styling, rendering, and data save) but create SignalLive and SignalConst classes which inherit from it that deal with the data loading, updating, and min/max calculations in their own ways.

I'm looking forward to hearing what you think! Thanks again for your excellent work.
Scott

@StendProg
Copy link
Contributor Author

I also really do not like reduce speed of signal.I think its not posible to make non generic base class for Signal and SignalConst, because he must hold source array, that generic type for SignalConst.
I see only one possible way to make it.
Full separate SignalConst implementanion without inheritance, that have his own copy pasted Render, RenderHighDensity etc.
PlotableSignal stay as it was before SignalConst appeared(with small fixes and optimizations).
When you take you final decission on that, i will make it.

@swharden
Copy link
Member

  • Fully separate PlottableSignalConst (that does not inherit from PlotableSignal)
  • PlottableSignalConst will contain some copy/pasted functions from PlotableSignal
  • PlottableSignalConst will accept generics
  • PlotableSignal will be mostly as it was before PlottableSignalConst (with small fixes and optimizations)

This sounds like a good plan to me! Thank you @StendProg!

@swharden swharden changed the title Make PlottableSignal and PlottableSignalConst generic Make PlottableSignalConst generic Aug 17, 2019
@swharden
Copy link
Member

This line is crashing the audio monitor demo

https://github.com/swharden/ScottPlot/blob/1b2e5f896afd5f8daec8154d0e93f1c13ac846ed/src/ScottPlot/Settings.cs#L460

System.InvalidOperationException
  HResult=0x80131509
  Message=This operation is only valid on generic types.
  Source=mscorlib
  StackTrace:
   at System.RuntimeType.GetGenericTypeDefinition()
   at ScottPlot.Settings.Clear(Boolean axLines, Boolean scatters, Boolean signals, Boolean text, Boolean bar, Boolean finance) in C:\Users\scott\Documents\GitHub\ScottPlot\src\ScottPlot\Settings.cs:line 460
   at ScottPlot.Plot.Clear(Boolean axisLines, Boolean scatterPlots, Boolean signalPlots, Boolean text, Boolean bar, Boolean finance) in C:\Users\scott\Documents\GitHub\ScottPlot\src\ScottPlot\Plot.cs:line 182
   at ScottPlotAudioMonitor.Form1.TimerPlot_Tick(Object sender, EventArgs e) in C:\Users\scott\Documents\GitHub\ScottPlot\demos\src\audio-monitor\Form1.cs:line 153
   at System.Windows.Forms.Timer.OnTick(EventArgs e)
   at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at ScottPlotAudioMonitor.Program.Main() in C:\Users\scott\Documents\GitHub\ScottPlot\demos\src\audio-monitor\Program.cs:line 19

@StendProg
Copy link
Contributor Author

My bad. Fixed this.

@swharden
Copy link
Member

Looks great, thanks again @StendProg!

@swharden swharden merged commit b5f1642 into ScottPlot:master Aug 17, 2019
@StendProg
Copy link
Contributor Author

You can make cookbook demo with 1 Billion points of 'byte', it need only 3 GB memory for data.

@StendProg
Copy link
Contributor Author

A bit late idea. In generic PlottableSignal check type for double and call fast not LinqExp implementation of min/max search. and LinqExp for other. That will stay speed for double[] at same level as before, and allow other types at reduced speed.

swharden added a commit that referenced this pull request Aug 17, 2019
swharden added a commit that referenced this pull request Aug 17, 2019
swharden added a commit that referenced this pull request Aug 17, 2019
@StendProg
Copy link
Contributor Author

I looks like it rendered in simple min/max implementation. Please check x64 mode, and trees ready flag. It can be rendered for 10-20 ms too. After long data generation and trees calculations

@swharden
Copy link
Member

swharden commented Aug 17, 2019

You can make cookbook demo with 1 Billion points of 'byte', it need only 3 GB memory for data.

Good idea!
https://github.com/swharden/ScottPlot/tree/master/cookbook#signalconst-one-billion-points

trees ready flag

Oops, that's what I did wrong.

A bit late idea. In generic PlottableSignal check type for double and call fast not LinqExp implementation of min/max search. and LinqExp for other. That will stay speed for double[] at same level as before, and allow other types at reduced speed.

Haha it is a bit late but I like the idea. I'm less familiar with LinqExp and generics though, so I'd probably have to look at a PR to really understand it.

I think for now it's in a good place though: If you are plotting a live double array use PlottableSignal. If you are plotting fixed data or data of another type, use PlottableSignalConst. That should probably cover most of the use cases.

Maybe we could even create an overload of Plot.PlotSignal() that automatically uses a PlottableSignalConst if the input data type is something other than a double array?

@StendProg
Copy link
Contributor Author

StendProg commented Aug 17, 2019

image

I wait long for preparation, but after that render time is only 4 ms

@swharden
Copy link
Member

What is your code to make that plot? Mine seems to keep going slow...

byte[] oneBillionPoints = ScottPlot.DataGen.SinSweepByte(1_000_000_000, 8);
var plt = new ScottPlot.Plot(width, height);
plt.Title("Display One Billion points with PlotSignalConst()");
plt.Benchmark();
plt.Parallel(false);
plt.PlotSignalConst(oneBillionPoints, sampleRate: 20_000_000);
plt.SaveFig(fileName);

@StendProg
Copy link
Contributor Author

Copy pasted yours. but i make it in gui app. Double check x64 mode. x86 dont allow more then 2-3 GB total ram for process.

swharden added a commit that referenced this pull request Aug 17, 2019
@swharden
Copy link
Member

@StendProg
Copy link
Contributor Author

StendProg commented Aug 17, 2019

Maybe we could even create an overload of Plot.PlotSignal() that automatically uses a PlottableSignalConst if the input data type is something other than a double array?

Simple overload works:

public PlottableSignalConst<T> PlotSignal<T>(
            T[] ys,
            double sampleRate = 1,
            double xOffset = 0,
            double yOffset = 0,
            Color? color = null,
            double lineWidth = 1,
            double markerSize = 5,
            string label = null
            ) where T : struct, IComparable
        {
            if (color == null)
                color = settings.GetNextColor();

            PlottableSignalConst<T> signal = new PlottableSignalConst<T>(
                ys: ys,
                sampleRate: sampleRate,
                xOffset: xOffset,
                yOffset: yOffset,
                color: (Color)color,
                lineWidth: lineWidth,
                markerSize: markerSize,
                label: label,
                useParallel: settings.useParallel
                );

            settings.plottables.Add(signal);
            return signal;
        } 

You can implement this, if you like.

@swharden
Copy link
Member

Thanks for this code! I started a bigger issue to track conversion of all plot types to generics (#103)

swharden added a commit that referenced this pull request Aug 17, 2019
@StendProg StendProg deleted the GenericSignal branch February 1, 2020 11:39
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
StendProg pushed a commit to StendProg/ScottPlot that referenced this pull request Mar 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants