14

It is generally very easy to call mex files (written in c/c++) in Matlab to speed up certain calculations. In my experience however, the true bottleneck in Matlab is data plotting. Creating handles is extremely expensive and even if you only update handle data (e.g., XData, YData, ZData), this might take ages. Even worse, since Matlab is a single threaded program, it is impossible to update multiple plots at the same time.

Therefore my question: Is it possible to write a Matlab GUI and call C++ (or some other parallelizable code) which would take care of the plotting / visualization? I'm looking for a cross-platform solution that will work on Windows, Mac and Linux, but any solution that get's me started on either OS is greatly appreciated!

I found a C++ library that seems to use Matlab's plot() syntax but I'm not sure whether this would speed things up, since I'm afraid that if I plot into Matlab's figure() window, things might get slowed down again.

I would appreciate any comments and feedback from people who have dealt with this kind of situation before!

EDIT: obviously, I've already profiled my code and the bottleneck is the plotting (dozen of panels with lots of data).

EDIT2: for you to get the bounty, I need a real life, minimal working example on how to do this - suggestive answers won't help me.

EDIT3: regarding the data to plot: in a most simplistic case, think about 20 line plots, that need to be updated each second with something like 1000000 data points.

EDIT4: I know that this is a huge amount of points to plot but I never said that the problem was easy. I can not just leave out certain data points, because there's no way of assessing what points are important, before actually plotting them (data is sampled a sub-ms time resolution). As a matter of fact, my data is acquired using a commercial data acquisition system which comes with a data viewer (written in c++). This program has no problem visualizing up to 60 line plots with even more than 1000000 data points.

EDIT5: I don't like where the current discussion is going. I'm aware that sub-sampling my data might speeds up things - however, this is not the question. The question here is how to get a c / c++ / python / java interface to work with matlab in order hopefully speed up plotting by talking directly to the hardware (or using any other trick / way)

Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
memyself
  • 11,907
  • 14
  • 61
  • 102
  • FYI: I found a link that suggests using scatter instead of plot: http://www.mathworks.com/matlabcentral/answers/2529-figure-plot-slow. BTW, does anyone out there know why graphics in MATLAB and Octave are so incredibly slow compared to the other functionality in the packages? – ahoffer Jan 21 '12 at 19:30
  • 1
    Any chance of getting data to see where the bottleneck is ? – Andrey Rubshtein Feb 05 '12 at 17:54
  • just imagine you have 20 line plots, which need to get updated every second with 1000000 data points. that's pretty much what my 'data' is. The data itself is processed in parallel by local workers and it's really that the updating of the line handles is currently the bottle neck. – memyself Feb 05 '12 at 20:00
  • 2
    @memyself, that is a HUGE amount of points! There isn't enough pixels on the screen to plot that amount. Maybe you should simplify the data by mathematical operations, like doing linear fit for every 1000 points, and plotting the sparse points set. (kind of like in 3D graphics) – Andrey Rubshtein Feb 05 '12 at 20:59
  • @Andrey see my EDIT4 - it is no possible for me to reduce the number of points simply because I can't determine what's important and what's not beforehand. – memyself Feb 05 '12 at 21:20
  • @memyself, do you expect that the user will ever use zoom? – Andrey Rubshtein Feb 05 '12 at 21:28
  • @Andrey in my current (slow plotting) implementation, the user is allowed to zoom and change the ROI. However, since I'm currently only looking for a way to speed up things, zooming is not essential. This could be implemented later by just clearing the plots, building a new ROI and re-plotting everything accordingly. – memyself Feb 05 '12 at 21:31
  • 1
    @memyself, you don't need to know what points to take or not. Simply interpolate for the x locations of the pixels in the screen. Of course, you need to figure out something for zoom case. Check out my updated answer please. – Andrey Rubshtein Feb 05 '12 at 21:48
  • 4
    This question is off-base. As many people have mentioned, it is physically impossible to plot more than about 2,000 data points on a screen. Realistically, the number of points that you can legibly plot is probably around 500 in full screen mode. And of course, the number goes down if the OP really intends to show 20 plots simultaneously. So the only question is what algorithm you're using to decide which points are sampled. OP should decide on a criteria to determine "important" points, e.g. outliers and plot those. – Marc Feb 06 '12 at 20:11
  • What latency are you hoping to get with the refresh of the plot once the data is updated? Is the data being updated with new points appended to the end of the array, or a whole new data set? – Andrew Janke Feb 09 '12 at 02:07
  • I need something like 20FPS. New data (numel ~ 30000) is coming in every second and it would be good enough to just shift the entire graph to the left and add the new data points on the right. – memyself Feb 09 '12 at 07:33
  • Are the X values for the data points evenly spaced (e.g. snapped to 25 microsecond frequency, so you can locate a particular time by its index)? – Andrew Janke Feb 09 '12 at 21:28
  • @AndrewJanke yes. x is evenly spaced & the number of points will always be the same. `x = 1:numel(y);` – memyself Feb 09 '12 at 21:32

9 Answers9

7

Did you try the trivial solution of changing the render method to OpenGL ?

opengl hardware;
set(gcf,'Renderer','OpenGL');

Warning! There will be some things that disappear in this mode, and it will look a bit different, but generally plots will runs much faster, especially if you have a hardware accelerator.

By the way, are you sure that you will actually gain a performance increase? For example, in my experience, WPF graphics in C# are considerably slower than Matlabs, especially scatter plot and circles.

Edit: I thought about the fact that the number of points that is actually drawn to the screen can't be that much. Basically it means that you need to interpolate at the places where there is a pixel in the screen. Check out this object:

classdef InterpolatedPlot < handle
    properties(Access=private)
        hPlot;
    end

    methods(Access=public)
        function this = InterpolatedPlot(x,y,varargin)
            this.hPlot = plot(0,0,varargin{:});
            this.setXY(x,y);
        end        
    end    

    methods
        function setXY(this,x,y)
            parent = get(this.hPlot,'Parent');
            set(parent,'Units','Pixels')
            sz = get(parent,'Position');
            width = sz(3); %Actual width in pixels
            subSampleX = linspace(min(x(:)),max(x(:)),width);

            subSampleY = interp1(x,y,subSampleX);
            set(this.hPlot,'XData',subSampleX,'YData',subSampleY);
        end

    end
end

And here is an example how to use it:

function TestALotOfPoints()
    x = rand(10000,1);
    y = rand(10000,1);

    ip = InterpolatedPlot(x,y,'color','r','LineWidth',2);

end

Another possible improvement: Also, if your x data is sorted, you can use interp1q instead of interp, which will be much faster.

classdef InterpolatedPlot < handle
    properties(Access=private)
        hPlot;
    end

%     properties(Access=public)
%         XData;
%         YData;      
%     end

    methods(Access=public)
        function this = InterpolatedPlot(x,y,varargin)
            this.hPlot = plot(0,0,varargin{:});
            this.setXY(x,y);
%             this.XData = x;
%             this.YData = y;
        end        
    end    

    methods
        function setXY(this,x,y)
            parent = get(this.hPlot,'Parent');
            set(parent,'Units','Pixels')
            sz = get(parent,'Position');
            width = sz(3); %Actual width in pixels
            subSampleX = linspace(min(x(:)),max(x(:)),width);

            subSampleY = interp1q(x,y,transpose(subSampleX));
            set(this.hPlot,'XData',subSampleX,'YData',subSampleY);
        end

    end
end

And the use case:

function TestALotOfPoints()
    x = rand(10000,1);
    y = rand(10000,1);
    x = sort(x);
    ip = InterpolatedPlot(x,y,'color','r','LineWidth',2);

end
Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
  • the result is not good enough. Have a look at the following screenshot: http://i.imgur.com/6VBId.png the upper panel is your plot function using sub-sampling, The lower panel is my plot function plotting basically every data point. – memyself Feb 05 '12 at 22:09
  • 1
    @memyself, 2 advises : (1) Increase the amount of points from `width` to 2*`width` or whatever at the assignment to subSampleX (2) Increase line width to 3, if you want to get filling effect. – Andrey Rubshtein Feb 05 '12 at 22:22
  • @memyself, by the way, in terms of raw speed, is it fast enough now? – Andrey Rubshtein Feb 05 '12 at 22:28
  • the speed is quite bad. If I plot each of those 253193 data points, tic;plot();toc gives me 0.013264 seconds. Your plotting function takes 0.034375 seconds. – memyself Feb 05 '12 at 23:26
  • @memyself, it might be due to class function call - I will check out tomorrow. As for site for uploading - Maybe https://github.com/signup/free – Andrey Rubshtein Feb 05 '12 at 23:33
  • 1
    Here's an idea: isn't `interp1` more for getting a denser data set from a coarser set of samples, and sampling here going the other way? How about sampling by taking the first/min/max/last points for each pixel bucket, and plotting those? Should produce a plot pretty similar to the original, preserving all peaks. – Andrew Janke Feb 08 '12 at 21:30
4

There is no way you can fit 1000000 data points on a small plot. How about you choose one in every 10000 points and plot those?

You can consider calling imresize on the large vector to shrink it, but manually building a vector by omitting 99% of the points may be faster.

@memyself The sampling operations are already occurring. Matlab is choosing what data to include in the graph. Why do you trust matlab? It looks to me that the graph you showed significantly misrepresents the data. The dense regions should indicate that the signal is at a constant value, but in your graph it could mean that the signal is at that value half the time - or was at that value at least once during the interval corresponding to that pixel?

Mikhail
  • 7,749
  • 11
  • 62
  • 136
  • that's not the task here. I need to plot all points since I can not determine ahead of time which points could be omitted and which are important. – memyself Feb 05 '12 at 21:11
  • 3
    There is no way to "pack" that many points on the screen! There simply isn't enough pixel density. At some point such an evaluation is carried out that determines how to fit the 1000000 data points when there is only room for ~100. You can benefit if you do this evaluation yourself. I have had similar problems and this was the solution. Try using imresize and see how it looks. – Mikhail Feb 06 '12 at 00:38
4

As a number of people have mentioned in their answers, you do not need to plot that many points. I think it is important to rpeat Andrey's comment:

that is a HUGE amount of points! There isn't enough pixels on the screen to plot that amount.

Rewriting plotting routines in different languages is a waste of your time. A huge number of hours have gone into writing MATLAB, whay makes you think you can write a significantly faster plotting routine (in a reasonable amount of time)? Whilst your routine may be less general, and therefore would remove some of the checks that the MATLAB code will perform, your "bottleneck" is that you are trying to plot so much data.

I strongly recommend one of two courses of action:

  • Sample your data: You do not need 20 x 1000000 points on a figure - the human eye won't be able to distinguish between all the points, so it is a waste of time. Try binning your data for example.

  • If you maintain that you need all those points on the screen, I would suggest using a different tool. VisIt or ParaView are two examples that come to mind. They are parallel visualisation programs designed to handle extremenly large datasets (I have seen VisIt handle datasets that contained PetaBytes of data).

Chris
  • 44,602
  • 16
  • 137
  • 156
  • there must be a way to improve my plotting performance and I strongly believe that plotting in C++ or C has the potential to speed things up. see this link http://stackoverflow.com/a/8956211/561766 how someone managed to improve some python code to plot with 200FPS instead of 10. On a different note: thanks for the links! – memyself Feb 05 '12 at 21:48
  • 1
    No problem. I take it from your question that you have tried the technique suggested in that answer? Also, you "believe that plotting in C++ or C has the potential to speed things up", but don't you think that the MATLAB developers have also thought of this? Ultimately MATLAB is written in C (and Java). – Chris Feb 05 '12 at 22:04
  • have a look at this screenshot http://i.imgur.com/6VBId.png . The upper panel is using Andrey's code, the lower panel is using my code. I hope that from this example you can see that every data point does count. – memyself Feb 05 '12 at 22:13
  • 1
    @memyself, this kind of "filling effect" can be made artificially by using density measurements from the data. Please consider again uploading the data to the web, it will be much easier to help you. – Andrey Rubshtein Feb 05 '12 at 22:27
  • 1
    @memyself I'm afraid that that does not show that every point counts. Tell me what information you can get from your timeseries that you cannot get from Andrey's. From Wikipedia: "Analysis of data is a process of inspecting, cleaning, transforming, and modeling data with the goal of **highlighting useful information**, suggesting conclusions, and supporting decision making". If you were to analyses both timeseries you will find that they the the same (at least similar) means, standard deviations, frequency components etc. – Chris Feb 05 '12 at 22:31
  • 1
    BTW I am guessing a little bit here, since on the image you link to you don't show the y-axis scale. Also, I second Andrey's last comment. – Chris Feb 05 '12 at 22:33
  • @Andrey where could I upload the data to so it's in a convenient location? – memyself Feb 05 '12 at 23:22
  • @Chris you are right. I didn't specify why every point counts. The short answer is that I'm interested in certain peaks. Unfortunately, due to the nature of the data, you can't really anticipate whether a peak is noise or 'good data'. – memyself Feb 05 '12 at 23:30
  • 1
    @memyself, as Chris said, you should understand the nature of your of your data and what exactly you want to see. Is it an audio wave? If so, consider asking an audio expert. – Andrey Rubshtein Feb 05 '12 at 23:35
  • @Andrey I understand both your and Chris' argument. However I don't want to spend a lot of time in finding the right sub-sampling argument. Instead I want to plot the data as is - just as fast as possible. – memyself Feb 05 '12 at 23:39
4

Since you want maximum performance you should consider writing a minimal OpenGL viewer. Dump all the points to a file and launch the viewer using the "system"-command in MATLAB. The viewer can be really simple. Here is one implemented using GLUT, compiled for Mac OS X. The code is cross platform so you should be able to compile it for all the platforms you mention. It should be easy to tweak this viewer for your needs.

If you are able to integrate this viewer more closely with MATLAB you might be able to get away with not having to write to and read from a file (= much faster updates). However, I'm not experienced in the matter. Perhaps you can put this code in a mex-file?

EDIT: I've updated the code to draw a line strip from a CPU memory pointer.

// On Mac OS X, compile using: g++ -O3 -framework GLUT -framework OpenGL glview.cpp
// The file "input" is assumed to contain a line for each point:
// 0.1 1.0
// 5.2 3.0
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <GLUT/glut.h>
using namespace std;
struct float2 { float2() {} float2(float x, float y) : x(x), y(y) {} float x, y; };
static vector<float2> points;
static float2 minPoint, maxPoint;
typedef vector<float2>::iterator point_iter;
static void render() {
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(minPoint.x, maxPoint.x, minPoint.y, maxPoint.y, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 0.0f);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, sizeof(points[0]), &points[0].x);
    glDrawArrays(GL_LINE_STRIP, 0, points.size());
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
}
int main(int argc, char* argv[]) {
    ifstream file("input");
    string line;
    while (getline(file, line)) {
        istringstream ss(line);
        float2 p;
        ss >> p.x;
        ss >> p.y;
        if (ss)
            points.push_back(p);
    }
    if (!points.size())
        return 1;
    minPoint = maxPoint = points[0];
    for (point_iter i = points.begin(); i != points.end(); ++i) {
        float2 p = *i;
        minPoint = float2(minPoint.x < p.x ? minPoint.x : p.x, minPoint.y < p.y ? minPoint.y : p.y);
        maxPoint = float2(maxPoint.x > p.x ? maxPoint.x : p.x, maxPoint.y > p.y ? maxPoint.y : p.y);
    }
    float dx = maxPoint.x - minPoint.x;
    float dy = maxPoint.y - minPoint.y;
    maxPoint.x += dx*0.1f; minPoint.x -= dx*0.1f;
    maxPoint.y += dy*0.1f; minPoint.y -= dy*0.1f;
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(512, 512);
    glutCreateWindow("glview");
    glutDisplayFunc(render);
    glutMainLoop();
    return 0;
}

EDIT: Here is new code based on the discussion below. It renders a sin function consisting of 20 vbos, each containing 100k points. 10k new points are added each rendered frame. This makes a total of 2M points. The performance is real-time on my laptop.

// On Mac OS X, compile using: g++ -O3 -framework GLUT -framework OpenGL glview.cpp
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cmath>
#include <iostream>
#include <GLUT/glut.h>
using namespace std;
struct float2 { float2() {} float2(float x, float y) : x(x), y(y) {} float x, y; };
struct Vbo {
    GLuint i;
    Vbo(int size) { glGenBuffersARB(1, &i); glBindBufferARB(GL_ARRAY_BUFFER, i); glBufferDataARB(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW); } // could try GL_STATIC_DRAW
    void set(const void* data, size_t size, size_t offset) { glBindBufferARB(GL_ARRAY_BUFFER, i); glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); }
    ~Vbo() { glDeleteBuffers(1, &i); }
};
static const int vboCount = 20;
static const int vboSize = 100000;
static const int pointCount = vboCount*vboSize;
static float endTime = 0.0f;
static const float deltaTime = 1e-3f;
static std::vector<Vbo*> vbos;
static int vboStart = 0;
static void addPoints(float2* points, int pointCount) {
    while (pointCount) {
        if (vboStart == vboSize || vbos.empty()) {
            if (vbos.size() >= vboCount+2) { // remove and reuse vbo
                Vbo* first = *vbos.begin();
                vbos.erase(vbos.begin());
                vbos.push_back(first);
            }
            else { // create new vbo
                vbos.push_back(new Vbo(sizeof(float2)*vboSize));
            }
            vboStart = 0;
        }

        int pointsAdded = pointCount;

        if (pointsAdded + vboStart > vboSize)
            pointsAdded = vboSize - vboStart;

        Vbo* vbo = *vbos.rbegin();
        vbo->set(points, pointsAdded*sizeof(float2), vboStart*sizeof(float2));

        pointCount -= pointsAdded;
        points += pointsAdded;
        vboStart += pointsAdded;
    }
}
static void render() {
    // generate and add 10000 points
    const int count = 10000;
    float2 points[count];
    for (int i = 0; i < count; ++i) {
        float2 p(endTime, std::sin(endTime*1e-2f));
        endTime += deltaTime;
        points[i] = p;
    }
    addPoints(points, count);
    // render
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(endTime-deltaTime*pointCount, endTime, -1.0f, 1.0f, -1.0f, 1.0f);
    glColor3f(0.0f, 0.0f, 0.0f);
    glEnableClientState(GL_VERTEX_ARRAY);
    for (size_t i = 0; i < vbos.size(); ++i) {
        glBindBufferARB(GL_ARRAY_BUFFER, vbos[i]->i);
        glVertexPointer(2, GL_FLOAT, sizeof(float2), 0);

        if (i == vbos.size()-1)
            glDrawArrays(GL_LINE_STRIP, 0, vboStart);
        else
            glDrawArrays(GL_LINE_STRIP, 0, vboSize);
    }
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
    glutPostRedisplay();
}
int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(512, 512);
    glutCreateWindow("glview");
    glutDisplayFunc(render);
    glutMainLoop();
    return 0;
}
rasmus
  • 3,136
  • 17
  • 22
  • this is definitely the direction that I started to go. Immediate mode is however way too also. Remember, I want to plot 20 lines with 1000000 points each - rendering each data point every single time is way too expensive. Currently I believe that VBO with memory allocated on the graphics card is the way to go. – memyself Feb 11 '12 at 13:05
  • 1
    I see. I thought you were rendering points. But lines should be faster. Are you changing the data each render? In this case I think a vbo won't give you much performance gain. Instead you can render from a CPU memory pointer. – rasmus Feb 11 '12 at 13:31
  • the data are come from a recorded time-series, with a fixed interval dx, e.g: `y = rand(1, 100000); x = 1:numel(y)` whether I connect each data point with the next one (line plot) or whether points are not connected does not matter. Please also note: the number of points plotted will always stay fixed! Can you provide an example on how to render from a CPU memory pointer? – memyself Feb 11 '12 at 13:34
  • I have updated the code to draw a line strip from a CPU memory pointer. – rasmus Feb 11 '12 at 13:51
  • 2
    Now that I know more about your problem (you add new points each frame), you could create multiple vbo's. Each one responsible for a couple of thousand points. Use these in a queue so that you only need to add to the frontmost vbo. This way you can avoid sending all the points to the GPU each frame. – rasmus Feb 11 '12 at 13:53
  • can you update the code to show me how to, for example, use 10 vbos with 10^5 points each, so that I can render a total of 10^6 points. Then, please add a `update()` function, which will generate (just for the proof of concept) 10^5 points each second. This would be a placeholder for the new set of 10^5 points which will come in eventually. Then as far as I understand, it should be possible to shift 9 of the existing 10 vbos and only have to update one. Is that correct? Your code should also show the FPS so that I can assess the plot performance. – memyself Feb 11 '12 at 19:07
  • Yes you understood it correctly. I gave you the idea and it should be easy enough for you to test it yourself, no offense. I don't think there is a faster way to upload the data to the GPU through OpenGL. Rendering performance should be comparable to a large static vbo. – rasmus Feb 11 '12 at 23:41
  • From your code I unfortunately don't understand where you create the vbo and where you update it. Could you please add comments to your code so that it's clear what's happening where? thanks! For you to get the bounty, I would love if you could show me how to switch between vbos! – memyself Feb 12 '12 at 08:33
  • one more comment: you say your code is using `vbo`, however it seems to me like you are using `vertex array` here and not `vbo`. `vbo` would use `glBindBuffer()`, right? please clarify. thanks. – memyself Feb 12 '12 at 10:55
  • No, it is not using a vbo. First it used immediate mode, then you asked me to show you how to render from a CPU memory pointer (vertex array). This is what the code uses now. – rasmus Feb 12 '12 at 11:00
  • could I expect to see a performance increase by using vbo? if not, why? thanks! – memyself Feb 12 '12 at 11:01
  • Would you like me to change it to using a vbo? There would be a performance increase if you reuse the same data points for multiple renders, since there is no need to upload the data to the GPU. – rasmus Feb 12 '12 at 11:01
  • yes, please add the corresponding code using a vbo to claim bounty! thanks. – memyself Feb 12 '12 at 11:34
  • I've added a full example with great performance using multiple vbos. Each frame 10k new points are added. Enjoy! – rasmus Feb 12 '12 at 12:27
  • looks great - unfortunately I get a segmentation error: `Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () (gdb) backtrace #0 0x0000000000000000 in ?? () #1 0x000000000040148b in Vbo (size=800000, this=0x6ad900) at sin_plot.cpp:24 #2 addPoints (points=, pointCount=) at sin_plot.cpp:45 #3 render () at sin_plot.cpp:72 #4 0x00007ffff7bb6220 in ?? () from /usr/lib/libglut.so.3` – memyself Feb 12 '12 at 14:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7586/discussion-between-rasmus-and-memyself) – rasmus Feb 12 '12 at 14:56
3

Would it be possible to use an alternate architectue? For example, use MATLAB to generate the data and use a fast library or application (GNUplot?) to handle the plotting?

It might even be possible to have MATLAB write the data to a stream as the plotter consumes the data. Then the plot would be updated as MATLAB generates the data.

This approach would avoid MATLAB's ridiculously slow plotting and divide the work up between two separate processes. The OS/CPU would probably assign the process to different cores as a matter of course.

ahoffer
  • 6,347
  • 4
  • 39
  • 68
  • do you have an example on how to do this? I'm especially curious how you would achieve the communication between matlab and the external library. would the library create and manage its own window? right now my matlab program comes with an elaborate GUI because I need to interact with the incoming data. Therefore my idea to only replace the core plotting of my GUI. – memyself Jan 21 '12 at 12:28
  • I was thinking of file-based IPC. Normally, MATLAB creates the data and then the 'plot' command is used to plot them. Instead of calling plot, write the MATLAB data to a file. Create a little routine that waits for the file to close and then runs Gnuplot. The routine tells Gnuplot to use the file as the plot data using command line parameters. I'm not a great script programmer, but the routine could probably written in a scripting language or shell script. For a list of other kinds of IPC, look here: http://en.wikipedia.org/wiki/Interprocess_communication. – ahoffer Jan 21 '12 at 19:25
  • PS: File-based IPC and pipes can also be used to shared data as it is written-- it is not necessary to wait for the file or pipe to close. – ahoffer Jan 21 '12 at 19:26
  • @memyself, an idea for IPC - You can also compile your Matlab code as COM server, using Matlab NE Builder, and use it in your C++ aplication. – Andrey Rubshtein Feb 05 '12 at 20:05
1

I did a very similar thing many many years ago (2004?). I needed an oscilloscope-like display for kilohertz sampled biological signals displayed in real time. Not quite as many points as the original question has, but still too many for MATLAB to handle on its own. IIRC I ended up writing a Java component to display the graph.

As other people have suggested, I also ended up down-sampling the data. For each pixel on the x-axis, I calculated the minimum and maximum values taken by the data, then drew a short vertical line between those values. The entire graph consisted of a sequence of short vertical lines, each immediately adjacent to the next.

Actually, I think that the implementation ended up writing the graph to a bitmap that scrolled continuously using bitblt, with only new points being drawn ... or maybe the bitmap was static and the viewport scrolled along it ... anyway it was a long time ago and I might not be remembering it right.

William Payne
  • 3,055
  • 3
  • 23
  • 25
1

I think it's possible, but likely to require writing the plotting code (at least the parts you use) from scratch, since anything you could reuse is exactly what's slowing you down.

To test feasibility, I'd start with testing that any Win32 GUI works from MEX (call MessageBox), then proceed to creating your own window, test that window messages arrive to your WndProc. Once all that's going, you can bind an OpenGL context to it (or just use GDI), and start plotting.

However, the savings is likely to come from simpler plotting code and use of newer OpenGL features such as VBOs, rather than threading. Everything is already parallel on the GPU, and more threads don't help transfer of commands/data to the GPU any faster.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • thanks, I will look into this! your solution seems to be Windows specific, but I guess similar solutions should work on MacOS and Linux, right? – memyself Jan 20 '12 at 19:19
  • @memyself: Yes. I'm not as familiar with the functions used there, but the same approach should work. However, I like ahoffer's idea better, much less code would be needed. – Ben Voigt Jan 20 '12 at 19:48
0

Blockquote EDIT4: I know that this is a huge amount of points to plot but I never said that the problem was easy. I can not just leave out certain data points, because there's no way of assessing what points are important, before actually plotting them Blockquote

This is incorrect. There is a way to to know which points to leave out. Matlab is already doing it. Something is going to have to do it at some point no matter how you solve this. I think you need to redirect your problem to be "how do I determine which points I should plot?".

Based on the screenshot, the data looks like a waveform. You might want to look at the code of audacity. It is an open source audio editing program. It displays plots to represent the waveform in real time, and they look identical in style to the one in your lowest screen shot. You could borrow some sampling techniques from them.

Miebster
  • 2,365
  • 4
  • 21
  • 27
0

What you are looking for is the creation of a MEX file.

Rather than me explaining it, you would probably benefit more from reading this: Creating C/C++ and Fortran Programs to be Callable from MATLAB (MEX-Files) (a documentation article from MathWorks).

Hope this helps.

JonaGik
  • 1,533
  • 5
  • 24
  • 35
  • a mex file isn't the solution, because if I'll still have to call this mex file 20 times (20 line plots), and since matlab is only a single threaded program, plotting will occur sequentially and not in parallel. then I'm basically back to matlab speed (which uses opengl anyway) – memyself Feb 10 '12 at 09:04
  • I'm not sure about the details but I would think that the use of a MEX file would a) allow threads to be created from the file, and b) allow shared memory space between the C++ and MATLAB code. – JonaGik Feb 10 '12 at 11:30