Weighting and the fit
The fit is weighted least squares, and the weights come straight from the quality flags. This page opens that box: what each flag is worth, what the coverage bar rejects, and why one unflagged spike moves every amplitude a little.
Flags become weights
Each sample enters the normal equations with a weight, and by default that weight is a direct function of its flag. Flag 1 is full weight; flag 2, probably good, is admitted at half; everything from flag 3 upward, and every gap, is dropped to zero and never touches the matrix.
| Flag | Meaning | Weight |
|---|---|---|
| 1 | good | 1.0 |
| 2 | probably good | 0.5 |
| 3 | probably bad | 0.0 |
| 4 | bad | 0.0 |
| 5 | filled | 0.0 |
| 9 | missing | 0.0 |
You can override the map with analyse(rec, weights={1:1.0, 2:0.8}) when you trust the probably-good samples more than the default allows, but changing it is a decision to document, not a knob to twirl until the residual looks nicer.
sol = tc.analyse(rec)
print(sol.weights_used)
# {1: 1.0, 2: 0.5, 3: 0.0, 4: 0.0, 5: 0.0, 9: 0.0}
print(f"{(sol.weights_used_count):d} samples carried weight")
# 88050 samples carried weight
The coverage bar
After the zero-weight samples are removed, what remains is the coverage, and analyse refuses to run if that fraction falls under min_coverage, which defaults to 0.75. The station-7 record keeps 98.9 % of its span after flagging, so it clears the bar with room to spare; a record that is half gaps would raise CoverageError rather than return a confident-looking fit built on a quarter of the data.
Coverage is measured against the span, not the sample count, which matters for irregular records: a month of dense sampling followed by a month of nothing is 50 % coverage even if every present sample is flag 1. Raising the bar with --min-coverage 0.9 is the right move when the terms you care about are weak and a long gap sits over a spring tide.
Why one spike tilts everything
Least squares spreads any single large error across all of the fitted amplitudes, because every basis cosine is non-zero at the offending timestamp. A lone four-metre spike left unflagged does not create a visible bump in one constituent; it nudges a dozen of them by a fraction of a per cent each, which is invisible in the table and fatal in a comparison between two stations. That is the whole reason the flaggers run first, and it is why a clean residual plot is worth more than a tidy amplitude table.
Next: reading the residual once the fit is trustworthy.