---
title: "Hold out a whole cluster and test a rotation clock"
description: "Download fixed author sources, recover all benchmark rows, retain sample-version differences, and independently reproduce conditional cluster-age checks."
canonical_url: "https://sandboxphysics.com/stories/stellar-rotation-ages/hold-out-a-cluster/"
language: "en"
page_type: "story"
alternate_languages:
  zh-CN: "https://sandboxphysics.com/zh/stories/stellar-rotation-ages/hold-out-a-cluster/"
last_modified: "2026-11-03"
---

[Starspots, rotation and stellar ages](https://sandboxphysics.com/stories/stellar-rotation-ages/)

AC27 · L4

# Hold out a whole cluster and test a rotation clock

Sandbox Physics · 2026-11-03

A whole-cluster holdout tests whether a rotation calibration transfers to stars it did not fit. Begin with fixed source files and an explicit selection. The first surprise in this example is practical: a plausible fixed-width parser silently loses every Ruprecht 147 benchmark star.

## Before you begin

Read A rotation age is a distribution on a chosen scale. You need Python 3.12, NumPy and SciPy, and enough familiarity with a table to distinguish a missing value from a missing row.

## Obtain the exact author versions

Download the standalone science ZIP below and extract it into a fresh directory. Its manifest lists the bytes and SHA 256 of every package member. The package contains our scientific code, synthetic surface observations and aggregate fitted coefficients. The author tables are fetched from their named original sources on your computer.

```
python verify_package.py
python fetch_sources.py --output inputs
python reproduce.py --inputs inputs --output results
python validate_science.py
```

The verified environment is Python 3.12.12, NumPy 2.4.4 and SciPy 1.17.1. The requirements file pins those versions. The downloader fetches Curtis 2020 arXiv2010.02272v1 and Curtis 2019 arXiv1905.06869v3 source archives, together 1,689,195 bytes. Each archive and each extracted member must match its named size and hash. A corrupt cache causes a failure, so a changed file cannot silently become the new reference.

The 2020 archive is 1,258,259 bytes with SHA-256: 0d1ef91cd427a4ca8617157f11d04bb995789da768bb9fbf51cbc7ca634c85dd. The source manifest separately names Benchmark\_Clusters.txt, Table\_1-Ruprecht147\_Catalog.txt and main.tex. The 2019 archive supplies Table1.tex and ms-arxiv.tex. The two versions are kept separate throughout the comparison.

Old AAS free access does not by itself establish a CC-BY license for redistributing these tables. The site therefore publishes its own synthetic and aggregate results, and a named-origin downloader. Original tables, row-wise derived catalogues and observed-star scatter remain local. The origin papers retain their own rights and terms.

Reading: Curtis et al. (2019), A Temporary Epoch of Stalled Spin-Down for Low-Mass Stars: Insights from NGC6811 with Gaia and Kepler arXiv1905.06869v3 · Curtis et al. (2020), When Do Stalled Stars Resume Spinning Down? Advancing Gyrochronology with Ruprecht147, arXiv2010.02272v1 · AAS Journals, article charges and copyright policy

## Count every row before choosing the stars

The combined benchmark table contains 923 rows:330 Pleiades,359 Praesepe,161 NGC 6811,8 NGC 752,30 NGC 6819 and 35 Ruprecht 147. A naive interpretation of its advertised fixed widths recovers 888. The missing 35 are exactly the old Ruprecht cluster, whose lines do not follow the advertised widths.

The included parser starts after the final table separator, uses the explicit Gaia DR 2 identifier delimiter and reads the eight terminal numeric columns. It validates positive periods and temperatures, unique cluster/identifier pairs and the total row count. Parse failures stop the calculation. No catch-and-continue loop is allowed to decide which ages survive.

The separate Ruprecht catalogue has 440 records, including two without a Gaia identifier. Select a positive rotation period and the literal Benchmark value Yes. This yields 35 stars; their identifiers match all 35 Ruprecht rows in the combined table. A prefix match such as Yes\*instead yields 39:three rapid outliers and one possible secondary-period case enter the sample.

The retained benchmark can contain wide binaries that act as effectively single rotators. Deleting every binary flag changes the author selection in another way. Membership remains that of the source catalogue. The exercise retains its stated subset and explains the selection.

Reading: Curtis et al. (2020), When Do Stalled Stars Resume Spinning Down? Advancing Gyrochronology with Ruprecht147, arXiv2010.02272v1

## Keep the different NGC 6811 samples visible

The 2020 machine table has 161 NGC 6811 rows. The text describing one polynomial selection refers to 135 YY rotators. The 2019 v 3 TeX table contains 172 rows with 162 Y,8 S and 2 Rcodes, whereas its abstract says 171 measured members. All 161 identifiers in the 2020 machine subset occur in the 2019 table;11 occur only in the older table.

These are distinct version and selection statements. Our fit is the temperature-limited 2020 machine-table subset. It is not named the published 135 YY calibration. The downloader supplies both sources so you can inspect the differences before interpreting the result.

Temperatures use the source dereddened Gaia DR 2 colour scale. Periods are derived periods in days, not the original K 2 or ground-based observing timestamps. The combined file does not provide a homogeneous per-star error column, cadence, exposure or time standard. Quarter-to-quarter information from a different sample cannot simply become an error column for these 161 stars.

Curtis 2019 refined NGC 6811 extinction to 0.15 mag with help from a gyrochronology comparison. Our imported temperatures inherit that choice. The whole-cluster holdout therefore remains conditional on that shared colour and extinction scale.

Reading: Curtis et al. (2019), A Temporary Epoch of Stalled Spin-Down for Low-Mass Stars: Insights from NGC6811 with Gaia and Kepler arXiv1905.06869v3 · Curtis et al. (2020), When Do Stalled Stars Resume Spinning Down? Advancing Gyrochronology with Ruprecht147, arXiv2010.02272v1

## Fit one young reference and watch a simple law fail

The first deliberately simple model fits 64 Praesepe stars between 4200 and 6000 K. Use a fourth-degree polynomial for log period against scaled temperature, with twelve Huber-style reweighting iterations and a 1.5 robust-scale threshold. Keep an ordinary least-squares fit as a separate comparison.

$$
x=\frac{T-5100\,\mathrm K}{900\,\mathrm K},\qquad \log P_{\rm ref}(T)=\sum_{j=0}^{4}a_jx^j,\qquad t_{\rm sep}=0.67\left(\frac{P}{P_{\rm ref}(T)}\right)^{1/n}\mathrm{Gyr}.
$$

The fixed exponents 0.5 and 0.62 impose a separable age law. They are hypotheses to test on withheld clusters.

Hold every other cluster out of that reference fit. At 4200–4600 K,27 NGC 6811 stars yield median ages 0.709 and 0.702 Gyr for the two exponents, compared with the fixed 1 Gyr source age. At 5500–6000 K,another 27 give 1.161 and 1.044 Gyr. The mismatch changes with temperature. This is the useful failure of a universal separable clock.

Resampling training stars 300 times estimates how that reference changes with training composition. It does not vary cluster ages, extinction, detection selection or missing period errors. The included reddening sensitivity changes only the adopted NGC 6811 colour correction and explicitly excludes shifted stars outside the temperature domain. In the cool bin the 0.62-law age moves from about 0.702 to 0.709 and 0.712 Gyr for the 0.15,0.22 and 0.25 mag extinction scenarios. The stall survives this particular sensitivity test.

Reading: Curtis et al. (2019), A Temporary Epoch of Stalled Spin-Down for Low-Mass Stars: Insights from NGC6811 with Gaia and Kepler arXiv1905.06869v3 · Curtis et al. (2020), When Do Stalled Stars Resume Spinning Down? Advancing Gyrochronology with Ruprecht147, arXiv2010.02272v1

## Build a supported nonseparable comparison

The later teaching model uses separate cubic log-period sequences from Praesepe, NGC 6811 and Ruprecht 147, with 64,103 and 24 stars in the 4200–6000 K initial selection. Their actual common support narrows to 4245.37–5832.12 K. Interpolation retains the temperature-dependent age response. The effective predictive width is specified in the previous chapter and the aggregate calibration file.

NGC 6819 and NGC 752 are whole-cluster holdouts. Within the actual support, the 19 NGC 6819 stars have median conditional ages around 2.40 Gyr versus the fixed 2.5 Gyr reference; the median central 95% width is about 0.80 Gyr. More than half receive a calibration-edge notice. Five NGC 752 stars give a median near 1.29 Gyr versus 1.4 Gyr, with about 0.99 Gyr median 95% width.

A stronger interpolation test removes NGC 6811 from the calibration itself. Of its stars,97 fall in the resulting support. Their median conditional age is about 0.850 Gyr; roughly 92.8% of central 95% intervals include the fixed 1 Gyr age, and about 61.9% raise an edge notice. This is valuable evidence about the prescription and its limits, not an absolute precision certificate.

For those catalogue probes, reported period and temperature condition exactly because homogeneous errors are absent. The predictive width remains. The numerical summary labels this exact conditioning and retains the boundary accumulations.

0

## Independently test the synthetic inference

The package also contains 180 own synthetic exposure-averaged observations from the shared finite surface. Its independent polar integration reproduces their noiseless fluxes. The period likelihood is checked against a full data-covariance Gaussian calculation, then the frequency search and age/temperature quadratures are refined.

The validation command preserves pole-on and short-lifetime failures, a two-longitude harmonic and exact daily aliases. It also compares native shear/envelope states with a separate polar chart, checks angular-momentum conservation and tests 400 ages drawn from the declared predictive model. These generated examples establish numerical and model-conditional checks for the calculation being taught.

Open results/summary.json and the separate validation summaries after the commands finish. They report aggregates and own synthetic results. Keep the original local inputs beside them if you want to inspect membership or individual published periods; their local provenance remains explicit.

0

## Exercises and explanations

1. A parser reads 888 rows without an exception. Which test exposes the loss?

   Read the explanation

   Compare the complete expected cluster counts and identifier sets. All 35 Ruprecht rows are absent. A successful numeric conversion is insufficient if it silently changes the age composition of the sample.

2. Why is leaving NGC 6811 out of the new period fit only a conditional validation?

   Read the explanation

   Its adopted temperatures and extinction still come from the source pipeline, which used a gyro comparison when refining extinction. The new fit is held out, but the imported temperature scale is shared.

## Try the prediction

### [Reproduce the same saved observation](https://sandboxphysics.com/labs/binary-star-mass/?analysis=rotation-age)

1. Export A lasting clock from the Lab and compare its schema and saved measurement fields with synthetic-observations.json.
2. Run the independent package on its supplied synthetic observation before replacing any inputs. Confirm the two clock alternatives and normalized age density.
3. Compare a daily-window or short-life export with the default. A useful model check preserves the failure instead of silently selecting the injected ten-day period.

[Previous: A rotation age is a distribution on a chosen scale](https://sandboxphysics.com/stories/stellar-rotation-ages/an-age-density-needs-a-scale/) [Next: Read the evidence for changing magnetic braking](https://sandboxphysics.com/stories/stellar-rotation-ages/read-the-changing-braking-evidence/)

## Public standalone science files

The ZIP contains independent science code, own synthetic observations, aggregate cluster comparisons and exact origin manifests. Two fixed author source archives are downloaded and hash-checked on your computer; original tables and observed-star rows are not redistributed.

[Download the complete standalone ZIP](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/rotation-age-science.zip)

SHA-256: `2b768a2960a429d265765bda1439d1b3571a12744a78c53942d64eaa92d7f9ed`

Individual scientific-file hashes are also inside package-manifest.json.

- [LICENSE.txt](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/LICENSE.txt) · 472 bytes
- [README.md](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/README.md) · 4,615 bytes
- [age\_calibration\_prototype.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/age_calibration_prototype.py) · 6,066 bytes
- [calibration-aggregate.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/calibration-aggregate.json) · 2,218 bytes
- [conditional\_age.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/conditional_age.py) · 6,101 bytes
- [empirical\_calibration.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/empirical_calibration.py) · 4,260 bytes
- [exposure-injections.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/exposure-injections.json) · 45,141 bytes
- [fetch\_sources.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/fetch_sources.py) · 2,400 bytes
- [frequency\_measure.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/frequency_measure.py) · 8,841 bytes
- [inspect\_cluster\_samples.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/inspect_cluster_samples.py) · 6,821 bytes
- [instantaneous-line-injections.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/instantaneous-line-injections.json) · 3,550,567 bytes
- [package-manifest.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/package-manifest.json) · 4,942 bytes
- [period\_likelihood.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/period_likelihood.py) · 3,927 bytes
- [reproduce.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/reproduce.py) · 7,630 bytes
- [requirements.txt](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/requirements.txt) · 27 bytes
- [rotation-age-science.zip](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/rotation-age-science.zip) · 602,006 bytes
- [rotation\_reference.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/rotation_reference.py) · 2,877 bytes
- [source-manifest.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/source-manifest.json) · 1,636 bytes
- [surface-injections.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/surface-injections.json) · 70,840 bytes
- [surface-reference.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/surface-reference.json) · 27,225 bytes
- [synthetic-observations.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/synthetic-observations.json) · 31,018 bytes
- [toy-rotation-reference.json](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/toy-rotation-reference.json) · 5,192 bytes
- [validate\_science.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/validate_science.py) · 669 bytes
- [verify\_angular\_momentum.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_angular_momentum.py) · 2,719 bytes
- [verify\_evolution.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_evolution.py) · 1,227 bytes
- [verify\_exposure.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_exposure.py) · 1,450 bytes
- [verify\_failure\_domains.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_failure_domains.py) · 6,308 bytes
- [verify\_hooks.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_hooks.py) · 2,528 bytes
- [verify\_instantaneous\_line.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_instantaneous_line.py) · 8,034 bytes
- [verify\_package.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_package.py) · 537 bytes
- [verify\_reddening\_sensitivity.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_reddening_sensitivity.py) · 2,900 bytes
- [verify\_sample\_versions.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_sample_versions.py) · 2,031 bytes
- [verify\_shared\_surface.py](https://sandboxphysics.com/stories/stellar-rotation-ages/materials/verify_shared_surface.py) · 4,200 bytes

## Sources and calculation scope

1. [Curtis et al. (2019), A Temporary Epoch of Stalled Spin-Down for Low-Mass Stars: Insights from NGC6811 with Gaia and Kepler arXiv1905.06869v3](https://arxiv.org/abs/1905.06869v3)

   Sections2–4 and source Table1: NGC6811 periods, quarter handling, membership, extinction and cool-star stalling. The TeX table has172rows; source-version differences are retained.

2. [Curtis et al. (2020), When Do Stalled Stars Resume Spinning Down? Advancing Gyrochronology with Ruprecht147, arXiv2010.02272v1](https://arxiv.org/abs/2010.02272v1)

   Sections2–6, AppendixA, Table4, Figures2and8–12; named Benchmark\_Clusters.txt and Table\_1-Ruprecht147\_Catalog.txt. The independent temperature-selected fit uses the actual machine table, not the135YY selection described for another fit.

3. [AAS Journals, article charges and copyright policy](https://journals.aas.org/article-charges-and-copyright/)

   Access and copyright policy reviewed2026-11-03. Free access to pre-2021articles does not automatically grant a CC-BY table redistribution license; named origin downloads keep original material local.
