Confidence factor

Day / terminator / night blend into CF_comb, Eqs. 16-22.

DEBRA confidence factor, Eqs. 16-22 (Eqs. 21-22 per the 2020 erratum).

Combines the dust tests under cloud-mask suppression into day / terminator / night confidence factors (Eqs. 16-18), normalizes each (Eq. 19), and blends them across the terminator with solar-zenith weights B_ngt_trm and B_trm_day (Eqs. 20-21, exponent 1.5) into the final CF_comb in [0, 1] (Eq. 22).

Eq. 19 as printed uses one interval, (0.25, 2.50), for all three branches. That is a scale error, and a visible one: Eq. 16 sums three DT terms and can reach 3.0, Eq. 18 sums two and can reach 1.5, so one shared interval caps CF_ngt at (1.5 - 0.25) / (2.50 - 0.25) = 0.556 while CF_day reaches 1. Dust appears to fade at dusk. The deviation here is to give each branch its own interval (shachen.constants.ConfidenceConstants), with the terminator interpolating between them on the Eq. 20 weight.

The two halves are also callable on their own: confidence_raw() is Eqs. 16-18, confidence_norm() is Eqs. 19-22. Everything the intervals touch lives in the second half, so a stored raw sum can be re-normalized on a different interval without the dust tests or the L1b behind them.

shachen.confidence.confidence_raw(tests: Dataset, cloud: Dataset, constants: ConfidenceConstants = ConfidenceConstants(dt3_weight_trm=0.5, dt3_weight_ngt=0.5, cf_norm_day=Bounds(min=0.25, max=2.5), cf_norm_ngt=Bounds(min=0.125, max=1.25), cf_norm_trm=None, blend_exponent=1.5, ngt_trm_zenith_deg=Bounds(min=105.0, max=90.0), trm_day_zenith_deg=Bounds(min=90.0, max=75.0))) → Dataset[source]

Eqs. 16-18 before the Eq. 19 normalization.

Returns cf_day_raw, cf_trm_raw and cf_ngt_raw on the scene grid, in the units the DT tests come in (each already suppressed by its cloud mask). Eq. 19 is a clipped monotone map of these, so they are what an evaluation needs in order to re-normalize with different intervals later without re-running the retrieval – and, because a monotone map commutes with taking a median, they can be spatially aggregated first and normalized afterwards, which the normalized factors cannot.

tests needs dt1, dt2, dt3; cloud needs cm_norm_day, cm_norm_ngt.

shachen.confidence.confidence(tests: Dataset, cloud: Dataset, zenith_deg: DataArray, constants: ConfidenceConstants = ConfidenceConstants(dt3_weight_trm=0.5, dt3_weight_ngt=0.5, cf_norm_day=Bounds(min=0.25, max=2.5), cf_norm_ngt=Bounds(min=0.125, max=1.25), cf_norm_trm=None, blend_exponent=1.5, ngt_trm_zenith_deg=Bounds(min=105.0, max=90.0), trm_day_zenith_deg=Bounds(min=90.0, max=75.0))) → Dataset[source]

Confidence factors and blend weights on the scene grid.

tests needs dt1, dt2, dt3 (from shachen.dust_tests.dust_tests()); cloud needs cm_norm_day, cm_norm_ngt (from shachen.cloudmask.cloud_mask()); zenith_deg is the solar zenith angle in degrees. All 2-D inputs must share one shape (ValueError otherwise); NaN propagates.

Returns a Dataset with cf_day, cf_trm, cf_ngt (each already normalized per Eq. 19; CF_trm and CF_ngt use cm_norm_day and cm_norm_ngt respectively, CF_ngt takes max(DT1, DT2)), the blend weights b_ngt_trm, b_trm_day (via shachen.norm.normalize_cos_zenith()), and cf_comb (Eq. 22).

The Eq. 19 intervals are per branch: constants.cf_norm_day for CF_day, constants.cf_norm_ngt for CF_ngt, and for CF_trm the two interpolated on b_ngt_trm, so its scale matches whichever neighbour Eq. 22 is blending it into. Passing cf_norm= to shachen.constants.ConfidenceConstants sets both intervals to one value and restores the printed single-interval behaviour.

shachen.confidence.blend_confidence(cf_day, cf_trm, cf_ngt, b_ngt_trm, b_trm_day)[source]

Eq. 22 (erratum): the nested day / terminator / night blend.

Split out so that anything normalizing the branches differently – a calibration layer built on top of this package, say – blends them the same way rather than keeping a second copy of Eq. 22.

shachen.confidence.confidence_norm(raw: Dataset, zenith_deg, constants: ConfidenceConstants = ConfidenceConstants(dt3_weight_trm=0.5, dt3_weight_ngt=0.5, cf_norm_day=Bounds(min=0.25, max=2.5), cf_norm_ngt=Bounds(min=0.125, max=1.25), cf_norm_trm=None, blend_exponent=1.5, ngt_trm_zenith_deg=Bounds(min=105.0, max=90.0), trm_day_zenith_deg=Bounds(min=90.0, max=75.0))) → Dataset[source]

Eqs. 19-22 on the raw sums confidence_raw() produces.

raw needs cf_day_raw, cf_trm_raw, cf_ngt_raw. Split out from confidence() because everything the Eq. 19 intervals touch is here and nothing upstream of them is: re-tuning the intervals on stored raw sums is this call, and needs neither the L1b nor the dust tests.

Returns the same variables confidence() does.