Is this ~30 Hz ringing transient in L1 (O4a, GPS 1382955253) a known glitch morphology?

Hi all,

I run an unsupervised glitch-discovery pipeline (DANTE) over public O4a strain. One 32 s window in L1 came out as the highest-scoring candidate of the whole search, and I cannot take it further with public data alone. I would like help deciding whether what it contains is a known glitch morphology, or whether my pipeline is reacting to something uninteresting.

Please read this as "what am I missing?", not as a detection claim. I am an independent researcher with no LVK access, so the auxiliary-channel question — the decisive one — is exactly the one I cannot answer myself.

The window, and the feature in it

PropertyValue
DetectorL1
Flagged windowGPS 1382955228 – 1382955260 (UTC 2023-11-02 10:13:30)
Loud feature inside itGPS 1382955253.17 (+25.17 s into the window)
Morphologysharp onset, then narrowband \~28–30 Hz ringing lasting several seconds, with structure near 50–60 Hz
Amplitudepeak whitened strain 27, about 45× the median per-second energy of the window
Datapublic GWOSC strain, CAT1-gated

An important caveat about what my pipeline actually selected. The anomaly score comes from a Top-k patch pooling over the window's spectrogram, and for this candidate that selection is diffuse: the patches span 27.7 s of the 32 s window, with 41% of them in the first 4 s, and only 3 of 68 within 1 s of the loud feature described above. So the window is anomalous as a window, and I cannot claim that the feature at +25.17 s is what drove the flag. I am showing it because it is the one obviously non-Gaussian thing in there, and because it is the part a detector expert can most plausibly recognise.

The figure

Attached: the full whitened window (top) and Q-scans around the loud feature. Deliberately produced with stock gwpy calls rather than my pipeline, so it reproduces in about ten lines:

ts = TimeSeries.fetch_open_data('L1', 1382955224, 1382955264, sample_rate=4096)

w  = ts.whiten(4, 2).crop(1382955228, 1382955260)

w.q_transform(outseg=(1382955249, 1382955257), frange=(10, 512)).plot()

What I checked with public data

  • Cross-detector coincidence — none. Normalized cross-correlation of the whitened strains over the light-travel lag window (validated at 1.00 for an identical injected waveform vs 0.043 for independent noise). No H1 counterpart.
  • Auxiliary-channel coherence — max 0.478 against a family-wise threshold of 0.663 from a time-shift surrogate null. No correlation found.
  • Morphological isolation — one of only 2 candidates out of 10,372 falling outside the single macro-cluster my clustering produces, and the highest anomaly score in the run.

What I could not check — the honest limits

  1. My auxiliary-channel test is much weaker than its name suggests. I used the 7 channels available to me for L1, and 5 of those 7 are calibration-related (CAL-PCALX/Y_RX_PD, SUS-ETMX_L1/L2/L3_CAL_LINE); the others are ASC-X_TR_A_NSUM and IMC-WFS_B_I_PIT. There is no seismometer, magnetometer, microphone or accelerometer in that set. For a hypothesis like "a mechanical resonance was rung up", that is close to no test at all.
  2. No Gravity Spy comparison was possible. The released classification sets cover O1/O2/O3a/O3b and stop at GPS ≈1.269e9; O4a starts near 1.369e9. Zero overlap, so my cross-match returned "not found" for all 10,372 candidates by construction. That is a coverage gap, not evidence of novelty, and I do not treat it as one.
  3. I have not checked GraceDB or the hardware-injection channel for this time.
  4. n = 1. Nothing like it recurs in my search, so this is not a glitch class — at most a single instance.

What I am asking

  1. Is the impulsive-onset-plus-30 Hz-ringing shape a known O4a morphology with a name? To me it looks like a mechanical resonance excited by an impulse, but that is a guess from outside.
  2. Does anything appear in the full auxiliary channel set at GPS 1382955253.17 in L1 — seismic, suspension, or ASC in particular? This is the decisive check and the one I cannot run.
  3. Was L1 in a normal operating state then? Any commissioning activity, injection, or known excursion?
  4. Is it present in Omicron triggers? If a standard trigger generator did not flag it, that would point at my preprocessing rather than at the instrument, which I would very much want to know.

If this turns out to be a well-known artefact, that is a genuinely useful answer for me — it bounds what my pipeline is finding, and I will say so publicly.

Context and reproducibility

Method and limitations: arXiv:2607.18136. Code: github.com/lucacirfeta/dante-gravi-signal-ml

One caveat on reproducibility, since it bears on any number above that comes from my pipeline rather than from raw strain: the whitening and Q-transform are provided by gwpy, and my dependency specification bounded versions from below rather than pinning them. Re-running under a later gwpy major release reproduces the analysis qualitatively but not numerically. The figure and the amplitude numbers in this post are independent of that — they come from stock gwpy on public strain, as shown above.

Happy to provide per-event records or re-run any check that would help.

Thanks

Correction to my post above. The caveat I added about "what my pipeline actually selected" was wrong, and it pointed away from the very feature I was asking about. I would rather flag that in public than leave it standing.

What was wrong

In the caveat I wrote that the pipeline's Top-k patch selection was diffuse — spanning 27.7 s of the 32 s window, with only 3 of 68 patches within 1 s of the loud 30 Hz feature at GPS 1382955253.17 — and concluded the window was anomalous "as a window", not on that feature. Two bugs in my own diagnostic code produced that:

  1. A candidate look-up with np.isclose(gps, target, atol=0.5). With NumPy's default rtol=1e-5 at GPS \~1.38e9 the effective tolerance is \~13,800 s, not 0.5 s, so it silently matched a different event \~3.8 hours away.
  2. A time/frequency axis transposition: gwpy's Q-transform array is (time, frequency), and I had read it as (frequency, time). Both axes are 256 px after resizing, so nothing errored.

The correct picture — the original question stands

There was a third, separate off-by-four: the GPS I quoted (1382955228) labels the start of the padded crop, not the analysis window. The window actually scored is GPS 1382955232–1382955264. I confirmed this the hard way — the stored scores reproduce to four decimal places only with that window, and not at all with the one I had been using.

With all three fixed, the Top-k patches concentrate on the feature I originally showed: they span GPS 1382955253–1382955264 in a 26–42 Hz band, and the 28.4 Hz feature at GPS 1382955253.17 sits right at the start of that region, with 20 of 68 patches within ±1 s of it. I verified this by overlaying the stored patches on the spectrogram and looking at it directly.

So the pipeline did select the impulsive-onset-plus-\~30 Hz-ringing feature. My original questions are the right ones, and I withdraw the caveat that suggested otherwise:

  1. Is the impulsive-onset-plus-30 Hz-ringing shape a known O4a morphology in L1 around GPS 1382955253?
  2. Does anything appear in the auxiliary channels there — seismic, suspension, ASC?
  3. Is it present in Omicron triggers?

What is unaffected, and one more correction

The figure and amplitude numbers in the original post come from stock gwpy on public strain and are unchanged. The auxiliary-channel result is unchanged and I have re-run it: maximum coherence 0.478 against a family-wise threshold of 0.663, reproduced bit-identically. The cross-detector coincidence result also still holds after re-running with the corrected band (0.149% of candidates exceed the time-shifted null threshold, against a 1% nominal rate).

One further correction: I earlier wrote that re-running under a later gwpy major release "reproduces the analysis qualitatively but not numerically". I have since tested that directly, in an isolated environment with gwpy 3.0.13 against 4.0.1: the spectrograms agree to 5×10-10 and the scores are identical to six decimal places. The gwpy version is not a source of disagreement, and I should not have said it was without testing it.

One caveat on cross-checking against it: I found the GPS-labelling offset described above after that version went up, so its singleton section still quotes the feature at +25.17 s into the window and 7 of 68 patches within ±1 s. The values in this post — +21.17 s and 20 of 68, against the corrected window — are the right ones, and the paper will be updated. The frequency band, the GPS of the feature itself, and every other result are unaffected.

Apologies for the noise; thanks to anyone still willing to look at GPS 1382955253 in L1.

Hi Luca — good catches on all three, especially the np.isclose rtol trap at GPS ~1.4e9. That one bites everyone eventually and it’s the kind of silent-match bug that’s almost impossible to notice without exactly the reproduce-to-N-decimals discipline you used.

I re-ran a few public-data checks on the corrected window (1382955232–1382955264, 26–42 Hz), and they line up with your revised picture rather than the original caveat:

Feature frequency. Independent peak-find in-band lands at 28.0 Hz, matching your 28.4 Hz — so we’re looking at the same thing, and it’s not a 60 Hz mains harmonic or sub-harmonic.

H1. Whitened, band-passed, max |corr| at the physical lag is 0.116 — no morphological counterpart in H1. Consistent with your coincidence null; the feature is local to L1.

Loudness. In-band energy of the window runs ~2 orders of magnitude above adjacent 32 s segments. I wouldn’t quote a precise factor — whitening self-inflates against a feature this loud, so treat it as “genuinely loud,” not a calibrated number — but it rules out your pipeline reacting to noise. There’s a real, loud, L1-only transient here.

So on your three questions, from public data alone I can only speak to the shape: impulsive onset + ~30 Hz ringing, single-detector, aux-clean by your own coherence result (0.478 vs 0.663). That profile is a close match to the low-frequency scattered-light family — except that scattered light usually leaves a trace in ASC or suspension channels, and you’re reporting aux-clean. That tension is the interesting part, and it’s exactly where public strain runs out: your questions 2 and 3 (Omicron triggers, specific aux channels) are the decisive ones and need LVK-side access, which I don’t have either.

If it helps, the checks above are a short gwpy script — happy to share so you can fold them into your reproduce set. And for what it’s worth, the way you’ve handled the errata here is more convincing than the original post was — the corrected version is the stronger paper.

Thank you for this — genuinely useful, not just kind. Three things in particular:

The independent 28.0 Hz peak-find is the check I most wanted someone else to run, since it's the one number in my corrected write-up that isn't just "the model agrees with itself." Two independent methods landing within 0.4 Hz of each other is a much stronger statement than either alone.

Same for the H1 cross-check (max |corr| 0.116 at the physical lag) — an independent implementation agreeing with our coincidence null is worth more than us re-running our own code twice.

The scattered-light / aux-clean tension is the right thing to flag, and I don't think it resolves cleanly with what I have. To be precise about what "aux-clean" means here: it's aux-clean with respect to the 9 L1 channels in the public GWOSC auxiliary release, none of which is a seismometer or an accelerometer. If the mechanism is scattered light coupling through a seismic or ASC path outside that set, our result is silent on it, not contradicting it. I'd rather say that plainly than let "aux-clean" imply more coverage than it has.

Yes please on the script — happy to fold it into the reproduce set with attribution, if you're comfortable sharing it that way.

And to close the loop: questions 2 and 3 (Omicron triggers, the full aux channel set) remain the ones only LVK-side access can answer. If anyone with that access reads this thread, they're still the open items.

Here it is — one file, stock gwpy on public strain, no auth needed:

Fold it in however’s useful; attribution’s appreciated but not required.
Two things I wrote into the file rather than leaving in a post, since they should travel with the code:
The energy check reports a plain ratio, not the z-score I quoted earlier. That z was inflated by whitening reacting to the feature itself, and it had no business being cited as a number. The docstring says so explicitly.
And your point about aux coverage is in there too — that the public release is 9 L1 channels with no seismometer or accelerometer, so a scattered-light coupling through a seismic or ASC path is invisible to it, and an aux-clean result there is silence rather than contradiction. That distinction gets lost when a script is passed around, so it’s in the header rather than in a post.
Agreed on where this stands: the shape is a close match to the low-frequency scattered-light family, the aux question is unresolved rather than answered, and questions 2 and 3 need LVK-side access. If nobody from that side picks it up, the honest version is “loud, L1-local, ~28 Hz, unclassified” — still a cleaner statement than most single-detector candidates get.Ran it here against the corrected window and got 28.0 Hz, max |corr| 0.116, and the loudness ratio quoted above — shout if it misbehaves on your setup.

Small correction to my own numbers, in the spirit of the thread: the H1 max-correlation figure isn’t stable. Re-running the script gives 0.059 at −12.0 ms, where I first got 0.116 at −1.0 ms. The lag wanders to the edge of the search window, which is what you’d expect when there’s no real peak to find — the maximiser is picking noise.

Both runs support the same conclusion (no H1 counterpart), but the value shouldn’t be quoted to three decimals as if it were a measurement. Treat it as consistent with zero.

The other two reproduce: peak 28.0 Hz, loudness ratio ~300× with the caveats already in the docstring.

Thanks — and I appreciate that the caveats are documented in the script rather than only in the post. That matters for reproducibility because the code may be passed around without the surrounding discussion. Attribution is absolutely fine by me. For an unambiguous reference, the comparison below uses revision 9ea0f8e4 of your public cross-check.

I have now checked the public gist line by line and rerun the same recipe on our local O4a mirror, using the 32 s window \[1382955232, 1382955264\], the feature time 1382955253.17, the 26–42 Hz band, and the same 16 adjacent background windows. The result reproduces your second run:

  • Peak frequency: 28.0 Hz.
  • In-band loudness ratio: 304× relative to the mean of the 16 adjacent windows, which is the denominator used in your script. Using the median only as a sensitivity diagnostic gives 315×. This is an order-of-magnitude descriptor, not a calibrated significance.
  • Raw H1–L1 correlation: 0.0585 at −11.96 ms. This is the same edge-of-window maximum that you reported as 0.059 at −12 ms. The value and lag should not be quoted as a stable measurement.

For transparency, the different values we previously obtained were produced by a different implementation: it used production whitening, a different feature/window treatment, a median background denominator, and a different correlation statistic. They should not have been described as an exact rerun of your script.

We have therefore generalized your recipe as a parameterized characterize-candidate step rather than hard-coding this event. It accepts the detector, 32 s window, feature time, frequency band, partner detector, number of background windows, and their spacing, so the same independent check can be applied to candidates in future observing runs. The output records the recipe, its exact source revision, and attribution. The generalized implementation and regression tests are public in commit 13c9fe8.

python main.py characterize-candidate \\

  --detector L1 \\

  --gps 1382955232 \\

  --feature-gps 1382955253.17 \\

  --band 26 42 \\

  --partner H1 \\

  --n-background 16 \\

  --bg-spacing 40 \\

  --catalog-gps 1382955228

For a later H1/L1 run, the descriptor calculation only requires changing the window, feature, band, partner, and background parameters. To include the optional production-veto comparison as well, --coincidence-artifact must point to the corresponding run's stored coincidence result.

We keep this raw descriptor separate from the authoritative production coincidence veto. For this candidate, the stored production result is cc_onsource = 0.0716, compared with a time-shift null mean of 0.1970 and null maximum of 0.2864 over seven admissible shifts. Thus the independent descriptor and the calibrated production test support the same limited conclusion: no robust H1 counterpart is resolved. The raw 0.0585 value by itself is not a significance test.

On the auxiliary channels, we are in the same position you are. The public data available to us do not contain the full seismic, suspension, and ASC witness set. A null result in the public subset therefore means that no coupling was resolved in the channels tested; it does not exclude scattered-light coupling through an unavailable witness channel.

Our most defensible description remains: a loud, L1-local transient with an approximately 28 Hz feature, qualitatively similar to the low-frequency scattered-light family, but still unclassified and with no resolved H1 counterpart under the production coincidence null.

The two checks that could materially advance the interpretation still require LVK-side access: whether an Omicron trigger is present and whether the full seismic, suspension, or ASC channel set shows a witness around GPS 1382955253.17 in L1, particularly in the 26–42 Hz band.

Nothing to add from my side — that reproduces closely enough that I’d call the descriptor settled, and generalising it into a parameterised step is more useful than the one-off was.

One small observation on the production numbers: cc_onsource = 0.0716 sits not just below threshold but below the time-slide null mean of 0.1970. With seven shifts that’s coarse and I wouldn’t lean on it, but it’s a slightly stronger statement than “does not exceed” — if there were a weak H1 counterpart you’d expect on-source at or above the null level, not under it. It reinforces “no resolved counterpart” rather than merely “not significant.”

Agreed on the defensible description as you’ve worded it, and on where it stops. The aux question stays open in the same way for both of us, and the two checks that would move it are still on the LVK side.

Regards Kretski

В вторник, 28 юли 2026 г. в 01:37:02 ч. Гринуич+3, Luca Cirfeta notifications@gwosc.discoursemail.com написа:

Someone replied to your post.

| lucacirfeta
July 27 |

  • | - |

Thanks — and I appreciate that the caveats are documented in the script rather than only in the post. That matters for reproducibility because the code may be passed around without the surrounding discussion. Attribution is absolutely fine by me. For an unambiguous reference, the comparison below uses revision 9ea0f8e4 of your public cross-check.

I have now checked the public gist line by line and rerun the same recipe on our local O4a mirror, using the 32 s window [1382955232, 1382955264], the feature time 1382955253.17, the 26–42 Hz band, and the same 16 adjacent background windows. The result reproduces your second run:

  • Peak frequency: 28.0 Hz.
  • In-band loudness ratio: 304× relative to the mean of the 16 adjacent windows, which is the denominator used in your script. Using the median only as a sensitivity diagnostic gives 315×. This is an order-of-magnitude descriptor, not a calibrated significance.
  • Raw H1–L1 correlation: 0.0585 at −11.96 ms. This is the same edge-of-window maximum that you reported as 0.059 at −12 ms. The value and lag should not be quoted as a stable measurement.

For transparency, the different values we previously obtained were produced by a different implementation: it used production whitening, a different feature/window treatment, a median background denominator, and a different correlation statistic. They should not have been described as an exact rerun of your script.

We have therefore generalized your recipe as a parameterized characterize-candidate step rather than hard-coding this event. It accepts the detector, 32 s window, feature time, frequency band, partner detector, number of background windows, and their spacing, so the same independent check can be applied to candidates in future observing runs. The output records the recipe, its exact source revision, and attribution. The generalized implementation and regression tests are public in commit 13c9fe8.

python main.py characterize-candidate \

  --detector L1 \

  --gps 1382955232 \

  --feature-gps 1382955253.17 \

  --band 26 42 \

  --partner H1 \

  --n-background 16 \

  --bg-spacing 40 \

  --catalog-gps 1382955228

For a later H1/L1 run, the descriptor calculation only requires changing the window, feature, band, partner, and background parameters. To include the optional production-veto comparison as well, --coincidence-artifact must point to the corresponding run’s stored coincidence result.

We keep this raw descriptor separate from the authoritative production coincidence veto. For this candidate, the stored production result is cc_onsource = 0.0716, compared with a time-shift null mean of 0.1970 and null maximum of 0.2864 over seven admissible shifts. Thus the independent descriptor and the calibrated production test support the same limited conclusion: no robust H1 counterpart is resolved. The raw 0.0585 value by itself is not a significance test.

On the auxiliary channels, we are in the same position you are. The public data available to us do not contain the full seismic, suspension, and ASC witness set. A null result in the public subset therefore means that no coupling was resolved in the channels tested; it does not exclude scattered-light coupling through an unavailable witness channel.

Our most defensible description remains: a loud, L1-local transient with an approximately 28 Hz feature, qualitatively similar to the low-frequency scattered-light family, but still unclassified and with no resolved H1 counterpart under the production coincidence null.

The two checks that could materially advance the interpretation still require LVK-side access: whether an Omicron trigger is present and whether the full seismic, suspension, or ASC channel set shows a witness around GPS 1382955253.17 in L1, particularly in the 26–42 Hz band.