pyTimeGrapher is a Python-based acoustic analysis tool designed to act as a software timegrapher for regulating mechanical watches and pendulum clocks. It serves as a free, open-source alternative to dedicated hardware (like the Weishi No. 1000 or Witschi Watch Expert), using your computer's microphone or a contact piezo sensor to measure the heartbeat of a movement.
Current release: v0.9
The screenshot shows the live rate, beat error, waveform, trend graph, and real-time detection log while measuring a movement through an inductive/low-signal input.
- Universal Compatibility: Works with both fast-beat wristwatches (14,400 to 36,000 bph) and slow-beat pendulum clocks (3,600 to 7,200 bph).
- Dual-Mode Analysis:
- Instant Rate: Shows real-time stability and immediate escapement noise.
- Session Average: Uses Linear Regression (slope detection) to provide a "Chronometer-grade" daily rate (s/d) that ignores short-term jitter.
- Smart Noise Filtering:
- Dead Time Lockout: Automatically ignores "ringing" and echoes (80ms lockout) to prevent double-triggering on loud movements.
- Auto-Gain Control (AGC): Levels the displayed tick envelope to about 85% of the graph, using recurring ticks to resist isolated loud noises.
- Beat Error Measurement: Calculates the milliseconds of error between the "tick" and the "tock" (pallet fork centering).
- Advanced Visual Feedback:
- Waveform Scope: Real-time visualization of the acoustic signal.
- Beat Error Trend Graph: A scrolling 60-second graph showing individual beat deviations and a moving average line for visual rate trend analysis.
- LED Indicator: Simulated LED beat indicator and optional audio click.
- About & Support: Built-in "About" window with author information and a way to support the project.
You will need Python 3.x and the following libraries:
pip install numpy scipy matplotlib pyaudioNote for Linux Users: You may need to install the PortAudio development headers before installing pyaudio:
sudo apt-get install python3-pyaudio portaudio19-devWhile a standard microphone works for loud clocks, mechanical wristwatches require a contact microphone for accurate results due to their low acoustic energy.
- Best: A generic "Clip-on Guitar Pickup" or Piezo disc taped to the watch case.
- Good: A high-quality lapel mic clipped directly to the crown, or an Inductive Coupler (as used with analog telephones) which can sometimes pick up the electromagnetic pulse of certain movements.
- Okay: A standard webcam mic (works only for loud pocket watches or pendulum clocks).
- Launch the App:
python pyTimeGrapher.py
- Select Input: Choose your microphone from the dropdown list.
- Start Listening: Click Start/Stop.
- Calibration:
- Enable Auto AGC and Auto Thresh for automatic setup. Clear watch ticks typically level within about a second; slow clocks need a few ticks to establish a cadence.
- Watch the Input Level waveform graph. You want clear, distinct spikes.
- For manual setup, disable the corresponding automatic control, then adjust gain and set the Threshold slider above the background noise but below the main spikes.
- The LED in the top right should flash steadily with every tick.
- Read the Stats:
- Wait about 30-60 seconds for the Session Average to stabilize.
- Rate: How many seconds per day the watch is gaining (+) or losing (-).
- Beat Error (B.E.): The timing difference between the "tick" and "tock." A reading of 0.0ms is perfect; anything under 2.0ms is acceptable.
- Trend Graph: Observe the blue dots (individual beats) and the red line (moving average) to see how the watch is performing over time.
pyTimeGrapher uses a digital signal processing (DSP) pipeline:
- Bandpass Filter: Isolates frequencies between 2kHz and 10kHz (the "snap" of the pallet fork).
- Envelope & Smoothing: Converts the raw audio spikes into a smooth "hill" for detection.
- Heuristic Lockout: Once a tick is detected, the sensor goes "blind" for 80ms to ignore reverberation.
- Linear Regression: Instead of averaging simple intervals (which may drift wildly), the Session Rate calculates the slope of the total elapsed time, offering mathematically superior stability for long-term regulation.
Both automatic controls measure the filtered, smoothed envelope before software gain. A rolling 3.2-second history estimates background noise and finds recurring peaks near the supported beat rates. Gain targets the stronger tick/tock peaks at 28,000 on the 32,768-high scope; the threshold sits above estimated noise and below the quieter ticks when they are distinguishable. The two controls can be enabled independently.
Gain settles toward a new estimate in roughly 0.6 seconds, with no slow recovery mode after detection locks. Establishing or replacing the estimate can take a few ticks, especially for slow clocks or a large signal change. Isolated loud peaks are excluded from the recurring-tick estimate; a disturbance may run off the top of the scope without turning down the watch signal. Detection also requires the envelope to fall below the threshold before another edge can trigger it.
Automatic gain cannot recover audio already clipped at the microphone, separate ticks completely buried in noise, or fill the graph when the configured gain limit is insufficient. Inductive / Low Signal raises that limit from 500× to 5,000×. Continuous interference or other rhythmic sounds can still require better microphone placement or manual settings. Acquisition timings above are verified with synthetic audio and depend on the input signal.
Run the DSP regression checks without opening a microphone or GUI:
python -m unittest test_auto_levels test_reliability -vPull requests are welcome! We are currently looking for:
- Algorithm improvements for low-amplitude movements.
- Lift Angle / Amplitude calculation support.
