%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22yohou%5Bplotting%5D%22%2C%0A%23%20%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.8%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Signal%20Processing%20Transformers%0A%0A%20%20%20%20Yohou%20provides%20signal%20processing%20transformers%20for%20smoothing%2C%20trend%0A%20%20%20%20extraction%2C%20rate-of-change%20analysis%2C%20and%20cumulative%20integration.%0A%20%20%20%20These%20work%20best%20on%20high-frequency%20data.%0A%0A%20%20%20%20This%20notebook%20shows%20how%20to%20apply%20NumericalFilter%20(Butterworth%2C%20Chebyshev%2C%20Bessel)%2C%20NumericalDifferentiator%2C%20and%20NumericalIntegrator%20for%20signal%20smoothing%20and%20rate-of-change%20extraction.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20polars%20as%20pl%0A%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_electricity_demand%0A%20%20%20%20from%20yohou.plotting%20import%20plot_time_series%0A%20%20%20%20from%20yohou.preprocessing%20import%20NumericalDifferentiator%2C%20NumericalFilter%2C%20NumericalIntegrator%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20NumericalDifferentiator%2C%0A%20%20%20%20%20%20%20%20NumericalFilter%2C%0A%20%20%20%20%20%20%20%20NumericalIntegrator%2C%0A%20%20%20%20%20%20%20%20fetch_electricity_demand%2C%0A%20%20%20%20%20%20%20%20pl%2C%0A%20%20%20%20%20%20%20%20plot_time_series%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%201.%20Load%20High-Frequency%20Data%0A%0A%20%20%20%20Signal%20processing%20transformers%20are%20most%20useful%20on%20high-frequency%20data%0A%20%20%20%20where%20noise%20and%20rapid%20fluctuations%20are%20present.%20We%20load%20a%20two-week%20slice%0A%20%20%20%20of%20the%20half-hourly%20electricity%20demand%20dataset%20from%20Victoria%2C%20Australia.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_electricity_demand%2C%20mo%2C%20pl)%3A%0A%20%20%20%20elec%20%3D%20fetch_electricity_demand().frame%0A%20%20%20%20%23%20Use%20a%20manageable%20subset%20(first%202%20weeks%20%3D%20672%20half-hour%20periods)%0A%20%20%20%20elec_subset%20%3D%20elec.head(672).select(%22time%22%2C%20pl.col(%22vic__demand%22).alias(%22demand%22))%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22**Electricity%20Demand**%20(30-min%20intervals)%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22Full%20dataset%3A%20%7Blen(elec)%7D%20rows%2C%20using%20first%20%7Blen(elec_subset)%7D%20rows%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22Columns%3A%20%7Belec_subset.columns%7D%22%0A%20%20%20%20)%0A%20%20%20%20return%20(elec_subset%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F)%20renders%20the%20raw%20demand%20signal.%20The%20pronounced%20daily%0A%20%20%20%20cycles%20and%20intra-day%20noise%20are%20clearly%20visible.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(elec_subset%2C%20plot_time_series)%3A%0A%20%20%20%20plot_time_series(elec_subset%2C%20title%3D%22Electricity%20Demand%3A%20Raw%20(2%20Weeks)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%202.%20Low-Pass%20Filter%20(Smoothing)%0A%0A%20%20%20%20%5B%60NumericalFilter%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.signal.NumericalFilter%2F)%20applies%20a%20digital%20IIR%20filter%20to%20every%20numeric%20column.%0A%20%20%20%20A%20Butterworth%20low-pass%20filter%20with%20%60cutoff_frequency%3D0.05%60%20(as%20a%0A%20%20%20%20fraction%20of%20the%20Nyquist%20rate)%20attenuates%20fast%20oscillations%20and%20reveals%0A%20%20%20%20the%20underlying%20demand%20trend.%20We%20overlay%20the%20filtered%20and%20raw%20signals%0A%20%20%20%20using%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F)%20on%20a%20joined%20DataFrame.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalFilter%2C%20elec_subset%2C%20plot_time_series)%3A%0A%20%20%20%20lp_filter%20%3D%20NumericalFilter(%0A%20%20%20%20%20%20%20%20design%3D%22butterworth%22%2C%0A%20%20%20%20%20%20%20%20mode%3D%22lowpass%22%2C%0A%20%20%20%20%20%20%20%20order%3D4%2C%0A%20%20%20%20%20%20%20%20cutoff_frequency%3D0.05%2C%0A%20%20%20%20)%0A%20%20%20%20lp_filter.fit(elec_subset)%0A%20%20%20%20demand_smooth%20%3D%20lp_filter.transform(elec_subset)%0A%0A%20%20%20%20%23%20Combine%20for%20visual%20comparison%0A%20%20%20%20_combined%20%3D%20elec_subset.join(%0A%20%20%20%20%20%20%20%20demand_smooth.rename(%7B%22demand%22%3A%20%22demand_smooth%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22Low-Pass%20Filter%20(cutoff%3D0.05)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%203.%20High-Pass%20Filter%20(Residual%20Extraction)%0A%0A%20%20%20%20A%20high-pass%20%5B%60NumericalFilter%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.signal.NumericalFilter%2F)%20removes%20the%20slow-moving%20trend%20and%20keeps%0A%20%20%20%20only%20the%20fast-changing%20component.%20This%20is%20useful%20for%20isolating%20noise%2C%0A%20%20%20%20short-term%20demand%20spikes%2C%20or%20intra-day%20fluctuations%20away%20from%20the%0A%20%20%20%20baseline%20level.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalFilter%2C%20elec_subset%2C%20plot_time_series)%3A%0A%20%20%20%20hp_filter%20%3D%20NumericalFilter(%0A%20%20%20%20%20%20%20%20design%3D%22butterworth%22%2C%0A%20%20%20%20%20%20%20%20mode%3D%22highpass%22%2C%0A%20%20%20%20%20%20%20%20order%3D4%2C%0A%20%20%20%20%20%20%20%20cutoff_frequency%3D0.05%2C%0A%20%20%20%20)%0A%20%20%20%20hp_filter.fit(elec_subset)%0A%20%20%20%20demand_residual%20%3D%20hp_filter.transform(elec_subset)%0A%0A%20%20%20%20_combined_hp%20%3D%20elec_subset.join(%0A%20%20%20%20%20%20%20%20demand_residual.rename(%7B%22demand%22%3A%20%22demand_highpass%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined_hp%2C%20title%3D%22High-Pass%20Filter%20(cutoff%3D0.05)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%204.%20Different%20Filter%20Designs%0A%0A%20%20%20%20%5B%60NumericalFilter%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.signal.NumericalFilter%2F)%20supports%20three%20classical%20IIR%20designs.%20**Butterworth**%0A%20%20%20%20has%20the%20flattest%20passband%20response.%20**Chebyshev%20Type%201**%20allows%20a%0A%20%20%20%20steeper%20transition%20band%20at%20the%20cost%20of%20passband%20ripple%20(controlled%20by%0A%20%20%20%20%60passband_ripple%60).%20**Bessel**%20preserves%20the%20signal's%20time-domain%20shape%0A%20%20%20%20best%20but%20has%20the%20gentlest%20cutoff.%20We%20compare%20all%20three%20on%20the%20first%20200%0A%20%20%20%20samples%20using%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalFilter%2C%20elec_subset%2C%20plot_time_series)%3A%0A%20%20%20%20_designs%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22butterworth%22%3A%20NumericalFilter(design%3D%22butterworth%22%2C%20mode%3D%22lowpass%22%2C%20order%3D4%2C%20cutoff_frequency%3D0.05)%2C%0A%20%20%20%20%20%20%20%20%22chebyshev1%22%3A%20NumericalFilter(%0A%20%20%20%20%20%20%20%20%20%20%20%20design%3D%22chebyshev1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lowpass%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20order%3D4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cutoff_frequency%3D0.05%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20passband_ripple%3D1.0%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%22bessel%22%3A%20NumericalFilter(design%3D%22bessel%22%2C%20mode%3D%22lowpass%22%2C%20order%3D4%2C%20cutoff_frequency%3D0.05)%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20_result%20%3D%20elec_subset.select(%22time%22)%0A%20%20%20%20for%20_name%2C%20_filt%20in%20_designs.items()%3A%0A%20%20%20%20%20%20%20%20_filt.fit(elec_subset)%0A%20%20%20%20%20%20%20%20_out%20%3D%20_filt.transform(elec_subset)%0A%20%20%20%20%20%20%20%20_result%20%3D%20_result.with_columns(_out%5B%22demand%22%5D.alias(f%22demand_%7B_name%7D%22))%0A%0A%20%20%20%20plot_time_series(%0A%20%20%20%20%20%20%20%20_result.head(200)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Filter%20Design%20Comparison%20(First%20200%20Samples)%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%205.%20NumericalDifferentiator%3A%20Rate%20of%20Change%0A%0A%20%20%20%20%5B%60NumericalDifferentiator%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.signal.NumericalDifferentiator%2F)%20estimates%20the%20time%20derivative%20of%20the%20signal%0A%20%20%20%20using%20%60np.gradient%60.%20The%20output%20column%20is%20suffixed%20with%0A%20%20%20%20%60_differentiated%60.%20The%20fitted%20attribute%20%60sampling_interval_%60%20records%20the%0A%20%20%20%20detected%20time%20step%20in%20seconds.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalDifferentiator%2C%20elec_subset%2C%20mo)%3A%0A%20%20%20%20diff%20%3D%20NumericalDifferentiator(order%3D1)%0A%20%20%20%20diff.fit(elec_subset)%0A%20%20%20%20demand_rate%20%3D%20diff.transform(elec_subset)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22**Differentiator%20output**%3A%20%7Bdemand_rate.columns%7D%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22**Sampling%20interval**%3A%20%7Bdiff.interval_%7D%20(%7Bdiff.sampling_interval_%3A.0f%7D%20seconds)%22%0A%20%20%20%20)%0A%20%20%20%20return%20(demand_rate%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F)%20renders%20the%20first%20200%20samples%20of%20the%20differentiated%0A%20%20%20%20signal%2C%20showing%20how%20quickly%20demand%20rises%20or%20falls%20between%20half-hour%0A%20%20%20%20intervals.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(demand_rate%2C%20plot_time_series)%3A%0A%20%20%20%20plot_time_series(demand_rate.head(200)%2C%20title%3D%22Rate%20of%20Change%3A%20First%20200%20Samples%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%206.%20NumericalIntegrator%3A%20Cumulative%20Integration%0A%0A%20%20%20%20%5B%60NumericalIntegrator%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.signal.NumericalIntegrator%2F)%20computes%20the%20running%20trapezoidal%20(or%20Simpson)%0A%20%20%20%20integral%20of%20the%20signal.%20Applied%20to%20electricity%20demand%2C%20this%20gives%0A%20%20%20%20cumulative%20energy%20consumption%20over%20time.%20The%20output%20column%20is%20suffixed%0A%20%20%20%20with%20%60_integrated%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalIntegrator%2C%20elec_subset%2C%20mo)%3A%0A%20%20%20%20integ%20%3D%20NumericalIntegrator(method%3D%22cumulative_trapezoid%22)%0A%20%20%20%20integ.fit(elec_subset)%0A%20%20%20%20demand_cumulative%20%3D%20integ.transform(elec_subset)%0A%0A%20%20%20%20mo.md(f%22**Integrator%20output%20columns**%3A%20%7Bdemand_cumulative.columns%7D%5Cn%5Cn**Sampling%20interval**%3A%20%7Binteg.interval_%7D%22)%0A%20%20%20%20return%20(demand_cumulative%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F)%20shows%20the%20monotonically%20increasing%20cumulative%20energy%0A%20%20%20%20curve.%20Steeper%20slopes%20correspond%20to%20periods%20of%20higher%20demand.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(demand_cumulative%2C%20plot_time_series)%3A%0A%20%20%20%20plot_time_series(demand_cumulative%2C%20title%3D%22Cumulative%20Integration%3A%20Total%20Energy%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%207.%20Chaining%3A%20Smooth%20Then%20Differentiate%0A%0A%20%20%20%20Apply%20a%20low-pass%20filter%20first%20to%20remove%20noise%2C%20then%20differentiate%0A%20%20%20%20for%20a%20cleaner%20rate-of-change%20estimate.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NumericalDifferentiator%2C%20NumericalFilter%2C%20elec_subset%2C%20plot_time_series)%3A%0A%20%20%20%20_lp%20%3D%20NumericalFilter(design%3D%22butterworth%22%2C%20mode%3D%22lowpass%22%2C%20order%3D4%2C%20cutoff_frequency%3D0.05)%0A%20%20%20%20_lp.fit(elec_subset)%0A%20%20%20%20_smooth%20%3D%20_lp.transform(elec_subset)%0A%0A%20%20%20%20_diff2%20%3D%20NumericalDifferentiator(order%3D1)%0A%20%20%20%20_diff2.fit(_smooth)%0A%20%20%20%20_rate_smooth%20%3D%20_diff2.transform(_smooth)%0A%0A%20%20%20%20_diff_raw%20%3D%20NumericalDifferentiator(order%3D1)%0A%20%20%20%20_diff_raw.fit(elec_subset)%0A%20%20%20%20_rate_raw%20%3D%20_diff_raw.transform(elec_subset)%0A%0A%20%20%20%20_compare%20%3D%20_rate_smooth.join(%0A%20%20%20%20%20%20%20%20_rate_raw.rename(%7B%22demand_differentiated%22%3A%20%22demand_raw_rate%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20).rename(%7B%22demand_differentiated%22%3A%20%22demand_smooth_rate%22%7D)%0A%0A%20%20%20%20plot_time_series(%0A%20%20%20%20%20%20%20%20_compare.head(200)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Rate%20of%20Change%3A%20Raw%20vs%20Smoothed%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Next%20Steps%0A%0A%20%20%20%20-%20%5BApply%20Signal%20Processing%20Filters%5D(%2Fpages%2Fhow-to%2Fapply-signal-processing%2F)%20for%20the%20full%20guide%0A%20%20%20%20-%20%5BUse%20Preprocessing%20Transformers%5D(%2Fpages%2Fhow-to%2Fuse-preprocessing-transformers%2F)%20for%20related%20techniques%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
8a564aa88ad015f5333020e0ef6741f0