import%20marimo%0A%0A__generated_with%20%3D%20%220.19.11%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%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%20Example%3A%20fitting%20a%20waveform%20in%20the%20SXS%20catalog%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%20Import%20modules%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%20from%20jaxqualin.qnmode%20import%20mode%2C%20mode_list%0A%20%20%20%20from%20jaxqualin.waveforms%20import%20get_waveform_SXS%0A%20%20%20%20from%20jaxqualin.fit%20import%20QNMFitVaryingStartingTime%0A%20%20%20%20from%20jaxqualin.plot%20import%20plot_amplitudes%2C%20plot_phases%2C%20plot_omega_free%2C%20plot_predicted_qnms%0A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20QNMFitVaryingStartingTime%2C%0A%20%20%20%20%20%20%20%20get_waveform_SXS%2C%0A%20%20%20%20%20%20%20%20mode_list%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20plot_amplitudes%2C%0A%20%20%20%20%20%20%20%20plot_omega_free%2C%0A%20%20%20%20%20%20%20%20plot_phases%2C%0A%20%20%20%20%20%20%20%20plot_predicted_qnms%2C%0A%20%20%20%20%20%20%20%20plt%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%23%20Getting%20the%20SXS%20waveform%0A%0A%20%20%20%20The%20waveform%20will%20be%20downloaded%20with%20the%20%60sxs%60%20package%2C%20if%20not%20already.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(get_waveform_SXS)%3A%0A%20%20%20%20SXSnum%20%3D%20%220305%22%0A%20%20%20%20l%20%3D%202%0A%20%20%20%20m%20%3D%202%0A%0A%20%20%20%20h%2C%20Mf%2C%20af%2C%20Lev%20%3D%20get_waveform_SXS(SXSnum%2C%20l%2C%20m)%0A%20%20%20%20return%20Mf%2C%20SXSnum%2C%20af%2C%20h%2C%20l%2C%20m%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%20Case%201%3A%20Fit%20model%20with%20free%20QNMs%20(unfixed%20frequencies)%0A%0A%20%20%20%20Here%20we%20will%20fit%20with%20three%20free%20QNMs%20(%24N_%7Bf%7D%20%3D%203%24)%20and%20see%20if%20the%20resulting%20frequencies%20approach%20any%20of%20the%20QNMs%20we%20expect%20to%20find.%0A%20%20%20%20By%20default%2C%20the%20fit%20results%20are%20saved%20with%20%60pickle%60%20into%20%60.%2F.jaxqualin_cache%2Ffits%2F%60.%0A%20%20%20%20If%20%60load_pickle%60%20is%20%60True%60%2C%20the%20fitter%20will%20load%20the%20pickled%20result%20that%20matches%20%60run_string_prefix%60%20and%20the%20list%20of%20modes%20used.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(QNMFitVaryingStartingTime%2C%20SXSnum%2C%20h%2C%20l%2C%20m%2C%20np)%3A%0A%20%20%20%20_t0_arr%20%3D%20np.linspace(0%2C%2050%2C%20num%3D501)%20%20%23%20array%20of%20starting%20times%20to%20fit%20for%0A%20%20%20%20qnm_fixed_list%20%3D%20%5B%5D%20%20%23%20t0%20%3D%200%20is%20the%20peak%20of%20the%20strain%0A%20%20%20%20_run_string_prefix%20%3D%20f'SXS%7BSXSnum%7D_lm_%7Bl%7D.%7Bm%7D'%20%20%23%20list%20of%20QNMs%20with%20fixed%20frequencies%20in%20the%20fit%20model%0A%20%20%20%20_N_free%20%3D%203%20%20%23%20prefix%20of%20pickle%20file%20for%20saving%20the%20results%0A%20%20%20%20%23%20fitter%20object%0A%20%20%20%20fitter%20%3D%20QNMFitVaryingStartingTime(h%2C%20_t0_arr%2C%20N_free%3D_N_free%2C%20qnm_fixed_list%3Dqnm_fixed_list%2C%20load_pickle%3DFalse%2C%20run_string_prefix%3D_run_string_prefix)%20%20%23%20number%20of%20free%20modes%20to%20use%0A%20%20%20%20return%20(fitter%2C)%0A%0A%0A%40app.cell%0Adef%20_(fitter%2C%20mo)%3A%0A%20%20%20%20with%20mo.status.spinner(%22Running%20free-QNM%20fits...%22)%3A%0A%20%20%20%20%20%20%20%20fitter.do_fits()%0A%20%20%20%20mo.md(%22**Free-QNM%20fits%20complete.**%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fitter)%3A%0A%20%20%20%20%23%20fitter%20results%20object%0A%20%20%20%20result%20%3D%20fitter.result_full%0A%20%20%20%20return%20(result%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%20Plotting%20the%20results%0A%0A%20%20%20%20Different%20colored%20points%20trace%20out%20the%20frequency%20evolution%20of%20a%20free%20QNM%20from%20early%20to%20late%20%24t_0%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Mf%2C%20af%2C%20mode_list%2C%20plot_omega_free%2C%20plot_predicted_qnms%2C%20plt%2C%20result)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots()%0A%20%20%20%20predicted_qnms%20%3D%20mode_list(%5B'2.2.0'%2C%20'2.2.1'%2C%20'3.2.0'%5D%2C%20Mf%2C%20af)%0A%20%20%20%20%23%20mode%20locations%20to%20visualize%20on%20the%20plot%0A%20%20%20%20plot_omega_free(result%2C%20_ax)%0A%20%20%20%20plot_predicted_qnms(_ax%2C%20predicted_qnms)%0A%20%20%20%20_fig%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%20Case%202%3A%20Fixed%20QNMs%20(fixed%20frequencies)%0A%0A%20%20%20%20Here%20we%20assume%20that%20the%20%242%7B%2C%7D2%7B%2C%7D0%2C%202%7B%2C%7D2%7B%2C%7D1%24%20and%20%243%7B%2C%7D3%7B%2C%7D0%24%20modes%20are%20present%2C%20so%20we%20use%20a%20fit%20model%20including%20these%20three%20modes%20and%20fix%20their%20frequencies%20according%20to%20GR%20with%20the%20help%20of%20the%20%60qnm%60%20package.%0A%20%20%20%20We%20will%20use%20%24N_f%20%3D%200%24%2C%20meaning%20that%20we%20do%20not%20include%20additional%20free%20QNMs%20on%20top%20of%20the%20three%20fixed%20modes.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Mf%2C%20QNMFitVaryingStartingTime%2C%20SXSnum%2C%20af%2C%20h%2C%20l%2C%20m%2C%20mode_list%2C%20np)%3A%0A%20%20%20%20_t0_arr%20%3D%20np.linspace(0%2C%2050%2C%20num%3D501)%0A%20%20%20%20qnm_fixed_list_1%20%3D%20mode_list(%5B'2.2.0'%2C%20'2.2.1'%2C%20'3.2.0'%5D%2C%20Mf%2C%20af)%0A%20%20%20%20_run_string_prefix%20%3D%20f'SXS%7BSXSnum%7D_lm_%7Bl%7D.%7Bm%7D'%0A%20%20%20%20_N_free%20%3D%200%0A%20%20%20%20fitter_1%20%3D%20QNMFitVaryingStartingTime(h%2C%20_t0_arr%2C%20N_free%3D_N_free%2C%20qnm_fixed_list%3Dqnm_fixed_list_1%2C%20load_pickle%3DFalse%2C%20run_string_prefix%3D_run_string_prefix)%0A%20%20%20%20return%20fitter_1%2C%20qnm_fixed_list_1%0A%0A%0A%40app.cell%0Adef%20_(fitter_1%2C%20mo)%3A%0A%20%20%20%20with%20mo.status.spinner(%22Running%20fixed-QNM%20fits...%22)%3A%0A%20%20%20%20%20%20%20%20fitter_1.do_fits()%0A%20%20%20%20mo.md(%22**Fixed-QNM%20fits%20complete.**%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fitter_1)%3A%0A%20%20%20%20result_1%20%3D%20fitter_1.result_full%0A%20%20%20%20return%20(result_1%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%20We%20plot%20the%20amplitude%20and%20phase%20of%20the%20fixed%20modes%2C%20as%20a%20function%20of%20%24t_0%24%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_amplitudes%2C%20plot_phases%2C%20plt%2C%20qnm_fixed_list_1%2C%20result_1)%3A%0A%20%20%20%20_fig%2C%20_axs%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%205))%0A%20%20%20%20plot_amplitudes(result_1%2C%20fixed_modes%3Dqnm_fixed_list_1%2C%20ax%3D_axs%5B0%5D)%0A%20%20%20%20plot_phases(result_1%2C%20fixed_modes%3Dqnm_fixed_list_1%2C%20ax%3D_axs%5B1%5D%2C%20legend%3DFalse)%0A%20%20%20%20_fig%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%20Flatness%20diagnostics%20on%20fixed-frequency%20fit%0A%0A%20%20%20%20We%20now%20use%20the%20same%20stability%20tolerance%20as%20the%20mode-search%20workflow%20(%60fluc_tol%20%3D%200.2%60).%0A%20%20%20%20The%20bolded%20segments%20are%20the%20flattest%20windows%20of%20width%20%24%5CDelta%20T%20%3D%2010%20M%24%2C%20and%20the%20circle%20markers%20show%20the%20earliest%20window%20start%20that%20satisfies%20the%20flatness%20tolerance.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_amplitudes%2C%20plot_phases%2C%20plt%2C%20qnm_fixed_list_1%2C%20result_1)%3A%0A%20%20%20%20flatness_summary%20%3D%20result_1.summarize_fixed_mode_flatness(delta_t%3D10.0%2C%20fluc_tol%3D0.2)%0A%20%20%20%20bold_dict%2C%20t_flat_start_dict%20%3D%20result_1.fixed_mode_flatness_plot_overlays(delta_t%3D10.0%2C%20fluc_tol%3D0.2)%0A%0A%20%20%20%20_fig%2C%20_axs%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%205))%0A%20%20%20%20plot_amplitudes(%0A%20%20%20%20%20%20%20%20result_1%2C%0A%20%20%20%20%20%20%20%20fixed_modes%3Dqnm_fixed_list_1%2C%0A%20%20%20%20%20%20%20%20ax%3D_axs%5B0%5D%2C%0A%20%20%20%20%20%20%20%20use_label%3DFalse%2C%0A%20%20%20%20%20%20%20%20bold_dict%3Dbold_dict%2C%0A%20%20%20%20%20%20%20%20alpha%3D0.3%2C%0A%20%20%20%20%20%20%20%20t_flat_start_dict%3Dt_flat_start_dict%2C%0A%20%20%20%20%20%20%20%20flat_start_s%3D50%2C%0A%20%20%20%20%20%20%20%20flat_start_marker%3D%22o%22%2C%0A%20%20%20%20)%0A%20%20%20%20_axs%5B0%5D.legend(fontsize%3D9)%0A%20%20%20%20plot_phases(%0A%20%20%20%20%20%20%20%20result_1%2C%0A%20%20%20%20%20%20%20%20fixed_modes%3Dqnm_fixed_list_1%2C%0A%20%20%20%20%20%20%20%20ax%3D_axs%5B1%5D%2C%0A%20%20%20%20%20%20%20%20legend%3DFalse%2C%0A%20%20%20%20%20%20%20%20bold_dict%3Dbold_dict%2C%0A%20%20%20%20%20%20%20%20alpha%3D0.3%2C%0A%20%20%20%20%20%20%20%20t_flat_start_dict%3Dt_flat_start_dict%2C%0A%20%20%20%20%20%20%20%20flat_start_s%3D50%2C%0A%20%20%20%20%20%20%20%20flat_start_marker%3D%22o%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig%0A%20%20%20%20return%20(flatness_summary%2C)%0A%0A%0A%40app.cell%0Adef%20_(flatness_summary%2C%20mo%2C%20np)%3A%0A%20%20%20%20_lines%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22Per-mode%20flattest-window%20results%3A%22%2C%0A%20%20%20%20%5D%0A%20%20%20%20for%20_mode_string_summary%2C%20info%20in%20flatness_summary.items()%3A%0A%20%20%20%20%20%20%20%20_earliest%20%3D%20info%5B%22earliest_flat_start_time%22%5D%0A%20%20%20%20%20%20%20%20if%20np.isnan(_earliest)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_earliest_txt%20%3D%20%22nan%20(no%20qualifying%20window)%22%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_earliest_txt%20%3D%20f%22%7B_earliest%3A.2f%7D%22%0A%20%20%20%20%20%20%20%20_lines.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22-%20%60%7B_mode_string_summary%7D%60%3A%20flattest%20window%20%5B%7Binfo%5B'flattest_start_time'%5D%3A.2f%7D%2C%20%7Binfo%5B'flattest_end_time'%5D%3A.2f%7D%5D%20M%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22A%3D%7Binfo%5B'flattest_amplitude_median'%5D%3A.4g%7D%20(%2B%7Binfo%5B'flattest_amplitude_plus'%5D%3A.3g%7D%2F-%7Binfo%5B'flattest_amplitude_minus'%5D%3A.3g%7D)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22phi%3D%7Binfo%5B'flattest_phase_median'%5D%3A.4g%7D%20(%2B%7Binfo%5B'flattest_phase_plus'%5D%3A.3g%7D%2F-%7Binfo%5B'flattest_phase_minus'%5D%3A.3g%7D)%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22earliest%20flat%20start%3D%7B_earliest_txt%7D%20M%22%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20mo.md(%22%5Cn%22.join(_lines))%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
79b23f5415b08e0ae039488177cc0469