Anemometers are critical wind-speed sensors, but they can be affected by weather, icing, and miscalibration. Step 4_1 Wind Sensor Check runs two anemometer-related checks:

  • Step 4a: InterTurbineWindspeedAnomalyFlagging, a 10-minute peer-population anomaly flag written to fact_wtg_anemometer_anomaly_10m (WIND_WTG_ANEMOMETER_ANOMALY_TABLE).
  • Step 4b: AnemometerCheck, a daily rating that combines the Step 4a peer flag roll-up with an optional power-curve self-check and writes to fact_wtg_sensor_rating_1d (WIND_WTG_SENSOR_RATING_TABLE).

Inter-Turbine Anemometer Anomaly Detection

Purpose: Detect abnormal nacelle wind-speed patterns by comparing turbine measurements across a peer population.

Implemented by InterTurbineWindspeedAnomalyFlagging (wind/flagging/inter_turbine_windspeed_anomaly_flagging.py), run as Step 4a of Step 4_1 Wind Sensor Check.py.

Required Signals

Sensors: - WindSpeed (WNAC_WIND_SPEED) - nacelle anemometer wind-speed measurement, with the corresponding Step 3_2 DQ flag available.

Population Requirements

  • Minimum turbines: 3 (configurable via min_absolute_count)
  • Minimum population coverage: 80% (configurable via min_population_percent)
  • Terrain mode: default complex_terrain=False uses the whole-site population. When complex_terrain=True, each turbine is compared only against its configured referenceTurbines pool, including itself; turbines with no sufficient reference pool are skipped and left normal (0).

Filtering

  • Data quality only - bad-quality WindSpeed samples are discarded before the population Z-score is computed.

Compute Logic

Uses population-based Z-score analysis: 1. Build a combined turbine dataframe for WindSpeed. 2. Remove bad-quality samples. 3. Compute population Z-scores across all turbines at each timestamp (complex_terrain=False), or per turbine against its referenceTurbines pool (complex_terrain=True). 4. Set raw flags to 1 when abs(zscore) > k, 0 otherwise, and -1 when the Z-score cannot be computed. 5. For each turbine, apply the rolling temporal rule: within a consecutive_hours_threshold hour window, flag a timestamp as abnormal only when all valid points in the window are anomalous and at least consecutive_hours_threshold valid points are present.

Output: Categorical 10-minute flag AnemometerFlag (POINT_NAME_ANEMOMETER_ANOMALY) with signal category InterTurbineWindSpeedAnomality (WTUR_INTER_TURBINE_WINDSPEED_ANOMALY), written to fact_wtg_anemometer_anomaly_10m. - 1: Abnormal wind speed (anomaly detected) - 0: Normal operation - -1: Bad quality or Z-score could not be computed

Algorithm Parameters

  • k: Z-score threshold (default: 3.0) - sensitivity control
  • consecutive_hours_threshold: rolling window length in hours and minimum valid-point count for flagging (default: 2)
  • min_population_percent: minimum percentage of turbines (default: 80.0)
  • min_absolute_count: minimum absolute number of turbines (default: 3)
  • complex_terrain: use per-turbine referenceTurbines pools instead of the whole-site population (default: False)

Key Advantage: Unlike ARR and parameter estimation algorithms, inter-turbine anemometer detection requires no training data. It operates on the current data chunk directly using population statistics. This means even short observation windows (hours to days) can be analyzed without prior historical context, making it useful for real-time anomaly detection on new turbines or after maintenance.


Inter-Turbine Wind Speed Anomaly Detection

Figure: Population-based wind speed anomaly detection across turbine fleet


Anemometer Self-Check (daily grading)

Purpose: Catch an anemometer that drifts or under-reads, for example due to miscalibration or icing bias, using the turbine's own physics. This covers a blind spot of the inter-turbine method, which cannot see a fleet-wide bias or a fault masked by similar neighbours.

Implemented by AnemometerCheck (wind/data_preparation/anemometer_evaluation.py), run as Step 4b of Step 4_1 Wind Sensor Check.py. It emits one daily row per turbine to fact_wtg_sensor_rating_1d (WIND_WTG_SENSOR_RATING_TABLE) - the unified daily sensor-rating table shared with 4c/4d/4e/4f/4g.

Two complementary anchors

  1. Self bias (AnemometerSelfBiasMs) - daily mean of v_measured - v_expected, where v_expected is the wind speed implied by the turbine's own ActivePower inverted through its reference contractual power curve from Step 2_1 (DIM_WIND_CONTRACTUAL_CURVE_TABLE). - The inversion power -> wind speed is only well-posed on the monotonic Region II of the curve. The rated plateau (Region III) is degenerate and near-zero power is flat and noisy, so samples are gated to a [region2_low_frac, region2_high_frac] fraction-of-rated window and the curve is restricted to below its knee (find_knee_point).
  2. Peer flag fraction (AnemometerPeerFlagFrac) - daily roll-up (fraction of valid 10-minute samples flagged anomalous) of the Step 4a inter-turbine flag (AnemometerFlag). Flag value -1 is excluded from the denominator. This keeps a single source of truth for the population comparison: 4a stays the 10-minute primitive consumed by sensor selection, while 4b only summarises it daily.

Rating (AnemometerRating)

Reuses the shared WIND_SENSOR_RATING_* codes (0 normal, 1 suspect, 2 failed, 3 insufficient_data), self-check first then peer: - abs(self bias) >= self_bias_suspect_ms -> SUSPECT - peer_flag_frac >= peer_flag_frac_suspect -> SUSPECT - abs(self bias) >= self_bias_fail_ms -> FAILED - INSUFFICIENT_DATA (3) where neither anchor has data that day, for example fewer than min_daily_samples Region-II samples and no valid Step 4a peer flags. The daily metrics can be NaN while the rating is INSUFFICIENT_DATA; if there is no raw wind-speed daily index, no daily anemometer rows are emitted.

Algorithm Parameters (schemas/algorithm_defaults.py)

  • self_bias_suspect_ms (default 1.0), self_bias_fail_ms (default 2.0)
  • peer_flag_frac_suspect (default 0.2)
  • min_daily_samples (default 36 = 6 h of Region-II samples)
  • region2_low_frac (default 0.05), region2_high_frac (default 0.85)

Either anchor is optional: a turbine without a reference power curve is graded on the peer anchor alone; with no Step 4a flag it is graded on the self-check alone. The algorithm input validation requires at least one of these anchors.