This week I have come ridiculously close to finalising the second major part of my GSoC work: diagram plotting. Before submitting the two pull requests, I only have to add proper docstrings to a couple classes and to integrate the plotting with sympy.printing.preview for easier use. (Well, there also is a FiniteSet-related issue, but I hope to be able to fix it more or less swiftly.) The main functionality is ready, however, and that gives me hopes🙂
In terms of material progress, this week has been rather unimpressive: I haven’t written that many lines of code and that which I have written has introduced seemingly inessential changes to the aspect of the diagrams. Nevertheless, I think this week can be marked as one of the most thought-intensive.
In the beginning of this week I have extended the drawing of curved morphisms to take into account the situations when there are multiple morphisms between the same two pair of objects. This allows to automatically typeset diagrams such as Diagram 1.
The next two days I have been smashing my head against the simplest approach to the problem of positioning morphisms labels such that they don’t get intersected by morphisms. The upsetting part is that, despite the amount of thinking I have done and the amount of code and comments I have written, the actual output hasn’t really got much better. (It may be considered to be a success, though, that it hasn’t got much worse either🙂 ). Consider Diagram 2. No special care about the position of the labels is taken.
Now consider Diagram 3; notice that the labels are now on the outer sides of the diagram. The trick basically (very basically) consists in detecting those morphisms which form the outer edges of the diagram and then placing their labels on the proper side. While for vertical and horizontal morphisms the procedure is pretty straightforward, for diagonal morphisms I resolved to apply some basic ideas from analytic geometry and yes, I even do floating-point computations (although I of course try to do them as little as possible). Nevertheless, the approach I have implemented feels very far from perfect. I hope though that I have managed to achieve some balance between code that works sufficiently fast and well and code that is intelligible. Note that the positioning of the labels of the morphsisms which are in the bowels of the visual structure of the diagram remains pretty arbitrary, which may sometimes get ugly.
The next feature I have added is the possibility to draw “loop” morphisms, i.e., morphisms which have the same domains and codomains. While proper layout of such morphisms is not guaranteed for very crowded diagrams, this functionality is of some use, as can be seen in Diagram 4.
Finally, I have implemented the support for custom arrow formatters. Arrow formatters are associated to morphisms properties. Whenever a morphism with some properties is typeset, after the necessary thinking has been carried out, the resulting data is passed to the formatter. The formatter is free to modify anything it wants in order to influence the appearance of the arrow. A common usage is shown in Diagram 5. This effect was achieved with a two-line formatter.
I must confess that dealing with hash randomisation-related issues takes up much more time that I always expect. I have been constantly getting back to certain bits of my code and adding new and new invocations of sorted to assure stable output. Working on this, as well as on some obscure tuning of small details of the diagram is actually what has consumed the bulk of my time this week. The visual input of such modifications is usually minimal; yet, I do believe they bear a rather important role.