Skip to content

Commit be34c47

Browse files
Shravan's GSoC 2025 Report
1 parent aa4bd7a commit be34c47

File tree

3 files changed

+363
-0
lines changed

3 files changed

+363
-0
lines changed
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
---
2+
title: "Introducing DoodleBUGS: a Browser-Based Graphical Interface for JuliaBUGS"
3+
description: "Shravan Goswami's GSoC 2025 final report: goals, architecture, progress vs proposal, and how to try it."
4+
categories:
5+
- GSoC
6+
author:
7+
- name: Shravan Goswami
8+
url: https://shravangoswami.com/
9+
date: 2025-08-28
10+
aliases:
11+
- /news/doodlebugs-gsoc-2025-final-report
12+
- /news/doodlebugs-gsoc-2025
13+
- /news/doodlebugs-introduction
14+
- /news/shravan-gsoc-2025-doodlebugs
15+
- /doodlebugs-gsoc-2025-final-report
16+
- /doodlebugs-gsoc-2025
17+
- /doodlebugs-introduction
18+
- /shravan-gsoc-2025-doodlebugs
19+
bibliography: references.bib
20+
csl: university-of-york-ieee.csl
21+
link-citations: true
22+
nocite: |
23+
@*
24+
---
25+
26+
## TL;DR
27+
28+
- DoodleBUGS is a browser-based graphical editor for Bayesian models that targets JuliaBUGS for BUGS model compilation and connects to Julia inference backends (e.g., AdvancedHMC via AbstractMCMC).
29+
- Implemented: visual editor (nodes, edges, nested plates), legacy BUGS code generation that compiles with [JuliaBUGS](https://github.com/TuringLang/JuliaBUGS.jl) [@JuliaBUGS; @bugs-book], local execution via a Julia backend, unified standalone script generation (frontend), timeouts, multiple layouts, and extensive cleanup/typing.
30+
- Changed from proposal: frontend implemented in Vue 3 (instead of React); backend simplified (frontend is the single source of truth for standalone scripts).
31+
- Status: Working application. Live demo (static UI) available; for running inference locally, use the backend server.
32+
33+
## Project Links
34+
35+
- Repo: [https://github.com/TuringLang/JuliaBUGS.jl](https://github.com/TuringLang/JuliaBUGS.jl)
36+
- Live demo: [https://turinglang.org/JuliaBUGS.jl/DoodleBUGS/](https://turinglang.org/JuliaBUGS.jl/DoodleBUGS/)
37+
38+
## DoodleBUGS Project Structure
39+
40+
- `DoodleBUGS/` — Vite + Vue 3 app (UI editor)
41+
- `public/` — static assets served by Vite; example projects under `public/examples/`
42+
- `experiments/` — prototypes and exploratory work
43+
- `runtime/` — Julia HTTP backend for local runs (API endpoints and Julia dependencies)
44+
- `src/` — application source
45+
- `assets/` — styles and static assets
46+
- `components/` — Vue components composing the UI
47+
- `canvas/` — graph canvas and toolbars
48+
- `common/` — shared UI primitives
49+
- `layouts/` — app layout and modals
50+
- `left-sidebar/` — palette, project manager, execution settings
51+
- `panels/` — code preview and data input panels
52+
- `right-sidebar/` — execution, JSON editor, node properties
53+
- `ui/` — base UI elements (buttons, inputs, selects)
54+
- `composables/` — reusable logic (code generation, drag & drop, graph instance, validator, grid snapping)
55+
- `config/` — configuration and node definitions
56+
- `stores/` — Pinia state stores (graph, data, execution, project, UI)
57+
- `types/` — TypeScript types and ambient declarations
58+
- `tmp/` — local temporary outputs (ignored in builds)
59+
- `ztest/` — scratch/test artifacts
60+
61+
## Motivation
62+
63+
[JuliaBUGS](https://github.com/TuringLang/JuliaBUGS.jl) is a modern Julia implementation of the BUGS language [@bugs-rjournal; @bugs-book; @bugs-project]. DoodleBUGS revives the original visual modeling concept with a modern stack so users can:
64+
65+
- Construct probabilistic graphical models visually (nodes, edges, plates).
66+
- Export readable legacy BUGS code that compiles with JuliaBUGS [@bugs-rjournal; @bugs-book].
67+
- Run inference and inspect results from the UI. Common BUGS applications include parallel MCMC [@multibugs], survival analysis [@bugs-survival], and Gibbs-style samplers [@albert-chib-1993; @informs-gibbs].
68+
69+
## What Was Built
70+
71+
- Visual editor
72+
- Node types: stochastic, observed, deterministic
73+
- Plates with arbitrary nesting; robust drag-in/out and creation inside plates
74+
- Graph layouts: [WebCola](https://ialab.it.monash.edu/webcola/) and [ELK/KLay](https://www.eclipse.org/elk/); stable drag interactions
75+
- Legacy BUGS code generation [@bugs-rjournal; @bugs-book]
76+
- Topological ordering and plate-aware traversal
77+
- Parameter formatting and safe index expansion
78+
- Implemented in `DoodleBUGS/src/composables/useBugsCodeGenerator.ts`
79+
- Execution flow
80+
- Frontend sends `model_code`, `data`, `inits`, `settings` to backend
81+
- Backend compiles/samples and returns summaries and quantiles
82+
- Frontend unifies standalone script generation; backend no longer attaches duplicates
83+
- Timeouts/resilience
84+
- Configurable timeout (frontend); enforced in backend worker
85+
- Safe temp directory cleanup on Windows with retries
86+
- Cleanup/typing
87+
- TypeScript fixes in `DoodleBUGS/src/components/right-sidebar/ExecutionPanel.vue`
88+
- Removal of unused backend code; consistent naming and logs
89+
90+
## Architecture Overview
91+
92+
- Frontend: [Vue 3](https://vuejs.org/), [Pinia](https://pinia.vuejs.org/), [Cytoscape.js](https://js.cytoscape.org/) [@cytoscapejs], [CodeMirror](https://codemirror.net/)
93+
- Code generation: `DoodleBUGS/src/composables/useBugsCodeGenerator.ts`
94+
- Execution panel: `DoodleBUGS/src/components/right-sidebar/ExecutionPanel.vue`
95+
- Backend (Julia) HTTP server
96+
- Server: `DoodleBUGS/runtime/server.jl`
97+
- Project deps: `DoodleBUGS/runtime/Project.toml` (HTTP, JSON3, JuliaBUGS, AbstractMCMC, AdvancedHMC, ReverseDiff, MCMCChains, DataFrames, StatsBase, Statistics)
98+
- Endpoints: GET `/api/health`; POST `/api/run` and `/api/run_model`
99+
- Execution: creates temp dir, writes `model.bugs` and `payload.json`, generates `run_script.jl`, enforces optional timeout
100+
101+
## Design Principles and Architecture
102+
103+
**Design principles**
104+
105+
- Visual-first modeling with deterministic export to legacy BUGS [@bugs-rjournal; @bugs-book].
106+
- Separation of concerns: editing (graph), generation (BUGS), execution (backend), and results (summary/quantiles) are modular.
107+
- Deterministic ordering: topological sort + plate-aware traversal ensures readable, stable code output.
108+
- Robustness: cancellable frontend fetch, backend-enforced timeout, and resilient temp cleanup on Windows (`safe_rmdir()`).
109+
110+
**Frontend architecture (Vue 3 + Cytoscape.js)**
111+
112+
- Core graph state is managed in Vue; Cytoscape.js handles layout, hit-testing, and interaction semantics (including compound nodes for plates) [@cytoscapejs].
113+
- Code generation lives in `DoodleBUGS/src/composables/useBugsCodeGenerator.ts` and maps `GraphNode`/`GraphEdge` to BUGS:
114+
- Kahn topological sort for definition order
115+
- Plate-aware recursion for `for (...) { ... }` blocks
116+
- Parameter canonicalization (indices, numeric/expr passthrough)
117+
- Standalone Julia script generation uses `generateStandaloneScript()` in the same composable, mirroring backend execution.
118+
119+
**Backend architecture (Julia)**
120+
121+
- `run_model_handler()` in `DoodleBUGS/runtime/server.jl` materializes `model.bugs`, `payload.json`, and a transient `run_script.jl` that:
122+
- Builds `NamedTuple`s from JSON or string-literal data/inits
123+
- Compiles via `JuliaBUGS.@bugs`, wraps with `ADgradient(:ReverseDiff)` [@ReverseDiff]
124+
- Samples with `AdvancedHMC.NUTS` through `AbstractMCMC` (Threads or Serial) [@AdvancedHMC; @AbstractMCMC; @HoffmanGelman2014]
125+
- Emits summaries (`MCMCChains`, `DataFrames`) and quantiles to JSON
126+
[@MCMCChains; @DataFrames]
127+
- Timeout: worker process is killed if exceeding `timeout_s`.
128+
- Cleanup: `safe_rmdir()` retries with GC to avoid EBUSY on Windows.
129+
130+
## Why Vue (not React)
131+
132+
The proposal planned React; we chose Vue 3 after evaluating the graph layer and developer velocity for this app.
133+
134+
- Tried Konva (canvas) for custom graph editing: powerful drawing primitives, but required bespoke graph semantics (hit testing, edge routing, compound nodes) that Cytoscape.js provides out of the box.
135+
- Tried D3 force/layouts: flexible, but compound nodes (plates), nesting, and drag constraints became a significant amount of custom code to maintain.
136+
- Cytoscape.js offered:
137+
- Native graph model with compound nodes (great for plates)
138+
- Integrated layouts (WebCola, KLay) and rich interaction APIs [@webcola; @elk]
139+
- Mature ecosystem and performance characteristics for medium-sized graphs
140+
- Vue 3 (vs React) for this project:
141+
- Composition API made integrating an imperative graph library (Cytoscape) straightforward via composables and lifecycle hooks
142+
- SFC ergonomics and Pinia stores enabled quick iteration with strong TypeScript support
143+
- Template reactivity + refs reduced reconciliation overhead when bridging to Cytoscape’s imperative API
144+
- Minimal glue code for state management (Pinia) vs setting up reducers/selectors; enabled rapid iteration
145+
- Vite + Vue tooling yielded fast HMR for UI-heavy iterations
146+
- Design inspirations: draw.io for interaction affordances; Stan Playground for model/run UX [@drawio; @stan-playground].
147+
148+
## Comparison to Legacy DoodleBUGS
149+
150+
The legacy tool was a desktop application driving WinBUGS [@winbugs]; the new DoodleBUGS is a browser-based editor targeting JuliaBUGS [@JuliaBUGS]. Key differences:
151+
152+
- Platform and backend
153+
- Legacy: Desktop UI, WinBUGS execution pipeline
154+
- New: Web UI, Julia backend via `JuliaBUGS.@bugs`, sampling with `AdvancedHMC.NUTS` through `AbstractMCMC`
155+
- Graph engine and plates
156+
- Legacy: Bespoke graph handling with limited nesting semantics
157+
- New: Cytoscape.js with compound nodes for robust nested plates; custom DnD for drag-in/out and creating inside plates
158+
- Layouts and interactions
159+
- Legacy: Limited auto-layout support
160+
- New: Multiple layout engines (Cola, Klay) and stable interactions; positions updated after `layoutstop` [@webcola; @elk]
161+
- Code generation
162+
- Legacy: Export to BUGS without strong ordering guarantees
163+
- New: Deterministic topological + plate-aware traversal; parameter canonicalization and safe index expansion
164+
- Execution and tooling
165+
- Legacy: WinBUGS-managed runs
166+
- New: Lightweight Julia HTTP backend, configurable timeouts, resilient temp cleanup, JSON summaries via `MCMCChains`
167+
- DevX and maintainability
168+
- New: Vue 3 + TypeScript + Pinia; unified standalone script generation on the frontend; leaner backend responses
169+
170+
## Progress vs Proposal
171+
172+
- Implemented
173+
- Visual editor with nested plates and robust DnD
174+
- BUGS code generator (topological + plate-aware)
175+
- Local execution + summaries/quantiles
176+
- Unified standalone script generation (frontend)
177+
- Timeouts/resilience
178+
- Multiple layouts and interactions
179+
- Extensive cleanup/typing
180+
- Execution timeout (end-to-end)
181+
- Layout options (Cola, Klay) and interactions
182+
- Cleanup and stronger typing
183+
- Changed
184+
- Vue 3 instead of React
185+
- Backend responses smaller; no standalone script attachment
186+
- Deferred/Partial
187+
- Rich diagnostics (R-hat, ESS, PPC, trace/density plots)
188+
- WebKit/Safari support
189+
- UX polish for large graphs
190+
191+
## How to Run Locally
192+
193+
Frontend (Vite):
194+
195+
```bash
196+
# from repo root
197+
cd DoodleBUGS
198+
npm install
199+
npm run dev
200+
```
201+
202+
Backend (Julia):
203+
204+
```bash
205+
# from repo root
206+
julia --project=DoodleBUGS/runtime DoodleBUGS/runtime/server.jl
207+
# server listens on http://localhost:8081
208+
```
209+
210+
Notes:
211+
212+
- CORS is enabled in the backend so the dev UI can call `http://localhost:8081`.
213+
- Live demo (static UI): https://turinglang.org/JuliaBUGS.jl/DoodleBUGS/
214+
215+
## API Summary
216+
217+
- GET `/api/health``{ "status": "ok" }`
218+
- POST `/api/run` (alias: `/api/run_model`)
219+
- Body: `model_code`, `data`/`data_string`, `inits`/`inits_string`, `settings` `{ n_samples, n_adapts, n_chains, seed, timeout_s }`
220+
- Response: `{ success, summary, quantiles, logs, files[] }`
221+
222+
See `DoodleBUGS/runtime/server.jl`.
223+
224+
## Current Limitations
225+
226+
- WebKit/Safari/iOS: unsupported at this time (see `DoodleBUGS/README.md`).
227+
- Limited visualization beyond summary/quantiles.
228+
- No persisted projects; session-based.
229+
230+
## Future Work
231+
232+
- Diagnostics/visualization: R-hat, ESS, trace plots, PPC, posterior densities
233+
- UX: richer node templates, validation, distribution hints
234+
- Persistence/sharing: save/load and shareable links
235+
- Browser compatibility: WebKit/Safari and iOS/iPadOS
236+
- Performance: virtualization for large graphs
237+
238+
## Acknowledgements
239+
240+
Much appreciation goes to my mentors Xianda Sun and Hong Ge. The work is impossible without your help and support.
241+
242+
- Mentor: Xianda Sun ([\@sunxd3](https://github.com/sunxd3))
243+
- Advisor: Hong Ge ([\@yebai](https://github.com/yebai))
244+
- TuringLang/JuliaBUGS community and contributors
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
@misc{bugs-rjournal,
2+
title = {The BUGS Language},
3+
url = {https://journal.r-project.org/articles/RN-2006-005/RN-2006-005.pdf},
4+
note = {R Journal/News article}
5+
}
6+
7+
@misc{bugs-book,
8+
title = {The BUGS Book: A Practical Introduction to Bayesian Analysis},
9+
url = {https://onlinelibrary.wiley.com/doi/10.1111/anzs.12058},
10+
publisher = {Wiley}
11+
}
12+
13+
@misc{bugs-project,
14+
title = {The BUGS Project},
15+
url = {https://www.mrc-bsu.cam.ac.uk/software/bugs/}
16+
}
17+
18+
@misc{multibugs,
19+
title = {MultiBUGS: Parallel BUGS Modeling},
20+
url = {https://pmc.ncbi.nlm.nih.gov/articles/PMC7116196/}
21+
}
22+
23+
@misc{bugs-survival,
24+
title = {Bayesian survival analysis with BUGS},
25+
url = {https://onlinelibrary.wiley.com/doi/10.1002/sim.8933}
26+
}
27+
28+
@misc{albert-chib-1993,
29+
title = {Inference via Gibbs (Albert \& Chib)},
30+
url = {https://apps.olin.wustl.edu/faculty/chib/papers/albertchibjb93.pdf}
31+
}
32+
33+
@misc{informs-gibbs,
34+
title = {Bayesian Inference Using Gibbs Sampling},
35+
url = {https://pubsonline.informs.org/doi/10.1287/ited.2013.0120}
36+
}
37+
38+
@article{HoffmanGelman2014,
39+
title = {The No-U-Turn Sampler: Adaptively Setting Path Lengths in Hamiltonian Monte Carlo},
40+
author = {Hoffman, Matthew D. and Gelman, Andrew},
41+
year = {2014},
42+
url = {https://arxiv.org/abs/1111.4246},
43+
journal = {arXiv preprint arXiv:1111.4246}
44+
}
45+
46+
@misc{AbstractMCMC,
47+
title = {AbstractMCMC.jl},
48+
url = {https://github.com/TuringLang/AbstractMCMC.jl}
49+
}
50+
51+
@misc{AdvancedHMC,
52+
title = {AdvancedHMC.jl},
53+
url = {https://github.com/TuringLang/AdvancedHMC.jl}
54+
}
55+
56+
@misc{ReverseDiff,
57+
title = {ReverseDiff.jl},
58+
url = {https://github.com/JuliaDiff/ReverseDiff.jl}
59+
}
60+
61+
@misc{MCMCChains,
62+
title = {MCMCChains.jl},
63+
url = {https://github.com/TuringLang/MCMCChains.jl}
64+
}
65+
66+
@misc{DataFrames,
67+
title = {DataFrames.jl},
68+
url = {https://dataframes.juliadata.org/}
69+
}
70+
71+
@misc{cytoscapejs,
72+
title = {Cytoscape.js},
73+
url = {https://js.cytoscape.org/}
74+
}
75+
76+
@misc{webcola,
77+
title = {WebCola},
78+
url = {https://ialab.it.monash.edu/webcola/}
79+
}
80+
81+
@misc{elk,
82+
title = {Eclipse Layout Kernel (ELK / KLay)},
83+
url = {https://www.eclipse.org/elk/}
84+
}
85+
86+
@misc{drawio,
87+
title = {draw.io (diagrams.net)},
88+
url = {https://www.diagrams.net/}
89+
}
90+
91+
@misc{stan-playground,
92+
title = {Stan Playground},
93+
url = {https://stan-playground.flatironinstitute.org/}
94+
}
95+
96+
@misc{winbugs,
97+
title = {WinBUGS},
98+
url = {http://www.openbugs.net/w/FrontPage}
99+
}
100+
101+
@misc{JuliaBUGS,
102+
title = {JuliaBUGS.jl},
103+
url = {https://github.com/TuringLang/JuliaBUGS.jl}
104+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<style xmlns="http://purl.org/net/xbiblio/csl" version="1.0" default-locale="en-GB">
3+
<!-- This style was edited with the Visual CSL Editor (http://editor.citationstyles.org/visualEditor/) -->
4+
<info>
5+
<title>University of York - IEEE</title>
6+
<id>http://www.zotero.org/styles/university-of-york-ieee</id>
7+
<link href="http://www.zotero.org/styles/university-of-york-ieee" rel="self"/>
8+
<link href="http://www.zotero.org/styles/ieee" rel="independent-parent"/>
9+
<link href="https://subjectguides.york.ac.uk/referencing-style-guides/ieee" rel="documentation"/>
10+
<category citation-format="numeric"/>
11+
<category field="engineering"/>
12+
<updated>2025-07-11T09:55:45+00:00</updated>
13+
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
14+
</info>
15+
</style>

0 commit comments

Comments
 (0)