Endothelial <i>Adgrl2</i> Expression and Alternative Splicing Controls the Cerebrovasculature.
The 2 matches
- [1] § Materials and Methods › Quantification and statistical analysis › Vascular morphology analysis ↔ adaptive_vascular_analysis.py, lines 356–421 · score 0.90 · vessel mask, vessel diameter, Frangi filter, vessel area, Adaptive, Equalization
- [2] § Results › Endothelial Adgrl2 alternative splicing program prevents ectopic synaptogenesis ↔ adaptive_vascular_analysis.py, lines 226–294 · score 0.54 · vessel widths, point densities, branch points, CD31, vasculature
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
Python · 785 lines · 42 KB · CC-BY-4.0 · 2 matches
- import os
- import geojson
- from shapely.geometry import shape
- from shapely import affinity
- import rasterio
- from rasterio.transform import from_origin
- from rasterio.features import rasterize
- from rasterio.transform import Affine # Import Affine directly
- import numpy as np
- import scipy.ndimage as ndi
- from skimage import filters, morphology, measure, segmentation, io, restoration
- from skimage.filters import frangi, threshold_local
- from skimage.feature import peak_local_max
- from skimage.color import label2rgb
- from skimage.exposure import equalize_adapthist, rescale_intensity
- import matplotlib.pyplot as plt
- import pandas as pd
- from aicsimageio import AICSImage # This library works for TIFF, CZI, and more!
- import warnings
- import time
- import itertools # To iterate through parameter combinations
- import concurrent.futures # **** ADD FOR PARALLELISM ****
- import traceback # For detailed error logging in parallel tasks
- # --- Configuration ---
- # Input/Output Folders
- DATA_FOLDER = 'images'
- OUTPUT_CSV_FILENAME = 'choroid_plexus_analysis_param_sweep_um_params.csv'
- OUTPUT_PLOT_FOLDER = os.path.join(DATA_FOLDER, 'analysis_plots_param_sweep_um_params')
- # --- Global Physical Constant ---
- # This is the assumed physical size of a pixel if not found in image metadata.
- # ALL micrometer (_UM) parameters below are converted to pixels using this value.
- ASSUMED_PIXEL_SIZE_UM = 0.638148 # µm/pixel
- FORCE_ASSUMED_PIXEL_SIZE = True
- SAVE_PLOTS = True
- if SAVE_PLOTS and not os.path.exists(OUTPUT_PLOT_FOLDER):
- os.makedirs(OUTPUT_PLOT_FOLDER)
- # Channel indices
- DAPI_CHANNEL_INDEX = 0
- CD31_CHANNEL_INDEX = 0
- # --- Preprocessing Parameters (ALL SPATIAL PARAMS NOW IN MICROMETERS) ---
- # Note: These values are converted to pixels internally for image processing functions.
- CD31_MEDIAN_RADIUS_UM = 0.22 # In µm. Original: 1 pixel -> 1 * 0.2196 ≈ 0.22 µm
- CD31_ROLLING_BALL_RADIUS = 0 # Disabled
- DAPI_MEDIAN_RADIUS_UM = 0.44 # In µm. Original: 2 pixels -> 2 * 0.2196 ≈ 0.44 µm
- APPLY_CLAHE_TO_CD31 = True
- CLAHE_KERNEL_SIZE_DIVISOR = 8 # Unitless: divides image dims to get tile size.
- CLAHE_CLIP_LIMIT = 0.01 # Unitless: clipping limit for contrast.
- # --- Segmentation Parameters (ALL SPATIAL PARAMS NOW IN MICROMETERS) ---
- NUCLEI_THRESHOLD_METHOD = 'otsu'
- NUCLEI_MIN_DISTANCE_PEAKS_UM = 0.44 # In µm. Original: 2 pixels -> 2 * 0.2196 ≈ 0.44 µm
- # --- VESSELNESS SIGMA RANGES TO TEST (DEFINED IN MICROMETERS) ---
- # Each element is a tuple: (start_sigma_um, stop_sigma_um, step_sigma_um)
- # Original pixel range(20, 70, 1) -> (20*0.2196, 70*0.2196, 1*0.2196) -> (4.39, 15.37, 0.22)
- VESSELNESS_SIGMA_RANGES_TO_TEST_UM = [
- (4.4, 15.4, 0.22)
- # e.g., (2.0, 8.0, 0.5) to test sigmas from 2µm to 8µm in 0.5µm steps.
- ]
- # --- Post-processing Filter Parameters (ALREADY IN MICROMETERS) ---
- MIN_VESSEL_WIDTH_UM = 2.0 # In µm. Remove vessels narrower than this.
- MIN_VESSEL_SEGMENT_LENGTH_UM = 20.0 # In µm. Remove skeleton segments shorter than this.
- MIN_BRANCH_POINT_DISTANCE_UM = 10 # <<<--- Minimum distance between branch points in micrometers.
- # --- PARAMETER SWEEP DEFINITION (Adaptive Threshold in MICROMETERS) ---
- # Original pixel block_size 801 -> 801 * 0.2196 ≈ 175.9 µm. Let's use 176 µm.
- BLOCK_SIZES_TO_TEST_UM = [176.0]
- OFFSETS_TO_TEST = [-0.0001] # This is a unitless intensity offset, not a spatial parameter.
- ADAPTIVE_METHOD = 'gaussian'
- # --- PARALLELISM CONFIGURATION ---
- NUM_WORKERS = os.cpu_count() - 2 # A slightly more conservative default
- if NUM_WORKERS < 1:
- NUM_WORKERS = 1
- # --- Configuration Printout (Updated for Micrometer Parameters) ---
- print(f"--- Configuration ---")
- print(f"ASSUMED PIXEL SIZE: {ASSUMED_PIXEL_SIZE_UM} µm/pixel (used for all conversions)")
- print(f"Data Folder: {DATA_FOLDER}")
- print(f"Output CSV: {OUTPUT_CSV_FILENAME}")
- print(f"Save Plots: {SAVE_PLOTS}")
- if SAVE_PLOTS: print(f"Plot Folder: {OUTPUT_PLOT_FOLDER}")
- print(f"DAPI Channel: {DAPI_CHANNEL_INDEX}, CD31 Channel: {CD31_CHANNEL_INDEX}")
- print(f"CD31 Median Radius: {CD31_MEDIAN_RADIUS_UM} µm")
- print(f"DAPI Median Radius: {DAPI_MEDIAN_RADIUS_UM} µm")
- print(f"Apply CLAHE to CD31: {APPLY_CLAHE_TO_CD31}")
- if APPLY_CLAHE_TO_CD31:
- print(f" CLAHE Kernel Size Divisor: {CLAHE_KERNEL_SIZE_DIVISOR}")
- print(f" CLAHE Clip Limit: {CLAHE_CLIP_LIMIT}")
- print(f"Nuclei Threshold: {NUCLEI_THRESHOLD_METHOD}, Min Distance: {NUCLEI_MIN_DISTANCE_PEAKS_UM} µm")
- print(f"Vesselness Sigma Ranges to Test (in µm):")
- for i, (start, stop, step) in enumerate(VESSELNESS_SIGMA_RANGES_TO_TEST_UM):
- print(f" - Config {i+1}: start={start}µm, stop={stop}µm, step={step}µm")
- print(f"Minimum Vessel Width Filter: {MIN_VESSEL_WIDTH_UM} µm")
- print(f"Minimum Vessel Segment Length: {MIN_VESSEL_SEGMENT_LENGTH_UM} µm")
- print(f"--- Parameter Sweep Configuration (Adaptive Threshold) ---")
- print(f"Block Sizes to Test: {BLOCK_SIZES_TO_TEST_UM} µm")
- print(f"Offsets to Test: {OFFSETS_TO_TEST}")
- print(f"Adaptive Method: {ADAPTIVE_METHOD}")
- print(f"--- Parallelism Configuration ---")
- print(f"Using up to {NUM_WORKERS} worker processes.")
- print(f"---------------------------------")
- # --- Helper Functions ---
- ### CHANGED ### - Renamed function from load_czi_image to load_image
- def load_image(path):
- """Loads a bio-image (TIFF, CZI, etc.) using aicsimageio and extracts pixel size."""
- try:
- img_aics = AICSImage(path)
- dims_order = img_aics.dims.order
- has_c = 'C' in dims_order
- has_y = 'Y' in dims_order
- has_x = 'X' in dims_order
- if has_c and has_y and has_x:
- image_stack = img_aics.get_image_data("CYX", T=0, Z=0)
- elif has_y and has_x:
- print(f"Warning: Image {os.path.basename(path)} seems 2D (missing C dimension). Loading as YX.")
- image_stack = img_aics.get_image_data("YX", T=0, Z=0)
- else:
- print(f"Error: Image {os.path.basename(path)} missing Y or X dimension. Cannot process.")
- return None, None
- pixel_size_x_um = img_aics.physical_pixel_sizes.X
- pixel_size_y_um = img_aics.physical_pixel_sizes.Y
- # Use the global constant as the fallback
- provided_pixel_size = ASSUMED_PIXEL_SIZE_UM
- if pixel_size_x_um is None or pixel_size_y_um is None:
- # ### MODIFIED ### - Added 'TIFF' to warning for clarity. This is the expected path for many TIFFs.
- print(f"Warning: Could not read pixel size from image metadata (e.g., common for standard TIFF files). Using assumed value: {provided_pixel_size} µm.")
- pixel_size_xy_um = provided_pixel_size
- elif not np.isclose(pixel_size_x_um, pixel_size_y_um):
- print(f"Warning: Anisotropic pixel size in {os.path.basename(path)} metadata (X: {pixel_size_x_um}, Y: {pixel_size_y_um}). Using assumed value: {provided_pixel_size} µm.")
- pixel_size_xy_um = provided_pixel_size
- else:
- pixel_size_xy_um = pixel_size_x_um
- print(f"Image loaded: {os.path.basename(path)}, shape={image_stack.shape}, dtype={image_stack.dtype}, using pixel_size={pixel_size_xy_um:.4f} µm")
- return image_stack, pixel_size_xy_um
- except FileNotFoundError:
- print(f"Error: Image file not found at {path}")
- return None, None
- except Exception as e:
- print(f"Error loading image {path}: {e}")
- traceback.print_exc()
- return None, None
- def load_roi_polygon(geojson_path):
- """Loads the first Polygon feature from a GeoJSON file."""
- try:
- with open(geojson_path) as f:
- gj = geojson.load(f)
- roi_polygon = None
- if isinstance(gj, geojson.FeatureCollection):
- for feature in gj.features:
- if isinstance(feature.geometry, geojson.Polygon):
- roi_polygon = shape(feature.geometry)
- break
- elif isinstance(gj, geojson.Feature):
- if isinstance(gj.geometry, geojson.Polygon):
- roi_polygon = shape(gj.geometry)
- elif isinstance(gj, geojson.Polygon):
- roi_polygon = shape(gj)
- if roi_polygon:
- if not roi_polygon.is_valid:
- print(f"Warning: Loaded polygon from {geojson_path} is invalid, attempting to buffer(0).")
- roi_polygon = roi_polygon.buffer(0)
- if not roi_polygon.is_valid or roi_polygon.is_empty:
- print(f"Error: Polygon from {geojson_path} remains invalid or empty after buffer(0).")
- return None
- return roi_polygon
- else:
- print(f"Error: No Polygon geometry found in {geojson_path}")
- return None
- except FileNotFoundError:
- print(f"Error: GeoJSON file not found at {geojson_path}")
- return None
- except Exception as e:
- print(f"Error loading GeoJSON {geojson_path}: {e}")
- return None
- def create_roi_mask(image_shape_2d, roi_polygon, pixel_size_um):
- """Creates a 2D boolean mask from a Shapely polygon in µm coordinates."""
- if roi_polygon is None:
- print("Error: create_roi_mask called with None polygon.")
- return None
- # This transform correctly maps micron-space coordinates of the polygon to pixel-space of the image.
- transform = Affine(pixel_size_um, 0.0, 0.0, 0.0, pixel_size_um, 0.0)
- try:
- mask = rasterize(
- [(roi_polygon, 1)],
- out_shape=image_shape_2d,
- transform=transform,
- fill=0,
- dtype=np.uint8,
- all_touched=False
- )
- if not np.any(mask):
- img_extent_x_um = image_shape_2d[1] * pixel_size_um
- img_extent_y_um = image_shape_2d[0] * pixel_size_um
- print(f"Warning: Rasterization produced an empty mask for polygon.")
- print(f"-> Polygon bounds (µm): {roi_polygon.bounds}")
- print(f"-> Image expected extent (µm): X=[0, {img_extent_x_um:.2f}], Y=[0, {img_extent_y_um:.2f}]")
- print(f"-> Check GeoJSON coordinates, their scaling to µm, and pixel size ({pixel_size_um:.4f} µm).")
- except Exception as e:
- print(f"Error during rasterization: {e}")
- traceback.print_exc()
- raise
- return mask.astype(bool)
- def analyze_image_roi(image_path, geojson_path, current_sigma_range_um, adaptive_block_size_um, adaptive_offset):
- """
- Performs the full analysis pipeline for a single image/GeoJSON pair
- using specified parameters defined in micrometers.
- """
- # (The top part of the function remains the same)
- (param_sigma_start_um, param_sigma_stop_um, param_sigma_step_um) = current_sigma_range_um
- results = {
- 'filename_image': os.path.basename(image_path),
- 'filename_geojson': os.path.basename(geojson_path) if geojson_path else 'N/A (Full Image)',
- 'vesselness_sigma_start_um': param_sigma_start_um, 'vesselness_sigma_stop_um': param_sigma_stop_um, 'vesselness_sigma_step_um': param_sigma_step_um,
- 'adaptive_block_size_um': adaptive_block_size_um, 'adaptive_offset': adaptive_offset,
- 'min_vessel_width_um_param': MIN_VESSEL_WIDTH_UM, 'min_vessel_segment_length_um_param': MIN_VESSEL_SEGMENT_LENGTH_UM,
- 'pixel_size_um': None, 'roi_area_pixels': None, 'roi_area_um2': None, 'roi_area_mm2': None,
- 'vessel_area_pixels': None, 'vessel_area_um2': None, 'vaf_percent': None,
- 'mean_vessel_diameter_um': None, 'raw_skeleton_pixels': None, 'raw_skeleton_length_um': None,
- 'filtered_skeleton_pixels': None, 'filtered_skeleton_length_um': None, 'segments_analyzed': None, 'segments_kept': None,
- 'filtered_branch_points_count': None, 'filtered_branch_point_density_mm2': None, 'nuclei_count': None, 'nuclear_density_mm2': None,
- 'error_message': None
- }
- run_id_params = (f"Sigmas={param_sigma_start_um}-{param_sigma_stop_um}s{param_sigma_step_um}um, "
- f"Block={adaptive_block_size_um}um, Offset={adaptive_offset}, "
- f"MinWidth={MIN_VESSEL_WIDTH_UM}µm, MinLen={MIN_VESSEL_SEGMENT_LENGTH_UM}µm")
- run_id = f"{os.path.basename(image_path)} ({run_id_params})"
- print(f"--- Starting Task: {run_id} ---")
- start_time = time.time()
- try:
- image_stack, pixel_size_um = load_image(image_path)
- if image_stack is None or pixel_size_um is None or pixel_size_um <= 0:
- raise ValueError(f"Failed to load image or determine valid pixel size for {image_path}")
- if image_stack.ndim == 3 and image_stack.shape[0] == 1:
- print(f" -> Info for {run_id}: Image has shape (1, Y, X). Squeezing to 2D.")
- image_stack = image_stack.squeeze(axis=0)
- # ################################################
- results['pixel_size_um'] = pixel_size_um
- AREA_UNIT_FACTOR = pixel_size_um * pixel_size_um
- LENGTH_UNIT_FACTOR = pixel_size_um
- DENSITY_AREA_MM2 = 1e6
- cd31_median_radius_px = int(round(CD31_MEDIAN_RADIUS_UM / pixel_size_um))
- dapi_median_radius_px = int(round(DAPI_MEDIAN_RADIUS_UM / pixel_size_um))
- nuclei_min_distance_peaks_px = int(round(NUCLEI_MIN_DISTANCE_PEAKS_UM / pixel_size_um))
- if nuclei_min_distance_peaks_px < 1: nuclei_min_distance_peaks_px = 1
- adaptive_block_size_px = int(round(adaptive_block_size_um / pixel_size_um))
- if adaptive_block_size_px % 2 == 0: adaptive_block_size_px += 1
- if adaptive_block_size_px < 3:
- print(f"Warning for {run_id}: Calculated block size ({adaptive_block_size_px}px) is too small. Setting to 3.")
- adaptive_block_size_px = 3
- sigma_start_px = int(round(param_sigma_start_um / pixel_size_um))
- sigma_stop_px = int(round(param_sigma_stop_um / pixel_size_um))
- sigma_step_px = int(round(param_sigma_step_um / pixel_size_um))
- if sigma_start_px < 1: sigma_start_px = 1
- if sigma_stop_px <= sigma_start_px: sigma_stop_px = sigma_start_px + 1
- if sigma_step_px < 1: sigma_step_px = 1
- frangi_sigma_range_px = range(sigma_start_px, sigma_stop_px, sigma_step_px)
- if not list(frangi_sigma_range_px):
- error_msg = (f"Vesselness sigma range in pixels is empty. "
- f"Params(um): start={param_sigma_start_um}, stop={param_sigma_stop_um}, step={param_sigma_step_um} "
- f"-> Converted(px): start={sigma_start_px}, stop={sigma_stop_px}, step={sigma_step_px}")
- raise ValueError(error_msg)
- print(f" -> Converted Params for {run_id}:")
- print(f" CD31 Median Radius: {CD31_MEDIAN_RADIUS_UM}µm -> {cd31_median_radius_px}px")
- print(f" DAPI Median Radius: {DAPI_MEDIAN_RADIUS_UM}µm -> {dapi_median_radius_px}px")
- print(f" Nuclei Min Dist: {NUCLEI_MIN_DISTANCE_PEAKS_UM}µm -> {nuclei_min_distance_peaks_px}px")
- print(f" Adaptive Block Size: {adaptive_block_size_um}µm -> {adaptive_block_size_px}px")
- print(f" Frangi Sigmas: {current_sigma_range_um}µm -> range({frangi_sigma_range_px.start}, {frangi_sigma_range_px.stop}, {frangi_sigma_range_px.step})px")
- img_shape = image_stack.shape
- dapi_img, cd31_img = None, None
- img_shape_2d = None
- if len(img_shape) == 3 and img_shape[0] >= max(DAPI_CHANNEL_INDEX, CD31_CHANNEL_INDEX) + 1:
- dapi_img = image_stack[DAPI_CHANNEL_INDEX, :, :]
- cd31_img = image_stack[CD31_CHANNEL_INDEX, :, :]
- img_shape_2d = (img_shape[1], img_shape[2])
- elif len(img_shape) == 2:
- print(f"Info for {run_id}: Handling as 2D image (shape {img_shape}). Assigning channels based on index.")
- img_shape_2d = img_shape
- if CD31_CHANNEL_INDEX == 0 and DAPI_CHANNEL_INDEX != 0:
- cd31_img = image_stack
- elif DAPI_CHANNEL_INDEX == 0 and CD31_CHANNEL_INDEX != 0:
- dapi_img = image_stack
- else:
- # Default or ambiguous case: assume it's the primary channel (CD31)
- cd31_img = image_stack
- if DAPI_CHANNEL_INDEX == CD31_CHANNEL_INDEX:
- print(f"Warning for {run_id}: DAPI and CD31 channels are the same. Only CD31 will be processed from the 2D image.")
- else:
- print(f"Info for {run_id}: Assuming 2D image is CD31 channel (index {CD31_CHANNEL_INDEX}).")
- else:
- raise ValueError(f"Image {run_id}: Unexpected image dimensions: {img_shape}.")
- if cd31_img is None: raise ValueError(f"Image {run_id}: CD31 image could not be extracted. Check channel indices.")
- if img_shape_2d is None: raise ValueError(f"Image {run_id}: Could not determine 2D shape.")
- roi_mask = None
- if geojson_path:
- print(f" -> Loading ROI from {os.path.basename(geojson_path)}...")
- roi_polygon_pixels = load_roi_polygon(geojson_path)
- if roi_polygon_pixels is None:
- raise ValueError(f"Failed to load ROI polygon from {geojson_path}")
- roi_polygon_um = affinity.scale(roi_polygon_pixels, xfact=pixel_size_um, yfact=pixel_size_um, origin=(0, 0))
- roi_mask = create_roi_mask(img_shape_2d, roi_polygon_um, pixel_size_um)
- if roi_mask is None: raise ValueError(f"Image {run_id}: Failed to create ROI mask from GeoJSON.")
- else:
- print(f" -> No GeoJSON file provided. Using entire image as the Region of Interest.")
- roi_mask = np.ones(img_shape_2d, dtype=bool)
- total_roi_area_pixels = np.sum(roi_mask)
- if total_roi_area_pixels == 0:
- raise ValueError(f"ROI mask for {run_id} is empty. Check GeoJSON coordinates and image size.")
- total_roi_area_um2 = total_roi_area_pixels * AREA_UNIT_FACTOR
- total_roi_area_mm2 = total_roi_area_um2 / DENSITY_AREA_MM2
- results.update({'roi_area_pixels': total_roi_area_pixels, 'roi_area_um2': total_roi_area_um2, 'roi_area_mm2': total_roi_area_mm2})
- cd31_for_filter = cd31_img.astype(np.float32)
- if cd31_median_radius_px > 0:
- cd31_for_filter = filters.median(cd31_for_filter, morphology.disk(cd31_median_radius_px))
- if APPLY_CLAHE_TO_CD31:
- actual_ntiles_for_clahe = CLAHE_KERNEL_SIZE_DIVISOR
- print(f" -> Applying CLAHE to CD31 for {run_id} (ntiles={actual_ntiles_for_clahe}, clip_limit={CLAHE_CLIP_LIMIT})")
- normalized_cd31_for_clahe = rescale_intensity(
- cd31_for_filter,
- in_range='image',
- out_range=(0.0, 1.0)
- )
- cd31_clahe_output = equalize_adapthist(
- normalized_cd31_for_clahe,
- kernel_size=actual_ntiles_for_clahe,
- clip_limit=CLAHE_CLIP_LIMIT,
- nbins=256
- )
- cd31_for_filter = cd31_clahe_output.astype(np.float32)
- print(f" -> CLAHE applied. Output range: {cd31_for_filter.min():.3f} - {cd31_for_filter.max():.3f}, dtype: {cd31_for_filter.dtype}")
- frangi_output_full = np.zeros_like(cd31_for_filter)
- try:
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", category=UserWarning)
- frangi_output_full = frangi(cd31_for_filter.astype(np.float32), sigmas=frangi_sigma_range_px, black_ridges=False)
- except Exception as frangi_err:
- raise ValueError(f"Frangi filtering failed for {run_id}: {frangi_err}")
- vesselness_image_roi = np.zeros_like(frangi_output_full)
- vesselness_image_roi[roi_mask] = frangi_output_full[roi_mask]
- vessel_mask_initial = np.zeros_like(vesselness_image_roi, dtype=bool)
- if np.any(vesselness_image_roi > 1e-9):
- try:
- local_thresh_map = threshold_local(
- frangi_output_full,
- block_size=adaptive_block_size_px,
- method=ADAPTIVE_METHOD,
- offset=adaptive_offset
- )
- vessel_mask_initial = (frangi_output_full > local_thresh_map) & roi_mask
- if not np.any(vessel_mask_initial):
- print(f"Warning for {run_id}: Initial vessel mask is empty after adaptive thresholding.")
- except Exception as e:
- raise ValueError(f"Adaptive thresholding failed for {run_id}: {e}")
- else:
- print(f"Warning for {run_id}: No significant Frangi signal in ROI. Initial vessel mask empty.")
- mean_diameter_um = 0.0
- if np.any(vessel_mask_initial):
- distance_map_on_initial_mask_um = ndi.distance_transform_edt(vessel_mask_initial, sampling=[pixel_size_um, pixel_size_um])
- skeleton_of_initial_mask = morphology.skeletonize(vessel_mask_initial) & roi_mask
- if np.any(skeleton_of_initial_mask):
- radii_at_skeleton_points_um = distance_map_on_initial_mask_um[skeleton_of_initial_mask]
- valid_radii = radii_at_skeleton_points_um[radii_at_skeleton_points_um > 1e-6]
- if len(valid_radii) > 0:
- mean_diameter_um = 2 * np.mean(valid_radii)
- results['mean_vessel_diameter_um'] = mean_diameter_um
- vessel_mask = vessel_mask_initial.copy()
- if MIN_VESSEL_WIDTH_UM is not None and MIN_VESSEL_WIDTH_UM > 0 and pixel_size_um > 0:
- if np.any(vessel_mask):
- min_width_px = MIN_VESSEL_WIDTH_UM / pixel_size_um
- if min_width_px >= 1:
- radius_px_se = int(round((min_width_px - 1) / 2))
- if radius_px_se >= 1:
- vessel_mask = morphology.binary_opening(vessel_mask, footprint=morphology.disk(radius_px_se))
- vessel_area_pixels = np.sum(vessel_mask)
- vessel_area_um2 = vessel_area_pixels * AREA_UNIT_FACTOR
- vaf = (vessel_area_pixels / total_roi_area_pixels) * 100 if total_roi_area_pixels > 0 else 0
- results.update({'vessel_area_pixels': vessel_area_pixels, 'vessel_area_um2': vessel_area_um2, 'vaf_percent': vaf})
- raw_skeleton_pixels = 0; raw_skeleton_length_um = 0
- filtered_skeleton_pixels = 0; filtered_skeleton_length_um = 0
- segments_analyzed = 0; segments_kept = 0
- num_branch_points = 0; branch_point_density = 0
- skeleton_raw = None; skeleton_filtered = None; branch_points_mask = None
- if vessel_area_pixels > 5:
- skeleton_raw = morphology.skeletonize(vessel_mask) & roi_mask
- raw_skeleton_pixels = np.sum(skeleton_raw)
- raw_skeleton_length_um = raw_skeleton_pixels * LENGTH_UNIT_FACTOR
- results.update({'raw_skeleton_pixels': raw_skeleton_pixels, 'raw_skeleton_length_um': raw_skeleton_length_um})
- skeleton_filtered = skeleton_raw.copy()
- if MIN_VESSEL_SEGMENT_LENGTH_UM > 0:
- min_len_px = MIN_VESSEL_SEGMENT_LENGTH_UM / pixel_size_um
- if raw_skeleton_pixels > 0:
- labels, num_labels = measure.label(skeleton_raw, connectivity=2, return_num=True)
- segments_analyzed = num_labels
- kept_labels = [lbl for lbl in range(1, num_labels + 1) if np.sum(labels == lbl) >= min_len_px]
- segments_kept = len(kept_labels)
- if segments_kept < segments_analyzed:
- skeleton_filtered = skeleton_raw & np.isin(labels, kept_labels)
- filtered_skeleton_pixels = np.sum(skeleton_filtered)
- filtered_skeleton_length_um = filtered_skeleton_pixels * LENGTH_UNIT_FACTOR
- if filtered_skeleton_pixels > 0:
- # ### NEW/MODIFIED LOGIC FOR BRANCH POINT DETECTION ###
- # 1. Find all candidate branch points (original method)
- neighbor_kernel = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]], dtype=np.uint8)
- num_neighbors = ndi.convolve(skeleton_filtered.astype(np.uint8), neighbor_kernel, mode='constant', cval=0)
- branch_points_candidates_mask = (num_neighbors > 2) & skeleton_filtered
- # 2. Consolidate candidate clusters into single points
- num_branch_points = 0
- branch_points_mask = np.zeros_like(skeleton_filtered, dtype=bool)
- if np.any(branch_points_candidates_mask):
- # Convert the minimum distance from micrometers to pixels
- min_dist_px = max(1, int(round(MIN_BRANCH_POINT_DISTANCE_UM / pixel_size_um)))
- print(f" -> Merging branch points within {MIN_BRANCH_POINT_DISTANCE_UM}µm ({min_dist_px}px).")
- # Create a distance map where clusters of candidates become "hills"
- distance_from_candidates = ndi.distance_transform_edt(branch_points_candidates_mask)
- # Find the peak of each "hill", enforcing the minimum distance
- coords = peak_local_max(distance_from_candidates,
- min_distance=min_dist_px,
- exclude_border=False)
- # The number of coordinates found is our new branch point count
- num_branch_points = coords.shape[0]
- # Create the final mask with only the consolidated points for plotting
- if num_branch_points > 0:
- branch_points_mask[tuple(coords.T)] = True
- branch_point_density = num_branch_points / total_roi_area_mm2 if total_roi_area_mm2 > 0 else 0
- results.update({'filtered_skeleton_pixels': filtered_skeleton_pixels, 'filtered_skeleton_length_um': filtered_skeleton_length_um,
- 'segments_analyzed': segments_analyzed, 'segments_kept': segments_kept, 'filtered_branch_points_count': num_branch_points,
- 'filtered_branch_point_density_mm2': branch_point_density})
- num_nuclei = 0; nuclear_density = 0; nuclei_labels = None
- if dapi_img is not None:
- dapi_roi = dapi_img.copy().astype(np.float32)
- dapi_roi[~roi_mask] = 0
- if np.any(dapi_roi):
- dapi_processed = dapi_roi
- if dapi_median_radius_px > 0:
- dapi_processed = filters.median(dapi_processed, morphology.disk(dapi_median_radius_px))
- dapi_processed[~roi_mask] = 0
- dapi_pixels_in_roi = dapi_processed[roi_mask]
- if np.any(dapi_pixels_in_roi > 1e-6):
- significant_dapi_pixels = dapi_pixels_in_roi[dapi_pixels_in_roi > np.percentile(dapi_pixels_in_roi, 5)]
- if len(np.unique(significant_dapi_pixels)) > 1:
- nuclei_thresh_val = filters.threshold_otsu(significant_dapi_pixels)
- nuclei_thresholded_mask = (dapi_processed > nuclei_thresh_val) & roi_mask
- if np.any(nuclei_thresholded_mask):
- distance_dapi = ndi.distance_transform_edt(nuclei_thresholded_mask)
- coords = peak_local_max(distance_dapi, min_distance=nuclei_min_distance_peaks_px,
- labels=measure.label(nuclei_thresholded_mask), exclude_border=False)
- if coords.size > 0:
- mask_peaks = np.zeros(distance_dapi.shape, dtype=bool)
- mask_peaks[tuple(coords.T)] = True
- markers, _ = ndi.label(mask_peaks)
- nuclei_labels = segmentation.watershed(-distance_dapi, markers, mask=nuclei_thresholded_mask)
- nuclei_labels[~roi_mask] = 0
- num_nuclei = len(np.unique(nuclei_labels)) -1
- nuclear_density = num_nuclei / total_roi_area_mm2 if total_roi_area_mm2 > 0 else 0
- results.update({'nuclei_count': num_nuclei, 'nuclear_density_mm2': nuclear_density})
- # Plotting code remains the same...
- if SAVE_PLOTS:
- try:
- fig, axes = plt.subplots(2, 3, figsize=(18, 10))
- plot_title = (f"{os.path.basename(image_path)} | Sig={param_sigma_start_um}-{param_sigma_stop_um}s{param_sigma_step_um}µm, "
- f"B={adaptive_block_size_um}µm, O={adaptive_offset}, "
- f"MinWidth={MIN_VESSEL_WIDTH_UM}µm, MinLen={MIN_VESSEL_SEGMENT_LENGTH_UM}µm\n"
- f"ROI Area: {total_roi_area_um2:.1f} µm² ({total_roi_area_mm2:.3f} mm²)")
- fig.suptitle(plot_title, fontsize=10)
- ax = axes.ravel()
- def plot_img(ax_plot, img_data, title, cmap='gray', vmin=None, vmax=None, roi_m=None):
- if img_data is None:
- ax_plot.set_title(title + ' (N/A)'); ax_plot.axis('off'); return None
- effective_roi = roi_m if roi_m is not None else np.ones_like(img_data, dtype=bool)
- img_to_plot = img_data.copy().astype(float)
- img_to_plot[~effective_roi] = np.nan
- valid_pixels = img_data[effective_roi & np.isfinite(img_data)]
- vmin_calc, vmax_calc = (np.percentile(valid_pixels, [1, 99]) if valid_pixels.size > 10 else (0, 1))
- ax_plot.imshow(img_to_plot, cmap=cmap, vmin=vmin_calc, vmax=vmax_calc, interpolation='nearest')
- ax_plot.set_title(title); ax_plot.axis('off')
- plot_img(ax[0], cd31_img, 'CD31 (Full)', cmap='viridis', roi_m=roi_mask)
- plot_img(ax[1], dapi_img, 'DAPI (Full)', cmap='magma', roi_m=roi_mask)
- plot_img(ax[2], vesselness_image_roi, 'Frangi Vesselness (ROI)', cmap='hot', roi_m=roi_mask)
- overlay = label2rgb(vessel_mask.astype(int), image=rescale_intensity(cd31_img, out_range=(0,1)), bg_label=0, alpha=0.3, colors=['red'])
- ax[3].imshow(overlay); ax[3].set_title(f'Vessel Mask (VAF={vaf:.1f}%)'); ax[3].axis('off')
- # --- Define visualization parameters ---
- SKELETON_LINE_THICKNESS_PX = 2 # <-- Adjust for skeleton thickness
- BRANCH_POINT_MARKER_RADIUS_PX = 4 # <-- Adjust for branch point size
- # print(skeleton_raw)
- # --- Plot 4: Raw Skeleton Overlay (Thickened) ---
- background_raw = rescale_intensity(cd31_img, out_range=(0,1))
- overlay_raw = np.stack([background_raw]*3, axis=-1)
- if skeleton_raw is not None:
- dilated_skeleton_raw = morphology.binary_dilation(skeleton_raw, footprint=morphology.disk(SKELETON_LINE_THICKNESS_PX))
- overlay_raw[dilated_skeleton_raw] = [0.0, 1.0, 1.0] # Cyan
- ax[4].imshow(overlay_raw)
- ax[4].set_title(f'RAW Skel (L={raw_skeleton_length_um:.0f}µm)')
- ax[4].axis('off')
- # --- Plot 5: Filtered Skeleton & Branch Points (Thickened) ---
- background_filt = rescale_intensity(cd31_img, out_range=(0,1))
- overlay_filt = np.stack([background_filt]*3, axis=-1)
- # Draw skeleton first (lime green)
- if skeleton_filtered is not None:
- dilated_skeleton_filt = morphology.binary_dilation(skeleton_filtered, footprint=morphology.disk(SKELETON_LINE_THICKNESS_PX))
- overlay_filt[dilated_skeleton_filt] = [0.0, 1.0, 0.0] # Lime Green
- # Draw branch points on top (red)
- if branch_points_mask is not None and np.any(branch_points_mask):
- dilated_branch_mask = morphology.binary_dilation(branch_points_mask, footprint=morphology.disk(BRANCH_POINT_MARKER_RADIUS_PX))
- overlay_filt[dilated_branch_mask] = [1.0, 0.0, 0.0] # Red
- ax[5].imshow(overlay_filt)
- ax[5].set_title(f'FILTERED Skel (L={filtered_skeleton_length_um:.0f}µm) & Br ({num_branch_points})')
- ax[5].axis('off')
- # if branch_points_mask is not None and np.any(branch_points_mask): skel_overlay_filt[branch_points_mask] = (1,0,0)
- # ax[5].imshow(skel_overlay_filt); ax[5].set_title(f'FILTERED Skel (L={filtered_skeleton_length_um:.0f}µm) & Br ({num_branch_points})'); ax[5].axis('off')
- plt.tight_layout(rect=[0, 0.03, 1, 0.95])
- offset_str = f"{adaptive_offset:.4f}".replace('.', 'p').replace('-', 'neg')
- min_len_str = f"minLen{MIN_VESSEL_SEGMENT_LENGTH_UM:.1f}um".replace('.','p') if MIN_VESSEL_SEGMENT_LENGTH_UM is not None and MIN_VESSEL_SEGMENT_LENGTH_UM > 0 else "minLenOff"
- min_width_str = f"minWidth{MIN_VESSEL_WIDTH_UM:.1f}um".replace('.','p') if MIN_VESSEL_WIDTH_UM is not None and MIN_VESSEL_WIDTH_UM > 0 else "minWidthOff"
- sigma_fn_part = f"sigmas_{param_sigma_start_um}-{param_sigma_stop_um}s{param_sigma_step_um}um".replace('.','p')
- block_fn_part = f"block{adaptive_block_size_um}um".replace('.', 'p')
- output_fig_path = os.path.join(OUTPUT_PLOT_FOLDER, f"{os.path.splitext(os.path.basename(image_path))[0]}_{sigma_fn_part}_{block_fn_part}_offset{offset_str}_{min_width_str}_{min_len_str}_analysis.png")
- plt.savefig(output_fig_path, dpi=450)
- plt.close(fig)
- except Exception as plot_err:
- print(f"!!!! Warning: Could not generate plot for {run_id}. Error: {plot_err} !!!!")
- traceback.print_exc()
- if plt.gcf().get_axes(): plt.close(plt.gcf())
- except Exception as e:
- print(f"!!!! TASK FAILED: {run_id}. Error: {e} !!!!")
- traceback.print_exc()
- results['error_message'] = f"Task Failed: {str(e)}"
- end_time = time.time()
- status = "FAILED" if results['error_message'] else "finished"
- print(f"--- Task {run_id} {status} in {end_time - start_time:.2f} seconds ---")
- return results
- def load_image(path):
- """Loads a bio-image (TIFF, CZI, etc.) using aicsimageio and extracts pixel size."""
- try:
- img_aics = AICSImage(path)
- dims_order = img_aics.dims.order
- has_c = 'C' in dims_order
- has_y = 'Y' in dims_order
- has_x = 'X' in dims_order
- if has_c and has_y and has_x:
- image_stack = img_aics.get_image_data("CYX", T=0, Z=0)
- elif has_y and has_x:
- print(f"Warning: Image {os.path.basename(path)} seems 2D (missing C dimension). Loading as YX.")
- image_stack = img_aics.get_image_data("YX", T=0, Z=0)
- else:
- print(f"Error: Image {os.path.basename(path)} missing Y or X dimension. Cannot process.")
- return None, None
- pixel_size_xy_um = ASSUMED_PIXEL_SIZE_UM
- if FORCE_ASSUMED_PIXEL_SIZE:
- print(f"Info: FORCE_ASSUMED_PIXEL_SIZE is True. Using assumed value: {ASSUMED_PIXEL_SIZE_UM} µm.")
- else:
- pixel_size_x_um = img_aics.physical_pixel_sizes.X
- pixel_size_y_um = img_aics.physical_pixel_sizes.Y
- if pixel_size_x_um is None or pixel_size_y_um is None:
- print(f"Warning: Could not read pixel size from image metadata (e.g., common for standard TIFF files). Using assumed value: {pixel_size_xy_um} µm.")
- elif not np.isclose(pixel_size_x_um, pixel_size_y_um):
- print(f"Warning: Anisotropic pixel size in {os.path.basename(path)} metadata (X: {pixel_size_x_um}, Y: {pixel_size_y_um}). Using assumed value: {pixel_size_xy_um} µm.")
- else:
- # Only use the file's pixel size if it's not being forced and it's valid.
- pixel_size_xy_um = pixel_size_x_um
- print(f"Image loaded: {os.path.basename(path)}, shape={image_stack.shape}, dtype={image_stack.dtype}, using pixel_size={pixel_size_xy_um:.4f} µm")
- return image_stack, pixel_size_xy_um
- except FileNotFoundError:
- print(f"Error: Image file not found at {path}")
- return None, None
- except Exception as e:
- print(f"Error loading image {path}: {e}")
- traceback.print_exc()
- return None, None
- # --- Main Execution Logic (Updated for Micrometer Parameters) ---
- if __name__ == "__main__":
- all_results = []
- master_start_time = time.time()
- # ### CHANGED ### - Search for .tif and .tiff files instead of .czi
- image_files = sorted([f for f in os.listdir(DATA_FOLDER) if f.lower().endswith(('.tif', '.tiff'))])
- if not image_files:
- print(f"Error: No .tif or .tiff files found in {DATA_FOLDER}")
- exit()
- # ### CHANGED ### - Updated print statement
- print(f"Found {len(image_files)} image files. Generating analysis tasks...")
- tasks_to_run = []
- # ### CHANGED ### - Loop over `image_files` instead of `czi_files` and handle missing ROIs
- for image_file in image_files:
- base_name = os.path.splitext(image_file)[0]
- image_path = os.path.join(DATA_FOLDER, image_file)
- # Check for case-insensitive geojson file
- geojson_path_options = [
- os.path.join(DATA_FOLDER, base_name + '.geojson'),
- os.path.join(DATA_FOLDER, base_name + '.GEOJSON')
- ]
- geojson_path = None
- for path_option in geojson_path_options:
- if os.path.exists(path_option):
- geojson_path = path_option
- break
- # ### CHANGED ### - This logic now adds a task REGARDLESS of whether an ROI is found.
- # If geojson_path is None, the analysis function will use the full image.
- if geojson_path is None:
- print(f"--- NOTE: No matching GeoJSON for '{base_name}'. Will analyze full image. ---")
- # Iterate over the new micrometer-based parameter lists
- param_combinations = list(itertools.product(
- VESSELNESS_SIGMA_RANGES_TO_TEST_UM,
- BLOCK_SIZES_TO_TEST_UM,
- OFFSETS_TO_TEST
- ))
- for sigma_range_um, block_size_um, offset in param_combinations:
- # ### CHANGED ### - Append `image_path` to tasks, and `geojson_path` can now be None
- tasks_to_run.append((image_path, geojson_path, sigma_range_um, block_size_um, offset))
- if not tasks_to_run:
- print("Error: No analysis tasks were generated. Check for images in the folder and parameter settings.")
- else:
- num_tasks = len(tasks_to_run)
- num_images = len(image_files)
- print(f"Generated {num_tasks} analysis tasks from {num_images} image file(s).")
- print(f"Starting parallel execution with {NUM_WORKERS} workers...")
- completed_count = 0
- with concurrent.futures.ProcessPoolExecutor(max_workers=NUM_WORKERS) as executor:
- # ### CHANGED ### - Call the renamed `analyze_image_roi` function
- future_to_task_args = {executor.submit(analyze_image_roi, *args): args for args in tasks_to_run}
- for future in concurrent.futures.as_completed(future_to_task_args):
- task_args = future_to_task_args[future]
- try:
- result_data = future.result()
- all_results.append(result_data)
- except Exception as exc:
- print(f'\n!!!! Task for {os.path.basename(task_args[0])} with params (sigma_range_um={task_args[2]}, block_um={task_args[3]}, offset={task_args[4]}) failed unexpectedly at executor level: {exc} !!!!')
- traceback.print_exc()
- (failed_sigma_start, failed_sigma_stop, failed_sigma_step) = task_args[2]
- # ### CHANGED ### - Update dictionary key for failed tasks
- all_results.append({
- 'filename_image': os.path.basename(task_args[0]),
- 'filename_geojson': os.path.basename(task_args[1]) if task_args[1] else 'N/A (Full Image)',
- 'vesselness_sigma_start_um': failed_sigma_start,
- 'vesselness_sigma_stop_um': failed_sigma_stop,
- 'vesselness_sigma_step_um': failed_sigma_step,
- 'adaptive_block_size_um': task_args[3],
- 'adaptive_offset': task_args[4],
- 'min_vessel_width_um_param': MIN_VESSEL_WIDTH_UM,
- 'min_vessel_segment_length_um_param': MIN_VESSEL_SEGMENT_LENGTH_UM,
- 'error_message': f'Executor level failure: {exc}'
- })
- finally:
- completed_count += 1
- print(f"Progress: {completed_count}/{num_tasks} tasks completed.", end='\r' if completed_count < num_tasks else '\n')
- print(f"Parallel execution finished. Processed {completed_count} tasks.")
- if all_results:
- print(f"\n--- Consolidating {len(all_results)} results for CSV output. ---")
- results_df = pd.DataFrame(all_results)
- # ### CHANGED ### - Update column name for output CSV
- column_order = [
- 'filename_image', 'filename_geojson',
- 'vesselness_sigma_start_um', 'vesselness_sigma_stop_um', 'vesselness_sigma_step_um',
- 'adaptive_block_size_um', 'adaptive_offset',
- 'min_vessel_width_um_param', 'min_vessel_segment_length_um_param',
- 'pixel_size_um',
- 'roi_area_pixels', 'roi_area_um2', 'roi_area_mm2',
- 'vessel_area_pixels', 'vessel_area_um2', 'vaf_percent',
- 'mean_vessel_diameter_um',
- 'raw_skeleton_pixels', 'raw_skeleton_length_um',
- 'segments_analyzed', 'segments_kept',
- 'filtered_skeleton_pixels', 'filtered_skeleton_length_um',
- 'filtered_branch_points_count', 'filtered_branch_point_density_mm2',
- 'nuclei_count', 'nuclear_density_mm2',
- 'error_message'
- ]
- for col in column_order:
- if col not in results_df.columns:
- results_df[col] = pd.NA
- results_df = results_df.reindex(columns=column_order)
- output_csv_path = os.path.join(DATA_FOLDER, OUTPUT_CSV_FILENAME)
- try:
- # ### CHANGED ### - Update sort key
- results_df.sort_values(
- by=['filename_image', 'vesselness_sigma_start_um', 'vesselness_sigma_step_um', 'adaptive_block_size_um', 'adaptive_offset'],
- inplace=True, na_position='last'
- )
- results_df.to_csv(output_csv_path, index=False, float_format='%.5f')
- print(f"Results successfully saved to: {output_csv_path}")
- except Exception as e:
- print(f"!!!! Error saving CSV file to {output_csv_path}: {e} !!!!")
- traceback.print_exc()
- else:
- print("\nNo results were generated or collected.")
- master_end_time = time.time()
- print(f"\nTotal execution time: {master_end_time - master_start_time:.2f} seconds.")
- print("--- Script Finished ---")
adaptive_vascular_analysis.py, under CC-BY-4.0 · at the source
Overview
- Department of Molecular, Cell, and Systems Biology, University of California – Riverside, Riverside, California 92521
- Neuroscience Graduate Program, University of California – Riverside, Riverside, California 92521
- Laboratory of Neural Connectivity, Brain Research Institute, Faculties of Medicine and Science, University of Zürich, Zurich, Switzerland
- Department of Regenerative Medicine and Cell Biology, Medical University of South Carolina, Charleston, South Carolina 29425
Abstract
Central nervous system development requires parallel but interrelated processes of neural circuit assembly and vascularization. Intersecting between these two processes is the cell-adhesion G-protein coupled receptor Adgrl2. In select neuronal populations, Adgrl2 is localized and control the assembly of specific synaptic sites. In non-neuronal brain cells, Adgrl2 is restricted in expression to endothelial cells. Testing for Adgrl2 function in these cells in mice (of either sex), here we find that endothelial cell-specific Adgrl2 deletion results in an impairment in cerebrovascular integrity. To understand how it might be possible for Adgrl2 to function independently in neuronal and endothelial contexts, we surveyed Adgrl2 transcripts within these cell classes. By analyzing single-cell RNA sequencing datasets, we find that Adgrl2 mRNA is subject to robust cell type-specific alternative splicing that results in distinct isoforms being produced in neurons compared with endothelial cells. To probe the functional significance of this alternative splicing, we forced expression of the neuronal isoform of Adgrl2 in endothelial cells. This resulted in altered cerebrovascular properties including the formation of ectopic glutamatergic synaptic contacts onto endothelial cells, indicating alterations in the cell–cell recognition process. Functionally, in direct contrast to endothelial Adgrl2 deletion, this genetic expression switch instead enhances blood–brain barrier integrity. This overly restrictive cerebrovascular function results in dysregulation of blood to cerebrospinal fluid homeostasis, enlargement of brain ventricles, and a higher risk of hydrocephalus. Thus, alternative splicing serves as a cell type-specific mechanism that provides isoform-specific Adgrl2 for discerning functions controlling neural circuit assembly and cerebrovascular homeostasis.
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 2 matches between paragraphs and lines of code.
Zenodo 15802164
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
- 29 September 2026: the link answers (HTTP 200)
1 file
- adaptive_vascular_analys
is.py , Python, 785 lines
AllenCellModeling/aicsimageio
8dfaaba9893c0ee5931938a0def3a4d93a5d13eb, 1 December 2025Availability: 1 check, the latest on 29 September 2026: the link answers
- 29 September 2026: the link answers
80 files
- aicsimageio/
__init__.py , Python, 20 lines - aicsimageio/
aics_image.py , Python, 1,166 lines - aicsimageio/
constants.py , Python, 7 lines - aicsimageio/
dimensions.py , Python, 165 lines - aicsimageio/
exceptions.py , Python, 45 lines - aicsimageio/
formats.py , Python, 491 lines - aicsimageio/
image_container.py , Python, 85 lines - aicsimageio/
metadata/ , Python, 2 lines__init__.py - aicsimageio/
metadata/ , Python, 727 linesutils.py - aicsimageio/
readers/ , Python, 50 lines__init__.py - aicsimageio/
readers/ , Python, 456 linesarray_like_reader.py - aicsimageio/
readers/ , Python, 299 linesbfio_reader.py - aicsimageio/
readers/ , Python, 656 linesbioformats_reader.py - aicsimageio/
readers/ , Python, 1,031 linesczi_reader.py - aicsimageio/
readers/ , Python, 556 linesdefault_reader.py - aicsimageio/
readers/ , Python, 100 linesdv_reader.py - aicsimageio/
readers/ , Python, 881 lineslif_reader.py - aicsimageio/
readers/ , Python, 134 linesnd2_reader.py - aicsimageio/
readers/ , Python, 400 linesome_tiff_reader.py - aicsimageio/
readers/ , Python, 220 linesome_zarr_reader.py - aicsimageio/
readers/ , Python, 970 linesreader.py - aicsimageio/
readers/ , Python, 295 linessldy_reader/ __init__.py - aicsimageio/
readers/ , Python, 301 linessldy_reader/ sldy_image.py - aicsimageio/
readers/ , Python, 625 linestiff_glob_reader.py - aicsimageio/
readers/ , Python, 601 linestiff_reader.py - aicsimageio/
tests/ , Python, 3 lines__init__.py - aicsimageio/
tests/ , Python, 52 linesconftest.py - aicsimageio/
tests/ , Python, 326 linesimage_container_test_uti ls.py - aicsimageio/
tests/ , Python, 2 linesmetadata/ __init__.py - aicsimageio/
tests/ , Python, 2 linesreaders/ __init__.py - aicsimageio/
tests/ , Python, 2 linesreaders/ extra_readers/ __init__.py - aicsimageio/
tests/ , Python, 2 linesreaders/ extra_readers/ sldy_reader/ __init__.py - aicsimageio/
tests/ , Python, 103 linesreaders/ extra_readers/ sldy_reader/ test_sldy_image.py - aicsimageio/
tests/ , Python, 144 linesreaders/ extra_readers/ sldy_reader/ test_sldy_reader.py - aicsimageio/
tests/ , Python, 555 linesreaders/ extra_readers/ test_bioformats_reader.p y - aicsimageio/
tests/ , Python, 818 linesreaders/ extra_readers/ test_czi_reader.py - aicsimageio/
tests/ , Python, 308 linesreaders/ extra_readers/ test_default_reader.py - aicsimageio/
tests/ , Python, 141 linesreaders/ extra_readers/ test_dv_reader.py - aicsimageio/
tests/ , Python, 632 linesreaders/ extra_readers/ test_lif_reader.py - aicsimageio/
tests/ , Python, 272 linesreaders/ extra_readers/ test_nd2_reader.py - aicsimageio/
tests/ , Python, 234 linesreaders/ extra_readers/ test_ome_tiled_tiff_read er.py - aicsimageio/
tests/ , Python, 218 linesreaders/ extra_readers/ test_ome_zarr_reader.py - aicsimageio/
tests/ , Python, 1,142 linesreaders/ test_array_like_reader.p y - aicsimageio/
tests/ , Python, 253 linesreaders/ test_glob_reader.py - aicsimageio/
tests/ , Python, 853 linesreaders/ test_ome_tiff_reader.py - aicsimageio/
tests/ , Python, 754 linesreaders/ test_tiff_reader.py - aicsimageio/
tests/ , Python, 29 linestest_aics_image.py - aicsimageio/
tests/ , Python, 77 linestest_dimensions.py - aicsimageio/
tests/ , Python, 552 linestest_transforms.py - aicsimageio/
tests/ , Python, 2 linesutils/ __init__.py - aicsimageio/
tests/ , Python, 35 linesutils/ test_io_utils.py - aicsimageio/
tests/ , Python, 2 lineswriters/ __init__.py - aicsimageio/
tests/ , Python, 2 lineswriters/ extra_writers/ __init__.py - aicsimageio/
tests/ , Python, 157 lineswriters/ extra_writers/ test_timeseries_writer.p y - aicsimageio/
tests/ , Python, 83 lineswriters/ extra_writers/ test_two_d_writer.py - aicsimageio/
tests/ , Python, 468 lineswriters/ test_ome_tiff_writer.py - aicsimageio/
tests/ , Python, 217 lineswriters/ test_ome_zarr_writer.py - aicsimageio/
transforms.py , Python, 401 lines - aicsimageio/
types.py , Python, 26 lines - aicsimageio/
utils/ , Python, 2 lines__init__.py - aicsimageio/
utils/ , Python, 62 linesio_utils.py - aicsimageio/
writers/ , Python, 5 lines__init__.py - aicsimageio/
writers/ , Python, 714 linesome_tiff_writer.py - aicsimageio/
writers/ , Python, 423 linesome_zarr_writer.py - aicsimageio/
writers/ , Python, 230 linestimeseries_writer.py - aicsimageio/
writers/ , Python, 147 linestwo_d_writer.py - aicsimageio/
writers/ , Python, 47 lineswriter.py - benchmarks/
__init__.py , Python, 1 line - benchmarks/
benchmark_chunk_sizes.py , Python, 93 lines - benchmarks/
benchmark_image_containe , Python, 233 linesrs.py - benchmarks/
benchmark_lib.py , Python, 49 lines - docs/
_fix_internal_links.py , Python, 108 lines - docs/
conf.py , Python, 188 lines - presentations/
2021-dask-life-sciences/ , Jupyter, 219 linespresentation.ipynb - scripts/
download_test_resources. , Python, 117 linespy - scripts/
makezarr.ipynb , Jupyter, 115 lines - scripts/
upload_test_resources.py , Python, 168 lines - setup.py, Python, 177 lines
- LICENSE, License, 30 lines
- README.md, Text, 365 lines
shapely/shapely
30c0a51039d4b4b0b3b74ba117039e2c5849906b, 29 September 2026Availability: 1 check, the latest on 29 September 2026: the link answers
- 29 September 2026: the link answers
224 files
- benchmarks/
__init__.py , Python, 1 line - benchmarks/
benchmarks.py , Python, 374 lines - ci/
install_geos.sh , Shell, 64 lines - docs/
code/ , Python, 35 linesbuffer.py - docs/
code/ , Python, 35 linesbuffer_single_side.py - docs/
code/ , Python, 35 linesconvex_hull.py - docs/
code/ , Python, 53 linescoverage_simplify.py - docs/
code/ , Python, 38 linesdifference.py - docs/
code/ , Python, 30 linesfigures.py - docs/
code/ , Python, 39 linesgeometrycollection.py - docs/
code/ , Python, 38 linesintersection-sym-differe nce.py - docs/
code/ , Python, 31 lineslinearring.py - docs/
code/ , Python, 33 lineslinestring.py - docs/
code/ , Python, 28 linesmake_valid_geometrycolle ction.py - docs/
code/ , Python, 57 linesmake_valid_methods.py - docs/
code/ , Python, 27 linesmake_valid_multipolygon. py - docs/
code/ , Python, 33 linesminimum_rotated_rectangl e.py - docs/
code/ , Python, 36 linesmultilinestring.py - docs/
code/ , Python, 39 linesmultipolygon.py - docs/
code/ , Python, 58 linesparallel_offset.py - docs/
code/ , Python, 58 linesparallel_offset_mitre.py - docs/
code/ , Python, 36 linespolygon.py - docs/
code/ , Python, 37 linespolygon2.py - docs/
code/ , Python, 34 linesrotate.py - docs/
code/ , Python, 38 linesscale.py - docs/
code/ , Python, 35 linessimplify.py - docs/
code/ , Python, 51 linesskew.py - docs/
code/ , Python, 22 linestriangulate.py - docs/
code/ , Python, 32 linesunary_union.py - docs/
code/ , Python, 38 linesunion.py - docs/
code/ , Python, 22 linesvoronoi_diagram.py - docs/
conf.py , Python, 143 lines - generate_version.py, Python, 79 lines
- src/
shapely/ , Python, 54 lines__init__.py - src/
shapely/ , Python, 275 lines_coverage.py - src/
shapely/ , Python, 32 lines_enum.py - src/
shapely/ , Python, 1,121 lines_geometry.py - src/
shapely/ , Python, 475 lines_ragged_array.py - src/
shapely/ , Python, 266 linesaffinity.py - src/
shapely/ , Python, 1 linealgorithms/ __init__.py - src/
shapely/ , Python, 56 linesalgorithms/ _oriented_envelope.py - src/
shapely/ , Python, 50 linesalgorithms/ cga.py - src/
shapely/ , Python, 43 linesalgorithms/ polylabel.py - src/
shapely/ , Python, 70 linesconftest.py - src/
shapely/ , Python, 1,614 linesconstructive.py - src/
shapely/ , Python, 463 linescoordinates.py - src/
shapely/ , Python, 119 linescoords.py - src/
shapely/ , Python, 854 linescreation.py - src/
shapely/ , Python, 194 linesdecorators.py - src/
shapely/ , Python, 79 lineserrors.py - src/
shapely/ , Python, 27 linesgeometry/ __init__.py - src/
shapely/ , Python, 1,252 linesgeometry/ base.py - src/
shapely/ , Python, 63 linesgeometry/ collection.py - src/
shapely/ , Python, 154 linesgeometry/ geo.py - src/
shapely/ , Python, 216 linesgeometry/ linestring.py - src/
shapely/ , Python, 100 linesgeometry/ multilinestring.py - src/
shapely/ , Python, 109 linesgeometry/ multipoint.py - src/
shapely/ , Python, 135 linesgeometry/ multipolygon.py - src/
shapely/ , Python, 171 linesgeometry/ point.py - src/
shapely/ , Python, 364 linesgeometry/ polygon.py - src/
shapely/ , Python, 17 linesgeos.py - src/
shapely/ , Python, 413 linesio.py - src/
shapely/ , C, 39 lineslib/ c_api.c - src/
shapely/ , C/C++, 107 lineslib/ c_api.h - src/
shapely/ , C, 656 lineslib/ coords.c - src/
shapely/ , C/C++, 13 lineslib/ coords.h - src/
shapely/ , C/C++, 113 lineslib/ fast_loop_macros.h - src/
shapely/ , C, 38 lineslib/ geom_arr.c - src/
shapely/ , C/C++, 14 lineslib/ geom_arr.h - src/
shapely/ , C, 1,218 lineslib/ geos.c - src/
shapely/ , C/C++, 237 lineslib/ geos.h - src/
shapely/ , C, 284 lineslib/ geos_funcs_O_b.c - src/
shapely/ , C/C++, 6 lineslib/ geos_funcs_O_b.h - src/
shapely/ , C, 201 lineslib/ geos_funcs_YYO_b.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YYO_b.h - src/
shapely/ , C, 155 lineslib/ geos_funcs_YY_O.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YY_O.h - src/
shapely/ , C, 334 lineslib/ geos_funcs_YY_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YY_Y.h - src/
shapely/ , C, 304 lineslib/ geos_funcs_YY_b.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YY_b.h - src/
shapely/ , C, 292 lineslib/ geos_funcs_YY_d.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YY_d.h - src/
shapely/ , C, 269 lineslib/ geos_funcs_YYd_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YYd_Y.h - src/
shapely/ , C, 269 lineslib/ geos_funcs_YYd_b.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YYd_b.h - src/
shapely/ , C, 265 lineslib/ geos_funcs_YYd_d.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_YYd_d.h - src/
shapely/ , C, 151 lineslib/ geos_funcs_Y_O.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Y_O.h - src/
shapely/ , C, 370 lineslib/ geos_funcs_Y_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Y_Y.h - src/
shapely/ , C, 315 lineslib/ geos_funcs_Y_b.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Y_b.h - src/
shapely/ , C, 340 lineslib/ geos_funcs_Y_d.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Y_d.h - src/
shapely/ , C, 285 lineslib/ geos_funcs_Y_i.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Y_i.h - src/
shapely/ , C, 369 lineslib/ geos_funcs_Yd_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Yd_Y.h - src/
shapely/ , C, 346 lineslib/ geos_funcs_Ydb_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Ydb_Y.h - src/
shapely/ , C, 291 lineslib/ geos_funcs_Ydd_b.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Ydd_b.h - src/
shapely/ , C, 246 lineslib/ geos_funcs_Ydddd_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Ydddd_Y.h - src/
shapely/ , C, 279 lineslib/ geos_funcs_Ydi_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Ydi_Y.h - src/
shapely/ , C, 405 lineslib/ geos_funcs_Yi_Y.c - src/
shapely/ , C/C++, 8 lineslib/ geos_funcs_Yi_Y.h - src/
shapely/ , C/C++, 92 lineslib/ kvec.h - src/
shapely/ , C, 209 lineslib/ lib.c - src/
shapely/ , C, 498 lineslib/ pygeom.c - src/
shapely/ , C/C++, 29 lineslib/ pygeom.h - src/
shapely/ , C, 252 lineslib/ pygeos.c - src/
shapely/ , C/C++, 8 lineslib/ pygeos.h - src/
shapely/ , C, 17 lineslib/ signal_checks.c - src/
shapely/ , C/C++, 53 lineslib/ signal_checks.h - src/
shapely/ , C, 1,210 lineslib/ strtree.c - src/
shapely/ , C/C++, 57 lineslib/ strtree.h - src/
shapely/ , C, 1,997 lineslib/ ufuncs.c - src/
shapely/ , C/C++, 9 lineslib/ ufuncs.h - src/
shapely/ , C, 42 lineslib/ vector.c - src/
shapely/ , C/C++, 24 lineslib/ vector.h - src/
shapely/ , Python, 233 lineslinear.py - src/
shapely/ , Python, 350 linesmeasurement.py - src/
shapely/ , Python, 712 linesops.py - src/
shapely/ , Python, 222 linesplotting.py - src/
shapely/ , Python, 1,391 linespredicates.py - src/
shapely/ , Python, 74 linesprepared.py - src/
shapely/ , Python, 775 linesset_operations.py - src/
shapely/ , Python, 39 linesspeedups.py - src/
shapely/ , Python, 542 linesstrtree.py - src/
shapely/ , Python, 208 linestesting.py - src/
shapely/ , Python, 1 linetests/ __init__.py - src/
shapely/ , Python, 283 linestests/ common.py - src/
shapely/ , Python, 1 linetests/ geometry/ __init__.py - src/
shapely/ , Python, 90 linestests/ geometry/ test_collection.py - src/
shapely/ , Python, 127 linestests/ geometry/ test_coords.py - src/
shapely/ , Python, 117 linestests/ geometry/ test_decimal.py - src/
shapely/ , Python, 98 linestests/ geometry/ test_emptiness.py - src/
shapely/ , Python, 273 linestests/ geometry/ test_equality.py - src/
shapely/ , Python, 98 linestests/ geometry/ test_format.py - src/
shapely/ , Python, 431 linestests/ geometry/ test_geometry_base.py - src/
shapely/ , Python, 28 linestests/ geometry/ test_hash.py - src/
shapely/ , Python, 232 linestests/ geometry/ test_linestring.py - src/
shapely/ , Python, 11 linestests/ geometry/ test_multi.py - src/
shapely/ , Python, 77 linestests/ geometry/ test_multilinestring.py - src/
shapely/ , Python, 97 linestests/ geometry/ test_multipoint.py - src/
shapely/ , Python, 189 linestests/ geometry/ test_multipolygon.py - src/
shapely/ , Python, 201 linestests/ geometry/ test_point.py - src/
shapely/ , Python, 467 linestests/ geometry/ test_polygon.py - src/
shapely/ , Python, 1 linetests/ legacy/ __init__.py - src/
shapely/ , Python, 12 linestests/ legacy/ conftest.py - src/
shapely/ , Python, 308 linestests/ legacy/ test_affinity.py - src/
shapely/ , Python, 20 linestests/ legacy/ test_box.py - src/
shapely/ , Python, 173 linestests/ legacy/ test_buffer.py - src/
shapely/ , Python, 51 linestests/ legacy/ test_cga.py - src/
shapely/ , Python, 119 linestests/ legacy/ test_clip_by_rect.py - src/
shapely/ , Python, 217 linestests/ legacy/ test_create_inconsistent _dimensionality.py - src/
shapely/ , Python, 32 linestests/ legacy/ test_delaunay.py - src/
shapely/ , Python, 22 linestests/ legacy/ test_empty_polygons.py - src/
shapely/ , Python, 24 linestests/ legacy/ test_equality.py - src/
shapely/ , Python, 118 linestests/ legacy/ test_geointerface.py - src/
shapely/ , Python, 26 linestests/ legacy/ test_invalid_geometries. py - src/
shapely/ , Python, 72 linestests/ legacy/ test_linear_referencing. py - src/
shapely/ , Python, 43 linestests/ legacy/ test_linemerge.py - src/
shapely/ , Python, 52 linestests/ legacy/ test_locale.py - src/
shapely/ , Python, 15 linestests/ legacy/ test_make_valid.py - src/
shapely/ , Python, 14 linestests/ legacy/ test_mapping.py - src/
shapely/ , Python, 30 linestests/ legacy/ test_minimum_clearance.p y - src/
shapely/ , Python, 42 linestests/ legacy/ test_ndarrays.py - src/
shapely/ , Python, 18 linestests/ legacy/ test_nearest.py - src/
shapely/ , Python, 124 linestests/ legacy/ test_operations.py - src/
shapely/ , Python, 60 linestests/ legacy/ test_operators.py - src/
shapely/ , Python, 92 linestests/ legacy/ test_orient.py - src/
shapely/ , Python, 60 linestests/ legacy/ test_parallel_offset.py - src/
shapely/ , Python, 48 linestests/ legacy/ test_persist.py - src/
shapely/ , Python, 81 linestests/ legacy/ test_pickle.py - src/
shapely/ , Python, 43 linestests/ legacy/ test_polygonize.py - src/
shapely/ , Python, 85 linestests/ legacy/ test_polylabel.py - src/
shapely/ , Python, 95 linestests/ legacy/ test_predicates.py - src/
shapely/ , Python, 65 linestests/ legacy/ test_prepared.py - src/
shapely/ , Python, 13 linestests/ legacy/ test_products_z.py - src/
shapely/ , Python, 63 linestests/ legacy/ test_shape.py - src/
shapely/ , Python, 45 linestests/ legacy/ test_shared_paths.py - src/
shapely/ , Python, 15 linestests/ legacy/ test_singularity.py - src/
shapely/ , Python, 24 linestests/ legacy/ test_snap.py - src/
shapely/ , Python, 331 linestests/ legacy/ test_split.py - src/
shapely/ , Python, 220 linestests/ legacy/ test_substring.py - src/
shapely/ , Python, 213 linestests/ legacy/ test_svg.py - src/
shapely/ , Python, 116 linestests/ legacy/ test_transform.py - src/
shapely/ , Python, 67 linestests/ legacy/ test_union.py - src/
shapely/ , Python, 9 linestests/ legacy/ test_validation.py - src/
shapely/ , Python, 108 linestests/ legacy/ test_vectorized.py - src/
shapely/ , Python, 129 linestests/ legacy/ test_voronoi_diagram.py - src/
shapely/ , Python, 171 linestests/ legacy/ test_wkb.py - src/
shapely/ , Python, 61 linestests/ legacy/ test_wkt.py - src/
shapely/ , Python, 44 linestests/ legacy/ threading_test.py - src/
shapely/ , Python, 1,869 linestests/ test_constructive.py - src/
shapely/ , Python, 488 linestests/ test_coordinates.py - src/
shapely/ , Python, 520 linestests/ test_coverage.py - src/
shapely/ , Python, 771 linestests/ test_creation.py - src/
shapely/ , Python, 585 linestests/ test_creation_indices.py - src/
shapely/ , Python, 138 linestests/ test_decorators.py - src/
shapely/ , Python, 845 linestests/ test_geometry.py - src/
shapely/ , Python, 1,347 linestests/ test_io.py - src/
shapely/ , Python, 237 linestests/ test_linear.py - src/
shapely/ , Python, 368 linestests/ test_measurement.py - src/
shapely/ , Python, 228 linestests/ test_misc.py - src/
shapely/ , Python, 121 linestests/ test_plotting.py - src/
shapely/ , Python, 490 linestests/ test_predicates.py - src/
shapely/ , Python, 667 linestests/ test_ragged_array.py - src/
shapely/ , Python, 503 linestests/ test_set_operations.py - src/
shapely/ , Python, 1,950 linestests/ test_strtree.py - src/
shapely/ , Python, 97 linestests/ test_testing.py - src/
shapely/ , Python, 55 linesvalidation.py - src/
shapely/ , Python, 91 linesvectorized/ __init__.py - src/
shapely/ , Python, 70 lineswkb.py - src/
shapely/ , Python, 82 lineswkt.py - versioneer.py, Python, 2,205 lines
- LICENSE.txt, License, 29 lines
- README.rst, Text, 172 lines
Zenodo 15802163
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
- 29 September 2026: the link answers (HTTP 200)
1 file
- adaptive_vascular_analys
is.py , Python, 785 lines, 2 matches
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;
- 302 scripts, each with its path and the digest of its content;
- 2 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
- geo:GSE185862, at NCBI GEO; found in “Data Availability”
- github.com/
rvalieris/ , at github.com; found in the text, “scRNAseq data acquisition and processing”parallel-fastq-dump - portal.brain-map.org/
atlases-and-data/ , at Allen Brain Map; found in the text, “scRNAseq data acquisition and processing”rnaseq
Data Availability
Raw sequencing data used in this study are accessible from NCBI Gene Expression Omnibus database through accession numbers GSE185862 (https://
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, 29 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 9 authors, 5 keywords, 11 MeSH terms, 1 funder, 72 references.
Cite
This paper
King, A., Garcia, C., Blanton, C., Chen, A., Ahmad, A., Lukacsovich, D., Földy, C., Makita, T., & Anderson, G. R. (2026). Endothelial &
BibTeX
@article{king2026endothe
author = {King, Alexander and Garcia, Catherine and Blanton, Crisylle and Chen, Anna and Ahmad, Amna and Lukacsovich, David and Földy, Csaba and Makita, Takako and Anderson, Garret R},
title = {{Endothelial \&
journal = {The Journal of neuroscience : the official journal of the Society for Neuroscience},
year = {2026},
month = apr,
volume = {46},
number = {16},
pages = {e0019262026},
publisher = {Society for Neuroscience},
issn = {0270-6474},
doi = {10.1523/
url = {https://
pmid = {41876233},
pmcid = {PMC13108381}
}
RIS
TY - JOUR
AU - King, Alexander
AU - Garcia, Catherine
AU - Blanton, Crisylle
AU - Chen, Anna
AU - Ahmad, Amna
AU - Lukacsovich, David
AU - Földy, Csaba
AU - Makita, Takako
AU - Anderson, Garret R
TI - Endothelial &
T2 - The Journal of neuroscience : the official journal of the Society for Neuroscience
J2 - J Neurosci
PY - 2026
DA - 2026/
VL - 46
IS - 16
SP - e0019262026
SN - 0270-6474
PB - Society for Neuroscience
DO - 10.1523/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1523/
"type": "article-journal",
"title": "Endothelial &
"container-title": "The Journal of neuroscience : the official journal of the Society for Neuroscience",
"author": [
{
"family": "King",
"given": "Alexander"
},
{
"family": "Garcia",
"given": "Catherine"
},
{
"family": "Blanton",
"given": "Crisylle"
},
{
"family": "Chen",
"given": "Anna"
},
{
"family": "Ahmad",
"given": "Amna"
},
{
"family": "Lukacsovich",
"given": "David"
},
{
"family": "Földy",
"given": "Csaba"
},
{
"family": "Makita",
"given": "Takako"
},
{
"family": "Anderson",
"given": "Garret R"
}
],
"container-title-short":
"volume": "46",
"issue": "16",
"page": "e0019262026",
"DOI": "10.1523/
"PMID": "41876233",
"PMCID": "PMC13108381",
"ISSN": "0270-6474",
"publisher": "Society for Neuroscience",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
22
]
]
}
}
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-71619-1
- Structurally exclusive Teneurin complexes orchestrate divergent programs in early cortical development.Journal: Nature communicationsIn common: mouse, 10 references
- [2] doi:10.1038/s41467-026-73373-w [code]
- Mapping neuro-vascular unit communications reveals distinct angiogenic programs across developing mouse brain regions.Journal: Nature communicationsIn common: imageio, tifffile, scikit-image, 4 other tools, mouse, 3 references
- [3] doi:10.1016/j.cub.2026.04.038 [code]
- Ten3-Lphn2-mediated target selection across the extended hippocampal network demonstrates a repeated strategy for circuit assembly.Journal: Current biology : CBIn common: mouse, 7 references
- [4] doi:10.1016/j.isci.2026.116213 [code]
- Opioid receptor distribution in the claustrum-dorsal endopiriform complex.Journal: iScienceIn common: xarray, imageio, tifffile, 4 other tools, cellular / molecular, 1 reference
- [5] doi:10.1038/s41586-026-10679-1 [code]
- Cortical development dynamics across autism spectrum disorder mouse models.Journal: NatureIn common: imageio, tifffile, scikit-image, 4 other tools, mouse, cellular / molecular, 2 references
- [6] doi:10.1371/journal.pcbi.1014571 [code]
- SynAPSeg: A novel dataset and image analysis framework for deep learning-based synapse detection and quantification.Journal: PLoS computational biologyIn common: imageio, tifffile, scikit-image, 4 other tools, 2 references
- [7] doi:10.1016/j.celrep.2026.117255
- The atypical adhesion GPCR ADGRA1 controls hippocampal inhibitory circuit function.Journal: Cell reportsIn common: cellular / molecular, 6 references
- [8] doi:10.1016/j.isci.2026.115689 [code]
- Unperturbed dye-based imaging of spontaneous synchronized calcium activity in iPSC-derived neuronal cultures.Journal: iScienceIn common: xarray, imageio, tifffile, 4 other tools, cellular / molecular
- [9] doi:10.7554/elife.109717 [code]
- Retrosplenial cortex enables context-dependent goal-directed sensorimotor transformation.Journal: eLifeIn common: imageio, tifffile, scikit-image, 4 other tools, mouse, 1 reference
- [10] doi:10.3389/fnbeh.2026.1895371 [code]
- Discrete and differentiated encoding of distinct components of spatial experience occurs within the proximodistal subfields of the dorsoventral axis of the hippocampus.Journal: Frontiers in behavioral neuroscienceIn common: xarray, imageio, tifffile, 4 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, 302 scripts, and 2 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:318856d0cd810019…
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.
