Log in

HCMC Journal

MAJW / Pro-D 2023-04-17 to 2023-04-21

to : Martin Holmes
Minutes: 1610

Network map generation is something we’re going to need for many projects, and we propose doing this with force-directed-graphs created using D3. Figuring this out is the first part of my Pro-D this year, and I’ve got as far as a simple working example with hard-coded data. The next phase requires a real-life JSON file from a real project, and MAJW is the natural source right now, so I came back to the project to finish the process of breaking out the personography into a set of alphabetized prosopography files, with new person ids on the model of Landscapes; having done that, I had to rewrite a lot of the build process to take account of the new structures and ids, which I’ve now done. The build is working completely as far as I can see, and I should now be able to generate some JSON to build the visualization.

On Wednesday I wrote the code to generate the JSON and started experimenting with it. I’m producing one large file of everything -- too big to be useful -- and one file for each primary, which I can now render based on a paramater passed to the test page. This is now at the point where I could actually build it into the site.

By Thursday, the basic graph was working on MAJW pages. All of the Women’s pages on MAJW now have the new feature. If you scroll down to the relative list, there’s a new button View network which pops up the network graph. Some people have very small networks; others have very large ones, such as Unnamed daughter of Henna (unna20), who by virtue of being connected only once, to Henna, gets a massive network that’s a bit too big to fit into a regular page.

So I’m working on figuring out how to size things appropriately. I already reduce the repulsion force based on the number of nodes, so that a bigger graph is more densely packed, but I don’t think that will solve the problem for these large cases. I could also reduce the node size for larger graphs.

Several other problems still need solutions:

  1. When the browser window is resized, the graph is not redrawn. Even if I force-redraw it, it uses width and height parameters from the page load, so I need to figure out how to wipe out the graph completely and start from scratch on a window resize. However, I don’t want to be doing that over and over again as you size your window, so that’ll require a bit of thought. There are approaches to determining when a window resize event is complete, using timeouts; not elegant, but perfectly functional.
  2. The strength of connections (i.e. the number of historical records attesting to a connection) is reflected in the width of the connecting line, but I don’t know whether it even makes sense to do that, given that there’s no easy way to explain it; perhaps we should just draw all lines the same width.
  3. If you mouse over a line, a little popup tells you the nature of the connection (son, husband, etc.). However, mousing over a line is no mean feat unless it happens to be a big thick one. SVG lines don’t have padding attributes, so there’s no simple solution that will extend the hit-region for a mouseover. Options might be: include a second much thicker line which is basically transparent and attach the same title to it; that would require digging into the D3 codebase, because although it would be easy to clone and modify the initial line after it’s created, D3 would not know about the clone and would presumably not modify it as the graph changes or moves. Another option would be to try to write the relationship as a label along the line, but that would add even more text to graphs which are already quite text-heavy, and much of that text would be vertical or even upside-down. Suggestions welcome here, but perhaps it doesn’t actually matter much since most people’s display names already say something about their relationships.
  4. The design/style is rudimentary at best, so PS will need to give it his customary polish once I’ve finished all the remaining issues. All the SVG elements are styled through the regular majw.scss file, so it shouldn’t be too complicated.
  5. It’s not clear to me whether any other kind of interactivity should be added to the map -- when you click on a person, for example, should you have an option to navigate to their page? Most network maps don’t do this, but some do (e.g. https://www.cs.cornell.edu/~kt/post/site-graph/). It might be useful.

I’ve made a point of building network graphs only for the primaries (the women), in line with the rhetorical stance of the site: we want to present this data with women at the centre of it, with the men as satellites in the women’s networks.

These graphs are already revealing some interesting things. For instance, I noticed looking at the graph for Chera of Winchester (cher12) that there are two Floria wife of Eliases, one a primary, Floria wife of Elias son of Chera, flor16, and one a relative, Floria wife of Elias, flor64. We don’t have these tagged as possibly the same person, but surely they are, and flor64 should be deleted in favour of flor16, I think. This sort of thing is a little easier to see in the graphs than in the relative lists.

The code in MAJW for this is relatively straightforward, but heavily MAJW-oriented; next week I will have a shot at building something much more generic that can be deployed on any site, so that you could provide it with (for example) the id of an svg element and the path to a JSON file, and it would just build from that. I might also rework it to change the terminology from link to edge, to align more closely with conventional graph theory as used in e.g. Neo4J. On the other hand, graph theory seems to use node/vertex/point and edge/link/line interchangeably, so maybe that’s not necessary. But link seems a bit too generic in the environment of a website.

Update from Friday: I solved the issue of browser window resizing; the graph is now erased and redrawn. The main stumbling blocks were the requirement to debounce the resize event, otherwise it fires the redraw repeatedly, and the discovery that the D3 functions for emptying an element apparently do not work, so I just had to implement the erasure of the existing graph with regular JS. I also addressed the issue of fitting the bigger graphs into the page, by providing scaling functions for the nodes so that they’re more closely packed and smaller when there are lots of them. This is edging towards finding a way of showing the entire map of the prosopography, but that may not be practical.