You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expose Makefile animation parameters in makeMovie (#218)
Add framerate, magick_density, magick_resize_x, and magick_resize_y
keyword arguments so users can override the PhysiCell Makefile's
FRAMERATE, MAGICK_DENSITY, MAGICK_RESIZE_X, and MAGICK_RESIZE_Y
variables when generating a movie, instead of being stuck with
whatever the Makefile hardcodes.
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: PRD.md
+23Lines changed: 23 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -294,6 +294,29 @@
294
294
295
295
---
296
296
297
+
## Feature: Movie Generation
298
+
299
+
**One-line description:** Render a simulation's SVG snapshots into a movie via the PhysiCell Makefile's `jpeg`/`movie` targets.
300
+
301
+
**Priority:** Should-have
302
+
303
+
**Behavioral specification:**
304
+
-`makeMovie(simulation_id)` invokes `make jpeg` then `make movie` in `physicellDir()`, deletes the intermediate JPEGs, and leaves `out.mp4` in the simulation's output folder.
305
+
-`makeMovie(T::AbstractTrial)` / `makeMovie(out::PCMMOutput)` batch this over every simulation in the trial/output.
306
+
- Keyword arguments `framerate`, `magick_density`, `magick_resize_x`, `magick_resize_y` forward directly to the Makefile's `FRAMERATE`, `MAGICK_DENSITY`, `MAGICK_RESIZE_X`, `MAGICK_RESIZE_Y` variables (`movie`/`jpeg` targets respectively). Each defaults to `missing`, in which case the Makefile's own default for that variable is used unchanged.
307
+
-`magick_path`/`ffmpeg_path` locate the ImageMagick/FFmpeg executables; `verbose` prints the underlying `make` command output.
308
+
309
+
**Acceptance criteria:**
310
+
- Omitting the new framerate/density/resize keywords reproduces the exact previous behavior (Makefile defaults).
311
+
- Passing any of the four keywords changes the corresponding `make` invocation's variable assignment and is reflected in the produced movie.
312
+
- Re-running `makeMovie` when `out.mp4` already exists is a no-op (`false` return), regardless of these keywords.
313
+
314
+
**Edge cases:**
315
+
- No `s*.svg` files in the output folder → warn and skip (`false` return), independent of these keywords.
316
+
- ImageMagick or FFmpeg not discoverable on `PATH` → throws `ErrorException`.
317
+
318
+
---
319
+
297
320
## Feature: Post-Processing Hook & Quantities of Interest
298
321
299
322
**One-line description:** Let users compute per-simulation quantities of interest (QoIs) from intact output via a `post_processor` callback, and guarantee that PCMM's destructive pruning runs only after that callback.
Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -90,6 +90,7 @@ julia> out = run(inputs, dv; n_replicates = 3) # 3 replicates per apoptosis rate
90
90
-[x] Ready-made PhysiCell QoI builder (`populationCountQoI`) so a `post_processor` can be a one-liner — per-cell-type counts at the final snapshot or any indexed save
91
91
-[x] Intracellular model support (custom data, rules)
92
92
-[x] IC cell and IC ECM file management
93
+
-[x] Movie generation via the PhysiCell Makefile (`makeMovie`) — configurable `framerate`, `magick_density`, `magick_resize_x`/`magick_resize_y` keyword arguments
Copy file name to clipboardExpand all lines: docs/src/man/analyzing_output.md
+23Lines changed: 23 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -236,6 +236,29 @@ agent_ids = DataFrame(ID=[a.id for a in connected_components_1]) # get the IDs f
236
236
component_df =rightjoin(cells_df, agent_ids, on=:ID) # join on the agent IDs, keeping only the rows in the connected component
237
237
```
238
238
239
+
## Movies
240
+
241
+
[`makeMovie`](@ref) uses the PhysiCell Makefile to turn a simulation's SVG snapshots into `output/out.mp4`, deleting the intermediate JPEGs afterward. It requires ImageMagick and FFmpeg to be discoverable — on `PATH`, via `PCMM_IMAGEMAGICK_PATH`/`PCMM_FFMPEG_PATH`, or passed directly as `magick_path`/`ffmpeg_path`.
242
+
243
+
```julia
244
+
makeMovie(1) # simulation 1 -> output/out.mp4
245
+
makeMovie(sampling) # every simulation in a trial
246
+
makeMovie(out) # every simulation in a `run` result
247
+
```
248
+
249
+
The Makefile's own animation variables are exposed as keyword arguments. Omit any of them to keep that Makefile's default:
Everything above analyzes output *after* a run finishes. `run` also accepts a `post_processor` keyword: a callback invoked once per successful simulation, right after it finishes and before PhysiCellModelManager.jl prunes any output — so the callback always sees the intact output folder, however aggressive your `prune_options` are.
Use `makeMovie` to render a simulation's SVG snapshots into `out.mp4` via the PhysiCell Makefile. Override `framerate`, `magick_density`, `magick_resize_x`, or `magick_resize_y` to change frame rate or JPEG resolution/density; omit any to keep the Makefile's default. → [Analyzing output](@ref)
`makeMovie` (`src/movie.jl`) only ever forwarded `OUTPUT=` to the PhysiCell Makefile's `jpeg`/`movie` targets, even though that Makefile also reads `FRAMERATE`, `MAGICK_DENSITY`, `MAGICK_RESIZE_X`, `MAGICK_RESIZE_Y` (defaults 24 fps / 96 dpi / 1024×1024). Users had no way to control frame rate or JPEG resolution/density from Julia.
12
+
13
+
### Design
14
+
- Added four new keyword arguments to `makeMovie(simulation_id::Int; ...)`, each `Union{Missing,Int}=missing`, mirroring the existing `magick_path`/`ffmpeg_path` sentinel pattern already in this function rather than inventing a new convention.
15
+
- Each is only appended as a `"VAR=value"` string to the relevant `Cmd` when not `missing` — an unset keyword falls through to whatever the target project's own Makefile defines for that variable, rather than PCMM silently overriding a user's project-level Makefile customization.
16
+
-`framerate` targets the `movie` command; `magick_density`, `magick_resize_x`, `magick_resize_y` target the `jpeg` command (matches which Makefile target actually reads which variable).
17
+
-`makeMovie(T::AbstractTrial; kwargs...)` / `makeMovie(T::PCMMOutput; kwargs...)` needed no changes — they already forward `kwargs...` untouched.
18
+
19
+
### Testing
20
+
Extended `test/test-scripts/MovieTests.jl` with a case passing non-default values for all four new keywords and confirming `out.mp4` is still produced; existing no-kwargs path is unchanged and still covered.
21
+
22
+
### Docs
23
+
-`docs/src/lib/movie.md` needed no edit — it's an `@autodocs` page over `movie.jl`, so the updated docstring flows through automatically.
24
+
- Added a "Movies" section to `docs/src/man/analyzing_output.md` (before "Post-processing during a run") documenting `makeMovie` and a table mapping each new keyword to its Makefile variable and default.
25
+
- Added a matching recipe to the `examples.md` cookbook, linking back to that new section, following the existing task → minimal code → link pattern.
26
+
27
+
---
28
+
8
29
## 2026-07-08 — Task B: `populationCountQoI`, a ready-made `post_processor` builder
Copy file name to clipboardExpand all lines: src/movie.jl
+18-3Lines changed: 18 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -26,6 +26,10 @@ There are three ways to allow this function to find these dependencies:
26
26
- `magick_path::Union{Missing,String}`: The path to the ImageMagick executable. If not provided, uses `simulator().path_to_magick`.
27
27
- `ffmpeg_path::Union{Missing,String}`: The path to the FFmpeg executable. If not provided, uses `simulator().path_to_ffmpeg`.
28
28
- `verbose::Bool`: If `true`, prints the output of the commands used to generate the movie. Default is `false`.
29
+
- `framerate::Union{Missing,Int}`: Frames per second, forwarded to the Makefile's `FRAMERATE` variable. If not provided, uses the Makefile's own default.
30
+
- `magick_density::Union{Missing,Int}`: JPEG rendering density (dpi), forwarded to the Makefile's `MAGICK_DENSITY` variable. If not provided, uses the Makefile's own default.
31
+
- `magick_resize_x::Union{Missing,Int}`: JPEG resize width, forwarded to the Makefile's `MAGICK_RESIZE_X` variable. If not provided, uses the Makefile's own default.
32
+
- `magick_resize_y::Union{Missing,Int}`: JPEG resize height, forwarded to the Makefile's `MAGICK_RESIZE_Y` variable. If not provided, uses the Makefile's own default.
29
33
30
34
# Example
31
35
```julia
@@ -38,8 +42,12 @@ makeMovie(sampling) # make movies for all simulations in the sampling
38
42
out = run(sampling) # run the sampling
39
43
makeMovie(out) # make movies for all simulations in the output
0 commit comments