import%20marimo%0A%0A__generated_with%20%3D%20%220.23.11%22%0Aapp%20%3D%20marimo.App(%0A%20%20%20%20width%3D%22medium%22%2C%0A%20%20%20%20app_title%3D%22Overview%20-%20Hawk%2FDove%20with%20Evolving%20Risk-Attitudes%22%2C%0A%20%20%20%20html_head_file%3D%22..%2Fdocs_head.html%22%2C%0A)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20from%20simulatingrisk.doc_utils%20import%20docs_header%0A%0A%20%20%20%20docs_header()%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%20Hawk%2FDove%20with%20Evolving%20Risk-Attitudes%0A%0A%20%20%20%20Overview%20of%20simulation%20batch%20run%20data.%20Includes%20information%20about%20parameters%20and%20number%20of%20runs%2C%20with%20brief%20analysis%20of%20run%20length%20and%20convergence%20correlation%20with%20initial%20parameters.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20import%20altair%20as%20alt%0A%20%20%20%20import%20seaborn%20as%20sns%0A%0A%20%20%20%20from%20simulatingrisk.hawkdovemulti.batch_run%20import%20params%0A%0A%20%20%20%20data_dir%20%3D%20Path(%22data%2Fdefault%2F%22)%0A%20%20%20%20return%20alt%2C%20data_dir%2C%20mo%2C%20params%2C%20pl%2C%20sns%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20mo%2C%20params%2C%20pl%2C%20run_groups_df%2C%20runs_per_group)%3A%0A%20%20%20%20param_opts%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20key%2C%20value%20in%20params%5B%22default%22%5D.items()%3A%0A%20%20%20%20%20%20%20%20if%20isinstance(value%2C%20(list%2C%20tuple))%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20value_str%20%3D%20%22%2C%20%22.join(%5Bstr(v)%20for%20v%20in%20value%5D)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20value_str%20%3D%20str(value)%0A%20%20%20%20%20%20%20%20param_opts.append(f%22-%20**%7Bkey%7D**%3A%20%7Bvalue_str%7D%22)%0A%0A%20%20%20%20param_info%20%3D%20%22%5Cn%22.join(param_opts)%0A%0A%20%20%20%20%23%20aggregate%20by%20status%20for%20plotting%20and%20reporting%0A%20%20%20%20status_df%20%3D%20df.group_by(%22status%22).agg(count%3Dpl.len()%2C%20percent%3Dpl.len()%20%2F%20df.height)%0A%20%20%20%20%23%20export%20total%20and%20percent%20of%20runs%20that%20converged%20for%20inclusion%20in%20text%0A%20%20%20%20converged_stats%20%3D%20status_df.filter(pl.col.status.eq(%22converged%22)).to_dicts()%5B0%5D%0A%0A%20%20%20%20%23%20TODO%3A%20would%20be%20great%20to%20report%20how%20many%20runs%20per%20parameter%20combination%20(hopefully%20100)%0A%20%20%20%20overview_txt%20%3D%20f%22%22%22%0A%20%20%20%20Analyzing%20data%20from%20**%7Bdf.height%3A%2C%7D**%20total%20simulation%20runs.%0A%0A%20%20%20%20**%7Bconverged_stats%5B%22count%22%5D%3A%2C%7D%20(%7Bconverged_stats%5B%22percent%22%5D%20*%20100%3A.1f%7D%25)**%20%20simulations%20converged.%0A%0A%20%20%20%20Simulations%20were%20run%20on%20the%20following%20combination%20of%20initial%20parameters%3A%0A%20%20%20%20%7Bparam_info%7D%0A%0A%20%20%20%20This%20resulted%20in%20**%7Brun_groups_df.height%3A%2C%7D**%20combinations%3B%20each%20set%20of%20parameters%20was%20run%20**%7Bruns_per_group%3A%2C%7D%20times**.%0A%20%20%20%20%22%22%22%0A%0A%20%20%20%20mo.md(overview_txt)%0A%20%20%20%20return%20(status_df%2C)%0A%0A%0A%40app.cell%0Adef%20_(data_dir%2C%20pl)%3A%0A%20%20%20%20%23%20Load%20all%20model%20data%20in%20the%20folder%20for%20this%20set%20of%20simulations%20%2B%20parameter%20batch%20runs%0A%20%20%20%20df%20%3D%20pl.scan_csv(%5Bstr(file)%20for%20file%20in%20data_dir.glob(%22*_model.csv%22)%5D).collect()%0A%20%20%20%20return%20(df%2C)%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20mo%2C%20pl%2C%20status_df)%3A%0A%20%20%20%20%23%20display%20chart%20of%20number%20%2F%20percent%20of%20runs%20that%20converged%0A%0A%20%20%20%20%23%20generate%20a%20nice%20string%20version%20of%20the%20%25%20for%20display%0A%20%20%20%20_status_pct_df%20%3D%20status_df.with_columns(%0A%20%20%20%20%20%20%20%20percent_str%3Dpl.col.percent.map_elements(%0A%20%20%20%20%20%20%20%20%20%20%20%20lambda%20x%3A%20f%22%7Bx%20*%20100%3A%2C.1f%7D%25%22%2C%20return_dtype%3Dpl.String%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20_count_bar%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(_status_pct_df)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(y%3D%22status%22%2C%20x%3D%22count%22%2C%20color%3D%22status%22)%0A%20%20%20%20)%0A%0A%20%20%20%20text_color%20%3D%20%22white%22%20if%20mo.app_meta().theme%20%3D%3D%20%22light%22%20else%20%22black%22%0A%20%20%20%20_percent_text%20%3D%20_count_bar.mark_text(xOffset%3D17).encode(%0A%20%20%20%20%20%20%20%20y%3Dalt.Y(%22status%22%2C%20title%3D%22%22)%2C%0A%20%20%20%20%20%20%20%20x%3Dalt.X(%22count%22%2C%20title%3D%22Number%20of%20Simulations%22)%2C%0A%20%20%20%20%20%20%20%20text%3D%22percent_str%22%2C%0A%20%20%20%20%20%20%20%20color%3Dalt.value(text_color)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20mo.ui.altair_chart((_count_bar%20%2B%20_percent_text).properties(width%3D550))%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%20To%20check%20if%20convergence%20is%20correlated%20with%20any%20of%20the%20initial%20parameters%2C%20we%20generate%20and%20graph%20a%20correlation%20matrix.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(df%2C%20params%2C%20pl)%3A%0A%20%20%20%20%23%20we%20want%20to%20know%20if%20there%20is%20any%20correlation%20between%20convergence%20%2F%20run%20length%20and%20the%20starting%20parameters%0A%0A%20%20%20%20%23%20parameters%20to%20test%20correlation%0A%20%20%20%20corr_variables%20%3D%20%5B%22converged%22%2C%20%22Step%22%5D%0A%0A%20%20%20%20param_variables%20%3D%20%5B%0A%20%20%20%20%20%20%20%20param%0A%20%20%20%20%20%20%20%20for%20param%2C%20val%20in%20params%5B%22default%22%5D.items()%0A%20%20%20%20%20%20%20%20%23%20risk%20distribution%20is%20categorical%20and%20will%20be%20split%20out%3B%0A%20%20%20%20%20%20%20%20%23%20ignore%20any%20single-value%20fields%2C%20since%20there%20is%20no%20variance%20to%20check%0A%20%20%20%20%20%20%20%20if%20param%20not%20in%20%5B%22risk_distribution%22%5D%20and%20isinstance(val%2C%20list)%20and%20len(val)%20%3E%201%0A%20%20%20%20%5D%0A%0A%20%20%20%20%23%20risk%20distribution%20is%20categorical%3B%20convert%20to%20one-hot%200%2F1%20for%20each%0A%20%20%20%20_matrix_df%20%3D%20df.to_dummies(%22risk_distribution%22).with_columns(%0A%20%20%20%20%20%20%20%20converged%3Dpl.col.status.eq(%22converged%22)%0A%20%20%20%20)%0A%20%20%20%20param_variables.extend(%0A%20%20%20%20%20%20%20%20%5Bc%20for%20c%20in%20_matrix_df.columns%20if%20c.startswith(%22risk_distribution_%22)%5D%0A%20%20%20%20)%0A%0A%20%20%20%20corr_matrix_df%20%3D%20_matrix_df.select(*corr_variables%2C%20*param_variables).corr()%0A%0A%20%20%20%20%23%20add%20a%20label%20field%20to%20the%20matrix%20and%20reorder%20fields%20so%20label%20is%20first%0A%20%20%20%20corr_matrix_df%20%3D%20corr_matrix_df.with_columns(%0A%20%20%20%20%20%20%20%20pl.Series(%22var_x%22%2C%20corr_matrix_df.columns)%0A%20%20%20%20).select(%22var_x%22%2C%20*corr_matrix_df.columns)%0A%0A%20%20%20%20%23%20uncomment%20to%20display%0A%20%20%20%20%23%20corr_matrix_df%0A%20%20%20%20return%20(corr_matrix_df%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(alt%2C%20corr_matrix_df%2C%20pl)%3A%0A%20%20%20%20%23%20unpivot%20to%20long%20format%20for%20charting%0A%20%20%20%20corr_matrix_long_df%20%3D%20(%0A%20%20%20%20%20%20%20%20corr_matrix_df.unpivot(%20%20%23%20add%20row%20labels%0A%20%20%20%20%20%20%20%20%20%20%20%20on%3Dcorr_matrix_df.columns%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20index%3D%22var_x%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20variable_name%3D%22var_y%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20value_name%3D%22correlation%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.filter(pl.col.var_y.is_in(%5B%22Step%22%2C%20%22converged%22%5D))%0A%20%20%20%20%20%20%20%20.filter(~pl.col.var_x.is_in(%5B%22Step%22%2C%20%22converged%22%5D))%0A%20%20%20%20%20%20%20%20.with_columns(correlation%3Dpl.col.correlation.cast(pl.Float32))%0A%20%20%20%20%20%20%20%20.with_columns(%0A%20%20%20%20%20%20%20%20%20%20%20%20correlation_str%3Dpl.col.correlation.map_elements(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lambda%20x%3A%20f%22%7Bx%3A%2C.2f%7D%22%2C%20return_dtype%3Dpl.String%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20_heatmap_corr_chart%20%3D%20(%0A%20%20%20%20%20%20%20%20alt.Chart(corr_matrix_long_df)%0A%20%20%20%20%20%20%20%20.mark_rect()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22var_x%3AO%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axis%3Dalt.Axis(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20orient%3D%22top%22%2C%20%20%23%20move%20axis%20to%20top%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20labelAngle%3D-45%2C%20%20%23%20angle%20the%20labels%20(negative%20%3D%20counterclockwise)%0A%20%20%20%20%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%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22var_y%3AO%22%2C%20title%3D%22%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20use%20spectral%20theme%20since%20we%20have%20both%20negative%20and%20positive%20correlations%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20set%20the%20domain%20to%20make%20it%20even%20and%20more%20readable%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3Dalt.Color(%22correlation%22).scale(scheme%3D%22spectral%22%2C%20domain%3D%5B-0.2%2C%200.2%5D)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20_text_corr_chart%20%3D%20_heatmap_corr_chart.mark_text().encode(%0A%20%20%20%20%20%20%20%20x%3D%22var_x%3AO%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22var_y%3AO%22%2C%0A%20%20%20%20%20%20%20%20text%3D%22correlation_str%22%2C%0A%20%20%20%20%20%20%20%20%23%20for%20contrast%2C%20vary%20the%20color%20based%20on%20the%20intensity%20of%20the%20correlation%2C%20negative%20or%20positive%0A%20%20%20%20%20%20%20%20color%3Dalt.condition(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22abs(datum.correlation)%20%3E%200.14%22%2C%20alt.value(%22white%22)%2C%20alt.value(%22black%22)%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20(_heatmap_corr_chart%20%2B%20_text_corr_chart).properties(width%3D600%2C%20height%3D300)%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%20Most%20of%20these%20effects%20are%20very%20slight.%20The%20strongest%20effect%20is%20a%20correlation%20between%20adjustment%20neighborhood%20size%20and%20simulation%20run%20length%20(looking%20at%20a%20larger%20number%20of%20neighbors%20when%20adjusting%20risk-attitude%20results%20in%20longer%20runs).%20There%20is%20a%20similar%2C%20weaker%20effect%20for%20observed%20neighborhood%20size%20(the%20number%20of%20neighbors%20an%20agent%20looks%20at%20before%20choosing%20how%20to%20play).%20%20There%20is%20a%20slight%20correlation%20between%20grid%20size%20and%20both%20run%20length%20and%20convergence%3B%20the%20negative%20correlation%20means%20larger%20grid%20sizes%20tend%20to%20converge%20more%20quickly%20(shorter%20run%20length)%20and%20more%20frequently.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20%23%20generate%20aggregate%20counts%20by%20step%20for%20graphing%20(charting%20the%20full%20data%20without%20aggregation%20is%20too%20large%20for%20altair)%0A%20%20%20%20grid_runlength_df%20%3D%20df.group_by(%22Step%22%2C%20%22status%22%2C%20%22grid_size%22).agg(count%3Dpl.len())%0A%0A%20%20%20%20mo.ui.altair_chart(%0A%20%20%20%20%20%20%20%20alt.Chart(grid_runlength_df)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22Step%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22count%22%2C%20title%3D%22Number%20of%20Simulations%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%22count%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22status%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D225%2C%20height%3D150%2C%20title%3D%22Simulation%20run%20length%22)%0A%20%20%20%20%20%20%20%20.facet(%22grid_size%22%2C%20title%3D%22Simulation%20run%20length%20by%20grid%20size%22)%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(alt%2C%20df%2C%20mo%2C%20pl)%3A%0A%20%20%20%20%23%20generate%20aggregate%20counts%20by%20step%20for%20graphing%20(charting%20the%20full%20data%20without%20aggregation%20is%20too%20large%20for%20altair)%0A%20%20%20%20adjustnhood_runlength_df%20%3D%20df.group_by(%22Step%22%2C%20%22status%22%2C%20%22adjust_neighborhood%22).agg(%0A%20%20%20%20%20%20%20%20count%3Dpl.len()%0A%20%20%20%20)%0A%0A%20%20%20%20mo.ui.altair_chart(%0A%20%20%20%20%20%20%20%20alt.Chart(adjustnhood_runlength_df)%0A%20%20%20%20%20%20%20%20.mark_bar()%0A%20%20%20%20%20%20%20%20.encode(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dalt.X(%22Step%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dalt.Y(%22count%22%2C%20title%3D%22Number%20of%20Simulations%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20tooltip%3D%22count%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22status%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.properties(width%3D205%2C%20height%3D150%2C%20title%3D%22Simulation%20run%20length%22)%0A%20%20%20%20%20%20%20%20.facet(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22adjust_neighborhood%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Simulation%20run%20length%20by%20adjustment%20neighborhood%20size%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20pl)%3A%0A%20%20%20%20%23%20spot%20check%20pearson%20vs%20spearman%0A%0A%20%20%20%20df.with_columns(converged%3Dpl.col.status.eq(%22converged%22)).select(%0A%20%20%20%20%20%20%20%20gridsize_pearson%3Dpl.corr(%22Step%22%2C%20%22grid_size%22%2C%20method%3D%22pearson%22)%2C%0A%20%20%20%20%20%20%20%20gridsize_spearman%3Dpl.corr(%22Step%22%2C%20%22grid_size%22%2C%20method%3D%22spearman%22)%2C%0A%20%20%20%20%20%20%20%20play_nhood_pearson%3Dpl.corr(%22Step%22%2C%20%22play_neighborhood%22%2C%20method%3D%22pearson%22)%2C%0A%20%20%20%20%20%20%20%20play_nhood_spearman%3Dpl.corr(%22Step%22%2C%20%22play_neighborhood%22%2C%20method%3D%22spearman%22)%2C%0A%20%20%20%20%20%20%20%20converged_pearson%3Dpl.corr(%22Step%22%2C%20%22converged%22%2C%20method%3D%22pearson%22)%2C%0A%20%20%20%20%20%20%20%20randplay_pearson%3Dpl.corr(%22Step%22%2C%20%22random_play_odds%22%2C%20method%3D%22pearson%22)%2C%0A%20%20%20%20%20%20%20%20randplay_spearman%3Dpl.corr(%22Step%22%2C%20%22random_play_odds%22%2C%20method%3D%22spearman%22)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20df_spearman_corr%20%3D%20df.to_dummies(%22status%22).select(%22Step%22%2C%20%22grid_size%22%2C%20%22play_neighborhood%22%2C%20%22observed_neighborhood%22%2C%20%22adjust_neighborhood%22%2C%20%22hawk_odds%22%2C%20%22random_play_odds%22%2C%20%22status_converged%22%2C%20%22status_running%22).corr(method%3D%22spearman%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%20A%20%22boxenplot%22%20is%20a%20helpful%20way%20to%20see%20the%20distribution%20of%20simulation%20run%20lengths%20over%20grid%20sizes.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20sns)%3A%0A%20%20%20%20sns.boxenplot(data%3Ddf%2C%20y%3D%22Step%22%2C%20x%3D%22grid_size%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20sns)%3A%0A%20%20%20%20sns.boxenplot(data%3Ddf%2C%20y%3D%22Step%22%2C%20x%3D%22adjust_neighborhood%22)%0A%20%20%20%20%23%20need%20to%20filter%20the%20data%20so%20we%20have%20all%20same%20max%20length%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20sns)%3A%0A%20%20%20%20sns.boxenplot(data%3Ddf%2C%20y%3D%22Step%22%2C%20x%3D%22observed_neighborhood%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20sns)%3A%0A%20%20%20%20ax%20%3D%20sns.boxenplot(data%3Ddf%2C%20y%3D%22Step%22%2C%20x%3D%22grid_size%22%2C%20hue%3D%22risk_distribution%22)%0A%20%20%20%20%23%20move%20legend%0A%20%20%20%20ax.legend(%0A%20%20%20%20%20%20%20%20bbox_to_anchor%3D(1.01%2C%201)%2C%20%20%23%20just%20outside%20right%20edge%2C%20top-aligned%0A%20%20%20%20%20%20%20%20loc%3D%22upper%20left%22%2C%0A%20%20%20%20%20%20%20%20borderaxespad%3D0%2C%0A%20%20%20%20%20%20%20%20title%3D%22Risk%20Distribution%22%2C%0A%20%20%20%20)%0A%20%20%20%20%23%20plt.tight_layout()%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---%0A%0A%20%20%20%20%23%23%20Data%20file%20review%0A%0A%20%20%20%20List%20and%20checks%20on%20the%20files%2C%20parameters%2C%20and%20number%20of%20runs%20included%20in%20the%20data%20used%20for%20analysis.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data_dir%2C%20mo%2C%20pl)%3A%0A%20%20%20%20%23%20create%20a%20dataframe%20with%20overview%20information%20the%20files%20we're%20drawing%20from%2C%0A%20%20%20%20%23%20to%20confirm%20that%20the%20files%20have%20the%20data%20and%20parameters%20we%20expect%0A%0A%20%20%20%20def%20get_data_file_info(file_iter)%3A%0A%20%20%20%20%20%20%20%20%23%20NOTE%3A%20method%20copied%20from%20multi%2Foverview%20notebook%0A%20%20%20%20%20%20%20%20file_info%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20data_file%20in%20file_iter%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20file_size%20%3D%20data_file.stat().st_size%0A%20%20%20%20%20%20%20%20%20%20%20%20rows%20%3D%20None%0A%20%20%20%20%20%20%20%20%20%20%20%20max_step%20%3D%20None%0A%20%20%20%20%20%20%20%20%20%20%20%20cols%20%3D%20None%0A%20%20%20%20%20%20%20%20%20%20%20%20n_cols%20%3D%20None%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20file_size%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20file_df%20%3D%20pl.read_csv(data_file)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20earlier%20batch%20runs%20had%20different%20set%20of%20grid%20sizes%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20used%20this%20check%20to%20identify%2C%20then%20moved%20them%20into%20testing%20subfolder%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20grid_size_values%20%3D%20file_df%5B%22grid_size%22%5D.unique().to_list()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20grid_size_values%20!%3D%20%5B10%2C%2025%2C%2050%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20f%22%7Bdata_file%7D%20does%20not%20have%20expected%20grid%20sizes%20(has%20%7Bgrid_size_values%7D)%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rows%20%3D%20file_df.height%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%22Step%22%20in%20file_df.columns%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20max_step%20%3D%20file_df%5B%22Step%22%5D.max()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22data%20but%20no%20step%20in%20%7Bdata_file.name%7D%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cols%20%3D%20file_df.columns%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20n_cols%20%3D%20len(cols)%0A%20%20%20%20%20%20%20%20%20%20%20%20file_info.append(%0A%20%20%20%20%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%20%20%20%20%22file_name%22%3A%20data_file.name%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22file_size%22%3A%20file_size%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22rows%22%3A%20rows%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22max_step%22%3A%20max_step%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%22columns%22%3A%20cols%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22n_cols%22%3A%20n_cols%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20file_info_df%20%3D%20pl.from_dicts(file_info)%0A%20%20%20%20%20%20%20%20return%20file_info_df%0A%0A%20%20%20%20file_info_df%20%3D%20get_data_file_info(data_dir.glob(%22*_model.csv%22))%0A%0A%20%20%20%20mo.ui.table(file_info_df%2C%20page_size%3D15%2C%20selection%3DNone)%0A%20%20%20%20return%20(file_info_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%20Check%20that%20the%20data%20doesn't%20include%20any%20incomplete%20or%20unexpected%20data.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(file_info_df%2C%20pl)%3A%0A%20%20%20%20%23%20we%20expect%20the%20same%20number%20of%20parameters%20in%20each%20file%20(may%20be%20redundant%3B%20can't%20load%20into%20common%20dataframe%20if%20they%20don't%20match)%0A%20%20%20%20assert%20(file_info_df%5B%22n_cols%22%5D.n_unique())%20%3D%3D%201%2C%20(%0A%20%20%20%20%20%20%20%20%22All%20files%20should%20have%20the%20same%20number%20of%20parameters%22%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20less%20than%2014580%20means%20incomplete%20run%20(not%20all%20parameter%20combos)%0A%20%20%20%20assert%20file_info_df.filter(pl.col.rows.lt(14580)).height%20%3D%3D%200%2C%20(%0A%20%20%20%20%20%20%20%20%22Data%20should%20not%20include%20files%20with%20less%20than%203240%20rows%20(incomplete%20run)%22%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20max%20step%201500%20was%20used%20for%20the%20full%20set%20fo%20100%20batches%0A%20%20%20%20assert%20file_info_df.filter(pl.col.max_step.ne(1500)).height%20%3D%3D%200%2C%20(%0A%20%20%20%20%20%20%20%20%22Data%20should%20only%20include%20files%20with%20max%20step%20of%201500%22%0A%20%20%20%20)%0A%20%20%20%20%23%20use%20to%20identify%20sepcific%20files%3A%0A%20%20%20%20%23%20file_info_df.filter(pl.col.max_step.ne(1500))%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%20Aggregate%20collected%20data%20by%20the%20initial%20parameters%20and%20check%20combination%20of%20parameters%20and%20number%20of%20runs%20per%20parameter%20set.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20params%2C%20pl)%3A%0A%20%20%20%20%23%20runs%20per%20parameter%20combination%0A%20%20%20%20run_groups_df%20%3D%20df.group_by(params%5B%22default%22%5D.keys()).agg(runs%3Dpl.len())%0A%0A%20%20%20%20%23%20we%20expect%20the%20same%20number%20of%20runs%20for%20each%20parameter%20set%0A%20%20%20%20assert%20(run_groups_df%5B%22runs%22%5D.n_unique())%20%3D%3D%201%0A%0A%20%20%20%20runs_per_group%20%3D%20run_groups_df%5B%22runs%22%5D.max()%0A%0A%20%20%20%20run_groups_df%0A%20%20%20%20return%20run_groups_df%2C%20runs_per_group%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
56adb059268542429c4e0ac51bcbf41c