From fa52f6a81837ae553b68c7ad7d9b0965b4ee342c Mon Sep 17 00:00:00 2001 From: Senrokai Date: Tue, 29 Sep 2026 20:27:01 +0200 Subject: [PATCH] Give an archive star's distance error as the error on the distance it is, not as a parallax range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit formatDistance printed any error of a fifth or more as the range a parallax's error makes, d/(1+e) to d/(1−e). A star the ETL places from the Exoplanet Archive carries the mean of sy_disterr1 and 2 instead, which the archive defines as one-sided errors on sy_dist in parsecs, and many of those distances come from a lensing model with no parallax behind them. 129 of the 3 195 archive stars with an error were printed as ranges the archive does not give: KMT-2016-BLG-1836L as 5.8 to 9.2 kpc, where the archive publishes 7 100 +800 −2 400 pc, and AT2021ueyL as 664 pc to 2.4 kpc against 1 040 +740 −440. The card now tells formatDistance when the error is on the distance (source exoplanet-archive), and it keeps the ± at any size. Measured on the shipped catalogue: KMT-2016-BLG-1836L reads 7.1 ± 1.6 kpc, AT2021ueyL 1.0 ± 0.6 kpc, EPIC 201170410 134 ± 43 pc, KMT-2016-BLG-0212L 6.3 ± 1.3 kpc. The ETL keeps only the mean, so a lopsided interval such as KMT-2016-BLG-1836L's is shown symmetric; carrying both errors would take a second column in stars-meta.bin. The doc comments on formatDistance and on distanceError no longer say an archive distance is an inverted parallax. Controls, each failing its named test: the error on the distance read as a parallax's (2 of 790 failed), and the card not saying it is on the distance (1 of 790). Co-Authored-By: Claude Opus 5.5 (1M context) --- .../galaxy-system/star-readouts.spec.ts | 7 +++++++ .../features/galaxy-system/star-readouts.ts | 2 +- src/app/shared/format/quantity.spec.ts | 7 +++++++ src/app/shared/format/quantity.ts | 18 ++++++++++++------ src/app/shared/models/star.model.ts | 4 +++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/app/features/galaxy-system/star-readouts.spec.ts b/src/app/features/galaxy-system/star-readouts.spec.ts index b4ac341..88ff462 100644 --- a/src/app/features/galaxy-system/star-readouts.spec.ts +++ b/src/app/features/galaxy-system/star-readouts.spec.ts @@ -60,6 +60,13 @@ describe('starReadouts', () => { expect(value(starReadouts(GAIA_STAR), 'Distance')).toBe('117 ± 12 pc'); }); + it("gives an archive star's distance error as the archive does, on the distance, not as a parallax range", () => { + // KMT-2016-BLG-1836L, 7 100 +800 −2 400 pc: a mean of 22.5 %. + const lens = { ...GAIA_STAR, x: 7100, magnitudeBand: undefined, colorIndex: null, colorSystem: undefined, distanceError: 0.2254, distanceFromGaia: false, source: 'exoplanet-archive' }; + expect(value(starReadouts(lens), 'Distance')).toBe('7.1 ± 1.6 kpc'); + expect(value(starReadouts({ ...lens, source: 'hyg' }), 'Distance')).toBe('5.8 kpc to 9.2 kpc'); + }); + it('names the catalogue a star comes from, and whose distance it has', () => { expect(value(starReadouts(GAIA_STAR), 'Source')).toBe('Gaia DR3'); expect(value(starReadouts(HYG_STAR), 'Source')).toBe('HYG'); diff --git a/src/app/features/galaxy-system/star-readouts.ts b/src/app/features/galaxy-system/star-readouts.ts index 290859d..2cc0aa3 100644 --- a/src/app/features/galaxy-system/star-readouts.ts +++ b/src/app/features/galaxy-system/star-readouts.ts @@ -43,7 +43,7 @@ export function starReadouts(star: StarRecord, surface?: StarSurface): HudReadou return [ // Suppressed for the Sun rather than printed as `0.00 pc`, which is arithmetically right // and reads as a bug: the distance from here to here is not a measurement. - ...(distancePc > 0 ? [{ label: 'Distance', value: formatDistance(distancePc, star.distanceError) }] : []), + ...(distancePc > 0 ? [{ label: 'Distance', value: formatDistance(distancePc, star.distanceError, star.source === 'exoplanet-archive') }] : []), // A G magnitude and a V one are not comparable: a red dwarf is up to three brighter in G. { label: 'Magnitude', value: star.magnitudeBand ? `${star.magnitudeBand} ${star.magnitude.toFixed(2)}` : 'Not measured' }, ...(star.colorIndex !== null diff --git a/src/app/shared/format/quantity.spec.ts b/src/app/shared/format/quantity.spec.ts index 5d60584..94d334b 100644 --- a/src/app/shared/format/quantity.spec.ts +++ b/src/app/shared/format/quantity.spec.ts @@ -31,6 +31,13 @@ describe('formatDistance', () => { expect(formatDistance(606.06, 0.45 / 1.65)).toBe('476 pc to 833 pc'); expect(formatDistance(250, 1)).toBe('125 pc or more'); }); + + it('keeps an error on the distance itself symmetric, however large', () => { + // AT2021ueyL: 1 040 +740 −440 pc in the archive, whose mean is 57 % of it. + expect(formatDistance(1040, 0.567, true)).toBe('1.0 ± 0.6 kpc'); + expect(formatDistance(134, 0.319, true)).toBe('134 ± 43 pc'); + expect(formatDistance(134, 0.005, true)).toBe('134 pc'); + }); }); describe('formatAu', () => { diff --git a/src/app/shared/format/quantity.ts b/src/app/shared/format/quantity.ts index 0b785d4..6eb36a4 100644 --- a/src/app/shared/format/quantity.ts +++ b/src/app/shared/format/quantity.ts @@ -22,16 +22,22 @@ function parsecScale(distancePc: number): { divisor: number; digits: number; uni * digits the distance itself is shown to. Left off where it is 1 % or less, or would round to * nothing at those digits, since the figure is then already as good as it reads. * - * Past a fifth, a range: the distance is the inverse of a parallax, so the parallax's symmetric - * error bar is a lopsided one in distance — Alnilam's 1.65 ± 0.45 mas is 476 to 833 pc, not - * 606 ± 165. Only a Hipparcos or archive distance gets there; Gaia's query stops at a fifth. An - * error as large as the parallax leaves no upper bound at all. + * Past a fifth, a range: a distance inverted from a parallax takes the parallax's symmetric error + * bar as a lopsided one — Alnilam's 1.65 ± 0.45 mas is 476 to 833 pc, not 606 ± 165. Only a + * Hipparcos distance gets there; Gaia's query stops at a fifth. An error as large as the parallax + * leaves no upper bound at all. + * + * Not so where the error is on the distance itself, `onDistance`: the Exoplanet Archive's + * sy_disterr1 and 2, one-sided errors in parsecs, of which the catalogue keeps the mean. Many of + * those distances are no parallax at all — KMT-2016-BLG-1836L's 7.1 kpc comes from a lensing model + * — and read as one they gave 129 cards a range the archive does not: 5.8 to 9.2 kpc there, where + * it publishes 7 100 +800 −2 400 pc. They keep the ± at any size. */ -export function formatDistance(distancePc: number, relativeError: number | undefined): string { +export function formatDistance(distancePc: number, relativeError: number | undefined, onDistance = false): string { if (relativeError === undefined || relativeError <= 0.01) { return formatParsecs(distancePc); } - if (relativeError < 0.2) { + if (relativeError < 0.2 || onDistance) { const { divisor, digits, unit } = parsecScale(distancePc); const error = ((distancePc * relativeError) / divisor).toFixed(digits); return Number(error) === 0 ? formatParsecs(distancePc) : `${(distancePc / divisor).toFixed(digits)} ± ${error} ${unit}`; diff --git a/src/app/shared/models/star.model.ts b/src/app/shared/models/star.model.ts index a3f0ad9..392c281 100644 --- a/src/app/shared/models/star.model.ts +++ b/src/app/shared/models/star.model.ts @@ -35,7 +35,9 @@ export interface StarRecord { colorSystem?: 'B-V' | 'BP-RP'; /** * Relative uncertainty of the distance, σd/d: the relative error of the parallax it was - * inverted from, which to first order is the same. Absent where none was published. + * inverted from, which to first order is the same — or, for a star the Exoplanet Archive places, + * the mean of the two one-sided errors it gives on the distance itself, which is often no + * parallax's. Absent where none was published. */ distanceError?: number; /** Whether the distance is Gaia DR3's parallax, whichever catalogue describes the star. */