Google Summer of Code 2026 is done. I spent the summer with the United Nations Office of Information and Communications Technology, on a project owned by the Economic Analysis and Policy Division at UN DESA, and my work was the OG-Core side of a tool called MUIOGO.
MUIOGO is a browser interface for two open source policy models. CLEWS covers climate, land, energy and water, so it tells a country whether a plan is physically possible, like whether there’s enough land and water for a biofuel policy. OG-Core is an overlapping generations general equilibrium model, so it shows what a tax or pension change does to growth and jobs across generations. Both have been used in more than 20 countries.
Three things feed into MUIOGO, which is worth getting straight before anything else.
OG-Core itself is generic. A country becomes usable by calibrating it, which produces a separate Python package like OG-ETH for Ethiopia or OG-ZAF for South Africa, each pinned to its own OG-Core version. MUIOGO is downstream of MUIO, the existing OSeMOSYS interface, so anything I write has to keep future upstream syncs mergeable. CLEWS already had a UI through that lineage. OG-Core had none, and that was my project.
Colour key for the rest of this post. the models, the software around them, a baseline run, a reform measured against one.
What I worked on
| PR | What it does |
|---|---|
| #492 | The MUIOGO shell. Model selector, per-model menus, the OG calibration home |
| #495 | Install, update, add and remove a country calibration, with a live install log |
| #522 | Cases, parameters and run management |
| #525 | The results workspace |
Taking one policy question end to end shows what those four add up to. Say the question is what raising Ethiopia’s effective corporate tax rate does to the economy. Installing the OG-ETH calibration brings the country’s own estimated defaults. A baseline comes first, a run of the economy as calibrated with nothing changed. Then a reform on top of it, changing one parameter, adjustment_factor_for_cit_receipts, the factor that lifts the statutory corporate rate to the effective rate actually collected. Both runs solve, and the results page reports the reform against the baseline in steady state:
| Steady state | Reform against baseline |
|---|---|
| GDP | -1.05% |
| Consumption | -1.46% |
| Investment | -2.09% |
| Labour | +0.38% |
| Tax revenue | +5.36% |
| Business tax revenue | +48.7% |
| Real interest rate | -0.05 percentage points |
So the reform collects meaningfully more revenue and shrinks the capital stock doing it, and the consumption Gini barely moves. That trade-off, in those units, is the output the whole interface exists to produce.
Adding an OG-Core mode to the MUIOGO interface (#492)
MUIOGO could only show CLEWS, so before an OG-Core page could exist the app needed to hold two models at once.
- A two-button model selector in the header. Switching swaps the sidebar and the working area together.
- CLEWS mode is the existing interface, untouched and still on its own green accent.
- OG mode uses orange and opens a grid of country calibration cards, read live from the installer register.
- New styling is isolated in a new
muiogo.css, and OG markup sits under a.ogc-pageroot, so MUIOGO still merges cleanly with MUIO. - Country flags are vendored SVGs rather than CDN requests, since this tool gets used where the internet isn’t a given.
Installing an OG-Core country calibration from the interface (#495)
Each calibration is a separate package with its own environment, so setting one up previously meant cloning a repository and building a virtualenv by hand.
- Install a calibration from the catalogue, with the install log streaming while it runs.
- Add a calibration that isn’t in the catalogue, from either a local folder or a Git URL.
- A background update check, so an “update available” badge appears where upstream has moved ahead.
- Remove a calibration, which de-registers it inside MUIOGO and leaves the files on disk.
- Verified against the real backend rather than mocks. Ethiopia and South Africa from the catalogue, OG-USA from a Git URL, each producing an environment whose own Python imports the package.
Creating baselines and reforms, and running the model (#522)
This is the modelling workflow and the core of the project.
- Create, edit, duplicate and delete baselines and reforms.
- A parameter editor built on Tabulator. Each parameter shows its OG-Core name, its allowed range and the year it applies from, layered over the calibration’s own defaults.
- A run queue with live worker logs, cancellation and run history.
- Progress reports the stage and the iteration count rather than a percentage, because OG-Core doesn’t expose one.
- A reform whose baseline has no results can’t be run, and the row says why instead of failing part way through.
The live log is the model’s own output, streamed through to the browser:
1 | making dir: C:\Users\Aviral\.muiogo\og-state\cases\Baseline 1\res\New reform\SS |
Those GE loop errors are the general equilibrium residuals shrinking towards the solver’s tolerance, which is the honest version of a progress bar.
Comparing a baseline against a reform (#525)
A finished run leaves a folder of result files on disk, one directory per run.
1 | cases/<country_id>/<casename>/ |
- Select a baseline run and a reform run, and the page computes the percentage change between them for GDP, consumption, labour, investment and the tax aggregates, plus inequality measures.
- Charts on Apache ECharts, written as a model-neutral renderer instead of an OG-only one.
- Analysis tables with SVG and CSV export.
- ECharts replaced two commercial charting libraries the old viewer depended on, which I’d raised as an issue early in the summer.
Issues I raised along the way: #490, #491, #494, #500, #501, #521, #524 and #528.
How it fits together
Every OG-Core page reaches the backend through one wrapper under the /ogc prefix, and every route answers in the same shape, so the frontend has exactly one success check to write:
1 | { "message": "Case Baseline 1 created.", "status_code": "created" } |
A solve doesn’t run inside Flask. Each installed country gets its own virtual environment, and the worker process starts with that interpreter, so the model code never gets imported into the web app. That matters because two calibrations can pin different OG-Core versions. File ownership is split the same way. MUIOGO owns the run metadata and the log, the worker owns the status file and the results, and a run only counts as finished when the worker exits cleanly.
The workflow
Every completed run stores a fingerprint of its inputs, so changing a parameter invalidates that run’s results, and rerunning a baseline invalidates every reform sitting on top of it. The bottom lane of the diagram is where that gets enforced. Working out that these were real constraints and not details I could skip took me a while.
What’s left to do
The full project is four deliverables. A cross-platform baseline, OG-Core on its own, coupled one-way runs where one model’s output feeds the other, and a converging workflow that iterates both until the answers stop moving. My summer was the second one.
Coupled mode is the next piece of UI work. A coupled run means running CLEWS first, turning what the energy and land and water system did into the fiscal inputs OG-Core understands, then running OG-Core on top. Then the other direction. The hard part isn’t the running, it’s the translation, because the two models have different output shapes, different units and different time resolution. So the set of bridge variables has to be agreed first. After that it needs a guided run rather than one button, with the exchanged values shown at each handoff so an analyst can check them, and a combined view of the physical and fiscal side of the same scenario.
Then converging, which is the same thing in a loop until the numbers settle. The design problem there is showing distance to tolerance per iteration, so a stuck or oscillating run is obvious early enough to cancel it. Packaging the app into a downloadable installer per platform is also still ahead.
Thanks
One of our weekly calls.
Thanks to Alfonso and Marcelo for reviewing carefully, and to Aditya for the backend I spent four months calling. My favourite part was that this wasn’t a demo. The models get used by economists in developing countries to test real fiscal and climate policy, and the work carries on past GSoC through UN DESA’s country programmes.