%22%22%22Interactive%20wind-capacity%20explorer%20(marimo%20notebook).%0A%0ARun%3A%20%20%20%20python%20-m%20marimo%20edit%20wind.py%0AExport%3A%20python%20-m%20marimo%20export%20html%20wind.py%20-o%20docs%2Fwind.html%0A%22%22%22%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.5%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_intro(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Wind%20explorer%20%C2%B7%20Marktstammdatenregister%0A%0A%20%20%20%20Interactive%20choropleth%20of%20installed%20**wind**%20capacity%20per%20German%20county.%0A%20%20%20%20Slider%20walks%20the%20install%20date%3B%20the%20on%2Foffshore%20toggle%20controls%20whether%0A%20%20%20%20Nordsee%20%2B%20Ostsee%20turbines%20are%20included.%20Falls%20back%20to%20a%20synthetic%20demo%0A%20%20%20%20dataset%20when%20no%20MaStR%20scrape%20is%20present.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_imports()%3A%0A%20%20%20%20from%20datetime%20import%20date%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20mastr_plot%0A%0A%20%20%20%20return%20date%2C%20mastr_plot%0A%0A%0A%40app.cell%0Adef%20_data(mastr_plot%2C%20mo)%3A%0A%20%20%20%20df%2C%20demo%20%3D%20mastr_plot.load_records()%0A%20%20%20%20units%2C%20units_demo%20%3D%20mastr_plot.load_admin_units()%0A%20%20%20%20banner%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20%22%3E%20**Demo%20mode**%20%E2%80%94%20no%20MaStR%20scrape%20or%20kreise%20polygons%20found%2C%20%22%0A%20%20%20%20%20%20%20%20%22synthetic%20data%20is%20used.%22%0A%20%20%20%20%20%20%20%20if%20(demo%20or%20units_demo)%0A%20%20%20%20%20%20%20%20else%20%22%3E%20Loaded%20**real**%20MaStR%20records%20and%20OSM%20kreise%20polygons.%22%0A%20%20%20%20)%0A%20%20%20%20banner%0A%20%20%20%20return%20df%2C%20units%0A%0A%0A%40app.cell%0Adef%20_controls(date%2C%20df%2C%20mo)%3A%0A%20%20%20%20min_d%20%3D%20df%5B%22install_date%22%5D.min().date()%20if%20df%5B%22install_date%22%5D.notna().any()%20else%20date(2000%2C%201%2C%201)%0A%20%20%20%20max_d%20%3D%20date.today()%0A%20%20%20%20date_slider%20%3D%20mo.ui.date(%0A%20%20%20%20%20%20%20%20start%3Dmin_d%2C%20stop%3Dmax_d%2C%20value%3Ddate(2023%2C%201%2C%201)%2C%20label%3D%22Snapshot%20date%22%0A%20%20%20%20)%0A%20%20%20%20location%20%3D%20mo.ui.radio(%0A%20%20%20%20%20%20%20%20options%3D%5B%22onshore%20%2B%20offshore%22%2C%20%22onshore%20only%22%2C%20%22offshore%20only%22%5D%2C%0A%20%20%20%20%20%20%20%20value%3D%22onshore%20%2B%20offshore%22%2C%20label%3D%22Location%22%2C%0A%20%20%20%20)%0A%20%20%20%20bin_count%20%3D%20mo.ui.slider(start%3D3%2C%20stop%3D10%2C%20step%3D1%2C%20value%3D7%2C%20label%3D%22Color%20bins%22)%0A%20%20%20%20cmap_picker%20%3D%20mo.ui.dropdown(%0A%20%20%20%20%20%20%20%20options%3D%5B%22viridis%22%2C%20%22plasma%22%2C%20%22Blues%22%2C%20%22GnBu%22%2C%20%22BuPu%22%5D%2C%0A%20%20%20%20%20%20%20%20value%3D%22GnBu%22%2C%20label%3D%22Colormap%22%2C%0A%20%20%20%20)%0A%20%20%20%20scale_picker%20%3D%20mo.ui.radio(%0A%20%20%20%20%20%20%20%20options%3D%5B%22jenks%22%2C%20%22linear%22%2C%20%22log%22%5D%2C%20value%3D%22jenks%22%2C%20label%3D%22Color%20scale%22%0A%20%20%20%20)%0A%20%20%20%20controls%20%3D%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5Bdate_slider%2C%20location%2C%20bin_count%2C%20cmap_picker%2C%20scale_picker%5D%2C%20gap%3D2%0A%20%20%20%20)%0A%20%20%20%20controls%0A%20%20%20%20return%20bin_count%2C%20cmap_picker%2C%20date_slider%2C%20location%2C%20scale_picker%0A%0A%0A%40app.cell%0Adef%20_filtered(df%2C%20location)%3A%0A%20%20%20%20w%20%3D%20df%5Bdf%5B%22energy_type%22%5D%20%3D%3D%20%22Wind%22%5D.copy()%0A%20%20%20%20if%20location.value%20%3D%3D%20%22onshore%20only%22%3A%0A%20%20%20%20%20%20%20%20w%20%3D%20w%5Bw%5B%22off_shore%22%5D.isna()%5D%0A%20%20%20%20elif%20location.value%20%3D%3D%20%22offshore%20only%22%3A%0A%20%20%20%20%20%20%20%20w%20%3D%20w%5Bw%5B%22off_shore%22%5D.notna()%5D%0A%20%20%20%20w%0A%20%20%20%20return%20(w%2C)%0A%0A%0A%40app.cell%0Adef%20_map(%0A%20%20%20%20bin_count%2C%0A%20%20%20%20cmap_picker%2C%0A%20%20%20%20date_slider%2C%0A%20%20%20%20mastr_plot%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20scale_picker%2C%0A%20%20%20%20units%2C%0A%20%20%20%20w%2C%0A)%3A%0A%20%20%20%20agg%2C%20active%20%3D%20mastr_plot.aggregate_by_unit(%0A%20%20%20%20%20%20%20%20w%2C%20units%2C%20plot_date%3Ddate_slider.value%2C%20energy_type%3D%22Wind%22%0A%20%20%20%20)%0A%20%20%20%20bins%20%3D%20mastr_plot.jenks_bins(%0A%20%20%20%20%20%20%20%20agg%5B%22power_gw%22%5D%5Bagg%5B%22power_gw%22%5D%20%3E%200%5D.to_numpy()%2C%20k%3Dbin_count.value%0A%20%20%20%20)%0A%20%20%20%20fig%20%3D%20mastr_plot.plot_choropleth(%0A%20%20%20%20%20%20%20%20agg%2C%20plot_date%3Ddate_slider.value%2C%0A%20%20%20%20%20%20%20%20title%3Df%22Wind%20capacity%20%E2%80%94%20%7Bdate_slider.value.isoformat()%7D%5Cn%7Blen(active)%3A%2C%7D%20turbines%20active%22%2C%0A%20%20%20%20%20%20%20%20bins%3Dbins%2C%20cmap%3Dcmap_picker.value%2C%20scale%3Dscale_picker.value%2C%0A%20%20%20%20)%0A%20%20%20%20mo.mpl.interactive(fig)%0A%20%20%20%20return%20active%2C%20agg%0A%0A%0A%40app.cell%0Adef%20_stats(active%2C%20agg%2C%20mo)%3A%0A%20%20%20%20total_gw%20%3D%20float(agg%5B%22power_gw%22%5D.sum())%0A%20%20%20%20off%20%3D%20int(active%5B%22off_shore%22%5D.notna().sum())%20if%20%22off_shore%22%20in%20active%20else%200%0A%20%20%20%20on%20%3D%20len(active)%20-%20off%0A%20%20%20%20median_kw%20%3D%20float(active%5B%22power%22%5D.median())%20if%20len(active)%20else%200.0%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%20Summary%0A%0A%20%20%20%20%20%20%20%20-%20**Active%20turbines%3A**%20%7Blen(active)%3A%2C%7D%20%20%C2%B7%20%20onshore%20%7Bon%3A%2C%7D%20%20%C2%B7%20%20offshore%20%7Boff%3A%2C%7D%0A%20%20%20%20%20%20%20%20-%20**Total%20installed%20capacity%3A**%20%7Btotal_gw%3A%2C.2f%7D%20GW%0A%20%20%20%20%20%20%20%20-%20**Median%20turbine%20rating%3A**%20%7Bmedian_kw%2F1e3%3A%2C.2f%7D%20MW%0A%20%20%20%20%20%20%20%20-%20**Counties%20covered%3A**%20%7B(agg%5B'power_gw'%5D%20%3E%200).sum()%3A%2C%7D%20%2F%20%7Blen(agg)%3A%2C%7D%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_growth(mo%2C%20w)%3A%0A%20%20%20%20growth_monthly%20%3D%20(%0A%20%20%20%20%20%20%20%20w.assign(month%3Dw%5B%22install_date%22%5D.dt.to_period(%22M%22))%0A%20%20%20%20%20%20%20%20.groupby(%5B%22month%22%2C%20w%5B%22off_shore%22%5D.notna().rename(%22offshore%22)%5D)%5B%22power%22%5D%0A%20%20%20%20%20%20%20%20.sum()%0A%20%20%20%20%20%20%20%20.div(1e6)%0A%20%20%20%20%20%20%20%20.unstack(fill_value%3D0.0)%0A%20%20%20%20%20%20%20%20.cumsum()%0A%20%20%20%20)%0A%20%20%20%20growth_monthly.index%20%3D%20growth_monthly.index.to_timestamp()%0A%20%20%20%20import%20matplotlib.pyplot%20as%20growth_plt%0A%20%20%20%20growth_fig%2C%20growth_ax%20%3D%20growth_plt.subplots(figsize%3D(9%2C%203.4)%2C%20dpi%3D120)%0A%20%20%20%20if%20False%20in%20growth_monthly.columns%3A%0A%20%20%20%20%20%20%20%20growth_ax.fill_between(growth_monthly.index%2C%200%2C%20growth_monthly%5BFalse%5D.values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22%2386efac%22%2C%20alpha%3D0.5%2C%20label%3D%22onshore%22)%0A%20%20%20%20if%20True%20in%20growth_monthly.columns%3A%0A%20%20%20%20%20%20%20%20bottom%20%3D%20growth_monthly%5BFalse%5D.values%20if%20False%20in%20growth_monthly.columns%20else%200%0A%20%20%20%20%20%20%20%20growth_ax.fill_between(growth_monthly.index%2C%20bottom%2C%20bottom%20%2B%20growth_monthly%5BTrue%5D.values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22%230ea5e9%22%2C%20alpha%3D0.6%2C%20label%3D%22offshore%22)%0A%20%20%20%20growth_ax.set_ylabel(%22Cumulative%20wind%20%5BGW%5D%22)%0A%20%20%20%20growth_ax.set_title(%22Cumulative%20wind%20capacity%20over%20time%22)%0A%20%20%20%20growth_ax.legend(loc%3D%22upper%20left%22)%0A%20%20%20%20growth_ax.grid(alpha%3D0.3)%0A%20%20%20%20growth_fig.tight_layout()%0A%20%20%20%20mo.mpl.interactive(growth_fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_import_mo()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
d555febbec994626cccbf401e4b1a763