|
QChartViewer and pychartdir |
Posted by Naveen Michaud-Agrawal on Sep-22-2013 05:12 |
|
Hi Peter,
I've been using ChartDirector in a PyQt desktop application by wrapping
QChartViewer.cpp with sip and generating a PyQt widget from it. This mostly works
without any hassle, except for a few QChartViewer functions that take a ChartDirector
object as an argument (setChart and the axis syncing methods). I've looked at the
implementation of pychartdir.py and chartdir.h, and it seems that the only link between
the python representations of chartdir objects and the underlying chartdir objects is a
string containing the address of the relevant internal pointer. I can parse out this
address using a regular expression and pass it into my PyQt wrapper as a long and then
reinterpret_cast it into the pointer. For example, here is the wrapper implementation for
setChart:
void setChart(long address);
%MethodCode
BaseChart* chart = new BaseChart();
chart->init(reinterpret_cast<BaseChartInternal *>(a0));
sipCpp->setChart(chart);
%End
This approach works - however, it is a bit fragile (and I believe leaks a BaseChart
object). Python has a special type of object which can wrap a C pointer (CObject up to
py2.6 and Capsules in 2.7 and beyond). Do you think it would be possible to change the
python bindings to add a special attribute to each ChartDir python object that contains
one of these objects? That way I could pull out the pointer directly from the python
ChartDir object with out having to parse the address from the "this" attribute.
Incidentally, what license is the QChartViewer code under? Since I have a license to
chartdir can I freely use the QChartViewer code in my application? Thanks.
Regards,
Naveen Michaud-Agrawal |
Re: QChartViewer and pychartdir |
Posted by Peter Kwan on Sep-24-2013 03:36 |
|
Hi Naveen,
From your description, my understanding is that you are using the "ChartDirector for Python" to create the chart object, and you need to pass it to the QChartViewer from "ChartDirector for C++".
You may have already known that the real chart object is in an "internal pointer". The "ChartDirector for Python" is a Python wrapper to the "internal pointer". The "ChartDirector for C++" is a C++ wrapper to the "internal pointer". Your code is trying to extract the internal pointer from the "ChartDirector for Python" wrapper and use it to create the C++ wrapper, so that it can be used by QChartViewer.
However, the wrappers are not just wrapping method calls, they also perform memory management. When the Python XYChart object is deleted (no longer referenced and garbage collected by the Python interpreter), it may free the "internal object". Similarly, when the C++ object is deleted, it may delete the underlying "internal object". So there is a danger that one of the wrapper may access an internal object that was deleted another wrapper, or the internal object may end up being deleted twice or never deleted.
So even if there is a robust way to extracting the "internal pointer", there may be complications if the same "internal pointer" is used in both the Python wrapper and C++ wrapper. Some modifications may be needed to coordinate them to ensure the "internal object" is only deleted once at the right time.
Regards
Peter Kwan |
Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Daniel on Sep-24-2013 22:10 |
|
Attention: Naveen Michaud-Agrawal
Hi,
Looks like you are using chartdirector from pyqt:) I am not but considering it pretty soon!
As an aside to this thread, I am quite interested in getting your feedback on the python+chartdir combination. And specifically the python+pyqt One.
How effective is the combination. I appreciate chartdirector quite a lot and be glad to get a benchmark on the bundle and, possibly, how this compares to the proverbial python+matplotlib. Most notably in terms of speed on data-intensive plots.
Specifically, I'd be glad to hear as well about the value of using svg output (instead of, say, png) within pyqt QT-based applications.
Regards
Daniel |
Re: Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Naveen Michaud-Agrawal on Oct-02-2013 22:56 |
|
Hi Daniel,
Sorry for the late reply. I didn't receive any notice that there were further posts on my
question.
So far the combination of pychartdir and PyQt have worked fairly well for me, although as
Peter mentioned there are some object lifetime issues I have to still resolve (the main
problem is that the C++ api and Python api use their own individual reference counting
scheme, and there is no easy way to sync them).
I haven't used matplotlib in almost a decade so I can't comment on its speed. ChartDir can
comfortably render tens of thousands of points at interactive speeds using the
QChartViewer widget (which I've wrapped with sip so that it can be used from PyQt). One
issue could be memory usage - I'm not familiar with how the pychartdir wrapper works, so
when i pass it a numpy array I'm not sure if it's converting it into a python list or if it is able
to access the underlying data efficiently. Matplotlib is able to render using numpy arrays
directly so it might be more memory friendly. But so far I haven't had any problems
generating 1k-5k timeseries with pandas and interactively plotting them with PyQt.
I haven't tried SVG output - the Qt integration is fairly low level, calling makeChart on the
chart to generate an in memory buffer and then drawing that into the QChartViewer widget.
Naveen |
Re: Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Peter Kwan on Oct-03-2013 00:04 |
|
Hi Naveen,
In ChartDirector for Python, the data were passed to ChartDirector API as Python arrays of lists. ChartDirector will immediately copy the data into internal C arrays. So you can immediately delete the Python array after passing it to ChartDirector. ChartDirector does not keep a reference to the Python array. In fact, ChartDirector does not keep references to any Python objects. All Python data (strings, arrays of numbers, etc) are copied to internal C data structures.
Regards
Peter Kwan |
Re: Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Naveen Michaud-Agrawal on Oct-03-2013 07:44 |
|
Hi Peter,
Thanks for the clarification. How does the python api work with numpy arrays? When I
pass a numpy array to pychartdir it works without trouble, but is pychartdir internally
converting the numpy array into a python list and then copying the values into internal
arrays, or does it copy from numpy (which are implemented as strided C arrays) directly
into the internal chartdir arrays? Thanks.
Naveen Michaud-Agrawal |
Re: Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Peter Kwan on Oct-03-2013 20:21 |
|
Hi Naveen,
For "arrays", ChartDirector for Python can support any "iterable" objects (anything that can be used with the Python "iter" function). Basically, ChartDirector will try to iterate the object and copy its contents to an internal C array. If "numpy array" is iterable, then it is supported too.
Regards
Peter Kwan |
Re: Question aside on pychartdir (ie with or without QChartViewer) |
Posted by Daniel on Oct-03-2013 03:52 |
|
Hi Naveen and Peter,
Thanks for your documented answer. It certainly helps.
No issue with the timing. The python work has not started yet. We are still in the preliminary phase here (and still considering wx as an alternative to pyqt at this stage).
Thanks as well to Peter for his information about the way python communicates with chartdirector. I am not a C developper and certainly does not care about memory issues but I am glad to hear that Chartdir is using it sparingly.
I'll report on this forum when I have some benchmarking with our current implentation - via win32 COM.
Daniel |
|