biVector forum

Problems displaying ganja PGA scenes with Jupyter

Jupyter is a notebook environment that runs in a browser (e.g., Firefox). It is strongly associated with Anaconda python, Javascript and several other languages including Haskell. It would appear to be a superb environment for learning GA, especially PGA and CGA, but problems arise with some of the displayed ganja scenes. I will use the 2D PGA "project and reject as an example. Note that all of Steven’s distributed examples work correctly when opened as HTML files in Firefox.

I interface with Jupyter using the method posted by Hugo Hadfield on stack overflow two years ago:
Jupyter provides a DOM element to which graphical output (here SVG) can be added using element.append, unlike the more usual node.appendChild. The output appears below the notebook cell.

First Problem: In Jupyter, the annotated x- and y- axes do not appear. The SVG code that produces them appears in the console log without any line breaks, unlike the SVG from the working version in HTML. The muddled SVG code is rejected, and no axes appear.

Second Problem: In Jupyter, the geometric lines and points appear upside down, even though the labels are right side up. I have not traced this yet, but with SVG code being corrupted (see above), I am surprised that a recognizable figure appears at all.

What is different about Jupyter? Aside from append vs appendChild, Hugo’s method uses a double copy of the graphic output. I tried to put the call to append inside Algebra, but “element” is not recognized. I am a total novice with Javascript and would love suggestions. I also tried to read a local copy of ganja from localhost:8888 (Jupyter creates this URL at its launch directory) instead of from, but I consistently get a MIME error from the local copy.

So this is disappointing, since Jupyter looks so promising. It is excellent for working with the Clifford and galgebra GA packages. A number of CGA scenes do display correctly, but most 2D and 3D PGA scenes have the above problems. I have briefly tried Hugo’s pyganja package, which does not support R^*(2,0,1), and have successfully run his examples, but have not yet created a scene that replicates “project and reject”.

I have been interested in GA for some years, and have often used the Euclidean projective algebras in Browne’s Grassmann Algebra (Volume 2 out this year!). I am relatively inexperienced with CGA (I have tried CGUCalc and GAALOP), but I first ran into the dual PGA in the SIGGRAPH 2019 video.

Thank you in advance for any suggestions to get Jupyter working correctly with this wonderful generator.

Rod Hallsworth

1 Like

Hi there Rod,

I’m surprised that you have stumbled upon my old stack overflow question, but glad that it has been useful in some way :slight_smile: I wrote that question back when I was starting out with making pyganja and was just muddling along with making basic things work. pyganja is actually just a very thin wrapper around ganja.js + an API for constructing scenes from code.

Currently we only officially state that it supports 3D CGA and PGA as those are the only ones we have properly tested. In practice however it is likely to support any algebra that ganja.js supports we just haven’t verified that it does yet… If you are interested in helping out with the project I would be very grateful!

Almost all of the logic that handles the algebra signatures can be found around here in the code:

If you have a look at my previous pull request to update to ensure 3D PGA support you can see that almost all the code changes are actually just writing some tests to make sure that PGA works rather than modifying any of the actual logic!

I’ve opened a tracking issue on github here in the meantime:


1 Like

Hi Hugo

Thank you for your reply. My Python experience started only a couple of months ago, when I tried the Clifford and galgebra GA packages. I started using Jupyter, and tried other GA facilities like GAALOP and CLUCalc (now quite old). I am not yet ready to do anything serious with Python.

I ran across ganja with the SIGGRAPH 2019 talk and wanted to try it out with Jupyter. A net search for prior solutions revealed your Stack Overflow question and solution. Hugo, if you try your original code with R*(2,0,1) “Project and Reject”, do you observe the problems that I described? Your method of copying the graph to “output” and then to “element.append” should work, and I am at a loss to explain the strange behavior. If you have an updated Jupyter method, could you please post it, since Jupyter is a great platform to learn GA.

I would like to call "element.append"from inside Algebra, where “document.body.appendChild” appears in Steven’s HTML examples. All of Steven’s examples work for me in Firefox, and I also run Jupyter in Firefox. I cannot figure out how to make “element” visible inside Algebra. What class is “element” an instance of? There are a number of Javascript classes in Jupyter code that use “element”, but I have not located the right one. How did you figure out the element method two years ago, when Jupyter was still quite new?

Looks like a great community here. I am looking forward to participating.

Cheers, Rod

Hi Rod,

I would really strongly recommend not building off of my original javascript from that stack overflow post and instead would start from the existing pyganja repository, even if your python isn’t amazing you will be a lot better off starting with something that is tried and tested to work well!

I’ve knocked up a quick port of Steven’s “project reject” demo into clifford + pyganja as a Github Gist here:

The key thing that I have done here is to use a local version of generate_notebook_js without any guards for untested algebra signatures… if you are keen to just mess around with different algebras and pyganja you can just copy and paste that funtion into your jupyter notebooks and it should work… let me know what combo of algebras and settings you try and we can add those sometime to the officially supported algebra signatures :slight_smile:.

A quick comment re. discrepencies you might notice vs ganja.js coffeeshop, we pin the version number of ganja.js and only update on releases of pyganja, this lets us debug more easily and find where bugs have come in. We are due a new release of pyganja sometime soon (as soon as @eric-wieser and I find time basically, also due a new release of clifford) but in the meantime if you want to keep on pyganja with the bleeding edge release of ganja.js you will have to update your git submodule manually.

Glad to have you as a part of the community, let us know how you get on!

Best, Hugo

Hi Hugo

Thank you for the pyganja demo code; I will use it as a basis for developing my Python skills. I have developed previously in C++ and Java, and know Wolfram language quite well. I like your Python interface, since it can be meshed easily with Python Clifford (and maybe galgebra). I followed the link in your post and found your visualization from a few hours ago, and it looks exactly like mine!!! Even if you deprecate your old code (which I use), it produces the same visualization that pyganja does.

Now suppose I install the enki distribution at Then on my computer, I open “file:///C:/Users/rhallsw/Temp/ganja.js-master/examples/example_pga2d_project_and_reject.html” in a browser. The reference scene resembles our common visualization with 2 huge differences: i) the geometry in our scene is upside down relative to the browser version, and ii) the densely annotated x- and y-axes (from grid:true) in the browser are absent in our scene. We both ask for a grid and the axes do not appear.

Yes, this could arise from conflicting ganja versions but ganja is quite mature and discrepancies this large should have been noticed before. I am not trying to be deliberately difficult, but just wish to resolve these discrepancies that we both observe with different interfaces. I think that the source of the discrepancy is something like, but this is pure speculation. Since you have a PhD to work on (been there, done that), I would be happy to follow up suggestions.

All the best, Rod

Hi @rhallsw,

Welcome to the forum. Ganja.js recently had a big change where coordinate axis discrepancies were corrected. This explains the difference in orientation with the more recent version (it is btw easy to flip the display upside down by using the option camera:1e2). As to the display problems you are experiencing with SVG in the Jupyter context, I may have some ideas on what is causing that. I will make some changes and send you a link to test with so we can get this sorted out.

Welcome to the community!


Hi Steven

Thank you for the note with the camera:1e2 recommendation, which I tried immediately. Now the points are in the correct places, as in the HTML version from github. I am using the ganja version on unpkg (no tag), which (according to them) serves the latest version. I noticed that it is linked to github.

Great to hear from you. Look forward to a test link.

All the best, Rod

A quick update on this, we’ve just removed default algebra restrictions from pyganja in: Allows algebras without restriction, reformats the js generation a bit, adds tests for 2d cga and pga by hugohadfield · Pull Request #54 · pygae/pyganja · GitHub . We will likely bump the ganja.js version in pyganja and do a release shortly :slight_smile:

1 Like