%23%20pyright%3A%20reportUnusedExpression%3Dfalse%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.19.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20folium%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20polars%20as%20pl%0A%0A%20%20%20%20from%20src%20import%20defaults%0A%20%20%20%20from%20src.cache_parquet%20import%20cache_parquet%0A%20%20%20%20return%20cache_parquet%2C%20defaults%2C%20folium%2C%20mo%2C%20np%2C%20pl%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20%23%20Get%20CLI%20args%20(available%20when%20running%20with%3A%20marimo%20run%20notebook.py%20--%20--arg%3Dvalue)%0A%20%20%20%20cli_args%20%3D%20mo.cli_args()%0A%20%20%20%20return%20(cli_args%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%20Citizen%20Science%20Bioregionalization%0A%20%20%20%20%22%22%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%20Define%20inputs%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(cli_args%2C%20defaults%2C%20mo)%3A%0A%20%20%20%20%23%20Define%20Marimo%20input%20UI%20elements%0A%20%20%20%20%23%20CLI%20args%20override%20defaults%20when%20provided%20(e.g.%2C%20marimo%20run%20notebook.py%20--%20--geocode-precision%3D5)%0A%0A%20%20%20%20log_file_ui%20%3D%20mo.ui.text(%0A%20%20%20%20%20%20%20%20cli_args.get(%22log-file%22%2C%20defaults.LOG_FILE)%2C%20label%3D%22Log%20file%22%0A%20%20%20%20)%0A%20%20%20%20parquet_source_path_ui%20%3D%20mo.ui.text(%0A%20%20%20%20%20%20%20%20cli_args.get(%22parquet-source-path%22%2C%20defaults.PARQUET_SOURCE_PATH)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Input%20GCS%20directory%22%2C%0A%20%20%20%20)%0A%20%20%20%20geocode_precision_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22geocode-precision%22%2C%20defaults.GEOCODE_PRECISION)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Geocode%20precision%22%2C%0A%20%20%20%20)%0A%20%20%20%20min_clusters_to_test_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22min-clusters%22%2C%20defaults.MIN_CLUSTERS)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Min%20clusters%20to%20test%22%2C%0A%20%20%20%20)%0A%20%20%20%20max_clusters_to_test_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22max-clusters%22%2C%20defaults.MAX_CLUSTERS)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Max%20clusters%20to%20test%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20taxon_filter_ui%20%3D%20mo.ui.text(%0A%20%20%20%20%20%20%20%20cli_args.get(%22taxon-filter%22%2C%20defaults.TAXON_FILTER)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Taxon%20filter%20(optional)%22%2C%0A%20%20%20%20)%0A%20%20%20%20limit_results_enabled_ui%20%3D%20mo.ui.checkbox(%0A%20%20%20%20%20%20%20%20value%3D%22limit-results%22%20in%20cli_args%20or%20defaults.LIMIT_RESULTS_ENABLED%2C%0A%20%20%20%20%20%20%20%20label%3D%22Enable%20limit%22%2C%0A%20%20%20%20)%0A%20%20%20%20limit_results_value_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22limit-results%22%2C%20defaults.LIMIT_RESULTS%20or%201000)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Limit%20results%22%2C%0A%20%20%20%20)%0A%20%20%20%20max_taxa_enabled_ui%20%3D%20mo.ui.checkbox(%0A%20%20%20%20%20%20%20%20value%3D%22max-taxa%22%20in%20cli_args%20or%20defaults.MAX_TAXA_ENABLED%2C%0A%20%20%20%20%20%20%20%20label%3D%22Limit%20to%20top%20N%20taxa%22%2C%0A%20%20%20%20)%0A%20%20%20%20max_taxa_value_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22max-taxa%22%2C%20defaults.MAX_TAXA%20or%205000)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Keep%20top%20N%20taxa%20by%20occurrence%20count%22%2C%0A%20%20%20%20)%0A%20%20%20%20min_geocode_presence_enabled_ui%20%3D%20mo.ui.checkbox(%0A%20%20%20%20%20%20%20%20value%3D%22min-geocode-presence%22%20in%20cli_args%0A%20%20%20%20%20%20%20%20or%20defaults.MIN_GEOCODE_PRESENCE_ENABLED%2C%0A%20%20%20%20%20%20%20%20label%3D%22Filter%20rare%20taxa%22%2C%0A%20%20%20%20)%0A%20%20%20%20min_geocode_presence_value_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22min-geocode-presence%22%2C%20defaults.MIN_GEOCODE_PRESENCE%20or%200.05%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20label%3D%22Min%20fraction%20of%20hexagons%20a%20taxon%20must%20appear%20in%22%2C%0A%20%20%20%20%20%20%20%20step%3D0.01%2C%0A%20%20%20%20)%0A%20%20%20%20min_lon_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22min-lon%22%2C%20defaults.MIN_LON)%2C%20label%3D%22Longitude%22%0A%20%20%20%20)%0A%20%20%20%20min_lat_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22min-lat%22%2C%20defaults.MIN_LAT)%2C%20label%3D%22Latitude%22%0A%20%20%20%20)%0A%20%20%20%20max_lon_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22max-lon%22%2C%20defaults.MAX_LON)%2C%20label%3D%22Longitude%22%0A%20%20%20%20)%0A%20%20%20%20max_lat_ui%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20value%3Dcli_args.get(%22max-lat%22%2C%20defaults.MAX_LAT)%2C%20label%3D%22Latitude%22%0A%20%20%20%20)%0A%20%20%20%20%23%20For%20boolean%20flags%2C%20presence%20of%20the%20key%20means%20True%20(--no-stop%20becomes%20%7B'no-stop'%3A%20''%7D)%0A%20%20%20%20no_stop%20%3D%20%22no-stop%22%20in%20cli_args%0A%20%20%20%20run_button_ui%20%3D%20mo.ui.run_button()%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20geocode_precision_ui%2C%0A%20%20%20%20%20%20%20%20limit_results_enabled_ui%2C%0A%20%20%20%20%20%20%20%20limit_results_value_ui%2C%0A%20%20%20%20%20%20%20%20log_file_ui%2C%0A%20%20%20%20%20%20%20%20max_clusters_to_test_ui%2C%0A%20%20%20%20%20%20%20%20max_lat_ui%2C%0A%20%20%20%20%20%20%20%20max_lon_ui%2C%0A%20%20%20%20%20%20%20%20max_taxa_enabled_ui%2C%0A%20%20%20%20%20%20%20%20max_taxa_value_ui%2C%0A%20%20%20%20%20%20%20%20min_clusters_to_test_ui%2C%0A%20%20%20%20%20%20%20%20min_geocode_presence_enabled_ui%2C%0A%20%20%20%20%20%20%20%20min_geocode_presence_value_ui%2C%0A%20%20%20%20%20%20%20%20min_lat_ui%2C%0A%20%20%20%20%20%20%20%20min_lon_ui%2C%0A%20%20%20%20%20%20%20%20no_stop%2C%0A%20%20%20%20%20%20%20%20parquet_source_path_ui%2C%0A%20%20%20%20%20%20%20%20run_button_ui%2C%0A%20%20%20%20%20%20%20%20taxon_filter_ui%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(log_file_ui)%3A%0A%20%20%20%20log_file_ui%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(parquet_source_path_ui)%3A%0A%20%20%20%20parquet_source_path_ui%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(geocode_precision_ui)%3A%0A%20%20%20%20geocode_precision_ui%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(max_clusters_to_test_ui%2C%20min_clusters_to_test_ui%2C%20mo)%3A%0A%20%20%20%20_description%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20%22**Cluster%20Configuration%3A**%20Number%20of%20clusters%20will%20be%20automatically%20optimized%20using%20the%20elbow%20method%20(Kneedle%20algorithm).%22%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20_description%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20min_clusters_to_test_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20max_clusters_to_test_ui%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(taxon_filter_ui)%3A%0A%20%20%20%20taxon_filter_ui%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(limit_results_enabled_ui%2C%20limit_results_value_ui%2C%20mo)%3A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20limit_results_enabled_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20limit_results_value_ui%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20max_taxa_enabled_ui%2C%0A%20%20%20%20max_taxa_value_ui%2C%0A%20%20%20%20min_geocode_presence_enabled_ui%2C%0A%20%20%20%20min_geocode_presence_value_ui%2C%0A%20%20%20%20mo%2C%0A)%3A%0A%20%20%20%20_description%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20%22**Taxa%20Filtering%3A**%20Reduce%20dimensionality%20before%20pivoting%20by%20filtering%20to%20most%20informative%20taxa.%20%22%0A%20%20%20%20%20%20%20%20%22This%20significantly%20speeds%20up%20distance%20matrix%20computation%20for%20large%20datasets.%22%0A%20%20%20%20)%0A%0A%20%20%20%20_max_taxa_description%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20%22_Keep%20only%20the%20N%20most%20abundant%20taxa%20(by%20total%20occurrence%20count).%20%22%0A%20%20%20%20%20%20%20%20%22Recommended%3A%205%2C000%E2%80%9310%2C000%20for%20large%20datasets._%22%0A%20%20%20%20)%0A%0A%20%20%20%20_min_presence_description%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20%22_Remove%20rare%20taxa%20that%20appear%20in%20too%20few%20hexagons.%20%22%0A%20%20%20%20%20%20%20%20%22Taxa%20seen%20in%20very%20few%20locations%20add%20noise%20but%20don't%20help%20distinguish%20bioregions.%20%22%0A%20%20%20%20%20%20%20%20%22For%20example%2C%200.05%20means%20a%20taxon%20must%20appear%20in%20at%20least%205%25%20of%20hexagons%20to%20be%20included.%20%22%0A%20%20%20%20%20%20%20%20%22Recommended%3A%200.02%E2%80%930.05%20(2%E2%80%935%25)._%22%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20_description%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.hstack(%5Bmax_taxa_enabled_ui%2C%20max_taxa_value_ui%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_max_taxa_description%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.hstack(%5Bmin_geocode_presence_enabled_ui%2C%20min_geocode_presence_value_ui%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_min_presence_description%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(folium%2C%20max_lat_ui%2C%20max_lon_ui%2C%20min_lat_ui%2C%20min_lon_ui%2C%20mo)%3A%0A%20%20%20%20def%20build_map()%3A%0A%20%20%20%20%20%20%20%20map%20%3D%20folium.Map(%0A%20%20%20%20%20%20%20%20%20%20%20%20tiles%3D%22Esri.WorldGrayCanvas%22%2C%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20bounds%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bmin_lat_ui.value%2C%20min_lon_ui.value%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bmax_lat_ui.value%2C%20max_lon_ui.value%5D%2C%0A%20%20%20%20%20%20%20%20%5D%0A%0A%20%20%20%20%20%20%20%20folium.Rectangle(bounds%3Dbounds).add_to(map)%0A%0A%20%20%20%20%20%20%20%20map.fit_bounds(bounds%2C%20padding%3D%5B20%2C%2020%5D)%0A%0A%20%20%20%20%20%20%20%20return%20map%0A%0A%20%20%20%20mo.hstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22**Minimum**%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20min_lat_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20min_lon_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22**Maximum**%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20max_lat_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20max_lon_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20build_map()%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20widths%3D%22equal%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%20Resolved%20Inputs%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20geocode_precision_ui%2C%0A%20%20%20%20limit_results_enabled_ui%2C%0A%20%20%20%20limit_results_value_ui%2C%0A%20%20%20%20log_file_ui%2C%0A%20%20%20%20max_clusters_to_test_ui%2C%0A%20%20%20%20max_lat_ui%2C%0A%20%20%20%20max_lon_ui%2C%0A%20%20%20%20max_taxa_enabled_ui%2C%0A%20%20%20%20max_taxa_value_ui%2C%0A%20%20%20%20min_clusters_to_test_ui%2C%0A%20%20%20%20min_geocode_presence_enabled_ui%2C%0A%20%20%20%20min_geocode_presence_value_ui%2C%0A%20%20%20%20min_lat_ui%2C%0A%20%20%20%20min_lon_ui%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20no_stop%2C%0A%20%20%20%20parquet_source_path_ui%2C%0A%20%20%20%20run_button_ui%2C%0A%20%20%20%20taxon_filter_ui%2C%0A)%3A%0A%20%20%20%20from%20src.types%20import%20Bbox%0A%0A%20%20%20%20%23%20Resolve%20final%20values%20from%20UI%20elements%0A%20%20%20%20limit_results%20%3D%20(%0A%20%20%20%20%20%20%20%20limit_results_value_ui.value%20if%20limit_results_enabled_ui.value%20else%20None%0A%20%20%20%20)%0A%20%20%20%20log_file%20%3D%20log_file_ui.value%0A%20%20%20%20parquet_source_path%20%3D%20parquet_source_path_ui.value%0A%20%20%20%20min_lat%20%3D%20min_lat_ui.value%0A%20%20%20%20max_lat%20%3D%20max_lat_ui.value%0A%20%20%20%20min_lon%20%3D%20min_lon_ui.value%0A%20%20%20%20max_lon%20%3D%20max_lon_ui.value%0A%20%20%20%20taxon_filter%20%3D%20taxon_filter_ui.value%0A%20%20%20%20geocode_precision%20%3D%20geocode_precision_ui.value%0A%20%20%20%20min_clusters_to_test%20%3D%20min_clusters_to_test_ui.value%0A%20%20%20%20max_clusters_to_test%20%3D%20max_clusters_to_test_ui.value%0A%20%20%20%20max_taxa%20%3D%20max_taxa_value_ui.value%20if%20max_taxa_enabled_ui.value%20else%20None%0A%20%20%20%20min_geocode_presence%20%3D%20(%0A%20%20%20%20%20%20%20%20min_geocode_presence_value_ui.value%0A%20%20%20%20%20%20%20%20if%20min_geocode_presence_enabled_ui.value%0A%20%20%20%20%20%20%20%20else%20None%0A%20%20%20%20)%0A%20%20%20%20bounding_box%20%3D%20Bbox.from_coordinates(min_lat%2C%20max_lat%2C%20min_lon%2C%20max_lon)%0A%0A%20%20%20%20inputs_table%20%3D%20mo.ui.table(%0A%20%20%20%20%20%20%20%20label%3D%22Inputs%22%2C%0A%20%20%20%20%20%20%20%20selection%3DNone%2C%0A%20%20%20%20%20%20%20%20pagination%3DFalse%2C%0A%20%20%20%20%20%20%20%20data%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22limit_results%22%2C%20%22value%22%3A%20limit_results%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22log_file%22%2C%20%22value%22%3A%20log_file%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22parquet_source_path%22%2C%20%22value%22%3A%20parquet_source_path%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22min_lat%22%2C%20%22value%22%3A%20min_lat%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22max_lat%22%2C%20%22value%22%3A%20max_lat%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22min_lon%22%2C%20%22value%22%3A%20min_lon%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22max_lon%22%2C%20%22value%22%3A%20max_lon%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22taxon_filter%22%2C%20%22value%22%3A%20taxon_filter%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22geocode_precision%22%2C%20%22value%22%3A%20geocode_precision%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22min_clusters_to_test%22%2C%20%22value%22%3A%20min_clusters_to_test%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22max_clusters_to_test%22%2C%20%22value%22%3A%20max_clusters_to_test%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22max_taxa%22%2C%20%22value%22%3A%20max_taxa%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%22variable%22%3A%20%22min_geocode_presence%22%2C%20%22value%22%3A%20min_geocode_presence%7D%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20output2%20%3D%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20inputs_table%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20run_button_ui%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20if%20mo.running_in_notebook()%20and%20not%20no_stop%3A%0A%20%20%20%20%20%20%20%20mo.stop(not%20run_button_ui.value%2C%20output2)%0A%0A%20%20%20%20mo.md(%22Notebook%20started%22)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20bounding_box%2C%0A%20%20%20%20%20%20%20%20geocode_precision%2C%0A%20%20%20%20%20%20%20%20limit_results%2C%0A%20%20%20%20%20%20%20%20log_file%2C%0A%20%20%20%20%20%20%20%20max_clusters_to_test%2C%0A%20%20%20%20%20%20%20%20max_taxa%2C%0A%20%20%20%20%20%20%20%20min_clusters_to_test%2C%0A%20%20%20%20%20%20%20%20min_geocode_presence%2C%0A%20%20%20%20%20%20%20%20parquet_source_path%2C%0A%20%20%20%20%20%20%20%20taxon_filter%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%20Set%20up%20logging%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(log_file)%3A%0A%20%20%20%20import%20logging%0A%0A%20%20%20%20logging.basicConfig(%0A%20%20%20%20%20%20%20%20filename%3Dlog_file%2C%0A%20%20%20%20%20%20%20%20format%3D%22%25(asctime)s%20%25(levelname)-8s%20%25(message)s%22%2C%0A%20%20%20%20%20%20%20%20level%3Dlogging.INFO%2C%0A%20%20%20%20%20%20%20%20datefmt%3D%22%25Y-%25m-%25d%20%25H%3A%25M%3A%25S%22%2C%0A%20%20%20%20%20%20%20%20encoding%3D%22utf-8%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%20Step%201.%20Fetch%20data%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(bounding_box%2C%20limit_results%2C%20parquet_source_path%2C%20taxon_filter)%3A%0A%20%20%20%20from%20src.dataframes.darwin_core%20import%20build_darwin_core_lf%0A%0A%20%20%20%20darwin_core_lf%20%3D%20build_darwin_core_lf(%0A%20%20%20%20%20%20%20%20source_path%3Dparquet_source_path%2C%0A%20%20%20%20%20%20%20%20bounding_box%3Dbounding_box%2C%0A%20%20%20%20%20%20%20%20limit%3Dlimit_results%2C%0A%20%20%20%20%20%20%20%20taxon_filter%3Dtaxon_filter%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(darwin_core_lf%2C)%0A%0A%0A%40app.cell%0Adef%20_(bounding_box%2C%20cache_parquet%2C%20darwin_core_lf%2C%20geocode_precision)%3A%0A%20%20%20%20from%20src.dataframes.geocode%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_lf%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_lf_with_edges%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_lf(%0A%20%20%20%20%20%20%20%20%20%20%20%20darwin_core_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_precision%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20bounding_box%3Dbounding_box%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeSchema%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_lf_with_edges%2C)%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_lf_with_edges)%3A%0A%20%20%20%20from%20src.dataframes.geocode%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeNoEdgesSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_no_edges_lf%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_unfiltered_lf%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_no_edges_lf(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_lf_with_edges%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeNoEdgesSchema%2C%0A%20%20%20%20)%0A%20%20%20%20return%20GeocodeNoEdgesSchema%2C%20geocode_unfiltered_lf%0A%0A%0A%40app.cell%0Adef%20_(geocode_lf_with_edges)%3A%0A%20%20%20%20from%20src.dataframes.geocode_neighbors%20import%20(%0A%20%20%20%20%20%20%20%20build_geocode_neighbors_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Build%20neighbors%20for%20all%20geocodes%20(including%20edges)%0A%20%20%20%20geocode_neighbors_with_edges_df%20%3D%20build_geocode_neighbors_df(%0A%20%20%20%20%20%20%20%20geocode_lf_with_edges.collect()%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_neighbors_with_edges_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_lf%2C%20geocode_neighbors_with_edges_df)%3A%0A%20%20%20%20from%20src.dataframes.geocode_neighbors%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeNeighborsSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_neighbors_no_edges_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Build%20neighbors%20for%20filtered%20geocodes%20only%0A%20%20%20%20geocode_neighbors_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_neighbors_no_edges_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_neighbors_with_edges_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_lf.collect()%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeNeighborsSchema%2C%0A%20%20%20%20).collect()%0A%20%20%20%20return%20(geocode_neighbors_df%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(folium%2C%20geocode_lf_with_edges%2C%20geocode_unfiltered_lf%2C%20pl)%3A%0A%20%20%20%20_center%20%3D%20geocode_unfiltered_lf.select(%0A%20%20%20%20%20%20%20%20pl.col(%22center%22).alias(%22geometry%22)%2C%0A%20%20%20%20).collect()%0A%20%20%20%20_boundary%20%3D%20geocode_lf_with_edges.select(%0A%20%20%20%20%20%20%20%20pl.col(%22boundary%22).alias(%22geometry%22)%2C%0A%20%20%20%20%20%20%20%20pl.col(%22is_edge%22)%2C%0A%20%20%20%20).collect()%0A%0A%20%20%20%20_map%20%3D%20folium.Map(%0A%20%20%20%20%20%20%20%20tiles%3D%22Esri.WorldGrayCanvas%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20folium.GeoJson(%0A%20%20%20%20%20%20%20%20_center.st%2C%0A%20%20%20%20%20%20%20%20marker%3Dfolium.Circle()%2C%0A%20%20%20%20).add_to(_map)%0A%0A%20%20%20%20def%20style(n)%3A%0A%20%20%20%20%20%20%20%20return%20%7B%22color%22%3A%20%22grey%22%20if%20n%5B%22properties%22%5D%5B%22is_edge%22%5D%20else%20%22blue%22%7D%0A%0A%20%20%20%20folium.GeoJson(_boundary.st%2C%20style_function%3Dstyle).add_to(_map)%0A%0A%20%20%20%20_map.fit_bounds(_map.get_bounds())%0A%0A%20%20%20%20_map%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20bounding_box%2C%0A%20%20%20%20cache_parquet%2C%0A%20%20%20%20darwin_core_lf%2C%0A%20%20%20%20geocode_precision%2C%0A%20%20%20%20geocode_unfiltered_lf%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.taxonomy%20import%20TaxonomySchema%2C%20build_taxonomy_lf%0A%0A%20%20%20%20taxonomy_lf%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_taxonomy_lf(%0A%20%20%20%20%20%20%20%20%20%20%20%20darwin_core_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_precision%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_unfiltered_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20bounding_box%3Dbounding_box%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DTaxonomySchema%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(taxonomy_lf%2C)%0A%0A%0A%40app.cell%0Adef%20_(taxonomy_lf)%3A%0A%20%20%20%20taxonomy_lf.limit(100).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20bounding_box%2C%0A%20%20%20%20cache_parquet%2C%0A%20%20%20%20darwin_core_lf%2C%0A%20%20%20%20geocode_precision%2C%0A%20%20%20%20geocode_unfiltered_lf%2C%0A%20%20%20%20taxonomy_lf%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.geocode_taxa_counts%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeTaxaCountsSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_taxa_counts_lf%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_taxa_counts_unfiltered_lf%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_taxa_counts_lf(%0A%20%20%20%20%20%20%20%20%20%20%20%20darwin_core_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_precision%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20taxonomy_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_unfiltered_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20bounding_box%3Dbounding_box%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeTaxaCountsSchema%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_taxa_counts_unfiltered_lf%2C)%0A%0A%0A%40app.cell%0Adef%20_(geocode_taxa_counts_unfiltered_lf%2C%20max_taxa%2C%20min_geocode_presence)%3A%0A%20%20%20%20from%20src.dataframes.geocode_taxa_counts%20import%20(%0A%20%20%20%20%20%20%20%20filter_top_taxa_lf%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Apply%20taxa%20filtering%20if%20configured%0A%20%20%20%20geocode_taxa_counts_lf%20%3D%20filter_top_taxa_lf(%0A%20%20%20%20%20%20%20%20geocode_taxa_counts_unfiltered_lf%2C%0A%20%20%20%20%20%20%20%20max_taxa%3Dmax_taxa%2C%0A%20%20%20%20%20%20%20%20min_geocode_presence%3Dmin_geocode_presence%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_taxa_counts_lf%2C)%0A%0A%0A%40app.cell%0Adef%20_(geocode_taxa_counts_lf)%3A%0A%20%20%20%20geocode_taxa_counts_lf.limit(100).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(GeocodeNoEdgesSchema%2C%20geocode_taxa_counts_lf%2C%20geocode_unfiltered_lf%2C%20pl)%3A%0A%20%20%20%20%23%20Filter%20geocode_unfiltered_lf%20to%20only%20include%20geocodes%20present%20in%20geocode_taxa_counts_lf%0A%20%20%20%20geocode_lf%20%3D%20GeocodeNoEdgesSchema.validate(%0A%20%20%20%20%20%20%20%20geocode_unfiltered_lf.join(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_taxa_counts_lf.select(pl.col(%22geocode%22).unique())%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20on%3D%22geocode%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20how%3D%22semi%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20eager%3DFalse%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_lf%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%20Step%202.%20Cluster%0A%20%20%20%20%22%22%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%20%60GeocodeConnectivity%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_neighbors_df)%3A%0A%20%20%20%20from%20src.matrices.geocode_connectivity%20import%20GeocodeConnectivityMatrix%0A%0A%20%20%20%20geocode_connectivity_matrix%20%3D%20GeocodeConnectivityMatrix.build(geocode_neighbors_df)%0A%0A%20%20%20%20geocode_connectivity_matrix._connectivity_matrix%0A%20%20%20%20return%20(geocode_connectivity_matrix%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%23%20%60GeocodeDistance%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_lf%2C%20geocode_taxa_counts_lf%2C%20mo%2C%20np)%3A%0A%20%20%20%20from%20src.matrices.geocode_distance%20import%20GeocodeDistanceMatrix%0A%0A%20%20%20%20geocode_distance_matrix%20%3D%20GeocodeDistanceMatrix.build(%0A%20%20%20%20%20%20%20%20geocode_taxa_counts_lf%2C%0A%20%20%20%20%20%20%20%20geocode_lf%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(GeocodeDistanceMatrix.__doc__)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.plain_text(np.array_repr(geocode_distance_matrix.squareform()))%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_distance_matrix%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%23%20Cluster%20Optimization%0A%20%20%20%20%22%22%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%23%20Build%20Clustering%20for%20All%20K%20Values%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cache_parquet%2C%0A%20%20%20%20geocode_connectivity_matrix%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20geocode_lf%2C%0A%20%20%20%20max_clusters_to_test%2C%0A%20%20%20%20min_clusters_to_test%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.geocode_cluster%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeClusterMultiKSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_cluster_multi_k_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20all_clusters_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_cluster_multi_k_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_connectivity_matrix%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20min_k%3Dmin_clusters_to_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20max_k%3Dmax_clusters_to_test%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeClusterMultiKSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(all_clusters_df%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%23%23%20Find%20Optimal%20K%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(all_clusters_df%2C%20geocode_distance_matrix)%3A%0A%20%20%20%20from%20src.cluster_optimization%20import%20optimize_num_clusters%0A%0A%20%20%20%20optimal_num_clusters%2C%20all_cluster_metrics%20%3D%20optimize_num_clusters(%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20all_clusters_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20all_cluster_metrics%0A%20%20%20%20return%20all_cluster_metrics%2C%20optimal_num_clusters%0A%0A%0A%40app.cell%0Adef%20_(all_cluster_metrics%2C%20cache_parquet)%3A%0A%20%20%20%20%23%20Cache%20the%20results%0A%20%20%20%20from%20src.dataframes.geocode_cluster_metrics%20import%20GeocodeClusterMetricsSchema%0A%0A%20%20%20%20all_cluster_metrics_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20all_cluster_metrics%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeClusterMetricsSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(all_cluster_metrics_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(all_clusters_df%2C%20cache_parquet%2C%20optimal_num_clusters)%3A%0A%20%20%20%20%23%20Create%20base%20GeocodeClusterSchema%20(single%20k)%20for%20downstream%20use%0A%20%20%20%20from%20src.dataframes.geocode_cluster%20import%20(%0A%20%20%20%20%20%20%20%20GeocodeClusterSchema%2C%0A%20%20%20%20%20%20%20%20build_geocode_cluster_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_cluster_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_geocode_cluster_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20all_clusters_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20optimal_num_clusters%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DGeocodeClusterSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(geocode_cluster_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(all_cluster_metrics_df)%3A%0A%20%20%20%20all_cluster_metrics_df%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%23%20Optimization%20Results%20Table%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(all_cluster_metrics_df)%3A%0A%20%20%20%20from%20src.dataframes.geocode_cluster_metrics%20import%20get_metrics_summary%0A%0A%20%20%20%20get_metrics_summary(all_cluster_metrics_df)%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%23%20Multi-Metric%20Cluster%20Validation%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(all_cluster_metrics_df%2C%20optimal_num_clusters)%3A%0A%20%20%20%20from%20src.plot.cluster_metrics%20import%20plot_all_metrics_vs_k%0A%0A%20%20%20%20plot_all_metrics_vs_k(%0A%20%20%20%20%20%20%20%20all_cluster_metrics_df%2C%0A%20%20%20%20%20%20%20%20optimal_k%3Doptimal_num_clusters%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%23%20Normalized%20Metrics%20Comparison%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(all_cluster_metrics_df%2C%20optimal_num_clusters)%3A%0A%20%20%20%20from%20src.plot.cluster_metrics%20import%20plot_normalized_metrics%0A%0A%20%20%20%20plot_normalized_metrics(%0A%20%20%20%20%20%20%20%20all_cluster_metrics_df%2C%0A%20%20%20%20%20%20%20%20optimal_k%3Doptimal_num_clusters%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%20%60ClusterNeighbors%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_cluster_df%2C%20geocode_neighbors_df)%3A%0A%20%20%20%20from%20src.dataframes.cluster_neighbors%20import%20(%0A%20%20%20%20%20%20%20%20ClusterNeighborsSchema%2C%0A%20%20%20%20%20%20%20%20build_cluster_neighbors_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20cluster_neighbors_lf%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_cluster_neighbors_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_neighbors_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_cluster_df%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DClusterNeighborsSchema%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_neighbors_lf%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_neighbors_lf)%3A%0A%20%20%20%20cluster_neighbors_lf.limit(3).collect()%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%20%60ClusterTaxaStatistics%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_cluster_df%2C%20geocode_taxa_counts_lf%2C%20taxonomy_lf)%3A%0A%20%20%20%20from%20src.dataframes.cluster_taxa_statistics%20import%20(%0A%20%20%20%20%20%20%20%20ClusterTaxaStatisticsSchema%2C%0A%20%20%20%20%20%20%20%20build_cluster_taxa_statistics_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20cluster_taxa_statistics_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_cluster_taxa_statistics_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_taxa_counts_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_cluster_df.lazy()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20taxonomy_lf%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DClusterTaxaStatisticsSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(cluster_taxa_statistics_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_taxa_statistics_df)%3A%0A%20%20%20%20cluster_taxa_statistics_df%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%20%60ClusterSignificantDifferences%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20cluster_neighbors_lf%2C%20cluster_taxa_statistics_df)%3A%0A%20%20%20%20from%20src.dataframes.cluster_significant_differences%20import%20(%0A%20%20%20%20%20%20%20%20ClusterSignificantDifferencesSchema%2C%0A%20%20%20%20%20%20%20%20build_cluster_significant_differences_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20cluster_significant_differences_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_cluster_significant_differences_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_taxa_statistics_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_neighbors_lf%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DClusterSignificantDifferencesSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(cluster_significant_differences_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_significant_differences_df)%3A%0A%20%20%20%20cluster_significant_differences_df%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%20%60ClusterBoundary%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_cluster_df%2C%20geocode_lf)%3A%0A%20%20%20%20from%20src.dataframes.cluster_boundary%20import%20(%0A%20%20%20%20%20%20%20%20ClusterBoundarySchema%2C%0A%20%20%20%20%20%20%20%20build_cluster_boundary_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20cluster_boundary_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_cluster_boundary_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_cluster_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_lf%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DClusterBoundarySchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(cluster_boundary_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_boundary_df)%3A%0A%20%20%20%20cluster_boundary_df%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(cluster_boundary_df%2C%20folium)%3A%0A%20%20%20%20_boundary%20%3D%20cluster_boundary_df.select(%5B%22geometry%22%2C%20%22cluster%22%5D)%0A%0A%20%20%20%20_map%20%3D%20folium.Map(%0A%20%20%20%20%20%20%20%20tiles%3D%22Esri.WorldGrayCanvas%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20folium.GeoJson(%0A%20%20%20%20%20%20%20%20_boundary.st%2C%0A%20%20%20%20%20%20%20%20popup%3Dfolium.GeoJsonPopup(%0A%20%20%20%20%20%20%20%20%20%20%20%20fields%3D%5B%22cluster%22%5D%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20).add_to(_map)%0A%0A%20%20%20%20_map.fit_bounds(_map.get_bounds())%0A%0A%20%20%20%20_map%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%20%60ClusterDistance%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_taxa_statistics_df)%3A%0A%20%20%20%20from%20src.matrices.cluster_distance%20import%20ClusterDistanceMatrix%0A%0A%20%20%20%20cluster_distance_matrix%20%3D%20ClusterDistanceMatrix.build(%0A%20%20%20%20%20%20%20%20cluster_taxa_statistics_df%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_distance_matrix%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_distance_matrix)%3A%0A%20%20%20%20cluster_distance_matrix.squareform()%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%20%60ClusterColor%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(optimal_num_clusters)%3A%0A%20%20%20%20%23%20Use%20taxonomic%20coloring%20if%20we%20have%20at%20least%2010%20clusters%2C%20otherwise%20use%20geographic%0A%20%20%20%20color_method%20%3D%20%22taxonomic%22%20if%20optimal_num_clusters%20%3E%3D%2010%20else%20%22geographic%22%0A%20%20%20%20return%20(color_method%2C)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cache_parquet%2C%0A%20%20%20%20cluster_neighbors_lf%2C%0A%20%20%20%20cluster_taxa_statistics_df%2C%0A%20%20%20%20color_method%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.cluster_color%20import%20ClusterColorSchema%2C%20build_cluster_color_df%0A%0A%20%20%20%20cluster_colors_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_cluster_color_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_neighbors_lf%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_taxa_statistics_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color_method%3Dcolor_method%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DClusterColorSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(cluster_colors_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(cluster_colors_df)%3A%0A%20%20%20%20cluster_colors_df%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%20Step%203.%20Analyze%0A%20%20%20%20%22%22%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%20%60PermanovaResults%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20geocode_cluster_df%2C%20geocode_distance_matrix%2C%20geocode_lf)%3A%0A%20%20%20%20from%20src.dataframes.permanova_results%20import%20(%0A%20%20%20%20%20%20%20%20PermanovaResultsSchema%2C%0A%20%20%20%20%20%20%20%20build_permanova_results_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20permanova_results_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_permanova_results_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_distance_matrix%3Dgeocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_cluster_df%3Dgeocode_cluster_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20geocode_lf%3Dgeocode_lf%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DPermanovaResultsSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(permanova_results_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(permanova_results_df)%3A%0A%20%20%20%20permanova_results_df%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%20%60GeocodeSilhouetteScore%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(all_clusters_df%2C%20geocode_distance_matrix%2C%20optimal_num_clusters%2C%20pl)%3A%0A%20%20%20%20from%20sklearn.metrics%20import%20silhouette_samples%0A%0A%20%20%20%20from%20src.dataframes.geocode_silhouette_score%20import%20GeocodeSilhouetteScoreSchema%0A%0A%20%20%20%20%23%20Get%20clustering%20for%20optimal%20k%0A%20%20%20%20k_df%20%3D%20all_clusters_df.filter(pl.col(%22num_clusters%22)%20%3D%3D%20optimal_num_clusters)%0A%0A%20%20%20%20%23%20Compute%20per-geocode%20silhouette%20scores%20for%20the%20optimal%20k%0A%20%20%20%20samples%20%3D%20silhouette_samples(%0A%20%20%20%20%20%20%20%20X%3Dgeocode_distance_matrix.squareform()%2C%0A%20%20%20%20%20%20%20%20labels%3Dk_df%5B%22cluster%22%5D%2C%0A%20%20%20%20%20%20%20%20metric%3D%22precomputed%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_silhouette_score_df%20%3D%20GeocodeSilhouetteScoreSchema.validate(%0A%20%20%20%20%20%20%20%20pl.DataFrame(%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22geocode%22%3A%20k_df%5B%22geocode%22%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22silhouette_score%22%3A%20list(samples)%2C%20%20%23%20type%3A%20ignore%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22num_clusters%22%3A%20%5Boptimal_num_clusters%5D%20*%20len(k_df)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20).with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22geocode%22).cast(pl.UInt64)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22num_clusters%22).cast(pl.UInt32)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_silhouette_score_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(geocode_silhouette_score_df)%3A%0A%20%20%20%20geocode_silhouette_score_df.sort(by%3D%22silhouette_score%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20geocode_cluster_df%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20geocode_silhouette_score_df%2C%0A)%3A%0A%20%20%20%20from%20src.plot.silhouette_score%20import%20plot_silhouette_scores%0A%0A%20%20%20%20plot_silhouette_scores(%0A%20%20%20%20%20%20%20%20geocode_cluster_df%2C%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_silhouette_score_df%2C%0A%20%20%20%20%20%20%20%20cluster_colors_df%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%20Step%204.%20Export%0A%20%20%20%20%22%22%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%20Build%20and%20plot%20GeoJSON%20feature%20collection%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_boundary_df%2C%20cluster_colors_df)%3A%0A%20%20%20%20from%20src.geojson%20import%20build_geojson_feature_collection%0A%0A%20%20%20%20feature_collection%20%3D%20build_geojson_feature_collection(%0A%20%20%20%20%20%20%20%20cluster_boundary_df%2C%0A%20%20%20%20%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(feature_collection%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%23%23%20Save%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(feature_collection)%3A%0A%20%20%20%20from%20src%20import%20output%0A%20%20%20%20from%20src.geojson%20import%20write_geojson%0A%0A%20%20%20%20write_geojson(feature_collection%2C%20output.get_geojson_path())%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%23%20Plot%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(feature_collection%2C%20folium)%3A%0A%20%20%20%20_map%20%3D%20folium.Map(%0A%20%20%20%20%20%20%20%20tiles%3D%22Esri.WorldGrayCanvas%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20folium.GeoJson(%0A%20%20%20%20%20%20%20%20feature_collection%2C%0A%20%20%20%20%20%20%20%20style_function%3Dlambda%20feature%3A%20feature%5B%22properties%22%5D%2C%0A%20%20%20%20).add_to(_map)%0A%0A%20%20%20%20_map.fit_bounds(folium.utilities.get_bounds(feature_collection%2C%20lonlat%3DTrue))%0A%0A%20%20%20%20_map%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%20Dimensionality%20reduction%20plot%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_colors_df%2C%20geocode_cluster_df%2C%20geocode_distance_matrix)%3A%0A%20%20%20%20from%20src.plot.dimensionality_reduction%20import%20create_dimensionality_reduction_plot%0A%0A%20%20%20%20_chart%20%3D%20create_dimensionality_reduction_plot(%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_df%2C%0A%20%20%20%20%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20%20%20%20%20method%3D%22umap%22%2C%0A%20%20%20%20)%0A%20%20%20%20_chart%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%20Clustermap%20visualization%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%23%20from%20src.plot.cluster_taxa%20import%20create_cluster_taxa_heatmap%0A%0A%20%20%20%20%23%20heatmap%20%3D%20create_cluster_taxa_heatmap(%0A%20%20%20%20%23%20%20%20%20%20geocode_lf%3Dgeocode_lf%2C%0A%20%20%20%20%23%20%20%20%20%20geocode_cluster_df%3Dgeocode_cluster_df%2C%0A%20%20%20%20%23%20%20%20%20%20cluster_colors_df%3Dcluster_colors_df%2C%0A%20%20%20%20%23%20%20%20%20%20geocode_distance_matrix%3Dgeocode_distance_matrix%2C%0A%20%20%20%20%23%20%20%20%20%20cluster_significant_differences_df%3Dcluster_significant_differences_df%2C%0A%20%20%20%20%23%20%20%20%20%20taxonomy_df%3Dtaxonomy_lf.collect(engine%3D%22streaming%22)%2C%0A%20%20%20%20%23%20%20%20%20%20geocode_taxa_counts_lf%3Dgeocode_taxa_counts_lf%2C%0A%20%20%20%20%23%20%20%20%20%20cluster_taxa_statistics_df%3Dcluster_taxa_statistics_df%2C%0A%20%20%20%20%23%20%20%20%20%20limit_species%3D5%2C%0A%20%20%20%20%23%20)%0A%0A%20%20%20%20%23%20if%20heatmap%20is%20None%3A%0A%20%20%20%20%23%20%20%20%20%20result%20%3D%20mo.md(%22No%20significant%20differences%20found%20between%20clusters.%22)%0A%20%20%20%20%23%20else%3A%0A%20%20%20%20%23%20%20%20%20%20result%20%3D%20heatmap.figure%0A%0A%20%20%20%20%23%20result%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20%60SignificantTaxaImages%60%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cache_parquet%2C%20cluster_significant_differences_df%2C%20taxonomy_lf)%3A%0A%20%20%20%20from%20src.dataframes.significant_taxa_images%20import%20(%0A%20%20%20%20%20%20%20%20SignificantTaxaImagesSchema%2C%0A%20%20%20%20%20%20%20%20build_significant_taxa_images_df%2C%0A%20%20%20%20)%0A%0A%20%20%20%20significant_taxa_images_df%20%3D%20cache_parquet(%0A%20%20%20%20%20%20%20%20build_significant_taxa_images_df(%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_significant_differences_df%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20taxonomy_lf.collect(engine%3D%22streaming%22)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20cache_key%3DSignificantTaxaImagesSchema%2C%0A%20%20%20%20).collect(engine%3D%22streaming%22)%0A%20%20%20%20return%20(significant_taxa_images_df%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(significant_taxa_images_df)%3A%0A%20%20%20%20significant_taxa_images_df%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%20Write%20output%20for%20frontend%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_boundary_df%2C%0A%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20cluster_significant_differences_df%2C%0A%20%20%20%20significant_taxa_images_df%2C%0A%20%20%20%20taxonomy_lf%2C%0A)%3A%0A%20%20%20%20from%20src.output%20import%20write_json_output%0A%0A%20%20%20%20taxonomy_df%20%3D%20taxonomy_lf.collect(engine%3D%22streaming%22)%0A%0A%20%20%20%20%23%20write_json_output(%0A%20%20%20%20%23%20%20%20%20%20cluster_significant_differences_df%2C%0A%20%20%20%20%23%20%20%20%20%20cluster_boundary_df%2C%0A%20%20%20%20%23%20%20%20%20%20taxonomy_df%2C%0A%20%20%20%20%23%20%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20%23%20%20%20%20%20significant_taxa_images_df%2C%0A%20%20%20%20%23%20%20%20%20%20%22%2Fdev%2Fstdout%22%2C%0A%20%20%20%20%23%20)%0A%0A%20%20%20%20write_json_output(%0A%20%20%20%20%20%20%20%20cluster_significant_differences_df%2C%0A%20%20%20%20%20%20%20%20cluster_boundary_df%2C%0A%20%20%20%20%20%20%20%20taxonomy_df%2C%0A%20%20%20%20%20%20%20%20cluster_colors_df%2C%0A%20%20%20%20%20%20%20%20significant_taxa_images_df%2C%0A%20%20%20%20%20%20%20%20%22frontend%2Faggregations.json%22%2C%0A%20%20%20%20)%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
541de34a02dc3151a9e1f89b95ce71e0