Response to architecture query

Excerpt response to a private query about matplotlib's architecture. Some
has asked me to post it as a possible addition to development docs.

All of matplotlib started off as pure python. As time went on, it was
re-worked into a backend/frontend design. The frontend is mostly in python,
with critical portions, such as path and vector handling implemented in
C++. We are also heavily reliant upon NumPy and use its C-API in those C++
parts. We also call out to various other libraries such as libfreetype to
perform our font-handling. The frontend is also a bit of a misnomer,
because it isn't really at the front, as most people are familiar with the
pyplot interface, which sits on top of the frontend.

The backends are what allows us to output the figures to the many different
"devices" (filetypes, GUI toolkits, etc.). Most are implemented in python
using the respective GUI toolkit's python bindings. The Tk backend, oddly
enough, is implemented in C/C++ (don't ask me why, I haven't a clue), and
the macosx backend is implemented in Obj-C. The AGG backend is implemented
in C++. PDF and PS backends are implemented in python as well.

AGG is critically important to matplotlib's functionality. Not only does it
serve as the default headless backend, and is often mixed with the GUI
backends (TkAgg, Qt4Agg, etc.) to produce consistent results across all
platforms, it also serves as the basis for our image-handling architecture.

This is a very broad-brush overview of the matplotlib architecture. It
isn't a simple layered system, unfortunately, but we do have some critical
portions off-loaded to C/C++ or NumPy. Probably some of the most
difficult-to-understand portions of the codebase isn't those parts, though.
It is the figure/axes/axis relationships for defining properties at the
right time (lots of multiple-inheritance confusion) as well as the
figure/canvas/manager relationships for interactivity.

Cheers!
Ben Root
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160209/9cd95dfd/attachment.html>

Only a rather small part of it. And there is a similar C++ component
for the GTKagg backend.

Eric

···

On 2016/02/09 6:52 AM, Benjamin Root wrote:

The Tk backend, oddly enough, is implemented in C/C++ (don't ask me why,
I haven't a clue)

I don't think multiple inheritance is such a problem in the mpl
codebase, but I find that circular references and long chains of
indirection can make it difficult to figure out what is going on.

Eric

···

On 2016/02/09 6:52 AM, Benjamin Root wrote:

It is the figure/axes/axis relationships for defining properties at the
right time (lots of multiple-inheritance confusion) as well as the
figure/canvas/manager relationships for interactivity.

I don't think multiple inheritance is such a problem in the mpl codebase,
but I find that circular references and long chains of indirection can make
it difficult to figure out what is going on.

What I have found confusing as heck is the initialization chain for an axes
with a non-default transform. The indirection and multiple inheritance both
confounded my ability to understand exactly what was getting initialized
when and how. It is the main reason why mplot3d still doesn't operate on
top of the transforms stack, preventing me from implementing the log scale
feature.

Only a rather small part of it. And there is a similar C++ component for

the GTKagg backend.

Ah, I forgot about that thing.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160209/b6d71d11/attachment.html&gt;

···

On Tue, Feb 9, 2016 at 3:54 PM, Eric Firing <efiring at hawaii.edu> wrote:

this is a big one -- I tried to debug the wxAgg backend once, and it was
simply littered with calls to render the screen -- and it was next to
impossible to figure out when rendering was actually supposed to happen. I
suspect class were simply added all over the place until it seemed to work.

I can image other back-end suffer from the same issues.

</rant>

-CHB

···

On Tue, Feb 9, 2016 at 8:52 AM, Benjamin Root <ben.v.root at gmail.com> wrote:

as well as the figure/canvas/manager relationships for interactivity.

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160209/590c2064/attachment.html&gt;

Funny story... in the WxAgg section of my book, the original draft had the
phrase "... add a call to `canvas.draw()` here because sometimes Wx needs a
kick in the butt.". The editors made me change that...

Ben Root

···

On Tue, Feb 9, 2016 at 5:27 PM, Chris Barker <chris.barker at noaa.gov> wrote:

On Tue, Feb 9, 2016 at 8:52 AM, Benjamin Root <ben.v.root at gmail.com> > wrote:

as well as the figure/canvas/manager relationships for interactivity.

this is a big one -- I tried to debug the wxAgg backend once, and it was
simply littered with calls to render the screen -- and it was next to
impossible to figure out when rendering was actually supposed to happen. I
suspect class were simply added all over the place until it seemed to work.

I can image other back-end suffer from the same issues.

</rant>

-CHB

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker at noaa.gov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160209/96e7bb7e/attachment-0001.html&gt;

Funny story... in the WxAgg section of my book, the original draft had the
phrase "... add a call to `canvas.draw()` here because sometimes Wx needs a
kick in the butt.". The editors made me change that...

darn -- you should have snuck that back in .....

-CHB

···

On Tue, Feb 9, 2016 at 2:37 PM, Benjamin Root <ben.v.root at gmail.com> wrote:

Ben Root

On Tue, Feb 9, 2016 at 5:27 PM, Chris Barker <chris.barker at noaa.gov> > wrote:

On Tue, Feb 9, 2016 at 8:52 AM, Benjamin Root <ben.v.root at gmail.com> >> wrote:

as well as the figure/canvas/manager relationships for interactivity.

this is a big one -- I tried to debug the wxAgg backend once, and it was
simply littered with calls to render the screen -- and it was next to
impossible to figure out when rendering was actually supposed to happen. I
suspect class were simply added all over the place until it seemed to work.

I can image other back-end suffer from the same issues.

</rant>

-CHB

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker at noaa.gov

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160210/c7e3867c/attachment.html&gt;

Anyone who is interested in matplotlib?s architecture may be interested in
a referred paper John and I wrote about it a few years ago (which is still
mostly current): http://www.aosabook.org/en/matplotlib.html

Excerpt response to a private query about matplotlib's architecture. Some

has asked me to post it as a possible addition to development docs.

All of matplotlib started off as pure python. As time went on, it was
re-worked into a backend/frontend design. The frontend is mostly in python,
with critical portions, such as path and vector handling implemented in
C++. We are also heavily reliant upon NumPy and use its C-API in those C++
parts.

I wouldn?t say heavily reliant ? it?s actually deliberately loosely
coupled. All of the Numpy usage is isolated to one file (numpy_cpp.h), such
that it can be replaced to use the new Python buffer protocol and
memoryviews once we?ve dropped support for Python 2.6 (which we?ve done, we
just haven?t gotten around to using the buffer protocol yet). All that is
just to have an abstract way of passing large binary arrays between Python
and C++. Numpy isn?t used from the C++ side for anything another than
passing buffers across the language barrier.

We also call out to various other libraries such as libfreetype to perform

our font-handling. The frontend is also a bit of a misnomer, because it
isn't really at the front, as most people are familiar with the pyplot
interface, which sits on top of the frontend.

We don?t really use the term ?frontend? in the code base anyway. We usually
refer to the ?Object-Oriented API? and the ?pyplot API?.

The backends are what allows us to output the figures to the many
different "devices" (filetypes, GUI toolkits, etc.). Most are implemented
in python using the respective GUI toolkit's python bindings. The Tk
backend, oddly enough, is implemented in C/C++ (don't ask me why, I haven't
a clue),

This is because Tkinter does not have an API to pass a binary image buffer
from Python to be displayed on the screen. We therefore had to write a very
small extension to Tk to do that. Same is true of the Gtk 2 backend. The
other more modern toolkits all have this API built-in, so we don?t have to
provide it ourselves.

and the macosx backend is implemented in Obj-C. The AGG backend is

implemented in C++. PDF and PS backends are implemented in python as well.

AGG is critically important to matplotlib's functionality. Not only does
it serve as the default headless backend, and is often mixed with the GUI
backends (TkAgg, Qt4Agg, etc.) to produce consistent results across all
platforms, it also serves as the basis for our image-handling architecture.

Just to elaborate on this: matplotlib really has two types of backends:
rendering backends and GUI backends. The rendering backends actually
perform the drawing either by rasterizing or outputting to a vector
filetype. These include Agg (which rasterizes), Pdf, Ps, Svg and Cairo. The
GUI backends create windows, copy a rendered buffer to the screen, and
provide toolbars and interaction etc. These include TkAgg, WxAgg, QtAgg,
GtkAgg etc. There are also some hybrid backends that do both, such as the
Mac OSX backend and the mostly deprecated Gdk and Wx backends.

This is a very broad-brush overview of the matplotlib architecture. It
isn't a simple layered system, unfortunately, but we do have some critical
portions off-loaded to C/C++ or NumPy. Probably some of the most
difficult-to-understand portions of the codebase isn't those parts, though.
It is the figure/axes/axis relationships for defining properties at the
right time (lots of multiple-inheritance confusion)

We don?t use a lot of multiple inheritance, and when we do, it?s usually
just as a mixin pattern.

as well as the figure/canvas/manager relationships for interactivity.

These are indeed a bit tricky to understand, but are fairly well-documented
in backend_base.py

Cheers,
Mike

···

On Tue, Feb 9, 2016 at 11:52 AM, Benjamin Root <ben.v.root at gmail.com> wrote:

Cheers!
Ben Root

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel at python.org
Matplotlib-devel Info Page

?

--
Michael Droettboom
Continuum Analytics
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160210/055fbf48/attachment-0001.html&gt;

as well as the figure/canvas/manager relationships for interactivity.

this is a big one -- I tried to debug the wxAgg backend once, and it was
simply littered with calls to render the screen -- and it was next to
impossible to figure out when rendering was actually supposed to happen.

The relationship between the backend classes is documented in
`backend_base.py`.

The interaction is essentially:

1) The GUI framework receives an event to redraw the window
2) This triggers the `paint` callback method
3) This calls the figure's draw method which renders the figure into an
image buffer
4) The image buffer is copied to the window's image buffer
5) The GUI framework through layers of abstraction we don't have to concern
ourselves with paints the window's image buffer to the screen

I suspect class were simply added all over the place until it seemed to
work.

The backend classes are actually some of the better-reasoned parts of the
code base. For more information, see
http://www.aosabook.org/en/matplotlib.html

···

On Tue, Feb 9, 2016 at 5:27 PM, Chris Barker <chris.barker at noaa.gov> wrote:

On Tue, Feb 9, 2016 at 8:52 AM, Benjamin Root <ben.v.root at gmail.com> > wrote:

I can image other back-end suffer from the same issues.

</rant>

-CHB

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker at noaa.gov

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel at python.org
Matplotlib-devel Info Page

--
Michael Droettboom
Continuum Analytics
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-devel/attachments/20160210/84700b96/attachment.html&gt;