Skip to content

April 11: Sharpening, Progress, and Time

Three compositing UX wins — unsharp masking is now exposed in the pipeline, the Auto preset quietly runs a gentle sharpen, and the process step shows elapsed time as stages progress. Plus the usual Friday-night dependabot wave.

Developer Journal

Expose unsharp masking in the composite pipeline (#1129)

Issue #683 had been sitting with "we should have unsharp masking" for months. The classic astrophoto move — subtract a blurred version of the image from itself to sharpen local contrast without amplifying noise in the flat regions.

Implementation is straightforward once the pipeline has clean stages from the April 9 refactor: between post-stack stretch and gamma encode, apply unsharp masking with configurable radius and amount. Exposed unsharp_radius (px, default 0 = disabled) and unsharp_amount (float, default 0.5) on the composite request. Bounded both to sane ranges — radius ≤ 50px, amount ≤ 3.0 — so a user can't accidentally ask for a 200px blur on a 4k image and wait five minutes.

Added tests with synthetic gradient inputs that lock in the expected edge response.

Auto preset runs a gentle sharpen (#1130)

With unsharp masking exposed, the Auto preset can use it. Set the Auto preset to unsharp_radius=2, unsharp_amount=0.3 — just enough to recover the subtle edge definition that asinh tends to smear, not so much that it introduces visible ringing on compact sources.

Spent some time tuning this on Cartwheel and Pillars. Anything above 0.4 amount started to produce visible halos around bright point sources; anything below 0.2 was indistinguishable from unsharpened. 0.3 + radius 2 landed where the gain was obvious without being obtrusive.

Elapsed-time progression in ProcessStep (#1133)

The composite ProcessStep UI was showing the current stage name but not how long the job had been running. For a 5-minute multi-instrument composite, users had no feedback on whether "blending" had been running for 30 seconds or 3 minutes.

Added elapsed time to each stage as it ticks past. Uses the SignalR progress update timestamps, so the display updates in real time without the client needing to poll a separate endpoint. Also kept a short list of completed stages' durations so after the job finishes, the user can see "reproject: 12s, blend: 186s, encode: 4s" and has some intuition for what's expensive.

Dependabot Friday

Ten bumps in the overnight drop — uvicorn, cachetools update requirement, ruff, @vitest/coverage-v8, pytest, prettier, pillow, @rolldown/binding-linux-x64-gnu, AWSSDK.S3. Nothing load-bearing in any of the changelogs, all green.

What shipped

PR Title
#1133 feat: elapsed-time stage progression in composite ProcessStep
#1130 fix: enable gentle sharpening in the Auto composite preset
#1129 feat: expose unsharp masking in composite pipeline (#683)
#1126 Bump AWSSDK.S3 from 4.0.20.3 to 4.0.21.1
#1125 chore(deps): Bump @rolldown/binding-linux-x64-gnu
#1124 chore(deps): Bump pillow from 12.1.1 to 12.2.0 in /processing-engine
#1123 chore(deps-dev): Bump prettier in /frontend/jwst-frontend
#1122 chore(deps): Bump pytest from 9.0.2 to 9.0.3 in /processing-engine
#1121 chore(deps-dev): Bump @vitest/coverage-v8 in /frontend/jwst-frontend
#1120 chore(deps): Bump ruff from 0.15.9 to 0.15.10 in /processing-engine
#1119 chore(deps): Update cachetools requirement in /processing-engine
#1118 chore(deps): Bump uvicorn from 0.43.0 to 0.44.0 in /processing-engine