import%20marimo%0A%0A__generated_with%20%3D%20%220.15.2%22%0Aapp%20%3D%20marimo.App(width%3D%22columns%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22We%20provide%20an%20comparison%20of%20the%20intrinsic%20and%20optimal%20detections%20(as%20defined%20in%20%5BMercier%20et%20al.%2C%202015%5D(%5Bhttps%3A%2F%2Fui.adsabs.harvard.edu%2Fabs%2F2015ApJ...805...15M%2Fabstract%5D(https%3A%2F%2Fui.adsabs.harvard.edu%2Fabs%2F2025arXiv250613881M%2Fabstract)))%20using%20four%20galaxies%20studied%20in%20the%20paper.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20%20%20astropy.visualization.mpl_normalize%20import%20simple_norm%0A%20%20%20%20from%20%20%20astropy.cosmology%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20import%20FlatLambdaCDM%0A%0A%20%20%20%20import%20marimo%20%20%20%20%20%20%20%20%20%20%20%20as%20mo%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20astropy.io.fits%20%20%20as%20fits%0A%20%20%20%20import%20numpy%20%20%20%20%20%20%20%20%20%20%20%20%20as%20np%0A%20%20%20%20import%20pathlib%0A%20%20%20%20import%20finder%0A%0A%20%20%20%20plt.style.use('default')%0A%0A%20%20%20%20path%20%3D%20pathlib.Path('data')%0A%20%20%20%20return%20FlatLambdaCDM%2C%20finder%2C%20fits%2C%20mo%2C%20np%2C%20path%2C%20plt%2C%20simple_norm%0A%0A%0A%40app.cell%0Adef%20_(fits%2C%20path)%3A%0A%20%20%20%20ids%20%20%20%20%20%20%20%3D%20%5B3%2C%2056%2C%2096%2C%20678%5D%0A%20%20%20%20redshifts%20%3D%20%5B1.6833%2C%201.4373%2C%201.7058%2C%202.2707%5D%0A%20%20%20%20images%20%20%20%20%3D%20%5B%5D%0A%20%20%20%20models%20%20%20%20%3D%20%5B%5D%0A%20%20%20%20segmaps%20%20%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20_idd%20in%20ids%3A%0A%0A%20%20%20%20%20%20%20%20%23%20Open%20image%0A%20%20%20%20%20%20%20%20with%20fits.open(path%20%2F%20'images'%20%2F%20f'%7B_idd%7D_f444w.fits')%20as%20hdul%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20images.append(hdul%5B0%5D.data)%0A%0A%20%20%20%20%20%20%20%20%23%20Open%20model%0A%20%20%20%20%20%20%20%20with%20fits.open(path%20%2F%20'models'%20%2F%20f'%7B_idd%7D_f444w.fits')%20as%20hdul%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20models.append(hdul%5B0%5D.data)%0A%0A%20%20%20%20%20%20%20%20%23%20Open%20segmentation%20map%0A%20%20%20%20%20%20%20%20with%20fits.open(path%20%2F%20'segmentation'%20%2F%20f'%7B_idd%7D.fits')%20as%20hdul%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20segmaps.append(hdul%5B0%5D.data)%0A%20%20%20%20return%20ids%2C%20images%2C%20models%2C%20redshifts%2C%20segmaps%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Compute%20the%20local%20%242%5Csigma%24%20flux%20threshold%20for%20each%20galaxy%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(finder%2C%20images%2C%20models%2C%20segmaps)%3A%0A%20%20%20%20thr%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20_image%2C%20_model%2C%20_segmap%20in%20zip(images%2C%20models%2C%20segmaps)%3A%0A%0A%20%20%20%20%20%20%20%20thr.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20finder.bg_threshold_n_sigma(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_image%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_model%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_segmap%20%3D%3D%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20n_sigma%20%3D%202%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%20return%20(thr%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Produce%20a%20%241%5C%2C%5Crm%20kpc%24%20mask%20to%20hide%20the%20bulge%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(FlatLambdaCDM%2C%20finder%2C%20images%2C%20np%2C%20redshifts)%3A%0A%20%20%20%20cosmo%20%20%20%20%20%20%20%3D%20FlatLambdaCDM(70%2C%200.3)%0A%20%20%20%20mask_bulges%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20_image%2C%20_z%20in%20zip(images%2C%20redshifts)%3A%0A%0A%20%20%20%20%20%20%20%20_center%20%20%3D%20np.array(_image.shape)%20%2F%2F%202%0A%0A%20%20%20%20%20%20%20%20mask_bulges.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20finder.generate_bulge_mask(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_center%5B0%5D%2C%20_center%5B1%5D%2C%20_z%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_image.shape%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cosmo%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20radius_kpc%20%3D%201%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pix_size%20%20%20%3D%200.03%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%20return%20cosmo%2C%20mask_bulges%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Perform%20the%20detections%20in%20the%20residuals%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cosmo%2C%20finder%2C%20images%2C%20mask_bulges%2C%20models%2C%20np%2C%20redshifts%2C%20segmaps%2C%20thr)%3A%0A%20%20%20%20sub_segmaps_opt%20%3D%20%5B%5D%0A%20%20%20%20sub_segmaps_int%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20_image%2C%20_model%2C%20_segmap%2C%20_mask_bulge%2C%20_thr%2C%20_z%20in%20zip(%0A%20%20%20%20%20%20%20%20images%2C%20models%2C%20segmaps%2C%20mask_bulges%2C%20thr%2C%20redshifts%0A%20%20%20%20%20%20%20%20)%3A%0A%0A%20%20%20%20%20%20%20%20%23%20Recover%20the%20value%20in%20the%20segmentation%20map%20corresponding%20to%20the%20galaxy%0A%20%20%20%20%20%20%20%20_center%20%20%3D%20np.array(_image.shape)%20%2F%2F%202%0A%20%20%20%20%20%20%20%20_gal_val%20%3D%20_segmap%5B_center%5B0%5D%2C%20_center%5B1%5D%5D%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20%23%20Setup%20the%20substructure%20finder%0A%20%20%20%20%20%20%20%20_cf%20%3D%20finder.ClumpFinder(%0A%20%20%20%20%20%20%20%20%20%20%20%20_image%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask%20%3D%20_segmap%20%3D%3D%20_gal_val%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bg%20%20%20%20%3D%20_segmap%20%3D%3D%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bulge%20%3D%20_mask_bulge%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%23%20Optimal%20detection%0A%20%20%20%20%20%20%20%20sub_segmaps_opt.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20_cf.detect(_model%2C%20_thr%2C%2020)%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%23%20Intrinsic%20detection%3A%0A%20%20%20%20%20%20%20%20%23%201.%20We%20compute%20the%20flux%20and%20surface%20thresholds%0A%20%20%20%20%20%20%20%20%23%202.%20We%20perform%20the%20detection%20%0A%20%20%20%20%20%20%20%20thr_int%20%3D%20finder.flux_detection_curve_pixel_level(%0A%20%20%20%20%20%20%20%20%20%20%20%20_z%2C%20cosmo%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20surf_int%20%3D%20finder.surface_detection_curve(%0A%20%20%20%20%20%20%20%20%20%20%20%20_z%2C%20cosmo%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%23%20We%20cast%20to%20an%20int%20the%20surface%20threshold%20by%20going%20from%20arcsec2%20to%20pixels%0A%20%20%20%20%20%20%20%20sub_segmaps_int.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20_cf.detect(_model%2C%20thr_int%2C%20int(surf_int%2F0.03%2F0.03))%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20return%20sub_segmaps_int%2C%20sub_segmaps_opt%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20Note%20that%2C%20by%20default%20the%20algorithm%20detects%20positive%20and%20negative%20substructures.%20In%20the%20paper%2C%20we%20only%20considered%20positive%20ones%2C%20that%20is%20over-densities%20with%20respect%20to%20the%20model.%20%0A%20%20%20%20In%20what%20follows%2C%20we%20discard%20negative%20substructures.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(sub_segmaps_int%2C%20sub_segmaps_opt)%3A%0A%20%20%20%20sub_segmaps_opt_pos%20%3D%20%5B%5D%0A%20%20%20%20sub_segmaps_int_pos%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20_sint%2C%20_sopt%20in%20zip(sub_segmaps_int%2C%20sub_segmaps_opt)%3A%0A%0A%20%20%20%20%20%20%20%20_sint%5B_sint%20%3C%200%5D%20%3D%200%0A%20%20%20%20%20%20%20%20sub_segmaps_int_pos.append(_sint)%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20_sopt%5B_sopt%20%3C%200%5D%20%3D%200%0A%20%20%20%20%20%20%20%20sub_segmaps_opt_pos.append(_sopt)%0A%20%20%20%20return%20sub_segmaps_int_pos%2C%20sub_segmaps_opt_pos%0A%0A%0A%40app.cell%0Adef%20_(plt)%3A%0A%20%20%20%20def%20show_im(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ax_loc%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20im%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20seg%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20cmap%20%20%20%20%20%20%20%3D%20'plasma'%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20norm%20%20%20%20%20%20%20%3D%20None%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20title%20%20%20%20%20%20%3D%20''%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bulge%20%3D%20None%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colors%20%20%20%20%20%3D%20'k'%0A%20%20%20%20%20%20%20%20)%3A%0A%0A%20%20%20%20%20%20%20%20%23%20Showing%20the%20galaxy%0A%20%20%20%20%20%20%20%20ax%20%3D%20f.add_subplot(*ax_loc)%0A%0A%20%20%20%20%20%20%20%20plt.imshow(%0A%20%20%20%20%20%20%20%20%20%20%20%20im%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20origin%20%3D%20'lower'%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20cmap%20%20%20%3D%20cmap%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20norm%20%20%20%3D%20norm%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20plt.contour(seg%2C%20origin%3D'lower'%2C%20colors%3Dcolors)%0A%0A%20%20%20%20%20%20%20%20if%20mask_bulge%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.contour(mask_bulge%2C%20origin%3D'lower'%2C%20colors%3Dcolors%2C%20linestyles%3D'--')%0A%0A%20%20%20%20%20%20%20%20ax.set_title(title)%0A%0A%20%20%20%20%20%20%20%20return%20ax%0A%20%20%20%20return%20(show_im%2C)%0A%0A%0A%40app.cell%0Adef%20_(show_im%2C%20simple_norm)%3A%0A%20%20%20%20def%20figure_galaxy(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20col%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20idd%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20image%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20model%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20segmap%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sub_segmap%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bulge%0A%20%20%20%20%20%20%20%20)%3A%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20axs%20%3D%20%5B%5D%0A%0A%20%20%20%20%20%20%20%20norm%20%3D%20simple_norm(image%2C%20stretch%3D'sqrt'%2C%20percent%3D99.5)%0A%0A%20%20%20%20%20%20%20%20%23%20For%20each%20plot%2C%20we%20add%20the%20bulge%20mask%0A%20%20%20%20%20%20%20%20axs.append(show_im(f%2C%20(4%2C%204%2C%200%20%2B%204*col%20%2B%201)%2C%20image%2C%20segmap%2C%20norm%20%3D%20norm%2C%20title%3Df'ID%20%7Bidd%7D'%2C%20mask_bulge%20%3D%20mask_bulge%2C%20colors%3D'w'))%0A%20%20%20%20%20%20%20%20axs.append(show_im(f%2C%20%20(4%2C%204%2C%200%20%2B%204*col%20%2B%202)%2C%20model%2C%20segmap%2C%20norm%20%3D%20norm%2C%20title%3D'Model'%2C%20mask_bulge%20%3D%20mask_bulge%2C%20colors%3D'w'))%0A%20%20%20%20%20%20%20%20axs.append(show_im(f%2C%20%20(4%2C%204%2C%200%20%2B%204*col%20%2B%203)%2C%20image%20-%20model%2C%20segmap%2C%20norm%20%3D%20norm%2C%20title%3D'Residuals'%2C%20mask_bulge%20%3D%20mask_bulge%2C%20colors%3D'w'))%0A%20%20%20%20%20%20%20%20axs.append(show_im(f%2C%20(4%2C%204%2C%200%20%2B%204*col%20%2B%204)%2C%20sub_segmap%2C%20%20%20%20segmap%2C%20cmap%20%3D%20'gnuplot2'%2C%20title%3D'Substructures'%2C%20mask_bulge%20%3D%20mask_bulge%2C%20colors%3D'w'))%0A%20%20%20%20%0A%20%20%20%20%20%20%20%20for%20ax%20in%20axs%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20ax.tick_params(direction%3D'in'%2C%20right%3DTrue%2C%20top%3DTrue%2C%20labelleft%3DFalse%2C%20labelbottom%3DFalse)%0A%0A%20%20%20%20return%20(figure_galaxy%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20Showing%20results%20for%20the%20intrinsic%20detection%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20figure_galaxy%2C%0A%20%20%20%20ids%2C%0A%20%20%20%20images%2C%0A%20%20%20%20mask_bulges%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20models%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20segmaps%2C%0A%20%20%20%20sub_segmaps_int_pos%2C%0A)%3A%0A%20%20%20%20_f%20%20%20%3D%20plt.figure(figsize%3D(8%2C%208)%2C%20dpi%3D300)%0A%0A%20%20%20%20for%20_pos%20in%20range(len(images))%3A%0A%0A%20%20%20%20%20%20%20%20figure_galaxy(%0A%20%20%20%20%20%20%20%20%20%20%20%20_f%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20_pos%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ids%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20images%5B_pos%5D%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20models%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20segmaps%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sub_segmaps_int_pos%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bulges%5B_pos%5D%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B_f%5D)%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%20Showing%20results%20for%20the%20optimal%20detection%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20figure_galaxy%2C%0A%20%20%20%20ids%2C%0A%20%20%20%20images%2C%0A%20%20%20%20mask_bulges%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20models%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20segmaps%2C%0A%20%20%20%20sub_segmaps_opt_pos%2C%0A)%3A%0A%20%20%20%20_f%20%20%20%3D%20plt.figure(figsize%3D(8%2C%208)%2C%20dpi%3D300)%0A%0A%20%20%20%20for%20_pos%20in%20range(len(images))%3A%0A%0A%20%20%20%20%20%20%20%20figure_galaxy(%0A%20%20%20%20%20%20%20%20%20%20%20%20_f%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20_pos%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20ids%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20images%5B_pos%5D%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20models%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20segmaps%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sub_segmaps_opt_pos%5B_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mask_bulges%5B_pos%5D%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5B_f%5D)%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
20156f1a3d02c0fa90b339566fb573af4337f5dd5cf79ef683cb0d5bf8ea7707