Graph-based modeling of optical system enables adaptive optics on dynamic samples with self-calibration.
The 13 matches · 5 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
- [1] § STAR★Methods › Method details › Synthetic data generation ↔ MATLAB code/sub-functions/createPhaseDiversityImages.m, the whole file · a weak match · score 0.87 · Gaussian noise, create phase, phase diversity images, ground truth, Zernike coefficient, Poisson
- [2] § STAR★Methods › Method details › Performance metrics ↔ MATLAB code/sub-functions/calculateImageQualityMetrics.m, the whole file · a weak match · score 0.72 · discrete cosine transform, image quality metrics, DCTS, zero, pixel
- [3] § STAR★Methods › Method details › Performance metrics ↔ MATLAB code/processPhaseDiversityImages.m, lines 1–72 · score 0.71 · square error, image quality metrics, sharpness, root, DCTS, cropping
- [4] § STAR★Methods › Method details › Synthetic data generation ↔ graphycs/forward_model_wf.py, the whole file · a weak match · score 0.69 · pupil plane, forward model, Zernike modes, diversity images, tetrafoil, shifting
- [5] § STAR★Methods › Method details › Wide-field adaptive optics system description ↔ GRAPHYCS_demo.ipynb, lines 43–91 · score 0.68 · deformable mirror, pupil plane, diameter, diversity images, camera, beam
- [6] § STAR★Methods › Method details › Training details and parameters ↔ graphycs/GRAPHYCS_spatially_variant_lsm.py, lines 8–43 · score 0.67 · Loss weights, affine transformation, spatially variant, motion, Fourier
- [7] § STAR★Methods › Method details › Aberration correction in light-sheet microscopy of larval zebrafish brain ↔ MATLAB code/processPhaseDiversityImages.m, lines 1–72 · score 0.67 · phase diversity, diversity images, Zernike coefficients, sharpness, DCTS, frame
- [8] § STAR★Methods › Method details › Sample-induced aberration correction in wide-field microscopy ↔ MATLAB code/sub-functions/createPhaseDiversityImages.m, the whole file · a weak match · score 0.64 · phase diversity images, Zernike coefficient, aberrated image, noise, ratio, signal
- [9] § Results › Spatially varying aberration sensing across the large field of view ↔ MATLAB code/sub-functions/calculateImageQualityMetrics.m, the whole file · a weak match · score 0.63 · discrete cosine transform, image quality metrics, DCTS
- [10] § STAR★Methods › Method details › Sample-induced aberration correction in wide-field microscopy ↔ GRAPHYCS_demo.ipynb, lines 182–283 · score 0.62 · Fourier domain, image domain, piston, aberrated image, tip, tilt
- [11] § STAR★Methods › Method details › Training details and parameters ↔ GRAPHYCS_demo.ipynb, lines 43–91 · score 0.59 · Loss weights, L1, Fourier, Training
- [12] § Results › Spatially varying aberration sensing across the large field of view ↔ graphycs/GRAPHYCS_spatially_invariant_lsm.py, lines 372–434 · score 0.56 · map visualized, phase maps, spatially invariant, component, wavefront, model
- [13] § Results › Spatially varying aberration sensing across the large field of view ↔ graphycs/GRAPHYCS_spatially_variant_lsm.py, lines 370–433 · score 0.51 · map visualized, phase maps, spatially variant, component, patch, model
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Jupyter notebook · 408 lines · 14 KB · GPL-3.0 · 3 matches
- # %%
- !pip install fft-conv-pytorch
- !pip install scikit-image
- # %%
- import sys
- from pathlib import Path
- # Find GRAPHYCS root (folder that contains graphycs/forward_model_wf.py)
- start = Path.cwd()
- root = None
- for p in [start, *start.parents]:
- if (p / "graphycs" / "forward_model_wf.py").exists():
- root = p
- break
- pkg = root / "graphycs"
- sys.path.insert(0, str(root))
- sys.path.insert(0, str(pkg))
- # %%
- from datetime import datetime
- import os
- import torch
- import numpy as np
- import matplotlib.pyplot as plt
- from tqdm import tqdm
- import skimage.io as skio
- import torch.nn.functional as F
- from torch.fft import fftshift, ifftshift, ifft2, fft2
- # your helper modules (now in working dir)
- from graphycs.forward_model_wf import forward_model_wf
- from graphycs.utils import *
- from graphycs.self_calibration import *
- # device
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
- print("Using device:", device)
- # %%
- self_calib_param_lr = 5e-4
- learning_rate = 5e-3
- object_learning_rate = 2e-3
- seed = 0
- data_path = 'Data/Diversity_Images_Lymph.tif'
- zernike_coeff_path = 'Data/appliedCoeff.txt'
- # ─── Calibration options ────────────────────────────────────────────────────────
- use_self_calibration = 1 # 1 or 0
- use_learnable_scales = 1 # 1 or 0
- use_scheduler = 0 # 1 or 0
- # ─── Optimization hyperparameters ───────────────────────────────────────────────
- epochs = 500
- batch_size = 22
- use_batch_shuffling = 0 # 1 or 0
- use_L1_loss = 1 # 1 or 0
- fourier_loss_weight = 1e-5
- # ─── Visualization controls for training loop ───────────────────────────────────
- vis_frequency = 200
- vis_intermediates = 1 # keep in-memory stacks only
- # ─── Zernike orders ─────────────────────────────────────────────────────────────
- n_max = 14
- n_max_estimated = 14
- # ─── Optical parameters ────────────────────────────────────────────────────────
- NA = 0.3
- camera_pixel_size = 0.5343e-6
- wavelength = 0.513e-6
- n_imm = 1.33
- gaussian_sigma = 10.0e-3
- avg_background = 0.0
- psf_size = 101
- img_num_factor = 1
- ### Dxp: diameter of the deformable mirror in m
- Dxp = 10e-3
- pad_w, pad_h = psf_size - 1, psf_size - 1
- # ─── Zernike basis and defining the beam and Deformable mirror in the pupil plane────────────────────────────────────────────────────────────
- M = 255
- _, zernikes = zernike_pd_generation_higher_order(6, n_max, M, camera_pixel_size, wavelength, NA)
- zernikes = zernikes.to(device)
- # %%
- # ─── Setup seeds ────────────────────────────────────────────────────
- torch.manual_seed(seed)
- np.random.seed(seed)
- torch.cuda.manual_seed(seed)
- torch.backends.cudnn.deterministic = True
- torch.backends.cudnn.benchmark = False
- # %%
- # ─── Load applied coefficients ────────────────────────────────────────────────
- coeffs = np.loadtxt(zernike_coeff_path)
- coeffs = coeffs[::img_num_factor]
- coeffs = torch.tensor(coeffs, dtype=torch.float32).to(device)
- # coeffs[pair_idx]: known DM-applied Zernike coefficients for each diversity image.
- # ─── Load data ────────────────────────────────────────────────────────────────
- phase_added = skio.imread(data_path).astype(np.float32)
- bg = np.min(phase_added[phase_added > 0])
- phase_added = np.clip(phase_added - bg, 0, None)
- phase_added /= phase_added.max()
- phase_added = np.squeeze(phase_added)[::img_num_factor]
- phase_added = torch.from_numpy(phase_added).to(device)
- # phase_added: normalized observed diversity stack with shape [num_images, H, W].
- # ─── Build learnable forward model ────────────────────────────────────────────
- forward_model = forward_model_wf(
- init_object=phase_added[0].clone(),
- n_max=n_max,
- psf_size=psf_size,
- M=M,
- lmbda=wavelength,
- pixel_size=camera_pixel_size,
- n=n_imm,
- NA=NA,
- diversity_imgs_num=len(coeffs),
- device=device,
- use_affine_transform=bool(use_self_calibration),
- use_scales=bool(use_learnable_scales),
- ).to(device)
- # Aliases used by downstream analysis cells.
- found_zernike_coef = forward_model.zernike_coef
- found_object = forward_model.estimated_obj
- if use_self_calibration:
- print("Using affine transformation self calibration parameters in forward_model_wf")
- self_calib_params = [
- forward_model.amp_x,
- forward_model.amp_y,
- forward_model.off_x,
- forward_model.off_y,
- forward_model.rot,
- forward_model.grid,
- ]
- else:
- print("Running without affine transformation self calibration")
- self_calib_params = []
- if use_learnable_scales:
- print("Using learnable Zernike scaling factors in forward_model_wf")
- scale_factors_list = list(forward_model.scales)
- else:
- print("Running without learnable Zernike scaling factors")
- scale_factors_list = []
- optimizer_param_groups = [
- {'params': [found_zernike_coef], 'lr': learning_rate},
- {'params': [found_object], 'lr': object_learning_rate},
- ]
- if use_self_calibration:
- for param in self_calib_params:
- optimizer_param_groups.append({'params': [param], 'lr': self_calib_param_lr})
- if use_learnable_scales:
- for scale_factor in scale_factors_list:
- optimizer_param_groups.append({'params': [scale_factor], 'lr': self_calib_param_lr})
- optimizer = torch.optim.Adam(optimizer_param_groups, lr=learning_rate)
- if use_scheduler:
- scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs, eta_min=0)
- L1_loss = torch.nn.L1Loss()
- # %%
- ## Freeze piston/tip/tilt and optional high-order modes during optimization.
- mask = torch.ones_like(found_zernike_coef, device=device)
- mask[:3] = 0
- if n_max_estimated < len(mask):
- mask[n_max_estimated + 1:] = 0
- train_loss_curve = []
- image_loss_curve = []
- fourier_loss_curve = []
- found_object_stack = []
- iPSF_stack = []
- amplitudes_stack = []
- generated_imgs = []
- mse_loss = torch.nn.MSELoss()
- do_vis = vis_frequency > 0
- t = tqdm(range(epochs))
- for epoch_idx in t:
- if use_batch_shuffling == 1:
- idxs = torch.randperm(len(coeffs)).long().to(device)
- else:
- idxs = torch.arange(len(coeffs)).long().to(device)
- forward_model.estimated_obj.requires_grad_()
- forward_model.zernike_coef.requires_grad_()
- epoch_train_loss = 0.0
- epoch_image_loss = 0.0
- epoch_fourier_loss = 0.0
- for it in range(0, len(coeffs), batch_size):
- idx = idxs[it:min(it + batch_size, len(coeffs))]
- coeff_batch, y_batch = coeffs[idx], phase_added[idx]
- optimizer.zero_grad()
- aberrated_imgs, psfs, amplitude_transformed = forward_model(coeff_batch, idx)
- recon_observed_imgs_FT = torch.real(torch.fft.fft2(aberrated_imgs, dim=(-2, -1)))
- observed_imgs_FT = torch.real(torch.fft.fft2(y_batch, dim=(-2, -1)))
- if use_L1_loss == 1:
- Fourier_loss = L1_loss(recon_observed_imgs_FT.squeeze(), observed_imgs_FT.squeeze())
- recon_loss = L1_loss(aberrated_imgs.squeeze(), y_batch.squeeze())
- else:
- Fourier_loss = mse_loss(recon_observed_imgs_FT.squeeze(), observed_imgs_FT.squeeze())
- recon_loss = mse_loss(aberrated_imgs.squeeze(), y_batch.squeeze())
- epoch_image_loss += recon_loss.item()
- epoch_fourier_loss += Fourier_loss.item()
- loss = recon_loss + fourier_loss_weight * Fourier_loss
- epoch_train_loss += loss.item()
- if do_vis and (epoch_idx % vis_frequency) == 0 and it == 0:
- psfs_squeezed = psfs.squeeze().detach().cpu().numpy()
- if vis_intermediates == 1:
- model_outputs_squeezed = aberrated_imgs.squeeze().detach().cpu().numpy()
- if model_outputs_squeezed.ndim == 3:
- generated_imgs.append(model_outputs_squeezed[-1, :, :])
- elif model_outputs_squeezed.ndim == 2:
- generated_imgs.append(model_outputs_squeezed)
- found_object_stack.append(forward_model.estimated_obj.detach().cpu().numpy())
- if psfs_squeezed.ndim == 3:
- iPSF_stack.append(psfs_squeezed[-1, :, :])
- elif psfs_squeezed.ndim == 2:
- iPSF_stack.append(psfs_squeezed)
- amplitudes_stack.append(amplitude_transformed.detach().cpu().numpy())
- loss.backward()
- if forward_model.zernike_coef.grad is not None:
- forward_model.zernike_coef.grad.mul_(mask)
- optimizer.step()
- if use_scheduler:
- scheduler.step()
- with torch.no_grad():
- forward_model.estimated_obj.data.clamp_(min=0.0)
- if use_learnable_scales:
- for p in forward_model.scales:
- p.data.clamp_(min=-1.0)
- train_loss_curve.append(epoch_train_loss)
- image_loss_curve.append(epoch_image_loss)
- fourier_loss_curve.append(epoch_fourier_loss)
- t.set_description(
- f"Epoch {epoch_idx + 1}/{epochs}, Total loss: {epoch_train_loss:.4f}, Image domain loss: {epoch_image_loss:.4f}, Fourier domain loss: {epoch_fourier_loss:.4f}"
- )
- # Keep explicit final handles to the trained model parameters for downstream cells.
- trained_model = forward_model
- final_found_object = trained_model.estimated_obj.detach()
- final_found_zernike_coef = trained_model.zernike_coef.detach()
- # %%
- # Base results path
- base_results = "Results"
- # Create a timestamp string, e.g. "20250429_163045"
- ts = datetime.now().strftime("%Y%m%d_%H")
- # Full path for this run
- results_dir = os.path.join(base_results, ts)
- os.makedirs(results_dir, exist_ok=True)
- # Read final trained parameters directly from the trained model.
- if 'trained_model' not in globals():
- trained_model = forward_model
- final_found_zernike_coef = trained_model.zernike_coef.detach()
- final_found_object = trained_model.estimated_obj.detach()
- zernike_coeffs_np = final_found_zernike_coef.cpu().numpy()
- found_obj_np = final_found_object.cpu().numpy()
- # Save Zernike coefficients
- np.savetxt(os.path.join(results_dir, "found_zernike_coefficients.txt"),
- zernike_coeffs_np, fmt="%.6e")
- # Save reconstructed object
- skio.imsave(os.path.join(results_dir, "estimated_object.tif"), found_obj_np)
- # Save loss curves collected in training loop
- np.save(os.path.join(results_dir, "train_loss_curve.npy"), np.array(train_loss_curve))
- np.save(os.path.join(results_dir, "image_loss_curve.npy"), np.array(image_loss_curve))
- np.save(os.path.join(results_dir, "fourier_loss_curve.npy"), np.array(fourier_loss_curve))
- # %%
- # — Plot training loss curves —
- plt.figure(figsize=(10, 4))
- plt.subplot(1, 3, 1)
- plt.plot(train_loss_curve, lw=2)
- plt.xlabel('Epoch')
- plt.ylabel('Loss')
- plt.title('Total Loss')
- plt.grid(True)
- plt.subplot(1, 3, 2)
- plt.plot(image_loss_curve, lw=2)
- plt.xlabel('Epoch')
- plt.ylabel('Loss')
- plt.title('Image Loss')
- plt.grid(True)
- plt.subplot(1, 3, 3)
- plt.plot(fourier_loss_curve, lw=2)
- plt.xlabel('Epoch')
- plt.ylabel('Loss')
- plt.title('Fourier Loss')
- plt.grid(True)
- plt.tight_layout()
- plt.show()
- # %%
- # — Compute & show estimated phase map from the trained model —
- if 'trained_model' not in globals():
- trained_model = forward_model
- final_found_zernike_coef = trained_model.zernike_coef.detach()
- estimated_phase = torch.einsum('i,ijk->jk', 1e-6 * final_found_zernike_coef, zernikes)
- est_phase_np = estimated_phase.detach().cpu().numpy()
- est_phase_np = (2 * n_imm * np.pi / wavelength) * est_phase_np # Convert from meters to radians
- plt.figure(figsize=(5,4))
- plt.imshow(est_phase_np, cmap='jet', vmin=-np.pi, vmax=np.pi)
- plt.colorbar(shrink=0.6)
- plt.title('Estimated Phase [radians]')
- plt.axis('off')
- plt.show()
- # %%
- # — Bar chart of learned Zernike coefficients from the trained model —
- if 'trained_model' not in globals():
- trained_model = forward_model
- coeffs_np = trained_model.zernike_coef.detach().cpu().numpy()
- modes = np.arange(len(coeffs_np))
- plt.figure(figsize=(5,3))
- plt.bar(modes, coeffs_np, color='C1')
- plt.xlabel('Zernike Mode Index')
- plt.ylabel('Coefficient [µm]')
- plt.title('Estimated Zernike Coefficients')
- plt.show()
- # %%
- ## Estimated zernike coefficients:
- print(coeffs_np)
- # %%
- # Display original vs. trained-model estimated object side-by-side
- if 'trained_model' not in globals():
- trained_model = forward_model
- orig_np = phase_added[0].detach().cpu().numpy()
- orig_np = (orig_np - orig_np.min()) / (orig_np.max() - orig_np.min()) # Normalize to [0, 1]
- est_obj_np = trained_model.estimated_obj.detach().cpu().numpy()
- est_min = est_obj_np.min()
- est_p999 = np.percentile(est_obj_np, 99.9)
- est_obj_np = np.clip((est_obj_np - est_min) / max(est_p999 - est_min, 1e-12), 0, 1) # Min->0, 99.9th percentile->1
- fig, axs = plt.subplots(1, 2, figsize=(10,5))
- axs[0].imshow(orig_np, cmap='gray', vmin=0, vmax=1)
- axs[0].set_title('Original Image')
- axs[0].axis('off')
- axs[1].imshow(est_obj_np, cmap='gray', vmin=0, vmax=0.8)
- axs[1].set_title('Estimated Object')
- axs[1].axis('off')
- plt.tight_layout()
- plt.show()
GRAPHYCS_demo.ipynb at commit 84c2c58, under GPL-3.0 · at the source
Overview
- School of Electrical Engineering, KAIST, Daejeon, Republic of Korea
- Department of Biomedical Engineering, Ulsan National Institute of Science and Technology (UNIST), Ulsan, Republic of Korea
- Department of Materials Science and Engineering, KAIST, Daejeon, Republic of Korea
- Department of Semiconductor System Engineering, KAIST, Daejeon, Republic of Korea
- KAIST Institute for Human Augmentation Convergence, Daejeon, Republic of Korea
Abstract
Sensor less adaptive optics offers significant advantages over hardware-based wavefront sensing but faces persistent challenges: Its performance degrades when idealized models fail to capture system imperfections, it is largely restricted to spatially invariant aberrations, and it cannot accommodate dynamic biological samples due to static-object assumptions. Here we present graph-modeling and phase-diversity-based computational adaptive optics with self-calibration (GRAPHYCS), a differentiable graph-based modeling framework that addresses all three limitations. GRAPHYCS automatically self-calibrates to correct system-specific non-idealities, enables spatially variant wavefront sensing across extended fields of view by modeling local aberrations, and supports dynamic live-sample imaging where conventional computational methods fail. In simulations, GRAPHYCS achieves up to a 9-fold improvement in wavefront sensing accuracy compared to analytic phase diversity under system non-idealities. In real microscopy experiments, it consistently outperforms phase-diversity-based methods compared in this study. Furthermore, in live zebrafish brain imaging, GRAPHYCS enables simultaneous wavefront sensing and neuronal activity detection—an application beyond the reach of existing approaches without additional hardware complexity.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 13 matches between paragraphs and lines of code.
NICALab/GRAPHYCS
84c2c588030f909abf4c6da899f65f40afb49a9f, 23 July 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
14 files
- GRAPHYCS_demo.ipynb, Jupyter, 408 lines, 3 matches
- graphycs/
GRAPHYCS_spatially_invar , Python, 434 lines, 1 matchiant_lsm.py - graphycs/
GRAPHYCS_spatially_invar , Python, 396 linesiant_wf.py - graphycs/
GRAPHYCS_spatially_varia , Python, 433 lines, 2 matchesnt_lsm.py - graphycs/
GRAPHYCS_spatially_varia , Python, 410 linesnt_wf.py - graphycs/
dset.py , Python, 34 lines - graphycs/
forward_model_lsm.py , Python, 173 lines - graphycs/
forward_model_lsm_varian , Python, 203 linest.py - graphycs/
forward_model_wf.py , Python, 151 lines, 1 match - graphycs/
forward_model_wf_variant , Python, 179 lines.py - graphycs/
self_calibration.py , Python, 210 lines - graphycs/
utils.py , Python, 300 lines - LICENSE, License, 674 lines
- README.md, Text, 181 lines
ceej640/PhaseDiversity
b0839b690fd965a9d5628b1ba45a3bfadeae80f0, 25 February 2025Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
30 files
- MATLAB code/
processPhaseDiversityIma , MATLAB, 347 lines, 2 matchesges.m - MATLAB code/
redist/ , MATLAB, 226 linesdftregistration.m - MATLAB code/
runPD_TestBeadData.m , MATLAB, 33 lines - MATLAB code/
runPD_TestCellData.m , MATLAB, 31 lines - MATLAB code/
script_calibration.m , MATLAB, 392 lines - MATLAB code/
sub-functions/ , MATLAB, 119 linesPlotMirror.m - MATLAB code/
sub-functions/ , MATLAB, 31 linesReadTifStack.m - MATLAB code/
sub-functions/ , MATLAB, 29 linesWriteTifStack.m - MATLAB code/
sub-functions/ , MATLAB, 41 linesaddnoiseScale.m - MATLAB code/
sub-functions/ , MATLAB, 35 linesaddnoise_getSignal.m - MATLAB code/
sub-functions/ , MATLAB, 28 linesaddnoise_snr2signal.m - MATLAB code/
sub-functions/ , MATLAB, 37 linescalc_defocusunit.m - MATLAB code/
sub-functions/ , MATLAB, 44 lines, 2 matchescalculateImageQualityMet rics.m - MATLAB code/
sub-functions/ , MATLAB, 21 linescalculatePupilRadius.m - MATLAB code/
sub-functions/ , MATLAB, 24 linescoeffs_rot.m - MATLAB code/
sub-functions/ , MATLAB, 128 lines, 2 matchescreatePhaseDiversityImag es.m - MATLAB code/
sub-functions/ , MATLAB, 29 linesdef_pupilcoor.m - MATLAB code/
sub-functions/ , MATLAB, 14 linesdetectGPU.m - MATLAB code/
sub-functions/ , MATLAB, 63 linesfileIO_lvtiff2mat.m - MATLAB code/
sub-functions/ , MATLAB, 13 linesimbin.m - MATLAB code/
sub-functions/ , MATLAB, 267 linesreconstructZernikeAberra tions.m - MATLAB code/
sub-functions/ , MATLAB, 26 lineswavefront2coeffs.m - MATLAB code/
sub-functions/ , MATLAB, 239 lineszernretrieve_loop.m - MATLAB code/
sub-functions/ , MATLAB, 71 lineszernretrieve_pre.m - MATLAB code/
zernike-polynomials/ , MATLAB, 59 linesMask.m - MATLAB code/
zernike-polynomials/ , MATLAB, 235 linesZernikePolynomials.m - MATLAB code/
zernike-polynomials/ , MATLAB, 3 lineshelperFunctions/ multiplyPagewise.m - MATLAB code/
zernike-polynomials/ , MATLAB, 3 lineshelperFunctions/ mustBeInFullRadialRange. m - MATLAB code/
zernike-polynomials/ , MATLAB, 19 lineshelperFunctions/ setInputParameters.m - Readme.md, Text, 90 lines
Intelligent-Sensing/NeuWS
c56b9bb8f3c722b4288af73a27e2507129a01de0, 30 June 2023Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
6 files
- dataset.py, Python, 61 lines
- networks.py, Python, 461 lines
- recon_exp_data.py, Python, 185 lines
- utils.py, Python, 354 lines
- LICENSE.txt, License, 27 lines
- README.md, Text, 54 lines
NICALab/SUPPORT
9fba0f415b35106d7d7b9c0144e72917329f0575, 11 August 2025Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
15 files
- colab/
functions.py , Python, 250 lines - colab/
model.py , Python, 553 lines - colab/
utils.py , Python, 362 lines - model/
SUPPORT.py , Python, 450 lines - model/
convhole.py , Python, 131 lines - src/
GUI/ , Python, 809 linestest_GUI.py - src/
GUI/ , Python, 795 linestrain_GUI.py - src/
test.py , Python, 82 lines - src/
test_directory.py , Python, 115 lines - src/
train.py , Python, 184 lines - src/
utils/ , Python, 306 linesdataset.py - src/
utils/ , Python, 148 linesdataset_pyqt.py - src/
utils/ , Python, 205 linesutil.py - LICENSE, License, 674 lines
- README.md, Text, 224 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 4 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 58 scripts, each with its path and the digest of its content;
- 13 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
Datasets cited
- zenodo:15421484, at Zenodo; found in “Data and code availability”
- zenodo:17049780, at Zenodo; found in “Data and code availability”
Data and code availability
The datasets generated and/
All original code has been deposited at a GitHub repository and is publicly available at https://
Any additional information required to reanalyze the data reported in this paper is available from the lead contact upon request.
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 9 authors, 4 keywords, 8 funders, 50 references.
Cite
This paper
Cho, E.-S., Park, J., Jin, H., Chung, Y., Eom, M., Shin, H., Chang, J.-B., Park, J.-H., & Yoon, Y.-G. (2026). Graph-based modeling of optical system enables adaptive optics on dynamic samples with self-calibration. iScience, 29(8), 116769. https://
BibTeX
@article{cho2026graph,
author = {Cho, Eun-Seo and Park, Joon and Jin, Hyungwon and Chung, Yoonjae and Eom, Minho and Shin, Hyejin and Chang, Jae-Byum and Park, Jung-Hoon and Yoon, Young-Gyu},
title = {{Graph-based modeling of optical system enables adaptive optics on dynamic samples with self-calibration}},
journal = {iScience},
year = {2026},
month = jul,
volume = {29},
number = {8},
pages = {116769},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/
url = {https://
pmid = {42519053},
pmcid = {PMC13382438}
}
RIS
TY - JOUR
AU - Cho, Eun-Seo
AU - Park, Joon
AU - Jin, Hyungwon
AU - Chung, Yoonjae
AU - Eom, Minho
AU - Shin, Hyejin
AU - Chang, Jae-Byum
AU - Park, Jung-Hoon
AU - Yoon, Young-Gyu
TI - Graph-based modeling of optical system enables adaptive optics on dynamic samples with self-calibration
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/
VL - 29
IS - 8
SP - 116769
SN - 2589-0042
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "Graph-based modeling of optical system enables adaptive optics on dynamic samples with self-calibration",
"container-title": "iScience",
"author": [
{
"family": "Cho",
"given": "Eun-Seo"
},
{
"family": "Park",
"given": "Joon"
},
{
"family": "Jin",
"given": "Hyungwon"
},
{
"family": "Chung",
"given": "Yoonjae"
},
{
"family": "Eom",
"given": "Minho"
},
{
"family": "Shin",
"given": "Hyejin"
},
{
"family": "Chang",
"given": "Jae-Byum"
},
{
"family": "Park",
"given": "Jung-Hoon"
},
{
"family": "Yoon",
"given": "Young-Gyu"
}
],
"container-title-short":
"volume": "29",
"issue": "8",
"page": "116769",
"DOI": "10.1016/
"PMID": "42519053",
"PMCID": "PMC13382438",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
7,
14
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1038/s41467-026-73389-2 [code]
- Physics-informed multi-encoder adaptive optics enables rapid aberration correction for intravital microscopy of deep complex tissue.Journal: Nature communicationsIn common: SciPy, Matplotlib, NumPy, 18 references
- [2] doi:10.1038/s41467-026-75347-4 [code]
- Sleep reveals dynamics integrating and segregating movement and stimulus representations in V1.Journal: Nature communicationsIn common: Curve Fitting Toolbox, imageio, Parallel Computing Toolbox, 7 other tools
- [3] doi:10.1038/s41467-026-73045-9 [code]
- Aberration-aware 3D localization microscopy via self-supervised neural-physics learning.Journal: Nature communicationsIn common: imageio, tifffile, scikit-image, 5 other tools, 2 references
- [4] doi:10.1038/s41592-026-03179-7 [code]
- Voltage imaging of neurons distributed across entire brains of larval zebrafish.Journal: Nature methodsIn common: scikit-image, h5py, SciPy, 2 other tools, 5 references
- [5] doi:10.1038/s41467-026-76242-8 [code]
- Whole-brain, all-optical interrogation of neuronal dynamics underlying gut and vascular interoception in zebrafish.Journal: Nature communicationsIn common: tifffile, Parallel Computing Toolbox, scikit-image, 5 other tools, 2 references
- [6] doi:10.1038/s41592-026-03066-1 [code]
- A multimodal adaptive optical microscope for in vivo imaging from molecules to organisms.Journal: Nature methodsIn common: Parallel Computing Toolbox, Image Processing Toolbox, NumPy, 5 references
- [7] doi:10.1126/sciadv.aee9298 [code]
- Synaptic zinc plasticity shapes adaptive and maladaptive cortical plasticity following cochlear injury.Journal: Science advancesIn common: imageio, tifffile, Parallel Computing Toolbox, 6 other tools
- [8] doi:10.1080/07853890.2026.2685416 [code]
- Pulmonary and cerebral damage in COVID-19 survivors: is there any association?Journal: Annals of medicineIn common: Curve Fitting Toolbox, imageio, scikit-image, 6 other tools
- [9] doi:10.1364/boe.605322 [code]
- Generalized plaque digitization framework for multi-dimensional mesoscopic images.Journal: Biomedical optics expressIn common: imageio, tifffile, scikit-image, 6 other tools
- [10] doi:10.1038/s41598-026-57519-w [code]
- Automated segmentation of neurons and spinal cord structures in immunofluorescence images using SpineDL.Journal: Scientific reportsIn common: imageio, tifffile, scikit-image, 6 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 4 repositories of the authors' code, each at its verified commit and with its license, 58 scripts, and 13 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:ace06f4f09f3b47e…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
