import%20marimo%0A%0A__generated_with%20%3D%20%220.15.3%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20import%20polars_st%20as%20pl_st%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20hashlib%0A%20%20%20%20import%20os%0A%20%20%20%20import%20polars_darwin_core%0A%20%20%20%20import%20folium%0A%20%20%20%20return%20folium%2C%20hashlib%2C%20mo%2C%20np%2C%20os%2C%20pl%2C%20polars_darwin_core%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Citizen%20Science%20Bioregionalization%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%23%23%20Define%20inputs%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20log_file_ui%20%3D%20mo.ui.text(%22run.log%22%2C%20label%3D%22Log%20file%22)%0A%20%20%20%20input_dir_ui%20%3D%20mo.ui.file_browser(multiple%3DFalse%2C%20label%3D%22Input%20directory%22%2C%20selection_mode%3D%22directory%22)%0A%20%20%20%20geocode_precision_ui%20%3D%20mo.ui.number(value%3D4%2C%20label%3D%22Geocode%20precision%22)%0A%20%20%20%20taxon_filter_ui%20%3D%20mo.ui.text(%22%22%2C%20label%3D%22Taxon%20filter%20(optional)%22)%0A%20%20%20%20num_clusters_ui%20%3D%20mo.ui.number(value%3D10%2C%20label%3D%22Number%20of%20clusters%22)%0A%0A%20%20%20%20%23%20Display%20inputs%0A%20%20%20%20(%0A%20%20%20%20%20%20%20%20mo.vstack(%0A%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%20log_file_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20input_dir_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20geocode_precision_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20taxon_filter_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20num_clusters_ui%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20if%20mo.running_in_notebook()%0A%20%20%20%20%20%20%20%20else%20None%0A%20%20%20%20)%0A%20%20%20%20return%20geocode_precision_ui%2C%20input_dir_ui%2C%20num_clusters_ui%2C%20taxon_filter_ui%0A%0A%0A%40app.cell%0Adef%20_(geocode_precision_ui%2C%20input_dir_ui%2C%20num_clusters_ui%2C%20taxon_filter_ui)%3A%0A%20%20%20%20import%20argparse%0A%0A%20%20%20%20parser%20%3D%20argparse.ArgumentParser(%0A%20%20%20%20%20%20%20%20description%3D%22Process%20Darwin%20Core%20CSV%20data%20and%20generate%20clusters.%22%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Add%20required%20options%0A%20%20%20%20parser.add_argument(%0A%20%20%20%20%20%20%20%20%22--geocode-precision%22%2C%0A%20%20%20%20%20%20%20%20type%3Dint%2C%0A%20%20%20%20%20%20%20%20help%3D%22Precision%20of%20the%20geocode%22%2C%0A%20%20%20%20%20%20%20%20default%3Dgeocode_precision_ui.value%2C%0A%20%20%20%20)%0A%20%20%20%20parser.add_argument(%0A%20%20%20%20%20%20%20%20%22--num-clusters%22%2C%0A%20%20%20%20%20%20%20%20type%3Dint%2C%0A%20%20%20%20%20%20%20%20help%3D%22Number%20of%20clusters%20to%20generate%22%2C%0A%20%20%20%20%20%20%20%20default%3Dnum_clusters_ui.value%2C%0A%20%20%20%20)%0A%20%20%20%20parser.add_argument(%22--log-file%22%2C%20type%3Dstr%2C%20help%3D%22Path%20to%20the%20log%20file%22)%0A%0A%20%20%20%20%23%20Add%20optional%20arguments%0A%20%20%20%20parser.add_argument(%0A%20%20%20%20%20%20%20%20%22--taxon-filter%22%2C%0A%20%20%20%20%20%20%20%20type%3Dstr%2C%0A%20%20%20%20%20%20%20%20default%3Dtaxon_filter_ui.value%2C%0A%20%20%20%20%20%20%20%20help%3D%22Filter%20to%20a%20specific%20taxon%20(e.g.%2C%20'Aves')%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Positional%20arguments%0A%20%20%20%20path%20%3D%20str(input_dir_ui.path(index%3D0))%20if%20input_dir_ui.path(index%3D0)%20else%20None%0A%20%20%20%20parser.add_argument(%0A%20%20%20%20%20%20%20%20%22input_dir%22%2C%20type%3Dstr%2C%20nargs%3D%22%3F%22%2C%20help%3D%22Path%20to%20the%20input%20directory%22%2C%20default%3Dpath%0A%20%20%20%20)%0A%0A%20%20%20%20args%20%3D%20parser.parse_args()%0A%20%20%20%20return%20(args%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Set%20up%20logging%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args)%3A%0A%20%20%20%20import%20logging%0A%0A%20%20%20%20logging.basicConfig(filename%3Dargs.log_file%2C%20encoding%3D%22utf-8%22%2C%20level%3Dlogging.INFO)%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%23%23%20%60DarwinCore%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20polars_darwin_core)%3A%0A%20%20%20%20darwin_core_csv_lazy_frame%20%3D%20polars_darwin_core.DarwinCoreLazyFrame.from_archive(%0A%20%20%20%20%20%20%20%20args.input_dir%2C%0A%20%20%20%20%20%20%20%20%23%20input_file%2C%20taxon_filter%3Dtaxon_filter%0A%20%20%20%20%20%20%20%20%23%20TODO%3A%20FIX%20THE%20TAXON%20FILTER%20ABOVE%0A%20%20%20%20)%0A%0A%20%20%20%20darwin_core_csv_lazy_frame._inner.limit(3).collect()%0A%20%20%20%20return%20(darwin_core_csv_lazy_frame%2C)%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20hashlib%2C%20os)%3A%0A%20%20%20%20with%20open(os.path.join(args.input_dir%2C%20%22occurrence.txt%22)%2C%20%22rb%22)%20as%20f%3A%0A%20%20%20%20%20%20%20%20file_digest%20%3D%20hashlib.file_digest(f%2C%20%22sha256%22).hexdigest()%0A%0A%20%20%20%20output_dir%20%3D%20%22tmp%22%0A%20%20%20%20os.makedirs(output_dir%2C%20exist_ok%3DTrue)%0A%20%20%20%20output_path%20%3D%20os.path.join(output_dir%2C%20f%22%7Bfile_digest%7D.parquet%22)%0A%20%20%20%20return%20(output_path%2C)%0A%0A%0A%40app.cell%0Adef%20_(darwin_core_csv_lazy_frame%2C%20os%2C%20output_path)%3A%0A%20%20%20%20if%20not%20os.path.exists(output_path)%3A%0A%20%20%20%20%20%20%20%20darwin_core_csv_lazy_frame._inner.sink_parquet(output_path)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(output_path%2C%20pl%2C%20polars_darwin_core)%3A%0A%20%20%20%20inner%20%3D%20pl.scan_parquet(output_path)%0A%0A%20%20%20%20darwin_core_lazy_frame%20%3D%20polars_darwin_core.DarwinCoreLazyFrame(inner)%0A%0A%20%20%20%20darwin_core_lazy_frame._inner.limit(200).collect()%0A%20%20%20%20return%20(darwin_core_lazy_frame%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60Geocode%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20darwin_core_lazy_frame)%3A%0A%20%20%20%20from%20src.dataframes.geocode%20import%20GeocodeSchema%0A%0A%20%20%20%20geocode_dataframe%20%3D%20GeocodeSchema.build(%0A%20%20%20%20%20%20%20%20darwin_core_lazy_frame%2C%0A%20%20%20%20%20%20%20%20args.geocode_precision%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_dataframe%0A%20%20%20%20return%20(geocode_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(folium%2C%20geocode_dataframe%2C%20pl)%3A%0A%20%20%20%20_center%20%3D%20geocode_dataframe.select(%0A%20%20%20%20%20%20%20%20pl.col(%22center%22).alias(%22geometry%22)%2C%0A%20%20%20%20)%0A%20%20%20%20_boundary%20%3D%20geocode_dataframe.select(%0A%20%20%20%20%20%20%20%20pl.col(%22boundary%22).alias(%22geometry%22)%2C%0A%20%20%20%20)%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%20folium.GeoJson(%0A%20%20%20%20%20%20%20%20_boundary.st%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%23%23%20%60Taxonomy%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(darwin_core_lazy_frame)%3A%0A%20%20%20%20from%20src.dataframes.taxonomy%20import%20TaxonomySchema%0A%0A%20%20%20%20taxonomy_dataframe%20%3D%20TaxonomySchema.build(darwin_core_lazy_frame)%0A%0A%20%20%20%20taxonomy_dataframe%0A%20%20%20%20return%20(taxonomy_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeSpeciesCounts%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20darwin_core_lazy_frame%2C%20taxonomy_dataframe)%3A%0A%20%20%20%20from%20src.dataframes.geocode_taxa_counts%20import%20GeocodeTaxaCountsSchema%0A%0A%20%20%20%20geocode_taxa_counts_dataframe%20%3D%20GeocodeTaxaCountsSchema.build(%0A%20%20%20%20%20%20%20%20darwin_core_lazy_frame%2C%0A%20%20%20%20%20%20%20%20args.geocode_precision%2C%0A%20%20%20%20%20%20%20%20taxonomy_dataframe%2C%0A%20%20%20%20)%0A%0A%20%20%20%20geocode_taxa_counts_dataframe%0A%20%20%20%20return%20(geocode_taxa_counts_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeConnectivity%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_dataframe)%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_dataframe)%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%23%23%20%60GeocodeDistance%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_dataframe%2C%20geocode_taxa_counts_dataframe%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_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_dataframe%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%23%23%20%60GeocodeCluster%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20args%2C%0A%20%20%20%20geocode_connectivity_matrix%2C%0A%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.geocode_cluster%20import%20GeocodeClusterSchema%0A%0A%20%20%20%20geocode_cluster_dataframe%20%3D%20GeocodeClusterSchema.build(%0A%20%20%20%20%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_connectivity_matrix%2C%0A%20%20%20%20%20%20%20%20args.num_clusters%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_cluster_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_cluster_dataframe)%3A%0A%20%20%20%20geocode_cluster_dataframe.limit(3)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20%23%20%23%20TMP%0A%0A%20%20%20%20%23%20from%20src.dataframes.geocode_cluster%20import%20GeocodeClusterDataFrame%0A%20%20%20%20%23%20from%20sklearn.metrics%20import%20silhouette_score%0A%0A%20%20%20%20%23%20results%20%3D%20%5B%5D%0A%0A%20%20%20%20%23%20for%20i%20in%20range(2%2C%20200)%3A%0A%20%20%20%20%23%20%20%20%20%20geocode_cluster_dataframe%20%3D%20GeocodeClusterDataFrame.build(%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20distance_matrix%2C%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20connectivity_matrix%2C%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20num_clusters%3Di%2C%0A%20%20%20%20%23%20%20%20%20%20)%0A%20%20%20%20%23%20%20%20%20%20score%20%3D%20silhouette_score(%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20X%3Ddistance_matrix.squareform()%2C%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20labels%3Dgeocode_cluster_dataframe.df%5B%22cluster%22%5D%2C%0A%20%20%20%20%23%20%20%20%20%20%20%20%20%20metric%3D%22precomputed%22%2C%0A%20%20%20%20%23%20%20%20%20%20)%0A%20%20%20%20%23%20%20%20%20%20print(f%22%7Bi%7D%3A%20%7Bscore%7D%22)%0A%20%20%20%20%23%20%20%20%20%20results.append((i%2C%20score))%0A%0A%20%20%20%20%23%20results%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%23%23%20%60ClusterNeighbors%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_cluster_dataframe%2C%20geocode_dataframe)%3A%0A%20%20%20%20from%20src.dataframes.cluster_neighbors%20import%20ClusterNeighborsSchema%0A%0A%20%20%20%20cluster_neighbors_dataframe%20%3D%20ClusterNeighborsSchema.build(%0A%20%20%20%20%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_neighbors_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_neighbors_dataframe)%3A%0A%20%20%20%20cluster_neighbors_dataframe%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%23%23%20%60ClusterTaxaStatistics%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20geocode_taxa_counts_dataframe%2C%0A%20%20%20%20taxonomy_dataframe%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.cluster_taxa_statistics%20import%20ClusterTaxaStatisticsSchema%0A%0A%20%20%20%20cluster_taxa_statistics_dataframe%20%3D%20ClusterTaxaStatisticsSchema.build(%0A%20%20%20%20%20%20%20%20geocode_taxa_counts_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20%20%20%20%20taxonomy_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_taxa_statistics_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_taxa_statistics_dataframe)%3A%0A%20%20%20%20cluster_taxa_statistics_dataframe%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%23%23%20%60ClusterSignificantDifferences%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_taxa_statistics_dataframe)%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)%0A%0A%20%20%20%20cluster_significant_differences_dataframe%20%3D%20(%0A%20%20%20%20%20%20%20%20ClusterSignificantDifferencesSchema.build(%0A%20%20%20%20%20%20%20%20%20%20%20%20cluster_taxa_statistics_dataframe%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_significant_differences_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_significant_differences_dataframe)%3A%0A%20%20%20%20cluster_significant_differences_dataframe%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%23%23%20%60ClusterBoundary%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_cluster_dataframe%2C%20geocode_dataframe)%3A%0A%20%20%20%20from%20src.dataframes.cluster_boundary%20import%20ClusterBoundarySchema%0A%0A%20%20%20%20cluster_boundary_dataframe%20%3D%20ClusterBoundarySchema.build(%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_boundary_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_boundary_dataframe)%3A%0A%20%20%20%20cluster_boundary_dataframe%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_boundary_dataframe%2C%20pl)%3A%0A%20%20%20%20(%0A%20%20%20%20%20%20%20%20cluster_boundary_dataframe.select(pl.col(%22geometry%22))%0A%20%20%20%20%20%20%20%20.st.plot(stroke%3D%22green%22)%0A%20%20%20%20%20%20%20%20.project(type%3D%22identity%22%2C%20reflectY%3DTrue)%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%23%23%20%60ClusterDistance%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_taxa_statistics_dataframe)%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_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_distance_matrix%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%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%23%23%20%60ClusterColor%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_boundary_dataframe%2C%0A%20%20%20%20cluster_neighbors_dataframe%2C%0A%20%20%20%20cluster_taxa_statistics_dataframe%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.cluster_color%20import%20ClusterColorSchema%0A%0A%20%20%20%20cluster_colors_dataframe%20%3D%20ClusterColorSchema.build(%0A%20%20%20%20%20%20%20%20cluster_neighbors_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_boundary_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_taxa_statistics_dataframe%2C%0A%20%20%20%20%20%20%20%20color_method%3D%22taxonomic%22%2C%0A%20%20%20%20%20%20%20%20%23%20color_method%3D%22geographic%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20cluster_colors_dataframe%0A%20%20%20%20return%20(cluster_colors_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60PermanovaResults%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_cluster_dataframe%2C%20geocode_dataframe%2C%20geocode_distance_matrix)%3A%0A%20%20%20%20from%20src.dataframes.permanova_results%20import%20PermanovaResultsSchema%0A%0A%20%20%20%20permanova_results_dataframe%20%3D%20PermanovaResultsSchema.build(%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%3Dgeocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%3Dgeocode_cluster_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_dataframe%3Dgeocode_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(permanova_results_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(permanova_results_dataframe)%3A%0A%20%20%20%20permanova_results_dataframe%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%23%23%20%60GeocodeSilhouetteScore%60%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%23%23%23%20Build%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_neighbors_dataframe%2C%0A%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A)%3A%0A%20%20%20%20from%20src.dataframes.geocode_silhouette_score%20import%20GeocodeSilhouetteScoreSchema%0A%0A%20%20%20%20geocode_silhouette_score_dataframe%20%3D%20GeocodeSilhouetteScoreSchema.build(%0A%20%20%20%20%20%20%20%20cluster_neighbors_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_silhouette_score_dataframe%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Preview%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_silhouette_score_dataframe)%3A%0A%20%20%20%20geocode_silhouette_score_dataframe.sort(by%3D%22silhouette_score%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20geocode_silhouette_score_dataframe%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_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20geocode_silhouette_score_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_colors_dataframe%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%23%23%20Build%20and%20plot%20GeoJSON%20feature%20collection%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cluster_boundary_dataframe%2C%20cluster_colors_dataframe)%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_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_colors_dataframe%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%23%23%23%20Save%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(feature_collection)%3A%0A%20%20%20%20from%20src.geojson%20import%20write_geojson%0A%20%20%20%20from%20src%20import%20output%0A%0A%20%20%20%20write_geojson(feature_collection%2C%20output.get_geojson_path())%0A%20%20%20%20return%20(output%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%20Plot%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(feature_collection%2C%20folium)%3A%0A%20%20%20%20map%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%20map.fit_bounds(folium.utilities.get_bounds(feature_collection%2C%20lonlat%3DTrue))%0A%0A%20%20%20%20map%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%23%23%20Build%20and%20display%20HTML%20output%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20cluster_significant_differences_dataframe%2C%0A%20%20%20%20feature_collection%2C%0A%20%20%20%20output%2C%0A%20%20%20%20taxonomy_dataframe%2C%0A)%3A%0A%20%20%20%20from%20src.html_output%20import%20prepare_full_report_data%2C%20render_html%2C%20write_html%0A%0A%20%20%20%20report_data%20%3D%20prepare_full_report_data(%0A%20%20%20%20%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_significant_differences_dataframe%2C%0A%20%20%20%20%20%20%20%20taxonomy_dataframe%2C%0A%20%20%20%20%20%20%20%20feature_collection%2C%0A%20%20%20%20)%0A%20%20%20%20html_content%20%3D%20render_html(%22cluster_report.html%22%2C%20report_data)%0A%20%20%20%20html_output%20%3D%20output.get_html_path()%0A%20%20%20%20write_html(html_content%2C%20html_output)%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%23%23%20Dimensionality%20reduction%20plot%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A)%3A%0A%20%20%20%20from%20src.plot.dimnesionality_reduction%20import%20create_dimensionality_reduction_plot%0A%0A%20%20%20%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_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20%20%20%20%20method%3D%22umap%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%23%23%20Clustermap%20visualization%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20cluster_colors_dataframe%2C%0A%20%20%20%20cluster_significant_differences_dataframe%2C%0A%20%20%20%20cluster_taxa_statistics_dataframe%2C%0A%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20geocode_dataframe%2C%0A%20%20%20%20geocode_distance_matrix%2C%0A%20%20%20%20geocode_taxa_counts_dataframe%2C%0A%20%20%20%20taxonomy_dataframe%2C%0A)%3A%0A%20%20%20%20from%20src.plot.cluster_taxa%20import%20create_cluster_taxa_heatmap%0A%0A%20%20%20%20create_cluster_taxa_heatmap(%0A%20%20%20%20%20%20%20%20geocode_dataframe%3Dgeocode_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%3Dgeocode_cluster_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_colors_dataframe%3Dcluster_colors_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_distance_matrix%3Dgeocode_distance_matrix%2C%0A%20%20%20%20%20%20%20%20cluster_significant_differences_dataframe%3Dcluster_significant_differences_dataframe%2C%0A%20%20%20%20%20%20%20%20taxonomy_dataframe%3Dtaxonomy_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_taxa_counts_dataframe%3Dgeocode_taxa_counts_dataframe%2C%0A%20%20%20%20%20%20%20%20cluster_taxa_statistics_dataframe%3Dcluster_taxa_statistics_dataframe%2C%0A%20%20%20%20%20%20%20%20limit_species%3D5%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
bae629e23ee174c3dcf314fe7df1aef5efef9bdb1977dd7ec54ab70981868dc6