import%20marimo%0A%0A__generated_with%20%3D%20%220.19.11%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%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%0A%20%20%20%20return%20(np%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20skimage%20import%20io%2C%20filters%0A%0A%20%20%20%20return%20filters%2C%20io%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20scipy%20as%20si%0A%20%20%20%20import%20scipy.ndimage%20as%20nd%0A%0A%20%20%20%20return%20nd%2C%20si%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20plt.ion()%3B%0A%20%20%20%20return%20(plt%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%20%20%20%20mo.pdf(src%3DPath(%22Homework4.pdf%22)%2C%20width%3D%22100%25%22%2C%20height%3D%2250vh%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%20Frequency%20Modulation%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(io)%3A%0A%20%20%20%20buster_keaton_general_train_512_png%20%3D%20io.imread(%22Buster_Keaton_General_Train_512.png%22%2C%20as_gray%3DTrue)%0A%20%20%20%20buster_keaton_general_train_512_sinmod_png%20%3D%20io.imread(%22Buster_Keaton_General_Train_512_sineMod.png%22%2C%20as_gray%3DTrue)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20buster_keaton_general_train_512_png%2C%0A%20%20%20%20%20%20%20%20buster_keaton_general_train_512_sinmod_png%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20buster_keaton_general_train_512_png%2C%0A%20%20%20%20buster_keaton_general_train_512_sinmod_png%2C%0A%20%20%20%20plt%2C%0A)%3A%0A%20%20%20%20fig1%2C%20(ax1a%2C%20ax1b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax1a.imshow(buster_keaton_general_train_512_png%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax1b.imshow(buster_keaton_general_train_512_sinmod_png%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20buster_keaton_general_train_512_png%2C%0A%20%20%20%20buster_keaton_general_train_512_sinmod_png%2C%0A%20%20%20%20np%2C%0A)%3A%0A%20%20%20%20buster_keaton_general_train_512_fft%20%3D%20np.abs(np.fft.fftshift(np.fft.fft2(buster_keaton_general_train_512_png)))%0A%20%20%20%20buster_keaton_general_train_512_sinmod_fft%20%3D%20np.abs(np.fft.fftshift(np.fft.fft2(buster_keaton_general_train_512_sinmod_png)))%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20buster_keaton_general_train_512_fft%2C%0A%20%20%20%20%20%20%20%20buster_keaton_general_train_512_sinmod_fft%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20buster_keaton_general_train_512_fft%2C%0A%20%20%20%20buster_keaton_general_train_512_sinmod_fft%2C%0A%20%20%20%20np%2C%0A%20%20%20%20plt%2C%0A)%3A%0A%20%20%20%20fig2%2C%20(ax2a%2C%20ax2b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax2a.imshow(np.log(buster_keaton_general_train_512_fft)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax2b.imshow(np.log(buster_keaton_general_train_512_sinmod_fft)%2C%20cmap%3D%22gray%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%20Quantized%20Aggregates%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(io)%3A%0A%20%20%20%20emitters_33px_100ph_png%20%3D%20io.imread(%22emitters_33px_100ph.png%22)%0A%20%20%20%20return%20(emitters_33px_100ph_png%2C)%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_png%2C%20plt)%3A%0A%20%20%20%20fig3%2C%20ax3%20%3D%20plt.subplots()%0A%20%20%20%20ax3.imshow(emitters_33px_100ph_png%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_png%2C%20plt)%3A%0A%20%20%20%20fig4%2C%20ax4%20%3D%20plt.subplots()%0A%20%20%20%20ax4.hist(emitters_33px_100ph_png.ravel()%2C%20bins%3D%22auto%22)%0A%20%20%20%20fig4%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_png%2C%20filters)%3A%0A%20%20%20%20emitters_33px_100ph_hflt%20%3D%20emitters_33px_100ph_png%20-%20255%20*%20filters.gaussian(emitters_33px_100ph_png%2C%208%2C%20mode%3D%22nearest%22)%0A%20%20%20%20return%20(emitters_33px_100ph_hflt%2C)%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_hflt%2C%20plt)%3A%0A%20%20%20%20fig6%2C%20(ax6a%2C%20ax6b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax6a.imshow(emitters_33px_100ph_hflt%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax6b.hist(emitters_33px_100ph_hflt.ravel()%2C%20bins%3D20)%0A%20%20%20%20fig6%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_hflt%2C%20np)%3A%0A%20%20%20%20ones%20%3D%20np.ones_like(emitters_33px_100ph_hflt%2C%20dtype%3Dbool)%0A%20%20%20%20zeros%20%3D%20np.zeros_like(ones%2C%20dtype%3Dbool)%0A%20%20%20%20x%2C%20y%20%3D%20np.arange(ones.shape%5B0%5D)%2C%20np.arange(ones.shape%5B1%5D)%0A%20%20%20%20xs%2C%20ys%20%3D%20np.meshgrid(x%2C%20y)%0A%20%20%20%20masks%20%3D%20%5Bnp.where((np.abs(xs%20-%2033%20*%20i)%20%3C%3D%202)%20%26%20(np.abs(ys%20-%2033%20*%20j)%20%3C%3D%202)%2C%20ones%2C%20zeros)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(1%2C%2011)%20for%20j%20in%20range(1%2C%2011)%5D%0A%20%20%20%20%23%20mask%20%3D%20np.where((xs%20%25%20(33%20%2B%204)%20%3E%20(33%20-%204))%20%26%20(ys%20%25%20(33%20%2B%204)%20%3E%20(33%20-%204))%2C%20ones%2C%20zeros)%0A%20%20%20%20mask%20%3D%20sum(masks)%0A%20%20%20%20return%20mask%2C%20masks%0A%0A%0A%40app.cell%0Adef%20_(emitters_33px_100ph_hflt%2C%20masks%2C%20np)%3A%0A%20%20%20%20intensities%20%3D%20%5Bnp.sum(emitters_33px_100ph_hflt%2C%20where%3Dm)%20for%20m%20in%20masks%5D%0A%20%20%20%20return%20(intensities%2C)%0A%0A%0A%40app.cell%0Adef%20_(intensities%2C%20mask%2C%20plt)%3A%0A%20%20%20%20fig7%2C%20(ax7a%2C%20ax7b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax7a.imshow(mask%2C%20cmap%3D%22gray%22)%0A%20%20%20%20counts%2C%20edges%2C%20_%20%3D%20ax7b.hist(intensities%2C%20bins%3D25)%0A%20%20%20%20fig7%0A%20%20%20%20return%20counts%2C%20edges%0A%0A%0A%40app.cell%0Adef%20_(counts%2C%20edges%2C%20np)%3A%0A%20%20%20%20irange%20%3D%20(np.max(edges)%20-%20np.min(edges))%0A%20%20%20%20imin%20%3D%20np.min(edges)%0A%20%20%20%20(sum(counts%5Bedges%5B1%3A%5D%20%3C%3D%20(irange%2F3)%20%2B%20imin%5D)%2C%0A%20%20%20%20%20sum(counts%5B((irange%2F3)%20%2B%20imin%20%3C%20edges%5B1%3A%5D)%20%26%20(edges%5B1%3A%5D%20%3C%3D%20(2*irange%2F3)%20%2B%20imin)%5D)%2C%0A%20%20%20%20%20sum(counts%5B((2*irange%2F3)%20%2B%20imin%20%3C%20edges%5B1%3A%5D)%5D)%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%0A%20%20%20%20%23%23%20A%20High-Resolution%20PSF%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20si)%3A%0A%20%20%20%20def%20psfker(l%2C%20NA%3D0.9%2C%20side%3D1.0%2C%20N%3D101%2C%20center%3D(0.0%2C%200.0))%3A%0A%20%20%20%20%20%20%20%20xs%2C%20ys%20%3D%20np.meshgrid(np.linspace(0.0%2C%20side%2C%20N)%2C%20np.linspace(0.0%2C%20side%2C%20N))%0A%20%20%20%20%20%20%20%20r2s%20%3D%20np.square(xs%20-%20side%20%2F%202%20-%20center%5B0%5D)%20%2B%20np.square(ys%20-%20side%20%2F%202%20-%20center%5B1%5D)%0A%20%20%20%20%20%20%20%20v%20%3D%202%20*%20np.pi%20*%20NA%20*%20np.sqrt(r2s)%20%2F%20l%0A%20%20%20%20%20%20%20%20psf%20%3D%204%20*%20np.square(si.special.j1(v)%20%2F%20v)%0A%20%20%20%20%20%20%20%20nans%20%3D%20np.isnan(psf)%0A%20%20%20%20%20%20%20%20psf%5Bnans%5D%20%3D%201%0A%20%20%20%20%20%20%20%20return%20psf%20%2F%20np.sum(psf)%0A%0A%20%20%20%20return%20(psfker%2C)%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20psfker)%3A%0A%20%20%20%20fig8%2C%20(ax8a%2C%20ax8b%2C%20ax8c)%20%3D%20plt.subplots(1%2C%203%2C%20figsize%3D(8%2C%202))%0A%20%20%20%20ax8a.imshow(psfker(0.5)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax8b.imshow(psfker(0.4)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax8c.imshow(psfker(0.4%2C%20NA%3D0.5)%2C%20cmap%3D%22gray%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%20A%20Worse%20Worm%20Image%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(io)%3A%0A%20%20%20%20fetter_celegans_cellfig10_png%20%3D%20io.imread(%22fetter_Celegans_cellfig10.jpg%22%2C%20as_gray%3DTrue)%0A%20%20%20%20return%20(fetter_celegans_cellfig10_png%2C)%0A%0A%0A%40app.cell%0Adef%20_(fetter_celegans_cellfig10_png%2C%20plt)%3A%0A%20%20%20%20fig9%2C%20ax9%20%3D%20plt.subplots()%0A%20%20%20%20ax9.imshow(fetter_celegans_cellfig10_png%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetter_celegans_cellfig10_png%2C%20nd%2C%20psfker)%3A%0A%20%20%20%20fetter_celegans_cellfig10_psf%20%3D%20nd.convolve(fetter_celegans_cellfig10_png%2C%20psfker(0.53%2C%20NA%3D0.7))%0A%20%20%20%20return%20(fetter_celegans_cellfig10_psf%2C)%0A%0A%0A%40app.cell%0Adef%20_(fetter_celegans_cellfig10_psf%2C%20plt)%3A%0A%20%20%20%20fig10%2C%20ax10%20%3D%20plt.subplots()%0A%20%20%20%20ax10.imshow(fetter_celegans_cellfig10_psf%2C%20cmap%3D%22gray%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%0A%20%20%20%20%23%23%20SNR%20and%20Poisson%20Noise%0A%20%20%20%20%24%24%20N_%5Ctext%7Bphoton%7D%20%5Csim%20SNR%5E2%20%24%24%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%20Simulated%20Point%20Sources%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20pixelate(image%2C%20inscale%2C%20shape%3D(15%2C%2015))%3A%0A%20%20%20%20%20%20%20%20outscale%20%3D%20image.shape%5B0%5D%20*%20inscale%20%2F%20shape%5B0%5D%20%0A%20%20%20%20%20%20%20%20assert%20outscale%20%3D%3D%20image.shape%5B1%5D%20*%20inscale%20%2F%20shape%5B1%5D%0A%20%20%20%20%20%20%20%20assert%20outscale.is_integer()%0A%0A%20%20%20%20%20%20%20%20ii%2C%20jj%20%3D%20np.indices(image.shape)%0A%0A%20%20%20%20%20%20%20%20ones%20%3D%20np.ones_like(image%2C%20dtype%3Dbool)%0A%20%20%20%20%20%20%20%20zeros%20%3D%20np.zeros_like(image%2C%20dtype%3Dbool)%0A%0A%20%20%20%20%20%20%20%20masks%20%3D%20%5Bnp.where((i%20*%20outscale%20%3C%3D%20ii%20*%20inscale)%20%26%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(ii%20*%20inscale%20%3C%20(i%20%2B%201)%20*%20outscale)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20(j%20*%20outscale%20%3C%3D%20jj%20*%20inscale)%20%26%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(jj%20*%20inscale%20%3C%20(j%20%2B%201)%20*%20outscale)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ones%2C%20zeros)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(shape%5B0%5D)%20for%20j%20in%20range(shape%5B1%5D)%5D%0A%0A%20%20%20%20%20%20%20%20outage%20%3D%20np.array(%5Bnp.sum(image%2C%20where%3Dm)%20for%20m%20in%20masks%5D).reshape(shape)%0A%0A%20%20%20%20%20%20%20%20return%20outage%2C%20outscale%0A%0A%20%20%20%20return%20(pixelate%2C)%0A%0A%0A%40app.cell%0Adef%20_(pixelate%2C%20psfker)%3A%0A%20%20%20%20simpoint%2C%20_%20%3D%20pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150)%2C%200.1)%0A%20%20%20%20return%20(simpoint%2C)%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20simpoint)%3A%0A%20%20%20%20fig11%2C%20ax11%20%3D%20plt.subplots()%0A%20%20%20%20ax11.imshow(simpoint%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20fishify(image%2C%20N%3D1%2C%20rng%3Dnp.random.default_rng())%3A%0A%20%20%20%20%20%20%20%20return%20rng.poisson(lam%3DN%20*%20(image%20%2F%20np.sum(image)))%0A%0A%20%20%20%20return%20(fishify%2C)%0A%0A%0A%40app.cell%0Adef%20_(fishify%2C%20pixelate%2C%20psfker)%3A%0A%20%20%20%20simpoint50%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150)%2C%200.1)%5B0%5D%2C%20N%3D50)%0A%20%20%20%20simpoint500%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150)%2C%200.1)%5B0%5D%2C%20N%3D500)%0A%20%20%20%20return%20simpoint50%2C%20simpoint500%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20simpoint50%2C%20simpoint500)%3A%0A%20%20%20%20fig12%2C%20(ax12a%2C%20ax12b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax12a.imshow(simpoint50%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax12b.imshow(simpoint500%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fishify%2C%20pixelate%2C%20psfker)%3A%0A%20%20%20%20simpoint50_shifted%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150%2C%20center%3D(0.3%2C%200.3))%2C%200.1)%5B0%5D%2C%20N%3D50)%0A%20%20%20%20simpoint500_shifted%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150%2C%20center%3D(0.3%2C%200.3))%2C%200.1)%5B0%5D%2C%20N%3D500)%0A%20%20%20%20return%20simpoint500_shifted%2C%20simpoint50_shifted%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20simpoint500_shifted%2C%20simpoint50_shifted)%3A%0A%20%20%20%20fig13%2C%20(ax13a%2C%20ax13b)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax13a.imshow(simpoint50_shifted%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax13b.imshow(simpoint500_shifted%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fishify%2C%20np%2C%20pixelate%2C%20psfker)%3A%0A%20%20%20%20uniform%20%3D%20np.ones((15%2C%2015))%20%2F%20np.sum(np.ones((15%2C%2015)))%0A%20%20%20%20simpoint_i%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150)%2C%200.1)%5B0%5D%2C%20N%3D50)%20%2B%20fishify(np.ones((15%2C%2015))%2C%20N%3D2%20*%2015**2)%0A%20%20%20%20simpoint_ii%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150%2C%20center%3D(0.03%2C%200.03))%2C%200.1)%5B0%5D%2C%20N%3D50)%20%2B%20fishify(np.ones((15%2C%2015))%2C%20N%3D2%20*%2015**2)%0A%20%20%20%20simpoint_iii%20%3D%20fishify(pixelate(psfker(0.5%2C%20NA%3D0.9%2C%20side%3D15%20*%200.1%2C%20N%20%3D%20150%2C%20center%3D(0.03%2C%200.03))%2C%200.1)%5B0%5D%2C%20N%3D500)%20%2B%20fishify(np.ones((15%2C%2015))%2C%20N%3D2%20*%2015**2)%0A%20%20%20%20return%20simpoint_i%2C%20simpoint_ii%2C%20simpoint_iii%0A%0A%0A%40app.cell%0Adef%20_(plt%2C%20simpoint_i%2C%20simpoint_ii%2C%20simpoint_iii)%3A%0A%20%20%20%20fig14%2C%20(ax14a%2C%20ax14b%2C%20ax14c)%20%3D%20plt.subplots(1%2C%203%2C%20figsize%3D(8%2C%202))%0A%20%20%20%20ax14a.imshow(simpoint_i%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax14b.imshow(simpoint_ii%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax14c.imshow(simpoint_iii%2C%20cmap%3D%22gray%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%20Simulating%20a%20Ring%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20ring(inner%2C%20outer%2C%20center%3D(0%2C%200)%2C%20scale%3D1%2C%20shape%3D(150%2C%20150)%2C%20rtol%3D1e-02%2C%20atol%3D1e-02)%3A%0A%20%20%20%20%20%20%20%20ii%2C%20jj%20%3D%20np.indices(shape)%0A%20%20%20%20%20%20%20%20r2s%20%3D%20np.square((ii%20-%20shape%5B0%5D%20%2F%202)%20*%20scale%20-%20center%5B0%5D)%20%2B%20np.square((jj%20-%20shape%5B1%5D%20%2F%202)%20*%20scale%20-%20center%5B1%5D)%0A%20%20%20%20%20%20%20%20return%20((r2s%20%3C%20np.square(outer))%20%26%20(r2s%20%3E%3D%20np.square(inner))).astype(np.float32)%0A%0A%20%20%20%20return%20(ring%2C)%0A%0A%0A%40app.cell%0Adef%20_(fishify%2C%20nd%2C%20plt%2C%20psfker%2C%20ring)%3A%0A%20%20%20%20fig15%2C%20(ax15a%2C%20ax15b%2C%20ax15c)%20%3D%20plt.subplots(1%2C%203%2C%20figsize%3D(8%2C%204))%0A%20%20%20%20ax15a.imshow(ring(0.5%2C%200.6%2C%20scale%3D0.01)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax15b.imshow(nd.convolve(ring(0.5%2C%200.6%2C%20scale%3D0.01)%2C%20psfker(0.1)%2C%20mode%3D%22nearest%22)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20ax15c.imshow(fishify(nd.convolve(ring(0.5%2C%200.6%2C%20scale%3D0.01)%2C%20psfker(0.1)%2C%20mode%3D%22nearest%22)%2C%20N%3D10_000)%2C%20cmap%3D%22gray%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%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
2052444b9c4e440561044f7994f30ae8