Chapter 12Rev. 1.0.0

Reconstructing a volume from its X-ray projections

Here the unknown is the attenuation field itself. We use projection gradients to recover it, with regularisation to constrain what the available views leave uncertain.

The registration problem gave us a volume and asked where it was. Reconstruction takes away the volume. We keep the calibrated source and detector positions, supply several radiographs, and estimate the attenuation field that could have produced them. The forward calculation is familiar, but the unknown now has one coefficient per voxel, which rather changes the storage bill.

Chapter 4 defined the sampled field and Chapter 5 its discrete derivatives. We will use those operators directly, first with a primary monochromatic count model. Chapter 8’s spectral model then lets us ask a harder question: which material mixtures are consistent with energy-resolved measurements?

The scalar example implements fixed-geometry voxel reconstruction with a quadratic spatial penalty. The complete material workflow in §12.8 extends that calculation to an assigned water/bone field from CT-derived anatomy, with simulated spectral observations and independent recovery checks. Its assigned fractions are not measurements of patient composition.

12.1 Specify the unknown volume and measured projections

Let μRN\boldsymbol\mu\in\mathbb{R}^{N} contain nonnegative attenuation coefficients in mm1\mathrm{mm}^{-1}. They are the samples of the trilinearly interpolated field from Chapter 4. The grid shape is (nz,ny,nx)(n_z,n_y,n_x), x varies fastest in memory, and its origin is the first sample centre. Spacing is specified along the grid’s x, y and z axes. An orientation matrix places those axes in object coordinates, and a fixed object-to-world transform places the volume in the calibrated acquisition.

For view kk, write the predicted optical depths as

Lk=Akμ,λk=n0,kexp(Lk).\mathbf L_k=A_k\boldsymbol\mu, \qquad \boldsymbol\lambda_k=\mathbf n_{0,k}\odot\exp(-\mathbf L_k).
(12.1)

AkA_k includes ray intersections with the volume support, the chosen midpoint quadrature and interpolation weights. Its entries have units of millimetres. n0,k\mathbf n_{0,k} contains the calibrated expected open-beam counts, and λk\boldsymbol\lambda_k is the predicted mean count image. The observed integer counts are yk\mathbf y_k. Conditioning on the supplied open-beam calibration treats its uncertainty as negligible. A noisy flat-field estimate would require another part of the statistical model.

This model assumes independent photon counts, primary transmission and a monochromatic beam or an effective-energy approximation justified for the acquisition. An energy-integrating detector’s processed pixel values do not become Poisson counts because we rename the file. Scatter, electronic noise and spectral hardening can all produce structured discrepancies that the optimiser will otherwise try to explain with incorrect attenuation.

The example requires an initial attenuation volume as supplied input, together with measured counts and open-beam means for every view. It neither interprets Hounsfield units nor derives an attenuation conversion from a material name. All source arrays carry units, checksums and provenance. Before using or redistributing acquired scans and independent reference volumes, document the rights governing those uses.

Figure 12.1 separates known geometry from unknown coefficients. A coefficient whose interpolation support misses every measured ray has a zero column in the combined projector. No choice of optimiser can make those measurements constrain it.

Four measured rays in a grid section

Sparse rays miss a full interpolation support A six-by-six node section has unit spacing. One source at (−4,2.5) illuminates endpoints (9,1.5) and (9,3.5). The other source at (2.5,9) illuminates (1.5,−4) and (3.5,−4). The highlighted support of the corner coefficient at (5,5) is the square [4,5.5] by [4,5.5]. No ray intersects it.Support of μⱼs₁s₂D₁D₂

Unit grid spacing. Hatching includes the corner basis’s half-cell boundary extension.

Fixed for every viewSource, detector, volume pose and discrete sampling rule
Unknownμ0\boldsymbol\mu\geq0

The ray operator maps coefficients to optical depth.

Lk=Akμ\mathbf L_k=A_k\boldsymbol\mu
For the highlighted coefficient j(Ak)pj=0(A_k)_{pj}=0

Its full basis support misses the rays, hence every quadrature sample on them.

A change in that coefficient is unobservedA(μ+tej)=AμA(\boldsymbol\mu+t\mathbf e_j)=A\boldsymbol\mu

For changes preserving nonnegativity, these measurements give no preference. Additional rays or a prior supply different information.

Figure 12.1From calibrated projections to an unknown volumeAll four schematic rays miss the highlighted corner support, leaving its coefficient unconstrained by these projections. That coefficient has a zero column in the combined discrete projector.

12.2 Derive the discrete volume gradient

For the fixed acquisition, AkA_k is linear in the voxel coefficients. The exponential that follows it is nonlinear. A detector-space objective k\ell_k supplies a cotangent sk=k/λk\mathbf s_k=\partial\ell_k/\partial\boldsymbol\lambda_k, giving

qk=λksk,μk=AkTqk.\mathbf q_k=-\boldsymbol\lambda_k\odot\mathbf s_k, \qquad \nabla_{\boldsymbol\mu}\ell_k=A_k^{\mathsf T}\mathbf q_k.
(12.2)

We use ordinary Euclidean inner products on the stored coefficient and detector vectors. Consequently, AkTA_k^{\mathsf T} is the matrix transpose of the implemented discrete map. A continuous backprojection formula, or the transpose of a different interpolation rule, need not give this derivative. If we instead defined volume and detector inner products through mass matrices MvM_v and MdM_d, their weighted adjoint would be Mv1AkTMdM_v^{-1}A_k^{\mathsf T}M_d. Those weights cannot be added twice, once in the objective and again as an unexplained voxel-volume factor.

Each reverse ray revisits its quadrature samples and scatters the seed through the same interpolation weights. Support clipping and the constant extension between the outer sample centres and half-cell faces remain the forward operator’s rules. Siddon’s radiological-path calculation is a useful reference for a different, cellwise-constant discretisation, but using its traversal does not make it the exact transpose of our sampled trilinear field. [1]

The implementation sets active_volume=True and active_pose=False. It clears the shared voxel gradient once, then accumulates each view’s contribution with projection_vjp. No system matrix or ray-by-sample tape is stored. The listing includes the count-space chain, so its seed differentiates the same objective and passes through the existing FP32 cotangent interfaces.

Accumulating the voxel gradient across viewspython/dpt/examples/reconstruction.pyL184–237
    def evaluate(self, volume: Any, volume_wp: Any, *, gradient: bool) -> float:
        """Evaluate every supplied view before an update; add the prior once."""
        if gradient:
            self.gradient.zero_()
        loss = 0.0
        for view in self.views:
            project_optical_depth(
                volume_wp,
                self.pose,
                workspace=view["projection"],
                out_L=view["depth"],
                stream=self.stream,
            )
            transmit(
                view["depth"],
                view["beam"],
                workspace=view["transmission"],
                out_counts=view["prediction"],
                stream=self.stream,
            )
            evaluate_objective(
                view["prediction"],
                view["observed"],
                workspace=view["objective"],
                out_loss=view["loss"],
                out_seed=view["image_seed"] if gradient else None,
                stream=self.stream,
            )
            if gradient:
                transmission_vjp(
                    view["depth"],
                    view["beam"],
                    seed_counts=view["image_seed"],
                    workspace=view["transmission"],
                    out_grad_L=view["depth_seed"],
                    stream=self.stream,
                )
                projection_vjp(
                    volume_wp,
                    self.pose,
                    adj_L=view["depth_seed"],
                    workspace=view["projection"],
                    out_mu=self.gradient_wp,
                    accumulate=True,
                    stream=self.stream,
                )
            loss += float(view["loss"].numpy()[0])
        loss += self.regularise(volume, gradient=gradient)
        if not math.isfinite(loss):
            raise NumericalError("The objective is non-finite; inspect counts and model range.")
        if gradient and not bool(self.torch.isfinite(self.gradient).all().item()):
            raise NumericalError("The volume gradient overflowed; discard this evaluation.")
        return loss

Figure 12.2 follows these quantities through both directions. Before accepting numerical results, test Au,v=u,ATv\langle A\mathbf u,\mathbf v\rangle=\langle\mathbf u,A^{\mathsf T}\mathbf v\rangle with independently chosen vectors and check the composed objective along volume perturbations. A reverse pass that merely returns finite numbers has met a rather modest ambition.

Forward · one calibrated view k

  1. Voxel coefficientsμ\boldsymbol\mu

    Unknown attenuation, with fixed grid and geometry.

  2. Optical depthLk=Akμ\mathbf L_k=A_k\boldsymbol\mu

    Ray quadrature and interpolation are inside Aₖ.

  3. Mean countsλk=n0,keLk\boldsymbol\lambda_k=\mathbf n_{0,k}\odot e^{-\mathbf L_k}

    The open-beam calibration is fixed.

  4. View lossk(λk;yk)\ell_k(\boldsymbol\lambda_k;\mathbf y_k)

    Compare with that view’s observed counts.

Reverse · from the loss to the volume

  1. Seed the scalar lossk=1\overline{\ell_k}=1

    One view’s contribution to the summed objective.

  2. Count seedsk=k/λk\mathbf s_k=\partial\ell_k/\partial\boldsymbol\lambda_k

    Differentiate the selected measurement objective.

  3. Optical-depth seedqk=λksk\mathbf q_k=-\boldsymbol\lambda_k\odot\mathbf s_k

    Pull the seed through the exponential.

  4. Volume contributiongk=AkTqk\mathbf g_k=A_k^{\mathsf T}\mathbf q_k

    Use the same discrete weights in reverse.

Sum the views, then add regularisation onceΦ=kAkTqk+βR\nabla\Phi=\sum_k A_k^{\mathsf T}\mathbf q_k+\beta\nabla R

Ordinary Euclidean inner products on stored arrays define the transpose. No extra voxel-volume factor belongs in this data term.

For the chapter’s Poisson half-deviance

For positive predicted means:

sk=1ykλk\mathbf s_k=\mathbf1-\mathbf y_k\oslash\boldsymbol\lambda_kqk=ykλk\mathbf q_k=\mathbf y_k-\boldsymbol\lambda_k
Count-seed arithmetic

The algebraic form of the optical-depth seed does not remove the count-seed interface’s numerical range limits.

Figure 12.2The reconstruction forward and adjoint operationsThe forward chain maps voxel coefficients to predicted counts, while the reverse chain sends loss gradients through the same discrete weights. Contributions from all views accumulate into a shared volume gradient.

12.3 Choose the likelihood and regularisation

For independent Poisson observations, the code minimises the half-deviance, which differs from the negative log-likelihood by an observation-only constant:

D(μ)=k,p[λkpykp+ykplog ⁣(ykpλkp)].D(\boldsymbol\mu) =\sum_{k,p}\left[ \lambda_{kp}-y_{kp} +y_{kp}\log\!\left(\frac{y_{kp}}{\lambda_{kp}}\right) \right].
(12.3)

For y=0y=0, the contribution is λ\lambda, and we never evaluate log0\log 0 as an intermediate observation term. For positive yy, the mean must be positive. The count derivative is 1y/λ1-y/\lambda, so the algebraically composed optical-depth derivative simplifies to yλy-\lambda. Thus

D=kAkT(ykλk),2D=kAkTdiag(λk)Ak.\nabla D=\sum_k A_k^{\mathsf T}(\mathbf y_k-\boldsymbol\lambda_k), \qquad \nabla^2 D=\sum_k A_k^{\mathsf T} \operatorname{diag}(\boldsymbol\lambda_k)A_k.
(12.4)

Under these fixed-geometry primary-count assumptions, the likelihood is convex in attenuation. That does not guarantee strict convexity or uniqueness. A null space survives wherever different coefficient fields have identical measured projections. Spectral mixing and joint geometry estimation will not generally retain this convenient structure.

The application composes the existing objective and transmission VJPs. They store count seeds in FP32, so an intermediate 1y/λ1-y/\lambda can exceed their range even when the simplified depth derivative is representable. Checked calls reject that evaluation. They also reject a mean rounded to zero beside a positive observation. The example does not silently floor it.

Any voxel change in the likelihood’s null space is invisible to the measurements. A spatial penalty states which possible fields we prefer. Here we favour smaller differences between neighbouring coefficients, using quadratic neighbouring-voxel regularisation:

Φ(μ)=D(μ)+βR(μ),R=ΔV2a{x,y,z}(i,j)Ea(μjμiha)2,μ0.\Phi(\boldsymbol\mu)=D(\boldsymbol\mu)+\beta R(\boldsymbol\mu), \qquad R=\frac{\Delta V}{2}\sum_{a\in\{x,y,z\}} \sum_{(i,j)\in\mathcal E_a} \left(\frac{\mu_j-\mu_i}{h_a}\right)^2, \qquad \boldsymbol\mu\geq0.
(12.5)

Ea\mathcal E_a contains each neighbouring pair along axis aa once, hah_a is that axis’s spacing and ΔV=hxhyhz\Delta V=h_xh_yh_z. Edges beyond the grid are omitted. This adds no boundary penalty against exterior zero, even though the projector’s field is zero outside its support. RR has units of mm1\mathrm{mm}^{-1}, so β\beta has units of millimetres when the count objective is dimensionless. Replacing millimetres with centimetres therefore changes the numerical regularisation coefficient as well as the grid metadata.

For one edge, the regulariser adds βΔV(μiμj)/ha2\beta\Delta V(\mu_i-\mu_j)/h_a^2 to voxel ii and its negative to voxel jj. The implementation uses FP64 differences and loss reductions, with FP32 updates to the stored volume gradient.

The spatial penalty and its voxel gradientpython/dpt/examples/reconstruction.pyL241–260
    def regularise(self, volume: Any, *, gradient: bool) -> float:
        """Quadratic physical-space differences; omit edges beyond the grid."""
        self.volume64.copy_(volume)
        penalty = 0.0
        for low, high, grad_low, grad_high, scratch, coefficient in self.edges:
            difference, derivative = scratch
            self.torch.sub(high, low, out=difference)
            if gradient:
                # Scale in FP64 before the FP32 accumulation boundary.
                difference.mul_(coefficient)
                derivative.copy_(difference)
                grad_low.sub_(derivative)
                grad_high.add_(derivative)
                # Restore unscaled differences for the objective.
                self.torch.sub(high, low, out=difference)
            difference.square_()
            self.torch.sum(difference, dim=(0, 1, 2), out=self.scalar)
            penalty += 0.5 * coefficient * float(self.scalar.item())
        return penalty

Quadratic smoothing penalises sharp genuine boundaries alongside noise. Total variation or a learned prior would change that bias and require a different solver or derivative. Here, nonnegativity is enforced by projection after an update. Unlike an exponential parameterisation, projection permits exact zero attenuation without driving a latent variable towards minus infinity.

The driver uses summed likelihood terms and all supplied pixels. Saturated or missing observations need an explicitly extended masking or censoring model before use, while zero observed counts are valid measurements. Choose β\beta and stopping rules on separate development data or a predefined protocol, keeping the final evaluation volume out of those choices.

12.4 Plan the GPU reconstruction iteration

The volume, trial volume, voxel gradient and update displacement remain on CUDA. Per-view observations, means and derivative buffers also stay there. Torch owns the voxel arrays, and Warp receives zero-copy views of their storage, and both frameworks use the same CUDA stream. Ownership lasts through the final stream synchronisation, including exception paths. The Warp interoperability documentation describes the array and stream conversions used here.

An iteration evaluates every supplied view at the accepted volume, adds regularisation once, and chooses a projected step. With g=Φ(μ)\mathbf g=\nabla\Phi(\boldsymbol\mu),

μα=max(0,μαg),dα=μαμ.\boldsymbol\mu_{\alpha}=\max(0,\boldsymbol\mu-\alpha\mathbf g), \qquad \mathbf d_{\alpha}=\boldsymbol\mu_{\alpha}-\boldsymbol\mu.
(12.6)

The line search accepts strict decrease satisfying Φ(μα)Φ(μ)+cgTdα\Phi(\boldsymbol\mu_\alpha)\leq\Phi(\boldsymbol\mu)+c\,\mathbf g^{\mathsf T}\mathbf d_\alpha, for configured 0<c<10<c<1. It reduces α\alpha geometrically when this condition fails. The gradient has units of millimetres, so α\alpha has units of mm2\mathrm{mm}^{-2}. The stopping quantity is dα0/α0\|\mathbf d_{\alpha_0}\|_\infty/\alpha_0 at a fixed configured reference step, measured in millimetres. A small objective change alone does not establish constrained stationarity.

Projected line search and the final prediction refreshpython/dpt/examples/reconstruction.pyL285–359
    def solve(
        self, callback: Callable[[int, dict[str, Any]], None] | None = None
    ) -> dict[str, Any]:
        """Solve with optional observation of accepted updates only.

        The callback receives the stable one-based accepted iteration and a
        detached history dictionary after ``mu`` has been updated. It may read
        or export the accepted fields but must not mutate solver state. Callback
        exceptions propagate with the last accepted volume intact.

        An optional fixed mapping step separates the stationarity diagnostic
        from the initial Armijo trial. Omitting it preserves the original
        diagnostic at ``initial_step_mm_inverse_squared``.
        """
        policy = self.policy
        mapping_step = (
            policy.initial_step_mm_inverse_squared
            if policy.mapping_step_mm_inverse_squared is None
            else policy.mapping_step_mm_inverse_squared
        )
        history: list[dict[str, Any]] = []
        reason = "iteration_budget"
        for iteration in range(policy.iterations):
            loss = self.evaluate(self.mu, self.mu_wp, gradient=True)
            step = policy.initial_step_mm_inverse_squared
            mapping, _ = self.displacement(mapping_step)
            if not math.isfinite(mapping):
                raise NumericalError("The trial update overflowed; reduce the initial step.")
            if mapping <= policy.gradient_mapping_tolerance_mm:
                reason = "projected_gradient_tolerance"
                break
            accepted = False
            for attempt in range(policy.maximum_backtracks):
                if step == 0:
                    break
                _, slope = self.displacement(step)
                if not math.isfinite(slope) or slope >= 0:
                    step *= policy.backtracking_factor
                    continue
                # Trial value evaluation leaves the accepted gradient unchanged.
                # Domain/range errors abort with the last accepted volume intact.
                trial_loss = self.evaluate(self.trial, self.trial_wp, gradient=False)
                if trial_loss < loss and trial_loss <= loss + policy.armijo * slope:
                    self.mu.copy_(self.trial)
                    history.append(
                        {
                            "iteration": iteration + 1,
                            "loss_before": loss,
                            "loss_after": trial_loss,
                            "step_mm_inverse_squared": step,
                            "backtracks": attempt,
                            "mapping_mm_before": mapping,
                        }
                    )
                    accepted = True
                    if callback is not None:
                        callback(iteration + 1, dict(history[-1]))
                    break
                step *= policy.backtracking_factor
            if not accepted:
                reason = "line_search_failed"
                break
        # Trial buffers may describe a rejected volume; refresh accepted outputs.
        final_loss = self.evaluate(self.mu, self.mu_wp, gradient=True)
        final_mapping, _ = self.displacement(mapping_step)
        if final_mapping <= policy.gradient_mapping_tolerance_mm:
            reason = "projected_gradient_tolerance"
        return {
            "termination": reason,
            "accepted_steps": len(history),
            "final_objective": final_loss,
            "final_gradient_mapping_mm": final_mapping,
            "history": history,
        }

Failed searches and iteration budgets are recorded separately from the projected-gradient criterion. Trial evaluations leave the accepted gradient intact. The final projection refresh matters: the most recently rendered trial may have been rejected.

The prepared volume workspace contains five FP32 arrays and two FP64 arrays, or 36N36N bytes before scalar buffers, plus six FP32 detector arrays per view and the canonical operator scratch. There is no optimiser history proportional to the iteration count. Torch finite checks and scalar reductions can allocate temporary storage. Checked operator calls synchronise, and Python receives scalar losses and line-search decisions.

All views are retained on device in this implementation. When all views do not fit, processing bounded groups requires accumulating the full gradient before each update. Updating after each group would instead change the optimisation schedule. Profiling must distinguish the projector’s memory access and FP32 atomic contention from the additional reduction and synchronisation costs. Atomic accumulation does not promise identical bits between runs, even though the objective contains no randomly sampled views.

12.5 Reconstruct with fewer or restricted views

Sparse angular sampling leaves gaps between otherwise broadly distributed views. Limited-angle acquisition restricts the directions themselves. Both can produce an apparently stable minimiser, but they constrain different structures poorly. Adding more views inside a narrow angular interval does not supply the missing directions outside it.

Direct optimisation of voxel fields is also used by DiffVox, which combines differentiable rendering with its own reconstruction formulation. This lets us study voxel reconstruction before introducing a neural field. [37] A flexible representation can express more possible volumes, but it cannot establish which unmeasured detail is correct.

Why the earlier sparse-versus-dense comparison needs matched stopping states

Figure 12.3 compares 144 broadly distributed views with 36 broad or 36 limited-angle views, holding the inverse grid and field of view fixed for each anatomy. The broad arrangements cover a full orbit, while the limited arrangement spans −60° to 60°. Three tilts are used in each arrangement. All three receive 28.8 million expected incident photons per detector pixel over the fitting acquisition: 200,000 per view in the dense case and 800,000 in the others. This fixes incident photon number without claiming equal absorbed dose. Another 24 whole views are reserved for evaluation, including nine inside the limited yaw interval and fifteen outside it.

For the monochromatic observations, the baseline is post-log penalised weighted least squares, using the same counts, geometry, starting field and physical penalty as Poisson reconstruction. Its fixed observed-count weights approximate the inverse log-data variance, and zero counts are excluded and reported. Both use the same projector, so this compares objectives rather than independently implemented forward models. The spectral comparison instead uses separately simulated three-channel observations. Its two methods differ in their projected optimisation step: one uses a fixed material metric and the other uses a Euclidean projection. The latter was prescribed for dense coverage only. Filtered backprojection cannot simply be transferred from parallel-beam to this cone-beam geometry without changing the algorithm.

The forty fits cover two anatomies and two noise replicates. Every fit reached its prescribed time limit with stationarity still unmet. The dense fits had 600 seconds each, and the sparse and limited fits had 300 seconds each. In all four matched anatomy/replicate pairs, the sparse material-metric fit has lower whole-box bone-fraction RMSE than its dense counterpart. It also completed 135–191 accepted updates against 70 for the dense fits. These records show the interaction between acquisition and the cost of an iteration. They cannot isolate the effect of angular sampling or rank converged solutions. The figure retains every outcome and uses the same physical planes and display windows throughout.

The retained checkpoints show why the stopping point matters. At 50 accepted updates, the case-2 dense fits have slightly lower bone-fraction RMSE than the sparse fits, about 0.106 against 0.109; sparse overtakes them by the unequal final stopping points. Case 0 already slightly favours sparse at 50 updates. Optimisation progress therefore contributes to the recorded comparison, but does not explain every difference. Matching updates would still leave different acquisitions and objective geometries, so it would not by itself rank converged reconstructions either.

Scalar Poisson

An attenuation field from separately simulated monochromatic 80 keV counts.

Scalar attenuation at 80 keV · Axial (z = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, axial (z = 0 mm)

Broad dense

Scalar Poisson, Broad dense, scalar attenuation at 80 kev, axial (z = 0 mm)

144 views · 47 accepted updates

Broad sparse

Scalar Poisson, Broad sparse, scalar attenuation at 80 kev, axial (z = 0 mm)

36 views · 92 accepted updates

Limited angle

Scalar Poisson, Limited angle, scalar attenuation at 80 kev, axial (z = 0 mm)

36 views · 92 accepted updates

Axial (z = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_poisson, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_poisson, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_poisson, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Scalar attenuation at 80 keV · Coronal (y = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, coronal (y = 0 mm)

Broad dense

Scalar Poisson, Broad dense, scalar attenuation at 80 kev, coronal (y = 0 mm)

144 views · 47 accepted updates

Broad sparse

Scalar Poisson, Broad sparse, scalar attenuation at 80 kev, coronal (y = 0 mm)

36 views · 92 accepted updates

Limited angle

Scalar Poisson, Limited angle, scalar attenuation at 80 kev, coronal (y = 0 mm)

36 views · 92 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_poisson, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_poisson, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_poisson, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 2 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Scalar attenuation at 80 keV · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Broad dense

Scalar Poisson, Broad dense, scalar attenuation at 80 kev, sagittal (x = 0 mm)

144 views · 47 accepted updates

Broad sparse

Scalar Poisson, Broad sparse, scalar attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 92 accepted updates

Limited angle

Scalar Poisson, Limited angle, scalar attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 92 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_poisson, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_poisson, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_poisson, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 1 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

First whole withheld view · 80 keV monochromatic channel

Simulated observation

First whole withheld scalar observation, negative log of count over known open beam

Broad dense: prediction

case2_dense_r0_scalar_poisson, first whole withheld prediction, negative log over known open beam

Broad sparse: prediction

case2_sparse_r0_scalar_poisson, first whole withheld prediction, negative log over known open beam

Limited angle: prediction

case2_limited_r0_scalar_poisson, first whole withheld prediction, negative log over known open beam

Common negative-log window 0 to 8. This entire view was withheld from every fit.

Withheld-view residuals and display clipping

Broad dense: observation − prediction

case2_dense_r0_scalar_poisson, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

548 pixels below the residual window and 371 above.

Prediction display: 0 below and 0 above.

Broad sparse: observation − prediction

case2_sparse_r0_scalar_poisson, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

295 pixels below the residual window and 329 above.

Prediction display: 0 below and 0 above.

Limited angle: observation − prediction

case2_limited_r0_scalar_poisson, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

193 pixels below the residual window and 184 above.

Prediction display: 0 below and 0 above.

Observation display: 2098 pixels below the window and 0 above.

The residual divides observation minus prediction by the square root of the predicted count. Its scale is fixed before evaluation.

Acquisition angles and stopping conditions

Broad dense

-15°15°−180°Yaw 0°180°

144 views × 200,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 609.19 s.

Broad sparse

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 302.89 s.

Limited angle

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 302.92 s.

Rows show tilt and dots show the recorded yaw angles. Equal incident photon population does not imply equal patient dose or equivalent scalar and spectral measurements.

Scalar log-WLS

An attenuation field from separately simulated monochromatic 80 keV counts.

Scalar attenuation at 80 keV · Axial (z = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, axial (z = 0 mm)

Broad dense

Scalar log-WLS, Broad dense, scalar attenuation at 80 kev, axial (z = 0 mm)

144 views · 60 accepted updates

Broad sparse

Scalar log-WLS, Broad sparse, scalar attenuation at 80 kev, axial (z = 0 mm)

36 views · 117 accepted updates

Limited angle

Scalar log-WLS, Limited angle, scalar attenuation at 80 kev, axial (z = 0 mm)

36 views · 117 accepted updates

Axial (z = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_pwls, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_pwls, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_pwls, scalar attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Scalar attenuation at 80 keV · Coronal (y = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, coronal (y = 0 mm)

Broad dense

Scalar log-WLS, Broad dense, scalar attenuation at 80 kev, coronal (y = 0 mm)

144 views · 60 accepted updates

Broad sparse

Scalar log-WLS, Broad sparse, scalar attenuation at 80 kev, coronal (y = 0 mm)

36 views · 117 accepted updates

Limited angle

Scalar log-WLS, Limited angle, scalar attenuation at 80 kev, coronal (y = 0 mm)

36 views · 117 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_pwls, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_pwls, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_pwls, scalar attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 2 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Scalar attenuation at 80 keV · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Broad dense

Scalar log-WLS, Broad dense, scalar attenuation at 80 kev, sagittal (x = 0 mm)

144 views · 60 accepted updates

Broad sparse

Scalar log-WLS, Broad sparse, scalar attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 117 accepted updates

Limited angle

Scalar log-WLS, Limited angle, scalar attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 117 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_scalar_pwls, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_scalar_pwls, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_scalar_pwls, scalar attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 1 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

First whole withheld view · 80 keV monochromatic channel

Simulated observation

First whole withheld scalar observation, negative log of count over known open beam

Broad dense: prediction

case2_dense_r0_scalar_pwls, first whole withheld prediction, negative log over known open beam

Broad sparse: prediction

case2_sparse_r0_scalar_pwls, first whole withheld prediction, negative log over known open beam

Limited angle: prediction

case2_limited_r0_scalar_pwls, first whole withheld prediction, negative log over known open beam

Common negative-log window 0 to 8. This entire view was withheld from every fit.

Withheld-view residuals and display clipping

Broad dense: observation − prediction

case2_dense_r0_scalar_pwls, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

457 pixels below the residual window and 305 above.

Prediction display: 0 below and 0 above.

Broad sparse: observation − prediction

case2_sparse_r0_scalar_pwls, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

264 pixels below the residual window and 307 above.

Prediction display: 0 below and 0 above.

Limited angle: observation − prediction

case2_limited_r0_scalar_pwls, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

166 pixels below the residual window and 152 above.

Prediction display: 0 below and 0 above.

Observation display: 2098 pixels below the window and 0 above.

The residual divides observation minus prediction by the square root of the predicted count. Its scale is fixed before evaluation.

Acquisition angles and stopping conditions

Broad dense

-15°15°−180°Yaw 0°180°

144 views × 200,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 602.86 s.

Broad sparse

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 300.28 s.

Limited angle

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 300.96 s.

Rows show tilt and dots show the recorded yaw angles. Equal incident photon population does not imply equal patient dose or equivalent scalar and spectral measurements.

Spectral fixed metric

Joint water and bone fractions from three spectral count channels.

Bone fraction · Axial (z = 0 mm)

Assigned reference

Assigned reference, bone fraction, axial (z = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, bone fraction, axial (z = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, bone fraction, axial (z = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, bone fraction, axial (z = 0 mm)

36 views · 135 accepted updates

Axial (z = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, bone fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, bone fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, bone fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 131 below and 16 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 17 below and 20 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 63 below and 45 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Bone fraction · Coronal (y = 0 mm)

Assigned reference

Assigned reference, bone fraction, coronal (y = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, bone fraction, coronal (y = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, bone fraction, coronal (y = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, bone fraction, coronal (y = 0 mm)

36 views · 135 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, bone fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, bone fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, bone fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 254 below and 40 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 44 below and 69 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 66 below and 102 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Bone fraction · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, bone fraction, sagittal (x = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, bone fraction, sagittal (x = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, bone fraction, sagittal (x = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, bone fraction, sagittal (x = 0 mm)

36 views · 135 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, bone fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, bone fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, bone fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 335 below and 87 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 104 below and 128 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 177 below and 205 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Axial (z = 0 mm)

Assigned reference

Assigned reference, water fraction, axial (z = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, water fraction, axial (z = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, water fraction, axial (z = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, water fraction, axial (z = 0 mm)

36 views · 135 accepted updates

Axial (z = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, water fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, water fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, water fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 16 below and 131 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 20 below and 17 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 45 below and 62 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Coronal (y = 0 mm)

Assigned reference

Assigned reference, water fraction, coronal (y = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, water fraction, coronal (y = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, water fraction, coronal (y = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, water fraction, coronal (y = 0 mm)

36 views · 135 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, water fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, water fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, water fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 41 below and 254 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 69 below and 44 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 102 below and 66 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, water fraction, sagittal (x = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, water fraction, sagittal (x = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, water fraction, sagittal (x = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, water fraction, sagittal (x = 0 mm)

36 views · 135 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, water fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, water fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, water fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 88 below and 334 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 128 below and 104 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 205 below and 177 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Axial (z = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, axial (z = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, derived attenuation at 80 kev, axial (z = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, derived attenuation at 80 kev, axial (z = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, derived attenuation at 80 kev, axial (z = 0 mm)

36 views · 135 accepted updates

Axial (z = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, derived attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, derived attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, derived attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 1 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Coronal (y = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, coronal (y = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, derived attenuation at 80 kev, coronal (y = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, derived attenuation at 80 kev, coronal (y = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, derived attenuation at 80 kev, coronal (y = 0 mm)

36 views · 135 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, derived attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, derived attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, derived attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 1 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, sagittal (x = 0 mm)

Broad dense

Spectral fixed metric, Broad dense, derived attenuation at 80 kev, sagittal (x = 0 mm)

144 views · 70 accepted updates

Broad sparse

Spectral fixed metric, Broad sparse, derived attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 135 accepted updates

Limited angle

Spectral fixed metric, Limited angle, derived attenuation at 80 kev, sagittal (x = 0 mm)

36 views · 135 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_metric, derived attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Broad sparse: recovered − reference

Recovered minus assigned reference, case2_sparse_r0_spectral_metric, derived attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Limited angle: recovered − reference

Recovered minus assigned reference, case2_limited_r0_spectral_metric, derived attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Broad sparse: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.
  • Limited angle: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

First whole withheld view · First disjoint spectral channel

Simulated observation

First whole withheld spectral observation, negative log of count over known open beam

Broad dense: prediction

case2_dense_r0_spectral_metric, first whole withheld prediction, negative log over known open beam

Broad sparse: prediction

case2_sparse_r0_spectral_metric, first whole withheld prediction, negative log over known open beam

Limited angle: prediction

case2_limited_r0_spectral_metric, first whole withheld prediction, negative log over known open beam

Common negative-log window 0 to 8. This entire view was withheld from every fit.

Withheld-view residuals and display clipping

Broad dense: observation − prediction

case2_dense_r0_spectral_metric, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

966 pixels below the residual window and 585 above.

Prediction display: 0 below and 0 above.

Broad sparse: observation − prediction

case2_sparse_r0_spectral_metric, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

361 pixels below the residual window and 433 above.

Prediction display: 0 below and 0 above.

Limited angle: observation − prediction

case2_limited_r0_spectral_metric, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

404 pixels below the residual window and 277 above.

Prediction display: 0 below and 0 above.

Observation display: 2128 pixels below the window and 0 above.

The residual divides observation minus prediction by the square root of the predicted count. Its scale is fixed before evaluation.

Acquisition angles and stopping conditions

Broad dense

-15°15°−180°Yaw 0°180°

144 views × 200,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 606.13 s.

Broad sparse

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 300.29 s.

Limited angle

-15°15°−180°Yaw 0°180°

36 views × 800,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 300.76 s.

Rows show tilt and dots show the recorded yaw angles. Equal incident photon population does not imply equal patient dose or equivalent scalar and spectral measurements.

Spectral Euclidean

Joint water and bone fractions from three spectral count channels. The Euclidean spectral baseline was prescribed for dense coverage only.

Bone fraction · Axial (z = 0 mm)

Assigned reference

Assigned reference, bone fraction, axial (z = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, bone fraction, axial (z = 0 mm)

144 views · 97 accepted updates

Axial (z = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, bone fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 213 below and 16 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Bone fraction · Coronal (y = 0 mm)

Assigned reference

Assigned reference, bone fraction, coronal (y = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, bone fraction, coronal (y = 0 mm)

144 views · 97 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, bone fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 323 below and 37 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Bone fraction · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, bone fraction, sagittal (x = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, bone fraction, sagittal (x = 0 mm)

144 views · 97 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, bone fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 527 below and 81 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Axial (z = 0 mm)

Assigned reference

Assigned reference, water fraction, axial (z = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, water fraction, axial (z = 0 mm)

144 views · 97 accepted updates

Axial (z = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, water fraction, axial (z = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 16 below and 213 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Coronal (y = 0 mm)

Assigned reference

Assigned reference, water fraction, coronal (y = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, water fraction, coronal (y = 0 mm)

144 views · 97 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, water fraction, coronal (y = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 41 below and 323 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Water fraction · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, water fraction, sagittal (x = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, water fraction, sagittal (x = 0 mm)

144 views · 97 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 1 fraction. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, water fraction, sagittal (x = 0 mm)

Blue -0.25 · pale 0 · red 0.25 fraction

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 90 below and 527 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Axial (z = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, axial (z = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, derived attenuation at 80 kev, axial (z = 0 mm)

144 views · 97 accepted updates

Axial (z = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, derived attenuation at 80 kev, axial (z = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Coronal (y = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, coronal (y = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, derived attenuation at 80 kev, coronal (y = 0 mm)

144 views · 97 accepted updates

Coronal (y = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, derived attenuation at 80 kev, coronal (y = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

Derived attenuation at 80 keV · Sagittal (x = 0 mm)

Assigned reference

Assigned reference, derived attenuation at 80 kev, sagittal (x = 0 mm)

Broad dense

Spectral Euclidean, Broad dense, derived attenuation at 80 kev, sagittal (x = 0 mm)

144 views · 97 accepted updates

Sagittal (x = 0 mm). Black → white: 0 to 0.05 mm⁻¹. Matched physical extent and display window.

Signed errors and display clipping

Broad dense: recovered − reference

Recovered minus assigned reference, case2_dense_r0_spectral_euclidean, derived attenuation at 80 kev, sagittal (x = 0 mm)

Blue -0.01 · pale 0 · red 0.01 mm⁻¹

Reference slice: 0 pixels below the window and 0 above.

  • Broad dense: recovered slice 0 below and 0 above. Signed error 0 below and 0 above.

Clipping affects displayed pixels. Numerical errors use the complete recorded fields.

First whole withheld view · First disjoint spectral channel

Simulated observation

First whole withheld spectral observation, negative log of count over known open beam

Broad dense: prediction

case2_dense_r0_spectral_euclidean, first whole withheld prediction, negative log over known open beam

Common negative-log window 0 to 8. This entire view was withheld from every fit.

Withheld-view residuals and display clipping

Broad dense: observation − prediction

case2_dense_r0_spectral_euclidean, first whole withheld observed minus predicted counts in predicted Poisson standard deviations

Blue -5 · pale 0 · red 5 predicted Poisson standard deviations.

1018 pixels below the residual window and 708 above.

Prediction display: 0 below and 0 above.

Observation display: 2128 pixels below the window and 0 above.

The residual divides observation minus prediction by the square root of the predicted count. Its scale is fixed before evaluation.

Acquisition angles and stopping conditions

Broad dense

-15°15°−180°Yaw 0°180°

144 views × 200,000 expected incident photons per detector pixel per view.

Time limit. Stationarity criterion unmet. Recorded solve: 607.63 s.

Rows show tilt and dots show the recorded yaw angles. Equal incident photon population does not imply equal patient dose or equivalent scalar and spectral measurements.

All 40 prescribed outcomes
Both CT-derived anatomies and both noise replicates. Fraction errors are dimensionless. Attenuation errors are in mm⁻¹, including separately derived 80 keV attenuation for spectral fits. Withheld deviance is per detector sample.
CaseReplicateCoverageMethodFit statusEvaluation statusAccepted updatesStopSolve (s)Water RMSEBone RMSE80 keV RMSE (mm⁻¹)Withheld devianceStationarityNumerical check
21denseScalar PoissonCompletedComplete47Time limit609.19UnavailableUnavailable0.00146810.160UnmetPassed
21denseScalar log-WLSCompletedComplete60Time limit602.86UnavailableUnavailable0.0013598.234UnmetPassed
21denseSpectral fixed metricCompletedComplete70Time limit606.130.09520.09440.00216410.942UnmetPassed
22denseScalar PoissonCompletedComplete47Time limit607.64UnavailableUnavailable0.00146810.162UnmetPassed
22denseScalar log-WLSCompletedComplete60Time limit603.99UnavailableUnavailable0.0013598.232UnmetPassed
22denseSpectral fixed metricCompletedComplete70Time limit605.790.09520.09440.00216310.946UnmetPassed
21sparseScalar PoissonCompletedComplete92Time limit302.89UnavailableUnavailable0.0017579.777UnmetPassed
21sparseScalar log-WLSCompletedComplete117Time limit300.28UnavailableUnavailable0.0017339.272UnmetPassed
21sparseSpectral fixed metricCompletedComplete135Time limit300.290.08640.08070.0019186.567UnmetPassed
22sparseScalar PoissonCompletedComplete92Time limit301.94UnavailableUnavailable0.0017579.780UnmetPassed
22sparseScalar log-WLSCompletedComplete117Time limit300.81UnavailableUnavailable0.0017329.274UnmetPassed
22sparseSpectral fixed metricCompletedComplete135Time limit300.380.08640.08070.0019186.563UnmetPassed
21limitedScalar PoissonCompletedComplete92Time limit302.92UnavailableUnavailable0.00181525.302UnmetPassed
21limitedScalar log-WLSCompletedComplete117Time limit300.96UnavailableUnavailable0.00177924.013UnmetPassed
21limitedSpectral fixed metricCompletedComplete135Time limit300.760.09640.09350.00216912.948UnmetPassed
22limitedScalar PoissonCompletedComplete91Time limit300.36UnavailableUnavailable0.00181725.398UnmetPassed
22limitedScalar log-WLSCompletedComplete117Time limit300.62UnavailableUnavailable0.00177924.030UnmetPassed
22limitedSpectral fixed metricCompletedComplete147Time limit302.350.09460.09160.00212912.415UnmetPassed
01denseScalar PoissonCompletedComplete52Time limit602.90UnavailableUnavailable0.0017298.494UnmetPassed
01denseScalar log-WLSCompletedComplete68Time limit605.27UnavailableUnavailable0.0016056.925UnmetPassed
01denseSpectral fixed metricCompletedComplete70Time limit604.300.12530.12380.00282212.007UnmetPassed
02denseScalar PoissonCompletedComplete47Time limit604.61UnavailableUnavailable0.0018159.572UnmetPassed
02denseScalar log-WLSCompletedComplete61Time limit609.02UnavailableUnavailable0.0017007.871UnmetPassed
02denseSpectral fixed metricCompletedComplete70Time limit606.060.12530.12380.00282211.993UnmetPassed
01sparseScalar PoissonCompletedComplete92Time limit300.72UnavailableUnavailable0.00204511.143UnmetPassed
01sparseScalar log-WLSCompletedComplete118Time limit300.28UnavailableUnavailable0.00199510.267UnmetPassed
01sparseSpectral fixed metricCompletedComplete136Time limit301.220.10850.10390.0024227.249UnmetPassed
02sparseScalar PoissonCompletedComplete92Time limit302.77UnavailableUnavailable0.00204511.111UnmetPassed
02sparseScalar log-WLSCompletedComplete140Time limit300.92UnavailableUnavailable0.0019509.549UnmetPassed
02sparseSpectral fixed metricCompletedComplete191Time limit300.990.10010.09480.0022295.674UnmetPassed
01limitedScalar PoissonCompletedComplete180Time limit300.62UnavailableUnavailable0.00182114.961UnmetPassed
01limitedScalar log-WLSCompletedComplete216Time limit300.16UnavailableUnavailable0.00179914.271UnmetPassed
01limitedSpectral fixed metricCompletedComplete189Time limit300.510.10450.09990.0023379.154UnmetPassed
02limitedScalar PoissonCompletedComplete179Time limit301.55UnavailableUnavailable0.00182214.965UnmetPassed
02limitedScalar log-WLSCompletedComplete215Time limit300.58UnavailableUnavailable0.00179914.269UnmetPassed
02limitedSpectral fixed metricCompletedComplete189Time limit300.050.10480.10030.0023469.220UnmetPassed
21denseSpectral EuclideanCompletedComplete97Time limit607.630.10480.10150.00230513.160UnmetPassed
22denseSpectral EuclideanCompletedComplete92Time limit600.460.10650.10320.00234614.022UnmetPassed
01denseSpectral EuclideanCompletedComplete73Time limit602.500.15560.14630.00331921.032UnmetPassed
02denseSpectral EuclideanCompletedComplete97Time limit605.140.14290.13300.00301315.032UnmetPassed

Download the complete numerical and display record

Recorded data and interpretation
  • Anatomy is acquired. Composition and primary-only observations are simulated.
  • Only the prescribed case 2, replicate 0 final accepted fields are displayed. All forty outcomes remain in the table.
  • Time, update and line-search limits do not establish stationarity or a global optimum.
  • Spectral attenuation is derived at 80 keV from the two fitted fractions and fixed physical coefficients.
  • Scalar and spectral observations use different physical models. Equal incident photon number is not equal patient dose.
  • Zero observed counts give positive-infinite optical depth and count above the display window. No pseudocount is added.
  • Physical zero slices interpolate only between adjacent stored planes. In-plane pixels, full box support and raw numerical metrics are unchanged.
  • Two paired noise replicates describe this comparison, not population uncertainty.

CC BY 3.0. Derived from Rister et al., CT-ORG, TCIA.

Figure 12.3Sparse views and limited angular coverageMatched slices and a withheld view compare dense, sparse and limited-angle fits for CT-ORG case 2’s first replicate at equal expected incident photon budgets. Errors and update counts reflect both angular sampling and iteration cost within the allotted runs.

12.6 Extend reconstruction to spectral material decomposition

A single attenuation field cannot explain how the same object changes appearance across distinct spectra. Represent attenuation instead as a combination of supplied energy-dependent basis curves. Alvarez and Macovski developed the energy-selective basis formulation. The inverse problem concerns basis coefficients, whose physical interpretation depends on the chosen model. [11]

The default material domain uses volume fractions fm(x)f_m(\mathbf x) of supplied reference materials, with fm0f_m\geq0 and mfm1\sum_m f_m\leq1. The supplied acquired-phantom reconstruction selects the explicit nonnegative domain instead. Its dimensionless PMMA- and Al-equivalent coefficients have no fraction-sum constraint, and the supplied attenuation curves carry their reference normalisation. Neither domain infers a mass density from the name of its output field. With linear reference attenuation am(E)a_m(E) in mm1\mathrm{mm}^{-1},

μ(x,E)=mfm(x)am(E),bkpm=(Akfm)p,λkpc=eskceexp ⁣[mam(Ee)bkpm].\mu(\mathbf x,E)=\sum_m f_m(\mathbf x)a_m(E), \qquad b_{kpm}=(A_k\mathbf f_m)_p, \qquad \lambda_{kpc}=\sum_e s_{kce} \exp\!\left[-\sum_m a_m(E_e)b_{kpm}\right].
(12.7)

The material paths bkpmb_{kpm} are in millimetres. For this count-channel model, skces_{kce} is the expected incident photon population integrated over energy bin ee, multiplied by the calibrated probability of detection in channel cc. Energy integration or quadrature weights are already absorbed into that population, so multiplying by a bin width again would count it twice. An energy-weighted signal requires different response units and generally a different noise model. Unassigned fraction means zero contribution from the represented attenuators. It is not an implicit, calibrated air material.

MaterialTable converts a supplied mass attenuation coefficient in cm2/g\mathrm{cm}^2/\mathrm g using its declared reference density in g/cm3\mathrm g/\mathrm{cm}^3, then divides by ten to obtain mm1\mathrm{mm}^{-1}. A table already in linear units has density included. Multiplying it by an unconstrained density again would change both its units and meaning. Mass-density basis reconstructions are possible, but they need a separate coefficient contract. Nor is a basis map automatically a tissue segmentation or a chemically unique composition.

The per-ray material sensitivity is

λkpcbkpm=eskceam(Ee)exp ⁣[jaj(Ee)bkpj].\frac{\partial\lambda_{kpc}}{\partial b_{kpm}} =-\sum_e s_{kce}a_m(E_e) \exp\!\left[-\sum_j a_j(E_e)b_{kpj}\right].
(12.8)

Locally stable first-order separation of unrestricted material paths requires sufficient rank in this sensitivity matrix. Having as many channels as materials is only a counting condition: nearly proportional columns still make their separation unstable. Inspect the noise-weighted singular values after declaring coefficient scales, across representative material thicknesses. Spectral hardening changes those sensitivities with the object itself. Independent Poisson channels give Fisher weights 1/λc1/\lambda_c, while detector effects that correlate channels require the appropriate likelihood instead. Alvarez’s analysis of noninvertibility gives a reason to examine the map beyond a favourable local derivative. [12]

Projection-domain decomposition first estimates material paths on corresponding rays, then reconstructs each field. Its convenience depends on genuinely corresponding acquisitions, and the intermediate estimates carry correlated, nonuniform uncertainty. Joint material-volume reconstruction instead composes the material projector and spectral adjoint directly, with the declared field constraints and spatial priors. The fraction example uses the simplex constraint. It can combine different view geometries, but remains dependent on their combined information. Priors may couple otherwise ambiguous coefficients: that is additional information assumed by the reconstruction.

Changing the unknown also changes the regulariser’s units. For dimensionless material coefficients, the physical-gradient construction in §12.3 has units of millimetres, so its multiplier has units mm1\mathrm{mm}^{-1}. For attenuation coefficients, that construction has units mm1\mathrm{mm}^{-1} and its multiplier has units of millimetres. Copying the monochromatic regularisation number into the material problem would quietly change what is being penalised.

The two material sensitivity columns can differ greatly in scale and be nearly proportional. A Euclidean step limited by the strongly constrained combination can then make slow progress along the weak combination. The material solver therefore permits a symmetric positive definite matrix HH in its projection. With a positive spatial factor DiD_i, the metric at voxel ii is Hi=DiHH_i=D_iH. It changes which feasible update we propose; the objective remains the summed Poisson half-deviance and the declared spatial penalty.

For the fraction problem, let C={uR2:u0, 1Tu1}\mathcal C=\{\mathbf u\in\mathbb R^2:\mathbf u\geq0,\ \mathbf1^{\mathsf T}\mathbf u\leq1\} and gi=fiΦ\mathbf g_i=\nabla_{\mathbf f_i}\Phi. The ordinary metric trial is

f~i=arg minuC{giT(ufi)+12α(ufi)THi(ufi)}=ΠCHi(fiαHi1gi),\widetilde{\mathbf f}_i =\operatorname*{arg\,min}_{\mathbf u\in\mathcal C} \left\{\mathbf g_i^{\mathsf T}(\mathbf u-\mathbf f_i) +\frac{1}{2\alpha}(\mathbf u-\mathbf f_i)^{\mathsf T}H_i(\mathbf u-\mathbf f_i)\right\} =\Pi_{\mathcal C}^{H_i}(\mathbf f_i-\alpha H_i^{-1}\mathbf g_i),
(12.9)

where ΠHi\Pi^{H_i} denotes projection in the HiH_i norm. For a fixed gradient and step, larger metric curvature reduces the unconstrained move in that direction; the projection enforces feasibility. The line search then decides whether to accept this trial.

Spatial scaling matters because rays through different material thicknesses carry different count sensitivity. At the accepted field, let jkpc\mathbf j_{kpc} be the two-component material-path derivative above. The expected Poisson Fisher block is Bkp=cjkpcjkpcT/λkpcB_{kp}=\sum_c\mathbf j_{kpc}\mathbf j_{kpc}^{\mathsf T}/\lambda_{kpc}. Choose κkp\kappa_{kp} as the largest eigenvalue of H1/2BkpH1/2H^{-1/2}B_{kp}H^{-1/2}. The nonnegative interpolation weights give the spatial row bound

D~data=kAkT[κk(Ak1)].\widetilde{\mathbf D}_{\mathrm{data}} =\sum_k A_k^{\mathsf T} \left[\boldsymbol\kappa_k\odot(A_k\mathbf 1)\right].
(12.10)

For one ray with weights ai0a_i\geq0, weighted Cauchy–Schwarz gives iaiuiH2(iai)iaiuiH2\|\sum_i a_i\mathbf u_i\|_H^2\leq(\sum_i a_i)\sum_i a_i\|\mathbf u_i\|_H^2. Combining this with BκHB\preceq\kappa H and summing rays produces the backprojected row bound. For the quadratic regulariser, let did_i be the sum of incident edge weights βΔV/ha2\beta\Delta V/h_a^2 at voxel ii. Adding 2di/λmin(H)2d_i/\lambda_{\min}(H) to the raw scale bounds that regulariser’s curvature as well.

The preparation applies a declared positive floor and divides by the mean to obtain D\mathbf D. This sets the mean scale to one and leaves the overall step length to α\alpha; the curvature bound above concerns the raw, unnormalised scale. Preparation uses the current fitted field and supplied calibration, without opening the reference volume. This is a local expected-Fisher construction, not the complete observed Hessian of the nonlinear objective. The line search still has work to do.

The metric sets the relative scaling of the update, but we still need its overall length, α\alpha. The Barzilai–Borwein two-point rule uses the change in gradient over the preceding accepted step to propose that length. In fixed metric coordinates it gives α=(iDisiTHsi)/(sTy)\alpha=(\sum_iD_i\mathbf s_i^{\mathsf T}H\mathbf s_i)/(\mathbf s^{\mathsf T}\mathbf y). [42] Here s\mathbf s and y\mathbf y are the differences between consecutive accepted fields and gradients. Nonpositive or nonfinite curvature falls back to ordinary step growth.

The optional inertial proposal also extrapolates from the preceding accepted field before metric projection. Extrapolation can continue useful progress, but it can overshoot. The line search therefore tests the true objective with strict Armijo decrease, using the gradient at the current accepted field. If an inertial proposal fails, it retries the same step length without extrapolation.

A metric refresh resets both the two-point and inertial histories. These safeguards govern which proposals are accepted; they do not supply a convergence-rate result for the spectral problem.

The material solver retains its fields, trial fields, gradients and optional proposal histories on CUDA. Step selection and acceptance read back scalar reductions, while exporting fields or predictions is an explicit operation. Fisher preparation allocates its scratch between solves; it is not repeated inside each update. The host still controls the line search, so keeping the arrays on the GPU does not make the calculation entirely asynchronous.

Stationarity is assessed separately: at the fixed diagnostic step α0\alpha_0, compute fΠC(fα0Φ)/α0\|\mathbf f-\Pi_{\mathcal C}(\mathbf f-\alpha_0\nabla\Phi)\|_\infty/\alpha_0, with ordinary Euclidean projection onto the per-voxel simplex C\mathcal C. Neither HH nor D\mathbf D enters this diagnostic. Otherwise, making the update metric sufficiently large could manufacture a small reported step while leaving the same unresolved gradient. That would be an admirably cheap reconstruction, provided nobody expected it to be finished.

Figure 12.4 follows both material fields from the uniform start to accepted reconstructions and compares them with the assigned reference. Check the material-path and voxel VJPs independently before interpreting material separation. A single uncalibrated broadband image cannot support unrestricted multi-material reconstruction, and supplying more output channels in the software is unlikely to persuade it otherwise.

For recorded mean signals, the effective spectral weights can also vary over detector pixels. Writing KkpceK_{kpce} for the effective spectral kernel in stored-signal units gives

y^kpc=eKkpceexp ⁣[mam(Ee)bkpm],DWLS=12k,p,cmkpcwkpc(y^kpcykpc)2.\widehat y_{kpc}=\sum_e K_{kpce} \exp\!\left[-\sum_m a_m(E_e)b_{kpm}\right], \qquad D_{\mathrm{WLS}}=\frac12\sum_{k,p,c}m_{kpc}w_{kpc} \bigl(\widehat y_{kpc}-y_{kpc}\bigr)^2.
(12.11)

KK already includes integrated energy-bin populations and the spatial open-beam factors. The fixed validity mask is mkpcm_{kpc}: the sum is restricted to valid entries, and invalid observations are skipped before residual arithmetic. The supplied acquired-phantom reconstruction sets ww to inverse squared predicted air signal, making the weighted residual contribution dimensionless. These deterministic weights do not estimate a joint inverse noise covariance. Nor does fitting KK identify the source spectrum and detector response separately. In that acquisition, the cumulative Total channel contains the High channel; the same photons do not become independent by appearing in two arrays.

12.7 Validate the volume independently

A small projection residual establishes agreement on the measured rays under the chosen model. To assess prediction, reserve entire views before solver development and report their count-space residuals. To assess volume correctness, compare against an independently known attenuation reference in physical units, accounting for reference uncertainty and any required spatial registration. These checks answer different questions: Figure 12.4 reports withheld-view mean errors alongside the assigned and reconstructed material fields, and requires both assessments to pass.

Start numerical verification with explicitly mathematical fields, whose definitions and discretisations are recorded. Use an independently implemented projector or different quadrature for forward reference checks, then compare directional derivatives over a range of perturbation sizes. Generating observations and reconstructing them with precisely the same discrete operator tests internal consistency while hiding shared modelling errors.

For acquired data, separate plausible contributors to error through controlled studies: count noise with fixed calibration, perturbed geometry with otherwise fixed inputs, and forward-model mismatch such as unmodelled hardening. Report attenuation bias and spatial resolution with task-relevant quantities, not only an image similarity score. A smoothed volume can look agreeably quiet while erasing the structure the reconstruction was supposed to recover.

Repeat acquisitions or justified noise replicates can estimate variability, provided the independence assumptions are stated. Local Hessian approximations give uncertainty conditional on the model and any prior, but they do not certify coverage when either is wrong. Include failed runs in the evaluation record and state how they affect aggregate metrics.

12.8 Complete the reconstruction study

The scalar example’s case manifest supplies the grid, fixed pose and calibrated views, with provenance for each input array. Its python/dpt/examples/README.md input guide specifies the array descriptors and invocation. Output consists of the accepted attenuation volume, refreshed fitted-view count predictions and the optimisation history, with source snapshots and input hashes.

The complete material worked example provides an executable acquisition-to-evaluation workflow with bundled, attributed inputs. CT-ORG case 2 supplies an assigned water/bone field, conservatively averaged from 192³ to 16³. That same coarse trilinear representation defines the simulated object and the unknowns. The experiment therefore asks whether the implemented inverse calculation recovers a known coarse field under its declared physical model; it does not test unresolved anatomical detail or establish patient composition.

The 48 fitting views cover three full-azimuth orbits at tilts of −15°, 0° and 15°. Twelve further views, at different yaw angles, are reserved for evaluation. Each view uses a 48 × 48 detector covering the complete box. Before drawing counts, the driver compares 512 and 1,024 ray samples at every pixel and checks fixed rays against exact CPU integration. This checks the projection calculation before count noise enters the example.

Both noise replicates start from uniform water. Each fit checks its derivatives independently, prepares the spatial metric at the initial field and refreshes it after 100 accepted updates. The supplied protocol fixes this schedule and the stopping criteria for both replicates. To reproduce the supplied observations exactly, the driver also verifies all four count-array hashes before either fit begins.

Run the command in the worked-example README to execute the sequence below. It completes both fits before evaluating either against the reference field, so the first result cannot be used to tune the second.

Acquiring both replicates, fixing both reconstructions, then evaluating themexperiments/worked-reconstruction/run.pyL933–978
def run_worked_example(args: argparse.Namespace) -> dict[str, Any]:
    """Generate once, freeze both fits, then assess every prescribed replicate."""
    config = json.loads(args.config.read_text())
    if config["replicates"] != [0, 1]:
        raise ValueError("the complete worked example requires both prescribed replicates [0, 1]")
    with RunRecorder(
        private_output(args.output, repository_root(__file__)),
        configuration={"protocol": config, "development": args.development},
        sources=sources(args.config, {}),
    ) as run:
        acquisition = args.output / "acquisition"
        acquisition_args = argparse.Namespace(**vars(args))
        acquisition_args.output = acquisition
        acquire(acquisition_args)
        fits = {}
        for replicate in config["replicates"]:
            fit_args = argparse.Namespace(**vars(args))
            fit_args.acquisition = acquisition
            fit_args.replicate = replicate
            fit_args.output = args.output / f"fit-rep{replicate}"
            fit(fit_args)
            fits[replicate] = fit_args.output
        # No reference or withheld assessment is opened until both fits exist.
        outcomes = []
        for replicate in config["replicates"]:
            evaluation_args = argparse.Namespace(**vars(args))
            evaluation_args.acquisition = acquisition
            evaluation_args.fit = fits[replicate]
            evaluation_args.output = args.output / f"evaluation-rep{replicate}"
            outcomes.append(evaluate(evaluation_args))
        child_records = {
            str(path.relative_to(args.output)): digest(path)
            for path in sorted(args.output.glob("*/run.json"))
        }
        summary = {
            "development": args.development,
            "replicates": outcomes,
            "numerical_passed": all(row["numerical_passed"] for row in outcomes),
            "accepted": all(row["accepted"] for row in outcomes),
            "all_fits_frozen_before_reference_evaluation": True,
            "child_records_sha256": child_records,
        }
        run.write_json("summary.json", summary)
    return summary

Let GG denote the infinity norm of the Euclidean projected-gradient mapping from §12.6, evaluated at the fixed diagnostic step α0=106\alpha_0=10^{-6}. The stopping test requires G/G0104G/G_0\leq10^{-4}, relative to its uniform-start value G0G_0, and α0G105\alpha_0G\leq10^{-5}, the allowed mapped fraction displacement. The latter condition gives G10G\leq10; for these initial fields it is the stricter requirement. Each fit shares a soft budget of 1,200 seconds across its stages and may accept at most 6,000 updates.

After fitting, an independent CPU simplex projection recomputes the mapping. Separate accuracy checks require whole-box RMSE no greater than 0.05 for each material and a withheld-view prediction error no greater than one generating Poisson standard deviation RMS across all twelve reserved views. Those predictions are compared with the generating means, so the check measures forward prediction error without adding another observation’s count noise.

Both recorded fits complete from uniform water. Their objectives fall from 34,193,738.24 and 34,180,078.94 to 165,071.27 and 164,412.08 after 475 and 426 accepted updates. Most of that reduction happens early. At update 100, the first objective is already 166,544.36, within 0.9% of its final value, but the mapping is still 1,831.10 against the threshold of 10. The nearly flat objective curve therefore hides substantial unfinished optimisation; the separate mapping curve tells us why the solve must continue.

Armijo requires the objective to decrease at accepted updates; it does not require the projected-gradient mapping to decrease at every update. The material viewer starts at physical plane z=0z=0. Use its controls to compare the two replicates and materials or move through the recorded slices. The fraction and signed-error windows remain fixed.

Reducing the fitting objective

Poisson half-deviance + penalty against Accepted update. The vertical scale is logarithmic. Replicate 0 and Replicate 1.Poisson half-deviance + penalty10⁶10⁷0200400Accepted update
  • Replicate 0
  • Replicate 1

Reaching stationarity

Euclidean projected mapping against Accepted update. The vertical scale is logarithmic. Replicate 0, Replicate 1 and Required ≤ 10.Euclidean projected mapping10100100010,000100,0000200400Accepted update
  • Replicate 0
  • Replicate 1
  • Required ≤ 10

Loading recorded arrays…

Display and array data

The same fraction and signed-error windows apply to both replicates and materials. The initial plane is z = 0 mm, halfway between two recorded sample planes. Moving the slice interpolates only between adjacent planes; no reconstruction is run in the page.

The starting field is uniform water. Only the 48 fitting views enter either solve. Both fields and their stopping diagnostics are fixed before the evaluator opens assigned references and 12 disjoint withheld views. The mapping tests constrained stationarity; material and withheld errors test recovery under the declared matched model. All must pass.

Recorded result and acceptance criteria
QuantityResultCriterion
Replicate 0: accepted updates475Stop by projected-gradient tolerance
Replicate 0: final mapping7.1181≤ 10
Replicate 0: water / bone RMSE0.00801 / 0.00656Each ≤ 0.05; whole coarse box
Replicate 0: withheld mean error0.10126 Poisson SD RMS≤ 1 across all 12 withheld views
Replicate 1: accepted updates426Stop by projected-gradient tolerance
Replicate 1: final mapping5.2557≤ 10
Replicate 1: water / bone RMSE0.00828 / 0.00633Each ≤ 0.05; whole coarse box
Replicate 1: withheld mean error0.09422 Poisson SD RMS≤ 1 across all 12 withheld views
Reproduction and recorded data
Figure 12.4From spectral counts to two recovered material fieldsCT-ORG case 2 supplies assigned water/bone anatomy in a declared matched 16³ trilinear basis. Both independent prescribed noise replicates are retained.

The final mappings are 7.11812 and 5.25572. Across both replicates, each material’s whole-box RMSE is below 0.0083, and withheld generating-mean error is below 0.102 Poisson standard deviations RMS. Both reconstructions pass all three kinds of check. The half-deviance need not vanish: the observed counts contain Poisson fluctuations, and the objective also charges the spatial penalty. Numerical completion, material accuracy and prediction of unseen views remain separate questions, even in this deliberately matched coarse model.

Paired unsmoothed bone surfaces: assigned CT-derived reference on the left, spectral reconstruction on the right. The vertebral column and cropped ribs are visible in both.
CT-derived simulation

126 fitting views · 18 withheld views

Acquisition, measurements and limitations

200,000 photons per ray integrated across three ideal channels.

Inverse grid
64 × 64 × 64 voxels (Z, Y, X)
Voxel spacing
2.326 × 2.326 × 3.000 mm (X, Y, Z)
Bone fraction RMSE
0.03326
Water fraction RMSE
0.03917
Convergence established
No
  • Assigned material phantom. Fractions are not measured patient composition.
  • 1,000-update budget reached. Stationarity and noise-limited performance are not established.
  • Vertebral region includes cropped ribs. Source-header laterality is not independently established.
  • Reference and recovered arrays share the inverse grid. Surfaces remain unsmoothed and open at cropped boundaries.

Rister et al. CT-ORG (2019), case 2 bone labels, cropped, assigned and volume averaged · SpekPy 2.5.4 spectrum generator · Hubbell and Seltzer, NIST SRD126, the water coefficient source used for simulation · NIST SRD126 ICRU-44 cortical bone coefficient source used for simulation

Coordinates are in the recorded object frame. Anatomical laterality is not asserted. Clipped surfaces stay open. The interactive camera uses perspective and the static plate uses orthographic projection. Surface lighting and volume opacity serve inspection. The slice and profile values come from the recorded fields.

Figure 12.5A spectral reconstruction from CT-derived anatomyAn earlier study stopped after 1,000 updates without establishing stationarity. The assigned and recovered bone surfaces share a fraction threshold of 0.325 and the same viewing geometry, exposing boundary errors.

20–55 keVWithheld view 5

Simulated observation

20–55 keV: simulated observation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 8

Generating expectation

20–55 keV: generating expectation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 8

Withheld-view prediction

20–55 keV: withheld-view prediction of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 8

Observation − prediction (Poisson scaled)

20–55 keV: observation − prediction (poisson scaled) of the assigned CT-derived vertebral phantom. Blue is negative, pale is zero and red is positive. The sign follows the panel label.

Blue -5 · pale 0 · red 5

Display clipping in this channel
  • Simulated observation: 1555 below the window, 1 above, 0 masked.
  • Generating expectation: 3119 below the window, 0 above, 0 masked.
  • Withheld-view prediction: 3119 below the window, 0 above, 0 masked.
  • Observation − prediction (Poisson scaled): 27 below the window, 75 above, 0 masked.

Clipping affects the image display only.

55–80 keVWithheld view 5

Simulated observation

55–80 keV: simulated observation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 5.5

Generating expectation

55–80 keV: generating expectation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 5.5

Withheld-view prediction

55–80 keV: withheld-view prediction of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 5.5

Observation − prediction (Poisson scaled)

55–80 keV: observation − prediction (poisson scaled) of the assigned CT-derived vertebral phantom. Blue is negative, pale is zero and red is positive. The sign follows the panel label.

Blue -5 · pale 0 · red 5

Display clipping in this channel
  • Simulated observation: 1550 below the window, 0 above, 0 masked.
  • Generating expectation: 3119 below the window, 0 above, 0 masked.
  • Withheld-view prediction: 3119 below the window, 0 above, 0 masked.
  • Observation − prediction (Poisson scaled): 43 below the window, 26 above, 0 masked.

Clipping affects the image display only.

80–120 keVWithheld view 5

Simulated observation

80–120 keV: simulated observation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 4

Generating expectation

80–120 keV: generating expectation of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 4

Withheld-view prediction

80–120 keV: withheld-view prediction of the assigned CT-derived vertebral phantom. Lighter pixels indicate greater negative log transmission.

Black 0 · white 4

Observation − prediction (Poisson scaled)

80–120 keV: observation − prediction (poisson scaled) of the assigned CT-derived vertebral phantom. Blue is negative, pale is zero and red is positive. The sign follows the panel label.

Blue -5 · pale 0 · red 5

Display clipping in this channel
  • Simulated observation: 1588 below the window, 16 above, 0 masked.
  • Generating expectation: 3119 below the window, 8 above, 0 masked.
  • Withheld-view prediction: 3119 below the window, 0 above, 0 masked.
  • Observation − prediction (Poisson scaled): 3 below the window, 0 above, 0 masked.

Clipping affects the image display only.

Residual: (observation − prediction) / √max(predicted count, 1). Positive values mean more observed photons than predicted. The entire view was withheld from fitting.

Recorded data and display

96 × 96 detector samples, displayed at their physical aspect ratio. The extent is384 × 384 mm. Full detector cell-face extent in centred detector coordinates. These are the original selected samples. Enlargement adds no detector resolution.

Assigned CT-derived material phantom with simulated independent Poisson channels: finite-budget reconstruction, not measured patient composition.

Observation display: -log((counts+0.5)/open_beam);0.5 is a display-only continuity correction. Residual display: (observed-predicted)/sqrt(max(predicted,1)); limits[-5,5].

Original data and attribution · Display records · Source identities

Figure 12.6What the spectral reconstruction predictsThe same earlier reconstruction predicts a complete withheld view in three energy channels. Observations, generating means and predictions show the image disagreement remaining outside the fitting views.

Throughout this chapter, someone else chose the acquisition. Chapter 13 makes that choice part of the problem: which next view, and which allocation of exposure, would improve a specified registration or reconstruction task?

References

  1. Siddon, Robert L. (1985). Fast calculation of the exact radiological path for a three-dimensional CT array. Medical Physics, 12(2), 252-255. https://doi.org/10.1118/1.595715
  2. Momeni, Mohammadhossein, Gopalakrishnan, Vivek, Dey, Neel, Golland, Polina and Frisken, Sarah (2024). Differentiable Voxel-based X-ray Rendering Improves Sparse-View 3D CBCT Reconstruction. arXiv. https://doi.org/10.48550/arXiv.2411.19224
  3. Alvarez, R. E. and Macovski, A. (1976). Energy-selective reconstructions in X-ray computerised tomography. Physics in Medicine and Biology, 21(5), 733-744. https://doi.org/10.1088/0031-9155/21/5/002
  4. Alvarez, Robert (2017). Conditions for the invertibility of dual energy data. arXiv. https://doi.org/10.48550/arXiv.1711.10836
  5. Barzilai, Jonathan and Borwein, Jonathan M. (1988). Two-Point Step Size Gradient Methods. IMA Journal of Numerical Analysis, 8(1), 141–148. https://doi.org/10.1093/imanum/8.1.141