import%20marimo%0A%0A__generated_with%20%3D%20%220.14.16%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%20numpy%20as%20np%0A%0A%20%20%20%20return%20mo%2C%20np%2C%20pl%0A%0A%0A%40app.cell%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%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_file_ui%20%3D%20mo.ui.file_browser(multiple%3DFalse%2C%20label%3D%22Input%20file%22)%0A%20%20%20%20geocode_precision_ui%20%3D%20mo.ui.slider(2%2C%205%2C%20value%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%20mo.vstack(%5Blog_file_ui%2C%20input_file_ui%2C%20geocode_precision_ui%2C%20taxon_filter_ui%2C%20num_clusters_ui%5D)%20if%20mo.running_in_notebook()%20else%20None%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%20input_file_ui%2C%0A%20%20%20%20%20%20%20%20num_clusters_ui%2C%0A%20%20%20%20%20%20%20%20taxon_filter_ui%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(geocode_precision_ui%2C%20input_file_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%20type%3Dint%2C%20help%3D%22Precision%20of%20the%20geocode%22%2C%20default%3Dgeocode_precision_ui.value%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%20type%3Dint%2C%20help%3D%22Number%20of%20clusters%20to%20generate%22%2C%20default%3Dnum_clusters_ui.value%0A%20%20%20%20)%0A%20%20%20%20parser.add_argument(%0A%20%20%20%20%20%20%20%20%22--log-file%22%2C%20type%3Dstr%2C%20help%3D%22Path%20to%20the%20log%20file%22%0A%20%20%20%20)%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_file_ui.path(index%3D0))%20if%20input_file_ui.path(index%3D0)%20else%20None%0A%20%20%20%20parser.add_argument(%22input_file%22%2C%20type%3Dstr%2C%20nargs%3D%22%3F%22%2C%20help%3D%22Path%20to%20the%20input%20file%22%2C%20default%3Dpath)%0A%0A%20%20%20%20args%20%3D%20parser.parse_args()%0A%20%20%20%20return%20(args%2C)%0A%0A%0A%40app.cell%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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60DarwinCoreCsvLazyFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args)%3A%0A%20%20%20%20from%20polars_darwin_core.lf_csv%20import%20read_darwin_core_csv%0A%0A%20%20%20%20darwin_core_csv_lazy_frame%20%3D%20read_darwin_core_csv(%0A%20%20%20%20%20%20%20%20args.input_file%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_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20darwin_core_csv_lazy_frame)%3A%0A%20%20%20%20from%20src.dataframes.geocode%20import%20GeocodeDataFrame%0A%0A%20%20%20%20geocode_dataframe%20%3D%20GeocodeDataFrame.build(%0A%20%20%20%20%20%20%20%20darwin_core_csv_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.df%0A%20%20%20%20return%20(geocode_dataframe%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60TaxonomyDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(darwin_core_csv_lazy_frame)%3A%0A%20%20%20%20from%20src.dataframes.taxonomy%20import%20TaxonomyDataFrame%0A%0A%20%20%20%20taxonomy_dataframe%20%3D%20TaxonomyDataFrame.build(darwin_core_csv_lazy_frame)%0A%0A%20%20%20%20taxonomy_dataframe.df%0A%20%20%20%20return%20(taxonomy_dataframe%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeohashSpeciesCountsDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(args%2C%20darwin_core_csv_lazy_frame%2C%20taxonomy_dataframe)%3A%0A%20%20%20%20from%20src.dataframes.geocode_taxa_counts%20import%20GeocodeTaxaCountsDataFrame%0A%0A%20%20%20%20geocode_taxa_counts_dataframe%20%3D%20GeocodeTaxaCountsDataFrame.build(%0A%20%20%20%20%20%20%20%20darwin_core_csv_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.df%0A%20%20%20%20return%20(geocode_taxa_counts_dataframe%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeConnectivityMatrix%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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeDistanceMatrix%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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeohashClusterDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20GeocodeClusterDataFrame%0A%0A%20%20%20%20geocode_cluster_dataframe%20%3D%20GeocodeClusterDataFrame.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%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.df.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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterNeighborsDataframe%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20ClusterNeighborsDataFrame%0A%0A%20%20%20%20cluster_neighbors_dataframe%20%3D%20ClusterNeighborsDataFrame.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%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.df%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterTaxaStatisticsDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20ClusterTaxaStatisticsDataFrame%0A%0A%20%20%20%20cluster_taxa_statistics_dataframe%20%3D%20ClusterTaxaStatisticsDataFrame.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%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.df%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterSignificantDifferencesDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20ClusterSignificantDifferencesDataFrame%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%20ClusterSignificantDifferencesDataFrame.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%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.df.limit(3)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeBoundaryDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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)%3A%0A%20%20%20%20from%20src.dataframes.geocode_boundary%20import%20GeocodeBoundaryDataFrame%0A%0A%20%20%20%20geocode_boundary_dataframe%20%3D%20GeocodeBoundaryDataFrame.build(%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(geocode_boundary_dataframe%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_(geocode_boundary_dataframe)%3A%0A%20%20%20%20geocode_boundary_dataframe.df%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(geocode_boundary_dataframe%2C%20pl)%3A%0A%20%20%20%20(%0A%20%20%20%20%20%20%20%20geocode_boundary_dataframe.df.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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterBoundaryDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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_boundary_dataframe%2C%20geocode_cluster_dataframe)%3A%0A%20%20%20%20from%20src.dataframes.cluster_boundary%20import%20ClusterBoundaryDataFrame%0A%0A%20%20%20%20cluster_boundary_dataframe%20%3D%20ClusterBoundaryDataFrame.build(%0A%20%20%20%20%20%20%20%20geocode_cluster_dataframe%2C%0A%20%20%20%20%20%20%20%20geocode_boundary_dataframe%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(cluster_boundary_dataframe%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_boundary_dataframe)%3A%0A%20%20%20%20cluster_boundary_dataframe.df%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.df.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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterDistanceMatrix%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60ClusterColorDataFrame%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%20ClusterColorDataFrame%0A%0A%20%20%20%20cluster_colors_dataframe%20%3D%20ClusterColorDataFrame.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.df%0A%20%20%20%20return%20(cluster_colors_dataframe%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60PermanovaResultsDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20PermanovaResultsDataFrame%0A%0A%20%20%20%20permanova_results_dataframe%20%3D%20PermanovaResultsDataFrame.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%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.df%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%60GeocodeSilhouetteScoreDataFrame%60%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%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%20GeocodeSilhouetteScoreDataFrame%0A%0A%20%20%20%20geocode_silhouette_score_dataframe%20%3D%20GeocodeSilhouetteScoreDataFrame.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%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.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_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%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%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%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)%3A%0A%20%20%20%20from%20src.render%20import%20plot_clusters%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20%23%20Set%20the%20figure%20size%0A%20%20%20%20plt.rcParams%5B%22figure.figsize%22%5D%20%3D%20%5B12%2C%207%5D%0A%0A%20%20%20%20plot_clusters(feature_collection)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(feature_collection)%3A%0A%20%20%20%20import%20folium%0A%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%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%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%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%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Data%20flow%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20from%20src.dependency_graph%20import%20plot_dependency_graph%0A%0A%20%20%20%20mo.mermaid(plot_dependency_graph())%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
a22f248d12f2659c2058b92ac633a58ec0946cdb2c600b4082c14fc0012363c3