CityStats: It's basically working (fingers crossed)
Worked through a range of bugs, and also a couple of new feature requests, and I think I have the whole thing basically working, producing three tables with (as far as I can tell) the correct results (based on comparison of single-ethnicity grouping results against results from the original code for the same ethnicity. The last remaining bugs were due to the necessity for a lot of our calculations to include zero-total records, because of cross-ethnicity, cross-city, and cross-year comparisons, where the original code could discard the zero counts earlier in the process.
Having done this once, I could now rewrite it to use half the code. One thing I now realize, that took a while to emerge from the process, is that the root of the data structure is actually an array of years; each year contains ethnicity groupings, and city tract sets. Right now, my data structure has two separate arrays of ethnicity groupings and city tract sets, which have a lot of their internal organization done by year, but a year-indexed array would be a better organizational principle. If the site gets a lot of attention and use, it will be worth rewriting on that basis for simplicity. But right now, it seems to work (although I suspect there may still be the odd edge case which can break it).