Skip to content

populate background from heuristic solve#815

Draft
brentwilder wants to merge 54 commits into
isofit:devfrom
brentwilder:bg_rfl
Draft

populate background from heuristic solve#815
brentwilder wants to merge 54 commits into
isofit:devfrom
brentwilder:bg_rfl

Conversation

@brentwilder

@brentwilder brentwilder commented Dec 11, 2025

Copy link
Copy Markdown
Contributor

Right now isofit relies on AOE to handle influence of adjacency effects and background pixels. A solution that would work for per-pixel and AOE, would be to set geom.bg_rfl based on heuristic solve averaged across x km window. Of course, there are a multitude of ways to do the aggregation, but this could be a logical first step. We could also perform some spectral smoothing here or other ideas if we are worried about the quality of the background spectra.

The full image heuristic solve would be cheap. This allows similar physics for the background/adjacency regardless if using AOE or not. And would not require any changes to radiative_transfer.py because the hooks are already in place.

@brentwilder brentwilder marked this pull request as ready for review December 16, 2025 17:46
@brentwilder

Copy link
Copy Markdown
Contributor Author

Something we could consider for this PR or subsequent ones, is that we could increase the complexity and store x0 as well as bg_rfl. I coded this out and realized there was too many changes at once and so my preference I think would be to only have the bg_rfl first in this PR to isolate any errors/bugs. This was suggested by Evan this week too in that we could essentially remove the inverse_simple() call wehn running OE. The x0 potentially could be stored in geom?

Comment thread isofit/utils/background_reflectance.py Outdated
@brentwilder

brentwilder commented Dec 18, 2025

Copy link
Copy Markdown
Contributor Author

@unbohn Comparing similar pixels in emit20250327T212148_rfl over Lake Mary, CA. surface_20240103.json. All were done with similar configs really just trying to sub out the emulator and the background pixel assumptions. Skyview was assumed to be 1.0 for all here.

image

--

The resulting bg_rfl spectra for this same location ^^

image

@evan-greenbrg

evan-greenbrg commented Dec 18, 2025

Copy link
Copy Markdown
Collaborator

Super interesting @brentwilder! I was curious why the analytical line w/ bkg solve didn't better match with the OE. I actually think as it's currently written, the two forward models (OE vs AOE) are not equivalent.

The linearization we do in the analytical line in its present form assumes that rho_dif_dir = rho_dif_dif and rho_dir_dir = rho_dir_dif. Is it true that this is not the case in the OE forward model where these two are equal to the geom.bg_rfl?

If this is the case, we just need to back out the non-simplified form of the linearized forward model and hook up geom.bg_rfl appropriately.

Full forward model:
$L=L_0+L_{11}\rho_{11}+L_{21}\rho_{21}+L_{12}\rho_{12}+L_{22}\rho_{22}+\frac{L_TS\rho_{22}^2}{1-S\rho_{22}}$

Assumptions:
$\rho_{12}=\rho_{22}=\rho_{Bg}$
$\rho_{11}=\rho_{21}=\rho$

Simplifies to
$L=L_0+(L_{11}+L_{21})\rho+(L_{12}+L_{22})\rho_{Bg}+\frac{L_TS\rho_{Bg}^2}{1-S\rho_{Bg}}$

Assume:
$L_{Bg} = (L_{12}+L_{22})\rho_{Bg}+\frac{L_TS\rho_{Bg}^2}{1-S\rho_{Bg}}$

AOE solves for the following linear fn w.r.t state-vector, $\rho$:
$L-L_0-L_{Bg}=(L_{11}+L_{21})\rho$

Is this right?

Edit: with the glint model:

Assuming:
$\rho_{11}=\rho + \alpha_1$
$\rho_{21}=\rho + \alpha_2$

AOE solves for the following linear fn w.r.t state-vector, $\rho, \alpha_1,\alpha_2$:
$L-L_0-L_{Bg}=(L_{11}+L_{21})\rho+L_{11}\alpha_1+L_{21}\alpha_2$

May actually help stability...

The tricky thing is how this can be "architectured" to be flexible w.r.t running w/ background and w/o background.

@unbohn

unbohn commented Dec 18, 2025

Copy link
Copy Markdown
Collaborator

Thanks for these updates, guys! @brentwilder I think your plot tells exactly the story that the current AOE implementation sets the target reflectance equal to the background, so that we can't get a match to the per pixel solve that includes the background. @evan-greenbrg I skimmed your equations and they look right to me. To your last point: In my opinion, we should always run with background, as the diffuse reflectance will never originate from the target pixel alone.

@brentwilder

Copy link
Copy Markdown
Contributor Author

@unbohn @evan-greenbrg On your last point Niklas I'd agree that being computationally cheap, you would always want to have this mode on. But I can definitely attempt to write it out to be optional, and we can decide on it as a group.

In writing this I realized also that the full bg_rfl file needs to be shared to analytical line call , to facilitate these above equations. But I think the way Evan has mapped it out here is very nice and can be used to improve AOE ... Essentially even for the 1C case, instead of using the superpixel $$\rho$$ we could always rely on the geom.bg_rfl , here .

@unbohn

unbohn commented Dec 18, 2025

Copy link
Copy Markdown
Collaborator

@brentwilder Yes, I fully agree! We've had some discussions about the usage of the background reflectance term in both OE and AOE a long while ago, and I think David came up with the idea of using the superpixel reflectance as background. Apparently, nobody thought about utilizing the heuristic solve back then.

Comment thread isofit/surface/surface_multicomp.py Outdated
theta = L_tot + (L_tot * background / (1 - background))
# theta = L_tot
# Isolate signal from target
theta = L_tot - L_bg

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you've tested yet, but this may be incorrect.

here it should be:

$\theta=L_{11} + L_{21}$

I don't think is equivalent to the definition of $L_{Bg}$ above in inverse_simple.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I think you are right, this was hasty on me and trying to reconcile 3c v 6c. I'll put as $$L_{dd} + L_{hd}$$ for now and try and think about this a little more how to make this work for both cases. Thanks Evan.

@brentwilder

brentwilder commented Jan 5, 2026

Copy link
Copy Markdown
Contributor Author

6c analytical solution after Evan's suggestions. My interpretation of the 1c case was to assume $$\theta \approx L_{tot}$$ . And the new L_bg term handles the constant spherical albedo scattering in xk (Line 366 of inverse_simple).

Although this 1c case exceeds the 95th percentile of ASD measurements, I think the math is pretty close here.. Hard to tell if this could just be a limitation of using 1c based radiance term. Or perhaps my math is wrong, which is certainly possible.

image

@brentwilder

Copy link
Copy Markdown
Contributor Author

To make this also useful for the per pixel and LUTSurface solutions, I expanded the meaning of use_superpixel a bit, such that its True to start ApplyOE so it can leverage speed up for presolve/background solve.

I'd assume we would never want to do the background solve without super pixel.

And then there is a check right before main config is built to set it back to False if AOE or Empirical Line is not turned on.

The main improvement from this latest commit is that it would allow @unbohn and I to run the Snow model with the advancements here in this PR.

@github-actions

github-actions Bot commented Mar 9, 2026

Copy link
Copy Markdown
📊 Generated results:

URL: isofit/isofit-test-results#21
SHA: 59c0e72

@pgbrodrick

Copy link
Copy Markdown
Collaborator

Ready for vigorous testing now.

@brentwilder brentwilder marked this pull request as draft May 1, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants