The last few days have been a lot of fun, as some of you will have noticed on my Twitter or LinkedIn feeds.
Since the last post, where I announced the fact we’ve been working on Project Rediscover, I’ve spent quite a bit of time reworking the graph to have more reusable chunks. Here’s a recent snapshot of the graph:
In the last post, the subgraph that generates text for the metrics and the radar chart as geometry – both to the right of the image – was hardcoded to the exact metrics we were dealing with. To make it easier to add new metrics – as well as to be used with different metrics in another graph – I refactored that section of the graph to be more flexible and accept a list of metrics along with information on whether they’re to be minimised or maximised by Refinery.
Here are the sections that display the text for the metrics as well as the radar graph:
I did my best to make the resultant graph customizable, such as with the number of bands to display. By default it displays 4 bands (representing 25% each). While making this configurable, I hit a really peculiar issue with DesignScript that I had to work around. We basically want to create a series of concentric circles (which we’ll use to create polygons): to do this we’ll use a range expression with a particular increment.
Ideally this should be 0..size..size/bands, where size is the radius of the outermost circle (and its circumscribed polygon) and bands is the number of bands you want. Basically the resulting list should be starting with 0 and ending with 4.7, with bands–2 entries in between.
I hit an interesting case where this failed, though. Let’s take the example of size being 4.7 and bands being 3. This expands out to 0..4.7..1.566666666666667. As the recurring 6 in the decimal rounds up, the range expression never actually reaches 4.7.
Here’s what I mean:
To “fix” this – at least in terms of getting a final value that approximates the final target value of 4.7 – I added some code that removes the rounding. I couldn’t find an easy approach to truncate the decimal, so I converted it to a string, removed the last digit, and converted it back to a number. Ugh.
Anyway, it works:
So now we’ll get the right number of bands, even when rounding errors might otherwise have stopped the range expressions from giving us what we wanted.
[Update: Jacob Small pointed out I can use a # within the DesignScript range to specify the number of bands, rather than the increment. This is much cleaner: 0..4.7..#4.
I’m embarassed I missed this, but there you go. Thanks, Jacob!]
In order to prepare the metrics to be displayed in the radar graph, we have to do a little work to normalise them between 0 and 1 (or between 1 and 0 if the metric is supposed to be minimised, as we want to invert the display of minimised metrics in the graph).
It’s nice to have the metric definition piece kept separate in a single place. The various metrics are calculated elsewhere, of course.
With that done, I decided to spend some time testing the graph with Refinery. Here’s a view of an optimisation run with the scatterplot displayed:
And here it is with the parallel coordinates view… as you can see, it’s quite crowded given the number of input parameters.
With Refinery generating options, I went and combined a few screengrabs into an animation.
That’s where I’ve left it, for now. We still have some work to do to finish the up the graph to be shared between now and AU London, particularly with respect to the daylight analysis… I’ll do what I can to share bits and pieces between now and June, where it makes sense.
The next topic I’m likely to cover relates to the use of Parallel.For[Each] in Python to get some performance gains, and whether that really makes sense in the context of Refinery, in particular.