starplast.celldiagram
An apicomplexan cell, colored from the same palette as the map.
A list of 27 compartment names is a legend; a parasite with its rhoptries filled in the color the
rhoptries have on the map is a picture of where the genes are. This draws the second from the first,
at draw time, from Window.color_of -- never from a second palette, because two palettes are two
claims about what a color means and one of them will drift.
The artwork is UniProt's subcellular-location diagram (data/icons/Apicomplexa_cells.svg): 59
organelles, each a <g> carrying a UniProt SL identifier. So the drawing already speaks a
controlled vocabulary and the work here is a mapping from hyperLOPIT compartment names onto SL
codes -- COMPARTMENT_SL -- rather than any renaming of the artwork.
Three decisions this module implements, all of them forced by the data
Several hyperLOPIT classes share one organelle. Both rhoptry classes, both nucleus classes and the three plasma-membrane classes map to a single shape, which cannot carry three colors at once. The shape takes the color of whichever class is SELECTED, and says which one it is showing. With nothing selected it is neutral: filling it with whichever class sorts first would be a claim nobody made. Clicking it cycles through the classes that share it, saying each time which is now selected.
Some compartments have no organelle in the drawing. The proteasome classes and apical 1/2 are
not in the artwork, and cytosol has no distinct shape worth clicking. They are listed beside the
diagram rather than silently absent -- between them they are a large part of this proteome, and a
compartment that vanishes from the legend reads as one that does not exist.
Absence stays gray. unassigned is 4,313 genes. It is never filled with a compartment color
and never looks like a measurement.
Remove the artwork's hidden text and links.
UniProt ships each organelle with a <text> description, a <text> name and an <a> link to
its own page, all visibility="hidden" -- and some of them nested INSIDE a <path>, where the
SVG content model does not allow them. Qt's renderer says so, three times per render:
qt.svg: <input>:42:452: Could not add child element to parent element because the types
are incorrect.
It then draws the file correctly, so the warnings are noise -- but noise printed on every repaint of every organelle mask is a console nobody can read, and a real warning would be lost in it. None of this is drawn: it is metadata for a page that is not this one.
Strip the artwork's own colors down to grey fills and grey lines.
Every fill becomes one light grey and every stroke one mid-grey, so the drawing reads on a dark
ground and on a light one, and so that ANY color in it is the selection. fill="none" is left
alone: it is not a color, it is the absence of one, and filling those shapes in would turn the
cell's internal outlines into solid blocks.
Where the artwork lives, resolved the way every other data file is.
Whether the drawing is there. It ships with the package; a missing file hides the diagram.
Every SL group the artwork actually contains.
Read from the file rather than trusted from the table above, because a mapping to a shape that is not in the drawing is a silent no-op -- the compartment would simply never color anything and nothing would say why.
Compartments with no organelle to color, in the order given.
Named rather than dropped. Between the proteasome classes, the apical classes and anything the artwork lacks, these are a large part of the proteome, and a compartment that vanishes from the legend reads as one that does not exist.
(start, end) of one SL group's markup, or None -- counting nested <g> as it goes.
A non-greedy <g id="SL...".*?</g> ends at the FIRST inner closing tag, and these groups nest:
the rhoptry holds its membrane, the Golgi holds four sub-compartments. Matched that way, most
organelles came back as a fragment -- which rendered as nothing, so eleven of the fourteen
hit-test masks were silently empty and the coloring painted part of a shape.
Drop the artwork's own background so the panel's shows through.
Two things make the card: a white rectangle behind everything, and the groups that stand for the space OUTSIDE the cell, which are drawn as filled sheets across the whole canvas. Both go.
Who drew the cell and under what licence, read out of the artwork itself.
Read rather than written down here: the file embeds property="creator" and a CC licence link,
and a hand-copied attribution is one that silently stops matching the file it credits. The
artwork is CC BY, so the attribution is a condition of using it, not a courtesy -- which is why
dropping the logo block from the drawing has to be paired with showing this.
Remove the credit block from the drawing (the credit itself travels via credit).
The artwork's own (x, y, width, height), or None. See CellDiagram.viewbox.
Turn the cell upright, apical end -- the rhoptries -- at the top.
The artwork is drawn lying down, apex to the left, which is the orientation of a textbook figure and the wrong one for a tall panel: laid out flat in a 260-pixel column it is a strip a centimetre high. Rotated a quarter turn it fills the column, and it matches how the parasite is drawn in every paper about invasion -- apex first, because that is the end that goes in.
Done by wrapping the drawing in a rotation and swapping the viewBox rather than by editing coordinates: the artwork has 59 groups and several thousand paths, and touching them would break the SL ids that everything else here depends on.
Set the fill of each SL group, returning the modified SVG text.
Done on the text at draw time rather than by shipping a recolored copy: there are four themes and the categorical palette changes with each, so any stored copy would be wrong for three of them and would drift from the map the moment a palette changed.
The fill is applied to the group AND its descendants' inline styles, because the artwork sets
fill on the individual paths -- a fill on the group alone is overridden by every path in it and
the diagram would come back gray while every test on the returned string passed.
Hollow every shape out and draw it in white line.
A cell drawn as outlines sits on whatever is behind it -- the panel, the theme, anything -- and the one filled thing in it is then unmistakably the selection. Filled shapes, however pale, are a card the diagram sits on.
Shapes that carried no stroke get one, because a shape whose fill is removed and which has no outline is simply gone: the nucleus and the cell body are both drawn as fills in this artwork.
The parasite, filled from the map's own palette, clickable in both directions.
pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL
types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.
Take the map's palette and the current selection, and redraw from them.
SL group -> color: the SELECTED compartment, and nothing else.
One colored organelle at a time, in the color that compartment has in the list and on the map. Coloring every organelle at once makes the diagram a second legend -- twenty-odd colors to read against twenty-odd names -- when what a person wants to know is where the thing they just clicked is. Everything else is grey, which is also what the map shows: the points of one compartment against a grey field.
Draw the cell grey, then tint the selected organelle.
The drawing is hollow -- white outlines on nothing -- so it sits on whatever is behind it and the one FILLED thing in it is unmistakably the selection, in the color that compartment has in the list beside it.
Hollowing it is also what finally made it neutral. Every fill, stroke and gradient stop in
this file can be set to grey and it still renders pink: 145 elements carry a colored class
and eleven gradients cross-reference each other, and nothing in the document accounts for it.
A shape with no fill has nothing to render in any color.
A point in the artwork's own frame to widget pixels, through the rotation and the fit.
Defined beside its inverse so the two cannot drift: an off-by-a-quarter-turn hit test is invisible until someone clicks an organelle and selects its neighbour.
Widget pixels back to the artwork's own frame -- the inverse of local_to_widget.
Which pixels each organelle actually covers, at the current size.
Hit-testing used bounding boxes, and the boxes are useless here: every group contains hidden
<text> blocks holding UniProt's description of that compartment, so the Golgi's box is
4,894 units wide in a 1,190-wide drawing. Clicking a rhoptry landed on whichever inflated box
happened to win -- the proteasome, the plasma membrane, anything.
So the shapes are rendered. Each organelle is drawn alone into a small image and its ink recorded; the hidden text does not render, so the mask is exactly what a person sees. Built once per size and cached, because it costs one render per organelle.