Interactive cockpit to inspect, measure and grade a set of subframes, and pick the best ones for stacking. [more]
Categories: DeepSkyColors, ImageInspection
Keywords: subframe selection, blink, culling, grading, FWHM, eccentricity, PSF signal weight, SNR, star count, star detection, weighting, SSWEIGHT, sessions, image inspection, quality metrics.
[hide]
[hide]
Welcome to SubframeStudio: a PixInsight process module for the job every deep-sky project starts with, deciding which subframes are worth keeping. It loads a set of frames, measures the per-frame quality metrics that matter (FWHM, eccentricity, PSF signal weight, star count, SNR, noise and more), and then lets us blink, plot, threshold, group and weight them so we can separate the keepers from the frames dragged down by wind, clouds, poor focus or tracking.
The idea is to bring the two halves of frame selection into a single, interactive surface: the visual side, where we flip through frames and see the differences with our own eyes, and the measured side, where numbers and thresholds do the sorting objectively. We can lean on either as much as we like, and a manual decision always wins over an automatic one.
SubframeStudio is an interface-only tool. It is not applied to a view and it is not run globally: we open the cockpit, load our frames into it, work through them, and export the approved set (optionally with a per-frame weight) for stacking. Our whole session, including the loaded frames, their metrics, the thresholds and the grades, can be saved to a session file and reopened later exactly where we left off.
[hide]
The only official distribution of SubframeStudio is via a PixInsight repository. This is the safest way to install a module or script, as the installation is handled by PixInsight itself, which will fetch the module directly and safely from our PixInsight repository at:
https://repo.deepskycolors.com/SubframeStudio/
Make sure the trailing / is part of the URL. Also, be sure to keep our repository URL in your list of PixInsight repositories to receive timely updates.
By distributing SubframeStudio only via our PixInsight repository, installation comes with the guarantee of our Developer and Repository certificates, verified by PixInsight itself from the moment it connects to our repository, until it validates and completes installation of the SubframeStudio module.
If we ever want to be sure that we have the latest version available to us, we go to PixInsight's RESOURCES menu, select Updates, then Manage Repositories to make sure our repository is still there, then RESOURCES > Updates > Check for Updates.
SubframeStudio does not operate on a target view, so there is nothing to select first. We just open the cockpit and load frames into it:
As soon as the frames are added, SubframeStudio begins loading and measuring them in the background, on several threads at once, so previews appear quickly and the metrics fill in as each frame is measured. Measured frames are cached, so re-loading the same files later is close to instant.
SubframeStudio runs on a trial-then-registered licensing model. During the trial period, the tool is fully functional with no feature restrictions. When the trial expires, SubframeStudio will display a notice at startup and will not open until a valid registration key is entered (see 3.8 Preferences and licensing). No internet connection is needed: keys are validated offline.
[hide]
The cockpit is organized top to bottom into: an action toolbar, a plot / grouping / weighting control strip, a live preview with its transport bar, the metric plot, the approval criteria panel, and the filmstrip navigator. A status line at the very bottom reports the running tally of kept, rejected and flagged frames. The following subsections walk through each area.
The toolbar along the top holds the file, grade, reference and session actions, grouped under small labels. Every button carries an icon and a caption.
Files.
Grade.
Reference.
Session.
.cull session file. The last file we used is remembered, so a later Save re-targets it..cull session file: it re-opens the listed images and restores their metrics, grades and thresholds.rejected/ subfolder) and write a measurements.csv alongside them. Non-destructive: the originals are untouched.SSWEIGHT FITS keyword set to each frame's weight, ready for weighted stacking in ImageIntegration. For a fully configurable export (custom folder, prefix, postfix, keyword name and error policy) use the Advanced window's Output panel instead (see 4.5 Output).The preview shows the current frame, stretched with a single locked screen stretch that is computed once and held constant across the whole set, so brightness does not jump as we flip through frames and differences read honestly. A small heads-up overlay reports the file name, the frame's FWHM, eccentricity, star count and PSF weight, and the image dimensions.
We zoom with the mouse wheel or the transport zoom buttons, pan by dragging with the left button, and fit the frame to the window with the Fit button. A double-click anywhere in the preview is a shortcut for Add, so an empty cockpit is one double-click away from loading files.
The transport bar under the preview drives navigation and the blink animation:
The control strip above the plot, framed and titled, selects what the plot shows and how frames are grouped and weighted.
The plot draws one dot per frame for the selected metric, in frame order (or by time). Its header names the metric and reminds us which way is worse, since the reject direction is fixed by the metric: FWHM, eccentricity, noise, median and star residual reject above the line (bigger is worse), while PSF weight, star count and SNR reject below it (bigger is better).
When the current metric has a threshold, a horizontal line marks it and the rejected side is shaded. We drag the line to set the threshold live: frames on the reject side flip grade immediately, and the criteria panel, the filmstrip and the status tally all follow. A small grab handle sits in the left margin, clear of the axis numbers, so we can pick the line up without fighting the labels.
Selecting the Approval criteria item in the Plot selector switches the plot to a pass-count view: instead of a single metric it shows how many of the enabled criteria each frame passes, which is a fast way to see how close the borderline frames are to the cut.
The Approval criteria panel, in its own titled frame below the plot, is where the automatic grading is defined. A Mode selector chooses which engine decides keep versus reject, and a running keep count shows how many frames survive. Whichever mode is active, a frame we have graded by hand keeps our decision.
In the Score and Sigma-clip modes the plot's Approval criteria view shows a draggable cutoff line as well, so the boundary can be nudged by hand and read back as a value.
The filmstrip along the bottom is a scrolling strip of thumbnails with a colored grade ribbon beneath them. Each thumbnail shows its frame's FWHM, and the ribbon paints a green bar for an approved frame and a red bar for a rejected one, so the balance of the whole set is visible at a glance even for hundreds of frames. The current frame is boxed, and the frames currently shown in the thumbnail window are bracketed on the ribbon so we always know where we are.
Frames that tripped an anomaly detector carry a small orange flag marker on the strip, and their reason (focus, tracking, cloud or dropped) is summarized in the status line. The flags are advisory: they call our attention to a frame but never reject it on their own. Which detectors are active is set in Preferences (see below).
With the cockpit focused, a few keys speed up the review:
| Left | Select the previous frame |
| Right | Select the next frame |
| Space | Approve / reject the current frame |
The Left and Right keys stop the blink animation if it is running, so we can pause on a frame and step through by hand.
The Preferences button (the wrench icon on the process interface bar) opens the SubframeStudio preferences dialog.
Anomaly flags. A group of checkboxes turns each advisory detector on or off: Focus (frames whose FWHM is well above the set), Tracking (an eccentricity spike), Cloud (high background or a low star count), and Dropped ((near-)empty frames). The flags are statistical and relative to the loaded set, so if a detector is firing on frames that look fine to us, we can simply turn it off here.
Metrics cache. A Clear cache button deletes the stored per-frame measurements (the source images are untouched; frames are simply re-measured the next time they are loaded).
LocalNormalization data. An optional fallback folder (with Browse...) for the .xnml files that PSFScale and PSFScaleSNR read (see 4.3 Expressions). Leave it blank to look only next to each subframe, which covers the common case.
License information. A License information... button opens the license dialog, which reports the current state:
When the module is not yet licensed, the dialog offers a link to register. Clicking it opens the registration dialog, where we enter our email and license key; the fields are validated as we type, and the Register button enables only once a valid email and key pair is present. After a successful registration the info dialog refreshes in place to the licensed state, with no need to reopen it.
[hide]
The Advanced... button on the plot control strip opens a companion window with the power-user surface: a full measurements table, a distribution histogram, and a tabbed panel holding the expression editors, the star-detection settings and the output options. It is a separate, always-available window that reads and drives the same one model as the cockpit, so a change made in either place is reflected immediately in the other. Its header shows the live count of frames and how many are approved.
The Advanced window:
As we interact with the Measurements table, Distribution histogram and the Expressions, the main window updates all pertinent information, image, etc.
The measurements table lists every loaded frame, one row per frame, with all of its metrics side by side. The columns are: a frame number, an App column (a green check for approved, a red cross for rejected), a Man column (a padlock when a manual grade is locking the frame), the File name, the export Weight, and then the metric columns: FWHM, FWHMs (the frame's FWHM in standard deviations from the set), Ecc, SNR, Median, Noise, Stars, Resid (the PSF goodness-of-fit residual) and PSFwt (the PSF signal weight). Cells fill in live as the background loader measures each frame.
A toolbar above the table controls sorting and per-row actions:
Clicking a row selects that frame in the cockpit; double-clicking a row toggles its grade.
The distribution panel is a histogram of one metric over the measured frames, with its own metric selector that is independent of the cockpit plot. Each bar is split into a green (kept) and a red (rejected) portion, and a thin curve traces the cumulative distribution, so we can see both the shape of the metric across the set and where the current cut falls. When the chosen metric has a threshold, a vertical line marks it and the rejected side is shaded; dragging the line moves the very same threshold the cockpit plot and criteria panel use.
The Expressions tab holds two independent editors, side by side, for driving the grade and the weight with our own formulas. The expressions are written in JavaScript and are 100% compatible with SubframeSelector: an approval or weighting expression written for SubframeSelector runs here unchanged, with the same variable names and the same syntax.
FWHM < 3.5 && Eccentricity < 0.55.PSFSignalWeight * SNRWeight.Each editor shows a live validity indicator as we type (a syntax error or an unknown variable is reported), but typing never changes anything on its own: a change is applied only when we press that editor's Apply button, which sets the cockpit's approval mode to Expression (or its weighting preset to Custom). A variable inserter below the editors composes a variable and drops it at the cursor of whichever editor we last clicked in: pick a property from the Variable list, pick value, Min, Max, Median or Sigma from the Statistic list, then press Insert.
For the full set, the Variable Finder... button opens a separate, non-modal window with every variable organized into a searchable, grouped tree (star shape, signal and noise, flux, position, and so on). Type in its filter box to narrow the list, then double-click a name to insert it, again into whichever editor last had focus. The Variable Finder can stay open alongside the Advanced window while we build an expression.
Available variables. Every measurement is exposed as a per-frame value plus four set-wide statistics, named <Property>Min, <Property>Max, <Property>Median and <Property>Sigma (the last is the frame's deviation from the set median, in mean-deviation units). So FWHM, FWHMMin, FWHMMax, FWHMMedian and FWHMSigma are all available, which lets us write set-relative rules such as FWHM < FWHMMedian or FWHMSigma < 2. The measurement properties are:
| Stars, FWHM, Eccentricity | star count, median FWHM, median eccentricity |
| FWHMMeanDev, EccentricityMeanDev, StarResidualMeanDev | the dispersion of those values across the frame's stars |
| StarResidual | PSF goodness-of-fit residual |
| PSFSignalWeight (alias PSFSignal), PSFSNR | PSF signal weight and PSF signal-to-noise ratio |
| SNRWeight (alias SNR) | noise-scaling signal-to-noise weight |
| PSFFlux, PSFFluxPower, PSFTotalMeanFlux, PSFTotalMeanPowerFlux, PSFCount | PSF flux estimates and the count of PSF-fitted stars |
| Median, MedianMeanDev | image median and its mean deviation |
| MStar, NStar, Noise | robust background and noise estimates |
| Altitude, Azimuth | read from the OBJCTALT / OBJCTAZ keywords when present |
| Weight | the frame's current export weight |
| Index | the frame index (this one has no statistics) |
FWHM units. Exactly like SubframeSelector, FWHM (and its statistics) is reported in the unit chosen in the Star detection tab: pixels, or arcseconds when an image scale is set. Storage and grading are unaffected; only the value the expression sees follows the unit.
PSFScale and PSFScaleSNR. These read the relative scale factor from a LocalNormalization .xnml file, exactly as SubframeSelector does: SubframeStudio does not compute local normalization itself, it only reads an existing .xnml. For each subframe it looks for <subframe-basename>.xnml next to the subframe file (LocalNormalization's own default output location), and, if not found there, in an optional fallback folder set in Preferences (see 3.8 Preferences and licensing). A subframe with no matching .xnml found leaves both at zero, the same as any other measurement with nothing to measure.
Not available. NoiseRatio evaluates to zero in this version: an expression that references it still runs, it just always sees zero.
The Star detection tab exposes the detector and PSF-fit settings that drive every measurement. The defaults reproduce a robust general-purpose configuration, but undersampled, noisy or wide-field data can measure better with a tuned detector. The controls are:
Edits here are staged: nothing is recomputed until we press a button, so several knobs can be dialed at once. Apply & re-measure commits the settings and re-measures the whole set (frames already measured under identical settings re-use the cache, so it is instant when nothing changed). Preview on current frame commits the settings without a full re-measure and opens the current frame in a new image window with the detected stars marked, for quick visual tuning. Reset defaults restores the default settings and re-measures.
A final row controls how FWHM is reported: Report FWHM in Pixels or Arcseconds, with an Image scale field in arcseconds per pixel. This is a display choice only, applied live: switching to arcseconds shows FWHM as pixels times the image scale everywhere it appears (the table, the plots, the readouts and the FWHM threshold), while the values stored internally, and therefore the grading, stay in pixels.
The Output tab is the fully configurable version of the toolbar's Weights export. It writes a copy of every approved frame with each frame's weight embedded in a FITS keyword, using options we set here:
_a).SSWEIGHT by default); leave it blank to write the image without a weight keyword.Two action buttons finish the panel: Output approved runs the export with the options above, and Star-detection preview re-runs the detector on the current frame and opens a new image window with the detected stars marked (the same preview available from the Star detection tab).
[hide]
Open SubframeStudio and Add the night's subframes. Let the background loader measure them; the previews and the plot fill in as it works.
If the session mixes filters or exposures, set Group so we grade each group on its own terms.
Blink the frames with Play to catch the obvious failures (trailing, wind shake, passing cloud), and glance at the filmstrip flags for the frames SubframeStudio thought were anomalous.
Pick an Approval criteria mode. For a quick pass, drag the FWHM (and maybe eccentricity) threshold on the plot until the keep count looks right. For a fixed keep fraction, use Score / keep best; to clip statistical outliers, use Sigma-clip; for a bespoke rule, write an Expression in the Advanced window.
Fine-tune by hand: step through with the arrow keys and toggle any frame with Space (or a double-click in the filmstrip or the table). Manual grades stick, so the automatic criteria will not undo them. Use Toggle lock in the table to pin a decision explicitly.
Open the Advanced window to read exact numbers in the table, check a metric's Distribution, and, if the default measurements look off for this data, tune the Star detection settings and re-measure.
Choose a Weight preset (or a Custom weighting expression) so the approved frames carry a sensible weight.
Export: use the toolbar's Weights, or the Advanced Output panel for full control, to write the approved frames with their SSWEIGHT for weighted integration. Save session if we want to revisit the exact selection later.
[hide]
Let the eye and the numbers agree. Blink first to catch gross failures the metrics might not rank obviously, then let the thresholds do the bulk sorting. The two together are stronger than either alone.
Drag thresholds, watch the keep count. The fastest way to a cut is to grab a threshold on the plot and watch the keep count and the filmstrip ribbon respond, rather than typing values blind.
Group before grading mixed sessions. FWHM and star counts are not comparable across filters or exposure times; set Group to Filter or Exposure so each group is judged on its own distribution.
Report FWHM in arcseconds to compare nights. Set the image scale and switch the unit to arcseconds so seeing reads in the same units from session to session; grading is unaffected because it stays in pixels internally.
Tune star detection for unusual data. If FWHM or star counts look wrong on undersampled, very noisy or wide-field frames, adjust the detector in the Advanced window and use Preview on current frame to check the detected stars before committing a re-measure.
Treat the flags as hints, not verdicts. Anomaly flags are relative to the loaded set; on a very consistent night they may fire on perfectly good frames. Turn off the detectors you do not want in Preferences.
Manual grades always win. A frame graded by hand keeps our decision through any threshold change; use Toggle lock in the table when we want that decision to be explicit and obvious.
Save the session. A .cull session stores the frames, metrics, thresholds and grades, so we can reopen the exact selection later or hand it off without re-measuring.
Copyright © 2026 Deep Sky Colors. All Rights Reserved.