Place a star at whichever of its two distances is the more precise, not at Gaia's regardless
placementDistancePc took Gaia's distance wherever the cross-match gave a usable one, and its
docstring and c64eea0 called that "the better measurement", adding that Gaia saturates on the
brightest stars "so those sit at their Hipparcos distance". For 273 of the 88 781 HYG stars with
both, Gaia's relative error is the larger, 257 of them naked-eye and 38 by more than twice: Eta Leo
was drawn at Gaia's 556.6 pc ±17 % against Hipparcos's 389 pc ±6.2 %, Schedar and Tarazed at
Gaia's though both have Gaia G of about 2.
placementDistancePc now takes both relative errors and picks the smaller, Gaia's as before when
either is missing; fetchStars gives the placed star the error and the Gaia-distance flag of the
distance it took. The merge's combine keeps the Gaia entry's direction, and now takes the other
entry's distance with its error where that is the more precise, so a bright star Gaia's main query
also holds lands at its Hipparcos distance too. Gaia still wins for the rest, whose parallaxes are
some fifty times more precise.
From cache: 424 stars move, 386 of them naked-eye; HYG rows at Gaia's distance 58 379 -> 58 109 and
HYG stars flagged so 8 129 -> 8 095. Eta Leo 556.6 -> 389.1 pc, Tarazed 178.9 -> 121.1, Imai 139.5 ->
105.8, Schedar 71.0 -> 70.0, Alphecca 23.7 -> 23.0, each now "±" its Hipparcos error. Where the two
disagree by more than 5 σ (21 stars, Iot Gem 11 σ), one of the formal errors is wrong, and this
takes the smaller one at its word. The validators pass unchanged.
Controls, each failing its named test: the placement ignoring the errors, the merge keeping Gaia's
distance whatever the errors, and taking the distance but not its error (1 of 805 each).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -192,6 +192,16 @@ describe('mergeStarCatalogues', () => {
|
||||
expect(merged).toMatchObject({ magnitude: 11.01, magnitudeBand: 'V', colorIndex: 1.807, colorSystem: 'B-V', distanceError: 0.000065, distanceFromGaia: true });
|
||||
});
|
||||
|
||||
it("takes a Hipparcos distance more precise than the Gaia entry it folds into, along Gaia's direction", () => {
|
||||
// Schedar: 71.0 pc ±3.5 % in Gaia, which saturates on it, and 70.0 pc ±1.0 % in Hipparcos.
|
||||
const hyg = at(3179, 10.1268, 56.5373, 70.0, { name: 'Schedar', magnitude: 2.24, distanceError: 0.0105, distanceFromGaia: false });
|
||||
const gaia = at(1000000100, 10.1268 + arcsecOfRa(0.2, 56.5373), 56.5373, 71.0, { name: 'Gaia DR3 425040000962559616', magnitude: 1.94, distanceError: 0.035, distanceFromGaia: true, source: 'gaia' });
|
||||
const [merged] = mergeStarCatalogues([{ ...HIPPARCOS, stars: [hyg] }, { ...GAIA, stars: [gaia] }]).stars;
|
||||
expect(Math.hypot(merged.x, merged.y, merged.z)).toBeCloseTo(70.0, 9);
|
||||
expect(directionCosine(merged, gaia)).toBeCloseTo(1, 12);
|
||||
expect(merged).toMatchObject({ name: 'Schedar', distanceError: 0.0105, distanceFromGaia: false, source: 'gaia' });
|
||||
});
|
||||
|
||||
it('keeps two entries of one source apart, however close they are', () => {
|
||||
// Gaia resolves doubles Hipparcos saw as one star: two source ids 0.8″ apart are two stars,
|
||||
// and only *another* catalogue can claim to have already listed either of them.
|
||||
@@ -320,6 +330,12 @@ describe('placementDistancePc', () => {
|
||||
expect(placementDistancePc(undefined, 180, 8, 250)).toBe(180);
|
||||
});
|
||||
|
||||
it("takes the distance with the smaller error, Hipparcos's where Gaia saturated", () => {
|
||||
// Eta Leo: 556.6 pc ±17 % in Gaia, 389.1 pc ±6.2 % in Hipparcos. Sirius the other way round.
|
||||
expect(placementDistancePc(389.1, 556.6, 3.5, 250, 0.062, 0.17)).toBe(389.1);
|
||||
expect(placementDistancePc(2.64, 2.67, -1.44, 250, 0.004, 0.002)).toBe(2.67);
|
||||
});
|
||||
|
||||
it('falls back to Hipparcos where Gaia has no usable distance', () => {
|
||||
expect(placementDistancePc(90, undefined, 8, 250)).toBe(90);
|
||||
});
|
||||
|
||||
@@ -92,8 +92,11 @@ export const NAKED_EYE_MAGNITUDE = 6.5;
|
||||
/**
|
||||
* Where to draw a star Hipparcos and Gaia both measured, and whether the map keeps it at all.
|
||||
*
|
||||
* Gaia's distance wherever it has a usable one, since its parallaxes are fifty times more
|
||||
* precise; Hipparcos's otherwise. The two catalogues used to be cut at the same radius, each on
|
||||
* At whichever distance has the smaller relative error, given both; Gaia's without them, or
|
||||
* Hipparcos's where Gaia has none. Gaia's parallaxes are some fifty times more precise, and its
|
||||
* distance wins for all but 273 of the 88 781 HYG stars with both; those are bright stars Gaia
|
||||
* saturates on, 257 of them naked-eye — Eta Leo is 556.6 pc ±17 % in Gaia and 389 pc ±6.2 % in
|
||||
* Hipparcos, Schedar ±3.5 % against ±1.0 %. The two catalogues used to be cut at the same radius, each on
|
||||
* its own distance, so a star Hipparcos put at 200 pc and Gaia at 300 was kept by one, never
|
||||
* downloaded from the other, and drawn at 200. That was 83% of the HYG stars left without a
|
||||
* Gaia counterpart, and at the median Hipparcos had them at two-thirds of Gaia's distance.
|
||||
@@ -101,12 +104,20 @@ export const NAKED_EYE_MAGNITUDE = 6.5;
|
||||
* Now a star either survey places inside `cutoffPc` is kept, and every kept star sits where the
|
||||
* better measurement puts it, inside the cutoff or not. So is every star the naked eye sees, at
|
||||
* any distance: the cutoff took 1 543 of HYG's 8 920 stars of V 6.5 or brighter, Rigel, Deneb
|
||||
* and Alnilam among them, while 11th-magnitude Gaia stars at the same distance were drawn. Gaia
|
||||
* saturates on the brightest of them, so those sit at their Hipparcos distance. `null` for a star
|
||||
* kept by neither rule, or that no survey gives a distance for.
|
||||
* and Alnilam among them, while 11th-magnitude Gaia stars at the same distance were drawn. Those
|
||||
* Gaia has no usable parallax for sit at their Hipparcos distance. `null` for a star kept by
|
||||
* neither rule, or that no survey gives a distance for.
|
||||
*/
|
||||
export function placementDistancePc(hipparcosPc: number | undefined, gaiaPc: number | undefined, magnitude: number, cutoffPc: number): number | null {
|
||||
const best = gaiaPc ?? hipparcosPc;
|
||||
export function placementDistancePc(
|
||||
hipparcosPc: number | undefined,
|
||||
gaiaPc: number | undefined,
|
||||
magnitude: number,
|
||||
cutoffPc: number,
|
||||
hipparcosError?: number,
|
||||
gaiaError?: number
|
||||
): number | null {
|
||||
const hipparcosBetter = hipparcosPc !== undefined && hipparcosError !== undefined && gaiaError !== undefined && hipparcosError < gaiaError;
|
||||
const best = hipparcosBetter ? hipparcosPc : (gaiaPc ?? hipparcosPc);
|
||||
if (best === undefined) {
|
||||
return null;
|
||||
}
|
||||
@@ -227,18 +238,23 @@ export function isSameStar(kept: StarRecord, entry: StarRecord): boolean {
|
||||
* and keeping Gaia's whole once cost the map 102 proper names and 32 000 spectral types. The id
|
||||
* travels with the description, so a star HYG knows keeps its HYG id from one refresh to the next,
|
||||
* and so does its photometry, V and B−V. `source` stays with the position, since that is what it
|
||||
* records, and so does the distance's error: Gaia's, not the Hipparcos one of a distance dropped.
|
||||
* records, and so does the distance's error: Gaia's, not the Hipparcos one of a distance dropped —
|
||||
* unless the other entry's distance is the more precise, as the Hipparcos one of a bright star
|
||||
* `placementDistancePc` keeps at it is, which then sets the distance along Gaia's direction.
|
||||
*/
|
||||
function combine(kept: StarRecord, other: StarRecord): StarRecord {
|
||||
const described = isDesignation(kept) && !isDesignation(other) ? other : kept;
|
||||
const otherBetter = other.distanceError !== undefined && kept.distanceError !== undefined && other.distanceError < kept.distanceError;
|
||||
const placed = otherBetter ? other : kept;
|
||||
const scale = otherBetter ? distanceOf(other) / distanceOf(kept) : 1;
|
||||
return {
|
||||
...described,
|
||||
x: kept.x,
|
||||
y: kept.y,
|
||||
z: kept.z,
|
||||
x: kept.x * scale,
|
||||
y: kept.y * scale,
|
||||
z: kept.z * scale,
|
||||
source: kept.source,
|
||||
distanceError: kept.distanceError,
|
||||
distanceFromGaia: kept.distanceFromGaia
|
||||
distanceError: placed.distanceError,
|
||||
distanceFromGaia: placed.distanceFromGaia
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user