Spatio-Temporal Dynamics of Macroglial Cell Organization and Proximity to Blood Vessels During Postnatal Development.
The 4 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
- [1] § Materials and Methods › Image Analysis ↔ src/main/java/VeCell_Tools/Tools.java, lines 1002–1064 · score 0.76 · standard deviation, Analyze Skeleton, branch length, junctions, neighbour, SDI
- [2] § Materials and Methods › Image Analysis ↔ src/main/java/VeCell_Tools/Cellpose/CellposeTask.java, the whole file · a weak match · score 0.73 · flow threshold, stitching threshold, pretrained model, Cellpose, diameter
- [3] § Materials and Methods › Image Analysis ↔ src/main/java/VeCell_Tools/Cellpose/CellposeTaskSettings.java, lines 61–126 · score 0.69 · cell probability, flow threshold, stitching threshold, Cellpose
- [4] § Materials and Methods › Image Analysis ↔ src/main/java/VeCell_Tools/Tools.java, lines 586–642 · score 0.51 · automated thresholding, Gaussian, median, CLIJ, filter
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
Java · 1,151 lines · 46 KB · no license · 2 matches
- package VeCell_Tools;
- import VeCell_Tools.Cellpose.CellposeTaskSettings;
- import VeCell_Tools.Cellpose.CellposeSegmentImgPlusAdvanced;
- import fiji.util.gui.GenericDialogPlus;
- import ij.IJ;
- import ij.ImagePlus;
- import ij.ImageStack;
- import ij.gui.Plot;
- import ij.gui.PolygonRoi;
- import ij.gui.Roi;
- import ij.io.FileSaver;
- import ij.measure.Calibration;
- import ij.measure.ResultsTable;
- import ij.plugin.ImageCalculator;
- import ij.plugin.RGBStackMerge;
- import ij.plugin.RoiEnlarger;
- import ij.plugin.RoiScaler;
- import ij.plugin.filter.Analyzer;
- import ij.plugin.filter.ParticleAnalyzer;
- import ij.plugin.frame.RoiManager;
- import ij.process.AutoThresholder;
- import java.awt.Color;
- import java.awt.Font;
- import java.io.BufferedWriter;
- import java.io.File;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.awt.Rectangle;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.IntStream;
- import javax.swing.ImageIcon;
- import loci.common.services.DependencyException;
- import loci.common.services.ServiceException;
- import loci.formats.FormatException;
- import loci.formats.meta.IMetadata;
- import loci.plugins.BF;
- import loci.plugins.in.ImporterOptions;
- import loci.plugins.util.ImageProcessorReader;
- import mcib3d.geom.Object3D;
- import mcib3d.geom.Objects3DPopulation;
- import mcib3d.image3d.ImageHandler;
- import mcib3d.geom2.Object3DInt;
- import mcib3d.geom2.Objects3DIntPopulation;
- import mcib3d.geom2.measurements.Measure2Distance;
- import mcib3d.geom2.measurements.MeasureCentroid;
- import mcib3d.geom2.measurements.MeasureIntensity;
- import mcib3d.geom2.measurements.MeasureVolume;
- import mcib3d.geom2.measurementsPopulation.MeasurePopulationDistance;
- import mcib3d.geom2.measurementsPopulation.PairObjects3DInt;
- import mcib3d.image3d.ImageFloat;
- import mcib3d.image3d.ImageInt;
- import mcib3d.image3d.ImageLabeller;
- import mcib3d.image3d.distanceMap3d.EDT;
- import mcib3d.spatial.descriptors.G_Function;
- import mcib3d.spatial.descriptors.SpatialDescriptor;
- import mcib3d.spatial.sampler.SpatialModel;
- import mcib3d.spatial.sampler.SpatialRandomHardCore;
- import mcib3d.utils.ThreadUtil;
- import net.haesleinhuepf.clij.clearcl.ClearCLBuffer;
- import net.haesleinhuepf.clij2.CLIJ2;
- import net.haesleinhuepf.clijx.bonej.BoneJSkeletonize3D;
- import org.apache.commons.io.FilenameUtils;
- import org.apache.commons.math3.stat.StatUtils;
- import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
- import sc.fiji.analyzeSkeleton.AnalyzeSkeleton_;
- import sc.fiji.analyzeSkeleton.Edge;
- import sc.fiji.analyzeSkeleton.Graph;
- import sc.fiji.analyzeSkeleton.Point;
- import sc.fiji.analyzeSkeleton.SkeletonResult;
- /**
- * @author ORION-CIRB
- */
- public class Tools {
- public final ImageIcon icon = new ImageIcon(this.getClass().getResource("/Orion_icon.png"));
- private final String helpUrl = "https://github.com/orion-cirb/VeCell/tree/version5";
- public CLIJ2 clij2 = CLIJ2.getInstance();
- private BufferedWriter resultsGlobal;
- private BufferedWriter resultsDetail;
- private Calibration cal;
- private double pixelVol;
- String[] chDialog = new String[]{"Astrocytes", "Vessels (optional)"};
- public int imgSeries = 0;
- public int roiScaling = 9;
- public double roiDilation = 50; // um
- public String cellposeEnvDir = IJ.isWindows()? System.getProperty("user.home")+File.separator+"miniconda3"+File.separator+"envs"+File.separator+"CellPose" : "/opt/miniconda3/envs/cellpose";
- public final String cellposeModelDir = IJ.isWindows()? System.getProperty("user.home")+File.separator+".cellpose"+File.separator+"models"+File.separator : "";
- public String cellposeModel = "cyto2_sox9_p5-15-60_27-11-24";
- public int cellposeDiam = 20;
- public double cellposeStitchTh = 0.5;
- public boolean filterOneZ = true;
- public double minCellVol = 300; // um3
- public double maxCellVol = 3000; // um3
- private int nbNei = 10; // K-nearest neighbors
- private boolean computeGFunction = false;
- private int nbRandomSamples = 50;
- private double dog1Sigma1 = 4;
- private double dog1Sigma2 = 8;
- private String vesselThMet1 = "Triangle";
- private boolean dog2 = true;
- private double dog2Sigma1 = 7;
- private double dog2Sigma2 = 14;
- private String vesselThMet2 = "Triangle";
- private double maxHoleArea = 100; // µm2
- public double minVesselVol = 600; // um3
- private double minVesselLength = 10; // um
- /**
- * Display a message in the ImageJ console and status bar
- */
- public void print(String log) {
- System.out.println(log);
- IJ.showStatus(log);
- }
- /**
- * Flush and close an image
- */
- public void closeImage(ImagePlus img) {
- img.flush();
- img.close();
- }
- /**
- * Check that needed modules are installed
- */
- public boolean checkInstalledModules() {
- ClassLoader loader = IJ.getClassLoader();
- try {
- loader.loadClass("net.haesleinhuepf.clij2.CLIJ2");
- } catch (ClassNotFoundException e) {
- IJ.log("CLIJ not installed, please install from update site");
- return false;
- }
- try {
- loader.loadClass("mcib3d.geom2.Object3DInt");
- } catch (ClassNotFoundException e) {
- IJ.log("3D ImageJ Suite not installed, please install from update site");
- return false;
- }
- return true;
- }
- /**
- * Get extension of the first image found in the folder
- */
- public String findImageType(File imagesFolder) {
- String ext = "";
- String[] files = imagesFolder.list();
- for (String name : files) {
- String fileExt = FilenameUtils.getExtension(name);
- switch (fileExt) {
- case "nd" :
- ext = fileExt;
- break;
- case "nd2" :
- ext = fileExt;
- break;
- case "lif" :
- ext = fileExt;
- break;
- case "czi" :
- ext = fileExt;
- break;
- case "ics" :
- ext = fileExt;
- break;
- case "ics2" :
- ext = fileExt;
- break;
- case "lsm" :
- ext = fileExt;
- break;
- case "tif" :
- ext = fileExt;
- break;
- case "tiff" :
- ext = fileExt;
- break;
- }
- }
- return(ext);
- }
- /**
- * Get images with given extension in folder
- */
- public ArrayList<String> findImages(String imagesFolder, String imageExt) {
- File inDir = new File(imagesFolder);
- String[] files = inDir.list();
- ArrayList<String> images = new ArrayList();
- for (String f : files) {
- String fileExt = FilenameUtils.getExtension(f);
- if (fileExt.equals(imageExt) && !f.startsWith("."))
- images.add(imagesFolder + f);
- }
- Collections.sort(images);
- return(images);
- }
- /**
- * Get image calibration
- */
- public void findImageCalib(IMetadata meta) {
- cal = new Calibration();
- cal.pixelWidth = meta.getPixelsPhysicalSizeX(0).value().doubleValue();
- cal.pixelHeight = cal.pixelWidth;
- if (meta.getPixelsPhysicalSizeZ(0) != null)
- cal.pixelDepth = meta.getPixelsPhysicalSizeZ(0).value().doubleValue();
- else
- cal.pixelDepth = 1;
- cal.setUnit("microns");
- System.out.println("XY calibration = " + cal.pixelWidth + ", Z calibration = " + cal.pixelDepth);
- }
- /**
- * Get channels name and add None at the end of channels list
- * @throws loci.common.services.DependencyException
- * @throws loci.common.services.ServiceException
- * @throws loci.formats.FormatException
- * @throws java.io.IOException
- */
- public String[] findChannels(String imageName, IMetadata meta, ImageProcessorReader reader) throws DependencyException, ServiceException, FormatException, IOException {
- int chs = reader.getSizeC();
- String[] channels = new String[chs+1];
- String imageExt = FilenameUtils.getExtension(imageName);
- switch (imageExt) {
- case "nd" :
- for (int n = 0; n < chs; n++)
- channels[n] = (meta.getChannelName(0, n).toString().equals("")) ? Integer.toString(n) : meta.getChannelName(0, n).toString();
- break;
- case "nd2" :
- for (int n = 0; n < chs; n++)
- channels[n] = (meta.getChannelName(0, n).toString().equals("")) ? Integer.toString(n) : meta.getChannelName(0, n).toString();
- break;
- case "lif" :
- for (int n = 0; n < chs; n++)
- if (meta.getChannelID(0, n) == null || meta.getChannelName(0, n) == null)
- channels[n] = Integer.toString(n);
- else
- channels[n] = meta.getChannelName(0, n).toString();
- break;
- case "czi" :
- for (int n = 0; n < chs; n++)
- channels[n] = (meta.getChannelFluor(0, n).toString().equals("")) ? Integer.toString(n) : meta.getChannelFluor(0, n).toString();
- break;
- case "ics" :
- for (int n = 0; n < chs; n++)
- channels[n] = meta.getChannelEmissionWavelength(0, n).value().toString();
- break;
- case "ics2" :
- for (int n = 0; n < chs; n++)
- channels[n] = meta.getChannelEmissionWavelength(0, n).value().toString();
- break;
- default :
- for (int n = 0; n < chs; n++)
- channels[n] = Integer.toString(n);
- }
- channels[chs] = "None";
- return(channels);
- }
- /**
- * Generate dialog box
- */
- public String[] dialog(String[] chMeta) {
- GenericDialogPlus gd = new GenericDialogPlus("Parameters");
- gd.setInsets(0, 180, 0);
- gd.addImage(icon);
- gd.addMessage("Channels", new Font("Monospace", Font.BOLD, 12), Color.blue);
- for (int n = 0; n < chDialog.length; n++)
- gd.addChoice(chDialog[n]+": ", chMeta, chMeta[n]);
- gd.addMessage("ROIs", new Font("Monospace", Font.BOLD, 12), Color.blue);
- gd.addNumericField("Scaling factor: ", roiScaling, 0);
- gd.addMessage("Astrocytes detection", new Font("Monospace", Font.BOLD, 12), Color.blue);
- gd.addStringField("Cellpose model: ", cellposeModel);
- gd.addToSameRow();
- gd.addNumericField("Cellpose diameter: ", cellposeDiam, 0);
- gd.addCheckbox("Delete single-slice cells", filterOneZ);
- gd.addNumericField("Min volume (µm3): ", minCellVol, 2);
- gd.addToSameRow();
- gd.addNumericField("Max volume (µm3): ", maxCellVol, 2);
- gd.addMessage("Astrocytes spatial distribution", new Font("Monospace", Font.BOLD, 12), Color.blue);
- gd.addNumericField("Neighbors nb: ", nbNei, 0);
- gd.addCheckbox("Compute G-function", computeGFunction);
- gd.addToSameRow();
- gd.addNumericField("Random samples nb: ", nbRandomSamples, 0);
- String[] methods = AutoThresholder.getMethods();
- gd.addMessage("Vessels segmentation", new Font("Monospace", Font.BOLD, 12), Color.blue);
- gd.addMessage("DoG filter 1", new Font("Monospace", Font.PLAIN, 12), Color.blue);
- gd.addNumericField("Sigma 1: ", dog1Sigma1, 2);
- gd.addToSameRow();
- gd.addNumericField("Sigma 2: ", dog1Sigma2, 2);
- gd.addChoice("Threshold: ", methods, vesselThMet1);
- gd.addMessage("DoG filter 2", new Font("Monospace", Font.PLAIN, 12), Color.blue);
- gd.addCheckbox("Apply filter", dog2);
- gd.addNumericField("Sigma 1: ", dog2Sigma1, 2);
- gd.addToSameRow();
- gd.addNumericField("Sigma 2: ", dog2Sigma2, 2);
- gd.addChoice("Threshold: ", methods, vesselThMet2);
- gd.addNumericField("Max hole area (µm2): ", maxHoleArea, 2);
- gd.addNumericField("Min volume (µm3): ", minVesselVol, 2);
- gd.addToSameRow();
- gd.addNumericField("Min length (µm): ", minVesselLength, 2);
- gd.addMessage("Image calibration", new Font("Monospace", Font.BOLD, 12), Color.blue);
- gd.addNumericField("XY pixel size (µm): ", cal.pixelWidth, 4);
- gd.addToSameRow();
- gd.addNumericField("Z pixel size (µm): ", cal.pixelDepth, 4);
- gd.addHelp(helpUrl);
- gd.showDialog();
- String[] chOrder = new String[chDialog.length];
- for (int n = 0; n < chOrder.length; n++)
- chOrder[n] = gd.getNextChoice();
- roiScaling = (int) gd.getNextNumber();
- if (roiScaling <= 0) {
- roiScaling = 1;
- print("ERROR: ROIs cannot be scaled by zero or negative values. ROI scaling factor set to 1.");
- }
- cellposeModel = gd.getNextString();
- cellposeDiam = (int) gd.getNextNumber();
- filterOneZ = gd.getNextBoolean();
- minCellVol = gd.getNextNumber();
- maxCellVol = gd.getNextNumber();
- nbNei = (int)gd.getNextNumber();
- computeGFunction = gd.getNextBoolean();
- nbRandomSamples = (int)gd.getNextNumber();
- dog1Sigma1 = (int) gd.getNextNumber();
- dog1Sigma2 = (int) gd.getNextNumber();
- vesselThMet1 = gd.getNextChoice();
- dog2 = gd.getNextBoolean();
- dog2Sigma1 = (int) gd.getNextNumber();
- dog2Sigma2 = (int) gd.getNextNumber();
- vesselThMet2 = gd.getNextChoice();
- maxHoleArea = gd.getNextNumber();
- minVesselVol = gd.getNextNumber();
- minVesselLength = gd.getNextNumber();
- cal.pixelWidth = cal.pixelHeight = gd.getNextNumber();
- cal.pixelDepth = gd.getNextNumber();
- pixelVol = cal.pixelWidth * cal.pixelHeight * cal.pixelDepth;
- if (gd.wasCanceled())
- chOrder = null;
- return(chOrder);
- }
- /**
- * Save images specific channel before sending it to QuantileBasedNormalization plugin
- * @throws Exception
- */
- public void saveChannel(ArrayList<String> imgFiles, int series, int channel, String normDir, String extension) throws Exception {
- try {
- for (String f : imgFiles) {
- String imgName = FilenameUtils.getBaseName(f);
- ImporterOptions options = new ImporterOptions();
- options.setId(f);
- options.setSplitChannels(true);
- options.setColorMode(ImporterOptions.COLOR_MODE_GRAYSCALE);
- options.setQuiet(true);
- // Open and save vessels channel
- ImagePlus imgVessels = openChannel(options, series, channel);
- IJ.saveAs(imgVessels, "Tiff", normDir+imgName+extension);
- closeImage(imgVessels);
- }
- } catch (Exception e) {
- throw e;
- }
- }
- public ImagePlus openChannel(ImporterOptions options, int series, int channel) throws FormatException, IOException {
- options.setCBegin(series, channel);
- options.setCEnd(series, channel);
- ImagePlus img = BF.openImagePlus(options)[0];
- return(img);
- }
- /**
- * Delete images specific channel after it was sent to QuantileBasedNormalization plugin
- * @throws Exception
- */
- public void deleteChannel(String dir, ArrayList<String> imageFiles, String extension) throws Exception {
- try {
- for (String f : imageFiles) {
- String rootName = FilenameUtils.getBaseName(f);
- new File(dir+rootName+extension).delete();
- }
- } catch (Exception e) {
- throw e;
- }
- }
- public List<Roi> loadRois(String imageDir, String imgName) {
- String roiName = imageDir+imgName+".zip";
- if (! new File(roiName).exists()) {
- print("ERROR: No ROI file found for image "+imgName+". Image not analyzed.");
- return(null);
- } else {
- RoiManager rm = new RoiManager(false);
- rm.runCommand("Open", roiName);
- List<Roi> rois = Arrays.asList(rm.getRoisAsArray());
- for (Roi roi : rois) {
- if(roi.getName().split(" ").length != 2) {
- print("ERROR: ROIs not correctly named in "+imgName +". Image not analyzed. Expected format: \"position layerName\" (e.g. \"0095-0429 l2\").");
- return(null);
- }
- }
- return(rois);
- }
- }
- /**
- * Scale ROIs
- */
- public List<Roi> scaleRois(List<Roi> rois, int scale, IMetadata meta, String imgName) {
- List<Roi> scaledRois = new ArrayList<Roi>();
- for (Roi roi : rois) {
- Roi scaledRoi = new RoiScaler().scale(roi, scale, scale, false);
- Rectangle rect = roi.getBounds();
- scaledRoi.setLocation(rect.x*scale, rect.y*scale);
- scaledRoi.setName(roi.getName());
- scaledRois.add(scaledRoi);
- }
- for (Roi roi : scaledRois) {
- Rectangle rect = roi.getBounds();
- if(rect.x < 0 || rect.x < 0 || rect.x+rect.width > meta.getPixelsSizeX(0).getValue() || rect.y+rect.height > meta.getPixelsSizeY(0).getValue()) {
- print("ERROR: ROIs exceed image size in "+imgName +". Image not analyzed. Check scaling factor.");
- return(null);
- }
- }
- return scaledRois;
- }
- /**
- * Get bounding box of multiple dilated ROIs combined together
- */
- public Roi getBoundingBox(List<Roi> rois) {
- Rectangle rect0 = RoiEnlarger.enlarge(rois.get(0), roiDilation/cal.pixelWidth).getBounds();
- int minX = rect0.x, minY = rect0.y, maxX = rect0.x+rect0.width, maxY = rect0.y+rect0.height;
- for (Roi roi : rois) {
- Rectangle rect = RoiEnlarger.enlarge(roi, roiDilation/cal.pixelWidth).getBounds();
- if(rect.x < minX) minX = rect.x;
- if(rect.y < minY) minY = rect.y;
- if(rect.x+rect.width > maxX) maxX = rect.x+rect.width;
- if(rect.y+rect.height > maxY) maxY = rect.y+rect.height;
- }
- minX = Math.max(minX, 0);
- minY = Math.max(minY, 0);
- return new Roi(minX, minY, maxX-minX, maxY-minY);
- }
- /**
- * Translate ROIs
- */
- public void translateRois(List<Roi> rois, Roi bBox) {
- Rectangle rectBBox = bBox.getBounds();
- for (Roi roi: rois) {
- Rectangle rectRoi = roi.getBounds();
- roi.setLocation(rectRoi.x-rectBBox.x, rectRoi.y-rectBBox.y);
- }
- }
- /**
- * Save ROIs in a zip file
- */
- public void saveRois(List<Roi> rois, String outDir, String imgName) {
- RoiManager rm = new RoiManager(false);
- for(Roi roi: rois) {
- String layerName = roi.getName().split(" ")[1];
- rm.addRoi(roi);
- String roiName = rm.getName(rm.getCount()-1) + " " + layerName;
- rm.rename(rm.getCount()-1, roiName);
- }
- rm.deselect();
- rm.save(outDir+imgName+"_rois.zip");
- rm.close();
- }
- /**
- * Crop stack around ROI
- */
- public ImagePlus cropImage(ImagePlus img, Roi roi) {
- img.setRoi(roi);
- ImagePlus imgCrop = img.crop("stack");
- img.deleteRoi();
- return(imgCrop);
- }
- /*
- * Look for all 3D cells in a Z-stack:
- * - apply Cellpose 2D slice by slice
- * - let CellPose reconstruct cells in 3D using the stitch_threshold parameter
- */
- public ImagePlus cellposeDetection(ImagePlus imgIn) throws IOException{
- ImagePlus img = imgIn.duplicate();
- // Define Cellpose settings
- CellposeTaskSettings settings = new CellposeTaskSettings(cellposeModel.equals("cyto")? cellposeModel : cellposeModelDir+cellposeModel, 1, cellposeDiam, cellposeEnvDir); // need to add Cellpose models folder path if own model (for Windows only, not Linux)
- settings.setStitchThreshold(cellposeStitchTh);
- settings.useGpu(true);
- // Run Cellpose
- CellposeSegmentImgPlusAdvanced cellpose = new CellposeSegmentImgPlusAdvanced(settings, img);
- ImagePlus imgOut = cellpose.run();
- if(imgOut.getNChannels() > 1)
- imgOut.setDimensions(1, imgOut.getNChannels(), 1);
- imgOut.setCalibration(cal);
- closeImage(img);
- return imgOut;
- }
- /**
- * Detect vessels applying a median filter + DoG filter + threshold + closing filter + median filter
- */
- public ImagePlus vesselsSegmentation(ImagePlus img) {
- ImagePlus imgMed = medianFilter3D(img, 4, 1);
- ImagePlus imgDOG = dogFilter2D(imgMed, dog1Sigma1, dog1Sigma2);
- ImagePlus imgBin = threshold(imgDOG, vesselThMet1);
- if(dog2) {
- ImagePlus imgDOG2 = dogFilter2D(imgMed, dog2Sigma1, dog2Sigma2);
- ImagePlus imgBin2 = threshold(imgDOG2, vesselThMet2);
- new ImageCalculator().run("Max stack", imgBin, imgBin2);
- closeImage(imgDOG2);
- closeImage(imgBin2);
- }
- ImagePlus imgClose = closingFilter3D(imgBin, 8, 1);
- ImagePlus imgMed2 = medianFilter3D(imgClose, 1, 1);
- ImagePlus imgOut = fillHoles2D(imgMed2, 0, maxHoleArea);
- ImageInt imgLabels = new ImageLabeller().getLabels(ImageHandler.wrap(imgOut));
- imgLabels.setCalibration(cal);
- Objects3DIntPopulation pop = new Objects3DIntPopulation(imgLabels);
- popFilterOneZ(pop);
- System.out.println(pop.getNbObjects() + " vessels detected");
- popFilterVol(pop, minVesselVol, Double.MAX_VALUE);
- System.out.println(pop.getNbObjects() + " vessels remaining after size filtering");
- ImageHandler imgFilter = ImageHandler.wrap(img).createSameDimensions();
- for(Object3DInt obj: pop.getObjects3DInt())
- obj.drawObject(imgFilter, 255);
- imgFilter.setCalibration(cal);
- closeImage(imgMed);
- closeImage(imgDOG);
- closeImage(imgBin);
- closeImage(imgClose);
- closeImage(imgMed2);
- closeImage(imgOut);
- closeImage(imgLabels.getImagePlus());
- return(imgFilter.getImagePlus());
- }
- /**
- * Median filter using CLIJ
- */
- public ImagePlus medianFilter3D(ImagePlus img, double sizeXY, double sizeZ) {
- ClearCLBuffer imgCL = clij2.push(img);
- ClearCLBuffer imgCLMed = clij2.create(imgCL);
- clij2.median3DSphere(imgCL, imgCLMed, sizeXY, sizeXY, sizeZ);
- clij2.release(imgCL);
- ImagePlus imgMed = clij2.pull(imgCLMed);
- clij2.release(imgCLMed);
- return(imgMed);
- }
- /**
- * Difference of Gaussians using CLIJ
- */
- public ImagePlus dogFilter2D(ImagePlus img, double size1, double size2) {
- ClearCLBuffer imgCL = clij2.push(img);
- ClearCLBuffer imgCLDOG = clij2.create(imgCL);
- clij2.differenceOfGaussian2D(imgCL, imgCLDOG, size1, size1, size2, size2);
- clij2.release(imgCL);
- ImagePlus imgDOG = clij2.pull(imgCLDOG);
- clij2.release(imgCLDOG);
- return(imgDOG);
- }
- /**
- * Automatic thresholding using CLIJ2
- */
- private ImagePlus threshold(ImagePlus img, String thMed) {
- ClearCLBuffer imgCL = clij2.push(img);
- ClearCLBuffer imgCLBin = clij2.create(imgCL);
- clij2.automaticThreshold(imgCL, imgCLBin, thMed);
- ImagePlus imgBin = clij2.pull(imgCLBin);
- clij2.release(imgCL);
- clij2.release(imgCLBin);
- return(imgBin);
- }
- /**
- * Closing filtering using CLIJ2
- */
- private ImagePlus closingFilter3D(ImagePlus img, double sizeXY, double sizeZ) {
- ClearCLBuffer imgCL = clij2.push(img);
- ClearCLBuffer imgCLMax = clij2.create(imgCL);
- clij2.maximum3DSphere(imgCL, imgCLMax, sizeXY, sizeXY, sizeZ);
- ClearCLBuffer imgCLMin = clij2.create(imgCLMax);
- clij2.minimum3DSphere(imgCLMax, imgCLMin, sizeXY, sizeXY, sizeZ);
- ImagePlus imgMin = clij2.pull(imgCLMin);
- clij2.release(imgCL);
- clij2.release(imgCLMax);
- clij2.release(imgCLMin);
- return(imgMin);
- }
- /**
- * Fill holes with areas between the specified min and max values
- */
- private ImagePlus fillHoles2D(ImagePlus img, double minArea, double maxArea) {
- ImagePlus imgFill = img.duplicate();
- // Invert image to detect background holes
- IJ.setRawThreshold(imgFill, 1, 255);
- IJ.run(imgFill, "Convert to Mask", "background=Dark black");
- IJ.run(imgFill, "Invert", "stack");
- // Analyze particles to detect holes within the specified area range
- double pixArea = cal.pixelWidth*cal.pixelHeight;
- ParticleAnalyzer pa = new ParticleAnalyzer(ParticleAnalyzer.ADD_TO_MANAGER, 0, new ResultsTable(), minArea/pixArea, maxArea/pixArea); // In pixels^2
- RoiManager rm = new RoiManager(true);
- pa.setRoiManager(rm);
- for (int s = 1; s <= imgFill.getNSlices(); s++) {
- imgFill.setSlice(s);
- pa.analyze(imgFill);
- // Reinvert image before filling holes
- IJ.run(imgFill, "Invert", "slice");
- // Fill the detected holes
- for (int i = 0; i < rm.getCount(); i++) {
- imgFill.setRoi(rm.getRoi(i));
- imgFill.setColor(Color.white);
- IJ.run(imgFill, "Fill", "slice");
- }
- imgFill.deleteRoi();
- rm.reset();
- }
- return(imgFill);
- }
- /**
- * Compute (inverse) 3D distance map
- */
- public ImageFloat distanceMap3D(ImagePlus img, boolean inverse) {
- img.setCalibration(cal);
- ImageFloat edt = new EDT().run(ImageHandler.wrap(img), 0, inverse, ThreadUtil.getNbCpus());
- return(edt);
- }
- /**
- * Skeletonize 3D with CLIJ2
- */
- public ImagePlus skeletonize3D(ImagePlus img) {
- ClearCLBuffer imgCL = clij2.push(img);
- ClearCLBuffer imgCLSkel = clij2.create(imgCL);
- new BoneJSkeletonize3D().bonejSkeletonize3D(clij2, imgCL, imgCLSkel);
- ImagePlus imgSkel = clij2.pull(imgCLSkel);
- clij2.release(imgCL);
- clij2.release(imgCLSkel);
- IJ.run(imgSkel, "8-bit","");
- imgSkel.setCalibration(cal);
- return(imgSkel);
- }
- /**
- * Prune skeleton branches with length smaller than threshold
- * https://imagej.net/plugins/analyze-skeleton/
- */
- public ImagePlus pruneSkeleton(ImagePlus image) {
- // Analyze skeleton
- AnalyzeSkeleton_ skel = new AnalyzeSkeleton_();
- skel.setup("", image);
- SkeletonResult skelResult = skel.run(AnalyzeSkeleton_.NONE, false, false, null, true, false);
- // Create copy of input image
- ImagePlus prunedImage = image.duplicate();
- if(skelResult.getBranches() != null) {
- ImageStack outStack = prunedImage.getStack();
- // Get graphs (one per skeleton in the image)
- Graph[] graphs = skelResult.getGraph();
- // Get list of end-points
- ArrayList<Point> endPoints = skelResult.getListOfEndPoints();
- for(Graph graph: graphs) {
- ArrayList<Edge> listEdges = graph.getEdges();
- // Go through all branches and remove branches under threshold in duplicate image
- for(Edge e: listEdges) {
- ArrayList<Point> p1 = e.getV1().getPoints();
- boolean v1End = endPoints.contains(p1.get(0));
- ArrayList<Point> p2 = e.getV2().getPoints();
- boolean v2End = endPoints.contains(p2.get(0));
- // If any of the vertices is end-point
- if(v1End || v2End) {
- if(e.getLength() < minVesselLength) { // in microns
- if(v1End)
- outStack.setVoxel(p1.get(0).x, p1.get(0).y, p1.get(0).z, 0);
- if(v2End)
- outStack.setVoxel(p2.get(0).x, p2.get(0).y, p2.get(0).z, 0);
- for(Point p: e.getSlabs())
- outStack.setVoxel(p.x, p.y, p.z, 0);
- }
- }
- }
- }
- }
- prunedImage = skeletonize3D(prunedImage);
- return(prunedImage);
- }
- /**
- * Get object in (dilated) ROI
- * @param dilationFactor in microns
- */
- public ImagePlus getImgInRoi(ImagePlus img, Roi roi, double dilationFactor) {
- ImagePlus imgClear = img.duplicate();
- imgClear.setRoi(dilationFactor == 0? roi : RoiEnlarger.enlarge(roi, dilationFactor/cal.pixelWidth)); // pixels
- IJ.run(imgClear, "Clear Outside", "stack");
- imgClear.setCalibration(cal);
- return(imgClear);
- }
- /**
- * Get object in (dilated) ROI
- */
- public Object3DInt getObjInRoi(ImagePlus img, Roi roi, double dilationFactor) {
- ImagePlus imgClear = getImgInRoi(img, roi, dilationFactor);
- Object3DInt obj = new Object3DInt(ImageHandler.wrap(imgClear));
- closeImage(imgClear);
- return(obj);
- }
- /**
- * Return population in ROI
- */
- public Objects3DIntPopulation getPopInRoi(ImagePlus img, Roi roi) throws IOException{
- ImagePlus imgClear = getImgInRoi(img, roi, 20);
- // Filter detections
- Objects3DIntPopulation pop = new Objects3DIntPopulation(ImageInt.wrap(imgClear));
- if(filterOneZ) popFilterOneZ(pop);
- popFilterCentroid(pop, roi);
- System.out.println(pop.getNbObjects() + " cells detected in ROI");
- popFilterVol(pop, minCellVol, maxCellVol);
- System.out.println(pop.getNbObjects() + " cells remaining after size filtering");
- pop.resetLabels();
- closeImage(imgClear);
- return(pop);
- }
- /**
- * Remove objects that appear in only one z-slice
- */
- private void popFilterOneZ(Objects3DIntPopulation pop) {
- pop.getObjects3DInt().removeIf(p -> (p.getObject3DPlanes().size() == 1));
- pop.resetLabels();
- }
- /**
- * Remove objects that do not have their centroid into a given ROI
- */
- public void popFilterCentroid(Objects3DIntPopulation pop, Roi roi) {
- pop.getObjects3DInt().removeIf(p -> (!roi.contains(new MeasureCentroid(p).getCentroidAsPoint().getRoundX(),
- new MeasureCentroid(p).getCentroidAsPoint().getRoundY())));
- pop.resetLabels();
- }
- /**
- * Remove objects with volume < min and volume > max
- */
- private void popFilterVol(Objects3DIntPopulation pop, double min, double max) {
- pop.getObjects3DInt().removeIf(p -> (new MeasureVolume(p).getVolumeUnit() < min) || (new MeasureVolume(p).getVolumeUnit() > max));
- pop.resetLabels();
- }
- /**
- * Remove objects with intensity < min
- */
- public void popFilterInt(Objects3DIntPopulation pop, ImagePlus img, double minInt) {
- ImageHandler imh = ImageHandler.wrap(img);
- pop.getObjects3DInt().removeIf(p -> (new MeasureIntensity(p, imh).getValueMeasurement(MeasureIntensity.INTENSITY_AVG) < minInt));
- pop.resetLabels();
- }
- /**
- * Compute distance between each cell and its closest vessel
- */
- public void computeCellsVesselsDists(Objects3DIntPopulation cellPop, ImageFloat vesselDistMapInv) {
- for (Object3DInt cell: cellPop.getObjects3DInt()) {
- double dist = vesselDistMapInv.getPixel(new MeasureCentroid(cell).getCentroidAsPoint());
- cell.setCompareValue(dist);
- }
- }
- /**
- * Draw results obtained in ROI
- */
- public void drawResultsInRoi(Objects3DIntPopulation popCell, Object3DInt objVessel, Object3DInt objSkel, ImageHandler imhCell,
- ImageHandler imhCellDist, ImageHandler imhVessel, ImageHandler imhSkel) {
- // Cells
- popCell.drawInImage(imhCell);
- // Cells + vessels
- if (objVessel != null) {
- for (Object3DInt cell: popCell.getObjects3DInt()) {
- cell.drawObject(imhCellDist, (float)cell.getCompareValue()+10);
- }
- objVessel.drawObject(imhVessel, 255);
- objSkel.drawObject(imhSkel, 255);
- }
- }
- /**
- * Save results in images
- */
- public void saveCloseDrawings(ImagePlus imgCell, ImagePlus imgVessel, ImageHandler imhCell, ImageHandler imhCellDist,
- ImageHandler imhVessel, ImageHandler imhSkel, String outDir, String imgName) {
- // Cells
- ImagePlus[] imgColors1 = {imhCell.getImagePlus(), null, null, imgCell};
- ImagePlus imgObjects1 = new RGBStackMerge().mergeHyperstacks(imgColors1, true);
- imgObjects1.setCalibration(cal);
- new FileSaver(imgObjects1).saveAsTiff(outDir+imgName+"_cells.tif");
- closeImage(imgObjects1);
- // Cells + vessels
- if (imgVessel != null) {
- IJ.run(imhCellDist.getImagePlus(), "mpl-inferno", "");
- IJ.run(imhSkel.getImagePlus(), "Green", "");
- IJ.run(imhVessel.getImagePlus(), "Blue", "");
- ImagePlus[] imgColors2 = {imhCellDist.getImagePlus(), imhSkel.getImagePlus(), imhVessel.getImagePlus(), imgVessel};
- ImagePlus imgObjects2 = new RGBStackMerge().mergeHyperstacks(imgColors2, true);
- imgObjects2.setCalibration(cal);
- new FileSaver(imgObjects2).saveAsTiff(outDir+imgName+"_vessels.tif");
- closeImage(imgObjects2);
- }
- closeImage(imhCell.getImagePlus());
- closeImage(imhCellDist.getImagePlus());
- closeImage(imhVessel.getImagePlus());
- closeImage(imhSkel.getImagePlus());
- }
- /**
- * Write headers in results files
- */
- public void writeHeaders(String outDir, boolean computeVessel) throws IOException {
- // Global results
- FileWriter fileGlobal = new FileWriter(outDir + "globalResults.csv", false);
- resultsGlobal = new BufferedWriter(fileGlobal);
- resultsGlobal.write("Image name\tROI name\tROI area (µm²)\tROI volume (µm³)\tNb cells\tCells total volume (µm³)\t"
- + "Cells mean volume (µm³)\tCells volume SD (µm³)\tCells mean distance to closest neighbor (µm)\t"
- + "Cells distance to closest neighbor SD (µm)\tCells mean distance to "+nbNei+" closest neighbors (µm)\t"
- + "Cells distance to "+nbNei+" closest neighbors SD (µm)"+"\tCells mean of max distance to "+nbNei+" neighbors (µm)\t"
- + "Cells SD of max distance to "+nbNei+" neighbors (µm)");
- if (computeGFunction) resultsGlobal.write("\tCells G-function SDI\tCells G-function AUC difference");
- if (computeVessel) resultsGlobal.write("\tCells mean distance to closest vessel (µm)\tVessels total volume (µm³)"
- + "\tVessels total length (µm)\tBranches mean length (µm)\tNb branches\tNb junctions\tVessels mean diameter (µm)\tVessels diameter SD (µm)");
- resultsGlobal.write("\n");
- resultsGlobal.flush();
- // Detailed results
- FileWriter fileDetail = new FileWriter(outDir +"cellsResults.csv", false);
- resultsDetail = new BufferedWriter(fileDetail);
- resultsDetail.write("Image name\tROI name\tCell ID\tCell volume (µm³)\tCell distance to closest neighbor (µm)\t"
- + "Cell mean distance to "+nbNei+" closest neighbors (µm)\tCell max distance to "+nbNei+" closest neighbors (µm)");
- if(computeVessel) resultsDetail.write("\tCell distance to closest vessel (µm)\tClosest vessel diameter (µm)");
- resultsDetail.write("\n");
- resultsDetail.flush();
- }
- /**
- * Compute parameters and save them in results files
- * @throws java.io.IOException
- */
- public void writeResultsInRoi(Objects3DIntPopulation popCellRoi, Object3DInt objSkelRoiDil, Object3DInt objSkelRoi,
- ImageFloat distMap, ImagePlus imgCell, Roi roi, double vesselVol, String outDir, String imgName) throws IOException {
- DescriptiveStatistics cellsVolume = new DescriptiveStatistics();
- DescriptiveStatistics cellsClosestVesselDist = new DescriptiveStatistics();
- DescriptiveStatistics cellsClosestNeighborDist = new DescriptiveStatistics();
- DescriptiveStatistics cellsNeighborsMeanDist = new DescriptiveStatistics();
- DescriptiveStatistics cellsNeighborsMaxDist = new DescriptiveStatistics();
- // CELLS INDIVIDUAL STATISTICS
- print("Computing cells individual statistics...");
- MeasurePopulationDistance allCellsDists = new MeasurePopulationDistance(popCellRoi, popCellRoi, Double.POSITIVE_INFINITY, "DistCenterCenterUnit");
- for (Object3DInt cell: popCellRoi.getObjects3DInt()) {
- double cellVol = new MeasureVolume(cell).getVolumeUnit();
- cellsVolume.addValue(cellVol);
- resultsDetail.write(imgName+"\t"+roi.getName()+"\t"+cell.getLabel()+"\t"+cellVol);
- resultsDetail.flush();
- if(popCellRoi.getNbObjects() == 1) {
- resultsDetail.write("\t"+Double.NaN+"\t"+Double.NaN+"\t"+Double.NaN);
- resultsDetail.flush();
- } else {
- List<PairObjects3DInt> cellCellsDists = allCellsDists.getPairsObject1(cell.getLabel(), true);
- double closestNeighborDist = cellCellsDists.get(1).getPairValue();
- cellsClosestNeighborDist.addValue(closestNeighborDist);
- DescriptiveStatistics cellNeighborsDists = new DescriptiveStatistics();
- for (int d=1; d <= Math.min(nbNei, popCellRoi.getNbObjects()-1); d++)
- cellNeighborsDists.addValue(cellCellsDists.get(d).getPairValue());
- double closestNeighborsMeanDist = cellNeighborsDists.getMean();
- cellsNeighborsMeanDist.addValue(closestNeighborsMeanDist);
- double closestNeighborsMaxDist = cellNeighborsDists.getMax();
- cellsNeighborsMaxDist.addValue(closestNeighborsMaxDist);
- resultsDetail.write("\t"+closestNeighborDist+"\t"+closestNeighborsMeanDist+"\t"+closestNeighborsMaxDist);
- resultsDetail.flush();
- }
- cellsClosestVesselDist.addValue(cell.getCompareValue());
- if (objSkelRoiDil != null) {
- double diam = 2*distMap.getPixel(new Measure2Distance(cell, objSkelRoiDil).getBorder2Pix());
- resultsDetail.write("\t"+cell.getCompareValue()+"\t"+diam);
- resultsDetail.flush();
- }
- resultsDetail.write("\n");
- resultsDetail.flush();
- }
- // CELLS GLOBAL STATISTICS
- print("Computing cells global statistics...");
- double[] roiParams = roiParams(roi, imgCell);
- resultsGlobal.write(imgName+"\t"+roi.getName()+"\t"+roiParams[0]+"\t"+roiParams[1]+"\t"+popCellRoi.getNbObjects()+"\t"+
- cellsVolume.getSum()+"\t"+cellsVolume.getMean()+"\t"+cellsVolume.getStandardDeviation()+"\t"+
- cellsClosestNeighborDist.getMean()+"\t"+cellsClosestNeighborDist.getStandardDeviation()+"\t"+
- cellsNeighborsMeanDist.getMean()+"\t"+cellsNeighborsMeanDist.getStandardDeviation()+"\t"+
- cellsNeighborsMaxDist.getMean()+"\t"+cellsNeighborsMaxDist.getStandardDeviation());
- if (computeGFunction) {
- if(popCellRoi.getNbObjects() <= 1) {
- resultsGlobal.write("\t"+Double.NaN+"\t"+Double.NaN);
- resultsGlobal.flush();
- } else {
- System.out.println("Computing G-function-related spatial distribution index...");
- Object3DInt mask = roiMask(imgCell, roi);
- double minDist = Math.pow(3*minCellVol/(4*Math.PI*pixelVol), 1/3) * 2; // min distance = 2 * min cell radius (in pixels)
- String plotName = outDir + imgName + "_" + roi.getName() + "_gfunction.tif";
- double[] res = computeSdiG(popCellRoi, mask, imgCell, minDist, nbRandomSamples, plotName);
- resultsGlobal.write("\t"+res[0]+"\t"+res[1]);
- resultsGlobal.flush();
- }
- }
- // VESSELS STATISTICS
- if(objSkelRoi == null) {
- resultsGlobal.write("\t0\t0\t0\t0\t0\t0\t0\t0");
- resultsGlobal.flush();
- } else {
- print("Computing vessels statistics...");
- ImageHandler imhSkel = ImageHandler.wrap(imgCell).createSameDimensions();
- objSkelRoi.drawObject(imhSkel, 255);
- IJ.run(imhSkel.getImagePlus(), "8-bit","");
- AnalyzeSkeleton_ analyzeSkeleton = new AnalyzeSkeleton_();
- analyzeSkeleton.setup("", imhSkel.getImagePlus());
- SkeletonResult skelResult = analyzeSkeleton.run(AnalyzeSkeleton_.NONE, false, false, null, true, false);
- closeImage(imhSkel.getImagePlus());
- if(skelResult.getBranches() == null) {
- resultsGlobal.write("\t0\t0\t0\t0\t0\t0\t0\t0");
- resultsGlobal.flush();
- } else {
- double[] branchLengths = skelResult.getAverageBranchLength();
- int[] branchNumbers = skelResult.getBranches();
- double totalLength = 0;
- for (int i = 0; i < branchNumbers.length; i++)
- totalLength += branchNumbers[i] * branchLengths[i];
- DescriptiveStatistics diams = new DescriptiveStatistics();
- for (Point pt: skelResult.getListOfSlabVoxels())
- diams.addValue(2*distMap.getPixel(pt.x, pt.y, pt.z));
- resultsGlobal.write("\t"+cellsClosestVesselDist.getMean()+"\t"+vesselVol+"\t"+totalLength+"\t"+StatUtils.mean(branchLengths)+"\t"+
- IntStream.of(branchNumbers).sum()+"\t"+IntStream.of(skelResult.getJunctions()).sum()+"\t"+
- diams.getMean()+"\t"+diams.getStandardDeviation());
- resultsGlobal.flush();
- }
- }
- resultsGlobal.write("\n");
- resultsGlobal.flush();
- }
- /**
- * Compute ROI area and volume
- */
- public double[] roiParams(Roi roi, ImagePlus img) {
- PolygonRoi poly = new PolygonRoi(roi.getFloatPolygon(), Roi.FREEROI);
- poly.setLocation(0, 0);
- img.setRoi(poly);
- ResultsTable rt = new ResultsTable();
- Analyzer analyzer = new Analyzer(img, Analyzer.AREA, rt);
- analyzer.measure();
- double area = rt.getValue("Area", 0);
- double vol = area * img.getNSlices() * cal.pixelDepth;
- double[] params = {area, vol};
- return(params);
- }
- // Get ROI as a 3D object
- public Object3DInt roiMask(ImagePlus img, Roi roi) {
- ImagePlus imgMask = img.duplicate();
- imgMask.setRoi(roi);
- for (int n = 1; n <= imgMask.getNSlices(); n++) {
- imgMask.setSlice(n);
- IJ.run(imgMask, "Fill", "stack");
- IJ.run(imgMask, "Clear Outside", "stack");
- }
- imgMask.setCalibration(cal);
- Object3DInt mask = new Object3DInt(ImageHandler.wrap(imgMask));
- closeImage(imgMask);
- return(mask);
- }
- /**
- * Compute G-function-related Spatial Distribution Index of cells population in a ROI
- * https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1000853
- */
- public double[] computeSdiG(Objects3DIntPopulation popInt, Object3DInt roiInt, ImagePlus img, double distHardCore, int numRandomSamples, String plotName) {
- // Convert Object3DInt & Objects3DIntPopulation objects into Object3D & Objects3DPopulation objects
- ImageHandler imhRoi = ImageHandler.wrap(img).createSameDimensions();
- roiInt.drawObject(imhRoi, 1);
- Object3D roi = new Objects3DPopulation(imhRoi).getObject(0);
- closeImage(imhRoi.getImagePlus());
- ImageHandler imhPop = ImageHandler.wrap(img).createSameDimensions();
- popInt.drawInImage(imhPop);
- Objects3DPopulation pop = new Objects3DPopulation(imhPop);
- closeImage(imhPop.getImagePlus());
- // Define spatial descriptor and model
- SpatialDescriptor spatialDesc = new G_Function();
- SpatialModel spatialModel = new SpatialRandomHardCore(pop.getNbObjects(), distHardCore, roi); // average diameter of a cell in pixels
- SpatialStatistics spatialStatistics = new SpatialStatistics(spatialDesc, spatialModel, numRandomSamples, pop); // nb of samples (randomized organizations simulated to compare with the spatial organization of the cells)
- spatialStatistics.setEnvelope(0.05); // 2.5-97.5% envelope error
- spatialStatistics.setVerbose(false);
- double sdiG = spatialStatistics.getSdi();
- double areaG = spatialStatistics.getAUCDifference();
- Plot plotG = spatialStatistics.getPlot();
- plotG.draw();
- plotG.addLabel(0.05, 0.1, "SDI = " + String.format("%.5f", sdiG));
- plotG.addLabel(0.05, 0.15, "Area = " + String.format("%.5f", areaG));
- ImagePlus imgPlot = plotG.getImagePlus();
- FileSaver plotSave = new FileSaver(imgPlot);
- plotSave.saveAsTiff(plotName);
- closeImage(imgPlot);
- double[] results = {sdiG, areaG};
- return(results);
- }
- /**
- * Close results files
- */
- public void closeResults() throws IOException {
- resultsGlobal.close();
- resultsDetail.close();
- }
- }
Tools.java at commit a84b038, no license · at the source
Overview
Abstract
The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.
Repository
Its files are read in the Code ↔ Paper reader above, with 4 matches between paragraphs and lines of code.
orion-cirb/VeCell
a84b0387457d39c2cd91b448712089fbbf9201c0, 10 December 2025Availability: 1 check, the latest on 26 September 2026: the link answers
- 26 September 2026: the link answers
11 files
- cellpose_finetuning/
P1/ , Jupyter, 220 linesquality_control.ipynb - cellpose_finetuning/
P5-P15-P60/ , Jupyter, 156 linesquality_control.ipynb - src/
main/ , Java, 208 linesjava/ VeCell.java - src/
main/ , Java, 113 linesjava/ VeCell_Tools/ Cellpose/ Cellpose.java - src/
main/ , Java, 132 linesjava/ VeCell_Tools/ Cellpose/ CellposeSegmentImgPlusAd vanced.java - src/
main/ , Java, 82 lines, 1 matchjava/ VeCell_Tools/ Cellpose/ CellposeTask.java - src/
main/ , Java, 126 lines, 1 matchjava/ VeCell_Tools/ Cellpose/ CellposeTaskSettings.jav a - src/
main/ , Java, 624 linesjava/ VeCell_Tools/ QuantileBasedNormalizati on.java - src/
main/ , Java, 252 linesjava/ VeCell_Tools/ SpatialStatistics.java - src/
main/ , Java, 1,151 lines, 2 matchesjava/ VeCell_Tools/ Tools.java - README.md, Text, 56 lines
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:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 10 scripts, each with its path and the digest of its content;
- 4 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
No dataset and no data link were found in the paper.
Data availability statement
The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:
- it says that the data are available on request
Read it in the paper: doi.org/10.1002/jdn.70161.
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 3, 28 September 2026
- Publisher: n/a → Wiley
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 6 keywords, 15 MeSH terms, 4 funders, 51 references.
Cite
This paper
Guille, N., Monnet, H., Hourcade, T., Mailly, P., Cohen‐Salmon, M., & Boulay, A. (2026). Spatio-Temporal Dynamics of Macroglial Cell Organization and Proximity to Blood Vessels During Postnatal Development. International journal of developmental neuroscience : the official journal of the International Society for Developmental Neuroscience, 86(5), e70161. https://
BibTeX
@article{guille2026spati
author = {Guille, Naomie and Monnet, Héloïse and Hourcade, Tristan and Mailly, Philippe and Cohen‐Salmon, Martine and Boulay, Anne‐Cécile},
title = {{Spatio-Temporal Dynamics of Macroglial Cell Organization and Proximity to Blood Vessels During Postnatal Development}},
journal = {International journal of developmental neuroscience : the official journal of the International Society for Developmental Neuroscience},
year = {2026},
month = aug,
volume = {86},
number = {5},
pages = {e70161},
publisher = {Wiley},
issn = {0736-5748},
doi = {10.1002/
url = {https://
pmid = {42517543},
pmcid = {PMC13411183}
}
RIS
TY - JOUR
AU - Guille, Naomie
AU - Monnet, Héloïse
AU - Hourcade, Tristan
AU - Mailly, Philippe
AU - Cohen‐Salmon, Martine
AU - Boulay, Anne‐Cécile
TI - Spatio-Temporal Dynamics of Macroglial Cell Organization and Proximity to Blood Vessels During Postnatal Development
T2 - International journal of developmental neuroscience : the official journal of the International Society for Developmental Neuroscience
J2 - Int J Dev Neurosci
PY - 2026
DA - 2026/
VL - 86
IS - 5
SP - e70161
SN - 0736-5748
PB - Wiley
DO - 10.1002/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1002/
"type": "article-journal",
"title": "Spatio-Temporal Dynamics of Macroglial Cell Organization and Proximity to Blood Vessels During Postnatal Development",
"container-title": "International journal of developmental neuroscience : the official journal of the International Society for Developmental Neuroscience",
"author": [
{
"family": "Guille",
"given": "Naomie"
},
{
"family": "Monnet",
"given": "Héloïse"
},
{
"family": "Hourcade",
"given": "Tristan"
},
{
"family": "Mailly",
"given": "Philippe"
},
{
"family": "Cohen‐Salmon",
"given": "Martine"
},
{
"family": "Boulay",
"given": "Anne‐Cécile"
}
],
"container-title-short":
"volume": "86",
"issue": "5",
"page": "e70161",
"DOI": "10.1002/
"PMID": "42517543",
"PMCID": "PMC13411183",
"ISSN": "0736-5748",
"publisher": "Wiley",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
8,
1
]
]
}
}
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.26508/lsa.202503546 [code]
- Interactions of LINE-1 ORF1p with proteins and chromatin suggest a role in neuronal physiology.Journal: Life science allianceIn common: pandas, NumPy, mouse, 3 references, author Héloïse Monnet
- [2] 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: Cellpose, pandas, Matplotlib, 1 other tool, 2 references
- [3] doi:10.1038/s42003-026-10063-9 [code]
- Conserved Kir channel mechanisms governing intrinsic excitability in human and rodent parvalbumin neurons.Journal: Communications biologyIn common: Cellpose, pandas, Matplotlib, 1 other tool, mouse, 1 reference
- [4] doi:10.1126/sciadv.aec4911 [code]
- Dendritic shaft constrictions shape synaptic integration in neurons.Journal: Science advancesIn common: pandas, Matplotlib, NumPy, mouse, 3 references
- [5] doi:10.1002/advs.202522762 [code]
- Enhancing Maturation of Human Neuromuscular Organoids via Electrical Stimulation.Journal: Advanced science (Weinheim, Baden-Wurttemberg, Germany)In common: Cellpose, pandas, Matplotlib, 1 other tool, 1 reference
- [6] doi:10.1038/s41467-026-73416-2 [code]
- Defective ventral neurogenesis due to midfetal Chd8 mutation drives autistic-like behavior in mice.Journal: Nature communicationsIn common: pandas, Matplotlib, NumPy, mouse, 2 references
- [7] doi:10.1016/j.isci.2026.117318
- Dynamic interactions with neuroblasts promote oligodendrocyte progenitor migration to injured cortex.Journal: iScienceIn common: 4 references
- [8] doi:10.3389/fcell.2026.1880548 [code]
- A pipeline for cell migration analysis in live-cell imaging data from human iPSC-derived forebrain assembloids.Journal: Frontiers in cell and developmental biologyIn common: 4 references
- [9] doi:10.1038/s41586-026-10323-y [code]
- Genetically encoded assembly recorder temporally resolves cellular history.Journal: NatureIn common: Cellpose, pandas, Matplotlib, 1 other tool, mouse
- [10] doi:10.1038/s41467-026-72130-3 [code]
- Retinoic acid drives cell fate specification, maturation and retinal regionality in human retinal organoids.Journal: Nature communicationsIn common: Cellpose, Matplotlib, NumPy, 1 reference
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: 1 repository of the authors' code, each at its verified commit and with its license, 10 scripts, and 4 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:c949980b7cb37dae…
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.
