Dentate gyrus and CA3 activity mediates light-tone second-order conditioning expression in mice.
The 6 matches
- [1] § STAR★Methods › Method details › CellRake’s classification algorithm ↔ cellrake/utils.py, lines 651 to 693 · score 0.67 · ROC AUC, F1 score, precision, AP, probabilities, metrics · Report a mismatch
- [2] § Results › CellRake accurately quantifies fluorescent markers in histological brain sections ↔ cellrake/utils.py, lines 651 to 693 · score 0.58 · ROC AUC, F1 score, precision, AP, metrics, recall · Report a mismatch
- [3] § STAR★Methods › Method details › CellRake’s segmentation algorithm ↔ cellrake/segmentation.py, lines 245 to 278 · score 0.52 · polygonal contours, clips, bounds, segmented, dictionary, CellRake · Report a mismatch
- [4] § STAR★Methods › Method details › CellRake’s classification algorithm ↔ cellrake/main.py, lines 130 to 245 · score 0.52 · semi supervised learning, spreading, clustering, algorithm, blobs, classify · Report a mismatch
- [5] § STAR★Methods › Method details › CellRake’s classification algorithm ↔ cellrake/training.py, lines 528 to 636 · score 0.51 · semi supervised learning, spreading, clustering, pipeline, algorithm, classify · Report a mismatch
- [6] § STAR★Methods › Method details › CellRake’s classification algorithm ↔ cellrake/training.py, lines 139 to 262 · score 0.51 · Minority, SMOTE, kernel, probabilities, entropy, confidence · Report a mismatch
Paper
Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 693 lines · 21 KB · MIT · 2 matches
- # Created by: Marc Canela
- from pathlib import Path
- from typing import Any, Dict, List, Optional, Tuple, Union
- import numpy as np
- import pandas as pd
- from scipy.stats import uniform
- from shapely.geometry import Polygon
- from skimage.draw import polygon
- from skimage.feature import graycomatrix, graycoprops, hog, local_binary_pattern
- from skimage.measure import label, regionprops
- from sklearn.decomposition import PCA
- from sklearn.ensemble import ExtraTreesClassifier, RandomForestClassifier
- from sklearn.linear_model import LogisticRegression
- from sklearn.metrics import (
- average_precision_score,
- f1_score,
- precision_score,
- recall_score,
- roc_auc_score,
- )
- from sklearn.model_selection import RandomizedSearchCV, cross_val_predict
- from sklearn.pipeline import Pipeline
- from sklearn.preprocessing import StandardScaler
- from sklearn.svm import SVC
- def export_data(data: pd.DataFrame, project_folder: Path, file_name: str) -> None:
- """
- Save data to CSV and Excel files in the specified project folder.
- Parameters
- ----------
- data : pd.DataFrame
- Data to save.
- project_folder : Path
- Folder to save the files.
- file_name : str
- Base name of the files (without extensions).
- """
- data.to_csv(project_folder / f"{file_name}.csv", index=False)
- data.to_excel(project_folder / f"{file_name}.xlsx", index=False)
- def get_cell_mask(layer: np.ndarray, coordinates: np.ndarray) -> np.ndarray:
- """
- Generate a binary mask for ROI regions defined by polygonal coordinates.
- Parameters
- ----------
- layer : np.ndarray
- 2D image layer determining mask dimensions.
- coordinates : np.ndarray
- Array of shape (N, 2) representing polygon vertices defining ROI.
- Returns
- -------
- np.ndarray
- Binary mask with ROI pixels set to 1, others to 0.
- """
- mask = np.zeros(layer.shape, dtype=np.uint8)
- # Extract x and y coordinates separately
- r = coordinates[0, :, 1] # y-coordinates
- c = coordinates[0, :, 0] # x-coordinate
- # Get the indices of the pixels that are inside the polygon
- rr, cc = polygon(r, c, mask.shape)
- # Fill the mask
- mask[rr, cc] = 1
- return mask
- def crop_cell(
- layer: np.ndarray,
- x_coords: Union[List[int], np.ndarray],
- y_coords: Union[List[int], np.ndarray],
- ) -> np.ndarray:
- """
- Extract a rectangular subregion from an image layer.
- Parameters
- ----------
- layer : np.ndarray
- 2D image layer to crop from.
- x_coords : Union[List[int], np.ndarray]
- X-coordinates defining horizontal crop boundaries.
- y_coords : Union[List[int], np.ndarray]
- Y-coordinates defining vertical crop boundaries.
- Returns
- -------
- np.ndarray
- Cropped rectangular region from the image layer.
- """
- # Extract min and max coordinates and convert to integers
- x_min, x_max = int(min(x_coords)), int(max(x_coords))
- y_min, y_max = int(min(y_coords)), int(max(y_coords))
- # Crop the rectangular region from the layer
- return layer[y_min : y_max + 1, x_min : x_max + 1]
- def extract_roi_stats(
- layer: np.ndarray, roi_info: Dict[str, Any]
- ) -> Tuple[np.ndarray, Dict[str, Any]]:
- """
- Extract statistical and texture features from a region of interest (ROI).
- Parameters
- ----------
- layer : np.ndarray
- 2D image layer for feature extraction.
- roi_info : Dict[str, Any]
- Dictionary with ROI coordinates containing "x" and "y" keys.
- Returns
- -------
- Tuple[np.ndarray, Dict[str, Any]]
- Binary mask and dictionary of extracted features including intensity,
- texture, and morphological statistics.
- """
- # Extract ROI coordinates from the dictionary
- x_coords, y_coords = roi_info["x"], roi_info["y"]
- coordinates = np.array([list(zip(x_coords, y_coords))], dtype=np.int32)
- # Create a binary mask for the ROI
- cell_mask = get_cell_mask(layer, coordinates)
- # If the mask is empty, skip
- if np.mean(cell_mask) == 0:
- cell_mask = None
- stats_dict = None
- return cell_mask, stats_dict
- # Crop the layer and mask to the bounding box of the ROI
- layer_cropped = crop_cell(layer, x_coords, y_coords)
- cell_mask_cropped = crop_cell(cell_mask, x_coords, y_coords)
- # Create a background mask
- background_mask_cropped = 1 - cell_mask_cropped
- # Extract pixel values for the ROI and background
- cell_pixels = layer[cell_mask == 1]
- cell_pixels_mean = np.mean(cell_pixels)
- background_pixels = layer_cropped[background_mask_cropped == 1]
- background_pixels_mean = (
- np.mean(background_pixels) if background_pixels.size > 0 else cell_pixels_mean
- )
- # Mask the cropped layer and calculate texture features
- layer_cropped_masked = layer_cropped * cell_mask_cropped
- layer_masked = layer * cell_mask
- # Calculate Local Binary Pattern (LBP)
- lbp = local_binary_pattern(layer_cropped_masked, P=8, R=1, method="uniform")
- # Calculate Gray Level Co-occurrence Matrix (GLCM) features
- glcm = graycomatrix(
- layer_masked, distances=[1], angles=[0], levels=256, symmetric=True, normed=True
- )
- # Calculate region properties
- prop = regionprops(label(cell_mask_cropped))[0]
- height, width = layer_cropped_masked.shape[:2]
- pixels_per_cell_val = 4
- cells_per_block_val = 2
- # Set the required minimum size based on the HOG parameters
- min_height = pixels_per_cell_val * cells_per_block_val
- min_width = pixels_per_cell_val * cells_per_block_val
- # Calculate the amount of padding needed
- pad_height = max(0, min_height - height)
- pad_width = max(0, min_width - width)
- # Apply padding to the image
- if pad_height > 0 or pad_width > 0:
- padded_image = np.pad(
- layer_cropped_masked,
- ((0, pad_height), (0, pad_width)),
- mode="constant",
- constant_values=0,
- )
- else:
- padded_image = layer_cropped_masked
- # Compute Histogram of Oriented Gradients (HOG) features
- h_values, _ = hog(
- padded_image,
- orientations=9,
- pixels_per_cell=(pixels_per_cell_val, pixels_per_cell_val),
- cells_per_block=(cells_per_block_val, cells_per_block_val),
- block_norm="L2-Hys",
- visualize=True,
- feature_vector=True,
- )
- # Flatten the HOG features if needed (though skimage.hog already returns a flat array if feature_vector=True)
- hog_descriptor_values = h_values.flatten()
- # Create a dictionary to store the extracted features
- stats_dict = {
- "mean_intensity": cell_pixels_mean,
- "median_intensity": np.median(cell_pixels),
- "sd_intensity": np.std(cell_pixels),
- "min_intensity": np.min(cell_pixels),
- "max_intensity": np.max(cell_pixels),
- "mean_ratio": cell_pixels_mean
- / (background_pixels_mean if background_pixels_mean != 0 else 1),
- "mean_difference": cell_pixels_mean - background_pixels_mean,
- "mean_all_ratio": None,
- "mean_all_difference": None,
- "mean_max_ratio": None,
- "mean_max_difference": None,
- "lbp_mean": np.mean(lbp),
- "lbp_std": np.std(lbp),
- "contrast": graycoprops(glcm, "contrast")[0, 0],
- "correlation": graycoprops(glcm, "correlation")[0, 0],
- "energy": graycoprops(glcm, "energy")[0, 0],
- "homogeneity": graycoprops(glcm, "homogeneity")[0, 0],
- "area": prop.area,
- "perimeter": prop.perimeter,
- "eccentricity": prop.eccentricity,
- "major_axis_length": prop.major_axis_length,
- "minor_axis_length": prop.minor_axis_length,
- "solidity": prop.solidity,
- "extent": prop.extent,
- "hog_mean": np.mean(hog_descriptor_values),
- "hog_std": np.std(hog_descriptor_values),
- }
- return cell_mask, stats_dict
- def create_stats_dict(
- roi_dict: Dict[str, Dict[str, Any]], layer: np.ndarray
- ) -> Dict[str, Dict[str, Any]]:
- """
- Calculate features for multiple ROIs with background statistics.
- Parameters
- ----------
- roi_dict : Dict[str, Dict[str, Any]]
- Dictionary mapping ROI names to coordinate dictionaries.
- layer : np.ndarray
- 2D image layer for feature extraction.
- Returns
- -------
- Dict[str, Dict[str, Any]]
- Dictionary with ROI names as keys and feature dictionaries as values.
- """
- cell_masks = []
- roi_props = {}
- # Extract statistics for each ROI
- for roi_name, roi_info in roi_dict.items():
- cell_mask, stats_dict = extract_roi_stats(layer, roi_info)
- if cell_mask is not None and stats_dict is not None:
- roi_props[roi_name] = stats_dict
- cell_masks.append(cell_mask)
- # Compute combined background statistics
- combined_cell_mask = np.bitwise_or.reduce(cell_masks)
- combined_background_mask = 1 - combined_cell_mask
- combined_background_pixels = layer[combined_background_mask == 1]
- nonzero_background_pixels = combined_background_pixels[
- combined_background_pixels != 0
- ]
- # Handle case when all background pixels are zero to avoid division by zero
- mean_background = (
- np.mean(nonzero_background_pixels) if nonzero_background_pixels.size > 0 else 0
- )
- # Update statistics with additional ratios and differences
- for stats_dict in roi_props.values():
- mean_intensity = stats_dict["mean_intensity"]
- stats_dict["mean_all_ratio"] = mean_intensity / (
- mean_background if mean_background != 0 else 1
- )
- stats_dict["mean_all_difference"] = mean_intensity - mean_background
- # Compute maximum mean intensity across all ROIs
- max_mean_intensity = max(
- stats_dict["mean_intensity"] for stats_dict in roi_props.values()
- )
- for stats_dict in roi_props.values():
- mean_intensity = stats_dict["mean_intensity"]
- stats_dict["mean_max_ratio"] = max_mean_intensity / (
- mean_intensity if mean_intensity != 0 else 1
- )
- stats_dict["mean_max_difference"] = max_mean_intensity - mean_intensity
- return roi_props
- def crop_cell_large(
- layer: np.ndarray,
- x_coords: List[float],
- y_coords: List[float],
- padding: Optional[int] = None,
- ) -> Tuple[np.ndarray, List[float], List[float]]:
- """
- Extract a padded subregion from an image layer with coordinate adjustment.
- Parameters
- ----------
- layer : np.ndarray
- 2D or 3D image layer to crop from.
- x_coords : List[float]
- X-coordinates defining the crop boundary.
- y_coords : List[float]
- Y-coordinates defining the crop boundary.
- padding : Optional[int]
- Padding to add around crop area. If None, uses ROI dimensions.
- Returns
- -------
- Tuple[np.ndarray, List[float], List[float]]
- Cropped image layer and adjusted coordinates.
- """
- # Determine cropping boundaries
- x_min, x_max = int(min(x_coords)), int(max(x_coords))
- y_min, y_max = int(min(y_coords)), int(max(y_coords))
- # Apply padding if specified
- if padding is not None:
- x_min -= padding
- x_max += padding
- y_min -= padding
- y_max += padding
- else:
- x_padding = x_max - x_min
- y_padding = y_max - y_min
- x_min -= x_padding
- x_max += x_padding
- y_min -= y_padding
- y_max += y_padding
- # Ensure cropping boundaries are within image dimensions
- layer_height, layer_width = layer.shape[:2]
- x_min = max(0, x_min)
- x_max = min(layer_width - 1, x_max)
- y_min = max(0, y_min)
- y_max = min(layer_height - 1, y_max)
- # Crop the image
- layer_cropped = layer[y_min : y_max + 1, x_min : x_max + 1]
- # Adjust coordinates relative to the cropped image
- x_coords_cropped = [x - x_min for x in x_coords]
- y_coords_cropped = [y - y_min for y in y_coords]
- return layer_cropped, x_coords_cropped, y_coords_cropped
- def fix_polygon(polygon: Polygon) -> Polygon:
- """
- Validate and fix invalid polygons using buffer operations.
- Parameters
- ----------
- polygon : Polygon
- Input polygon to validate and potentially fix.
- Returns
- -------
- Polygon
- Valid polygon or None if correction failed.
- """
- if not polygon.is_valid:
- # Attempt to fix the polygon by applying a zero-width buffer
- polygon = polygon.buffer(0)
- # Check if the polygon is still invalid after buffering
- if not polygon.is_valid:
- print("Polygon could not be fixed. Skipping this polygon.")
- return None
- return polygon
- def crop(layer: np.ndarray) -> np.ndarray:
- """
- Remove rows and columns containing only zero values from image layer.
- Parameters
- ----------
- layer : np.ndarray
- 2D image layer to trim.
- Returns
- -------
- np.ndarray
- Cropped image layer with zero-only rows and columns removed.
- """
- # Remove rows that are entirely zeros
- layer = layer[~np.all(layer == 0, axis=1)]
- # Remove columns that are entirely zeros
- layer = layer[:, ~np.all(layer == 0, axis=0)]
- return layer
- def train_svm(processed_dfs: Dict, random_state: int) -> Pipeline:
- """
- Train an SVM model with hyperparameter tuning using RandomizedSearchCV.
- Parameters
- ----------
- processed_dfs : Dict
- Dictionary containing processed data sets.
- random_state : int, default=42
- Random seed for reproducibility.
- Returns
- -------
- Pipeline
- Best SVM estimator found by random search.
- """
- # Perform randomized search with cross-validation with the validation data
- pipeline_steps = [
- ("scaler", StandardScaler()),
- ("pca", PCA(n_components=0.95, random_state=random_state)),
- (
- "svm",
- SVC(
- kernel="rbf",
- probability=True,
- class_weight="balanced",
- random_state=random_state
- ),
- ),
- ]
- pipeline = Pipeline(pipeline_steps)
- param_dist = {
- "svm__C": uniform(1, 100), # Regularization parameter
- }
- random_search = RandomizedSearchCV(
- pipeline,
- param_dist,
- n_iter=50,
- cv=3,
- random_state=42,
- n_jobs=-1,
- verbose=0,
- error_score="raise",
- )
- random_search.fit(processed_dfs['val']['X'], processed_dfs['val']['y'])
- best_params = random_search.best_params_
- # Perform training on the training set with the best parameters
- final_pipeline_steps = [
- ("scaler", StandardScaler()),
- ("pca", PCA(n_components=0.95, random_state=random_state)),
- (
- "svm",
- SVC(
- kernel="rbf",
- probability=True,
- class_weight="balanced",
- random_state=random_state,
- C=best_params['svm__C']
- ),
- ),
- ]
- final_model = Pipeline(final_pipeline_steps)
- final_model.fit(processed_dfs['train']['X'], processed_dfs['train']['y'])
- return final_model
- def train_rf(
- processed_dfs: Dict, model_type: str, random_state : int
- ) -> Union[RandomForestClassifier, ExtraTreesClassifier]:
- """
- Train a Random Forest or Extra Trees classifier with hyperparameter tuning.
- Parameters
- ----------
- processed_dfs : Dict
- Dictionary containing processed data sets.
- model_type : str
- Model type: 'rf' for Random Forest or 'et' for Extra Trees.
- random_state : int, default=42
- Random seed for reproducibility.
- Returns
- -------
- Union[RandomForestClassifier, ExtraTreesClassifier]
- Best estimator found by random search.
- """
- if model_type == "et":
- classifier = ExtraTreesClassifier(class_weight="balanced", random_state=random_state)
- elif model_type == "rf":
- classifier = RandomForestClassifier(class_weight="balanced", random_state=random_state)
- # Perform randomized search with cross-validation with the validation data
- param_dist = {
- f"{model_type}__n_estimators": [int(x) for x in np.linspace(start=50, stop=500, num=10)],
- f"{model_type}__max_features": ["sqrt", "log2", None],
- f"{model_type}__max_depth": [int(x) for x in np.linspace(10, 100, num=10)] + [None],
- f"{model_type}__min_samples_split": [2, 5, 10, 15, 20],
- f"{model_type}__min_samples_leaf": [1, 2, 4, 8, 10],
- f"{model_type}__bootstrap": [True, False],
- f"{model_type}__criterion": ["gini", "entropy"],
- }
- cv_pipeline = Pipeline([
- (model_type, classifier)
- ])
- random_search = RandomizedSearchCV(
- cv_pipeline,
- param_dist,
- n_iter=50,
- cv=3,
- random_state=random_state,
- n_jobs=-1,
- verbose=0,
- error_score="raise",
- )
- random_search.fit(processed_dfs['val']['X'], processed_dfs['val']['y'])
- best_params = random_search.best_params_
- # Perform training on the training set with the best parameters
- final_params = {k.replace(f'{model_type}__', ''): v for k, v in best_params.items()}
- if model_type == "et":
- final_classifier = ExtraTreesClassifier(class_weight="balanced", random_state=random_state, **final_params)
- else:
- final_classifier = RandomForestClassifier(class_weight="balanced", random_state=random_state, **final_params)
- final_classifier.fit(processed_dfs['train']['X'], processed_dfs['train']['y'])
- return final_classifier
- def train_logreg(processed_dfs : Dict, random_state : int) -> Pipeline:
- """
- Train a Logistic Regression model with hyperparameter tuning.
- Parameters
- ----------
- processed_dfs : Dict
- Dictionary containing processed data sets.
- random_state : int, default=42
- Random seed for reproducibility.
- Returns
- -------
- Pipeline
- Best estimator pipeline with PCA and LogisticRegression.
- """
- # Perform randomized search with cross-validation with the validation data
- pipeline_steps = [
- ("scaler", StandardScaler()),
- ("pca", PCA(n_components=0.95, random_state=random_state)),
- ("log_reg", LogisticRegression(class_weight="balanced", solver='liblinear', random_state=random_state)),
- ]
- cv_pipeline = Pipeline(pipeline_steps)
- param_dist = {
- "log_reg__C": uniform(1, 100),
- "log_reg__penalty": ['l1', 'l2', 'elasticnet']
- }
- random_search = RandomizedSearchCV(
- cv_pipeline,
- param_dist,
- n_iter=50,
- cv=3,
- random_state=random_state,
- n_jobs=-1,
- verbose=0,
- error_score="raise",
- )
- random_search.fit(processed_dfs['val']['X'], processed_dfs['val']['y'])
- best_params = random_search.best_params_
- # Perform training on the training set with the best parameters
- final_pipeline_steps = [
- ("scaler", StandardScaler()),
- ("pca", PCA(n_components=0.95, random_state=random_state)),
- (
- "log_reg",
- LogisticRegression(
- class_weight="balanced",
- random_state=random_state,
- solver='liblinear',
- C=best_params['log_reg__C'],
- penalty=best_params['log_reg__penalty']
- ),
- ),
- ]
- final_model = Pipeline(final_pipeline_steps)
- final_model.fit(processed_dfs['train']['X'], processed_dfs['train']['y'])
- return final_model
- def train_model(
- processed_dfs: Dict, model_type: str, random_state: int
- ) -> Union[Pipeline, RandomForestClassifier, ExtraTreesClassifier]:
- """
- Train a machine learning model based on the specified model type.
- Parameters
- ----------
- processed_dfs : Dict
- Dictionary containing processed data sets.
- model_type : str
- Model type: "svm", "rf", "et", or "logreg".
- random_state : int, default=42
- Random seed for reproducibility.
- Returns
- -------
- Union[Pipeline, RandomForestClassifier, ExtraTreesClassifier]
- Trained machine learning model.
- """
- if model_type == "svm":
- best_model = train_svm(processed_dfs, random_state)
- elif model_type in ["rf", "et"]:
- best_model = train_rf(processed_dfs, model_type, random_state)
- elif model_type == "logreg":
- best_model = train_logreg(processed_dfs, random_state)
- return best_model
- def evaluate_model(
- best_model: Union[Pipeline, RandomForestClassifier, ExtraTreesClassifier],
- processed_dfs: Dict,
- ) -> Dict[str, float]:
- """
- Evaluate model performance using cross-validated predictions.
- Parameters
- ----------
- best_model : Union[Pipeline, RandomForestClassifier, ExtraTreesClassifier]
- Model to be evaluated.
- processed_dfs : Dict
- Dictionary containing processed data sets.
- Returns
- -------
- Dict[str, float]
- Dictionary containing evaluation metrics: roc_auc, ap, precision, recall, f1_score.
- """
- X = processed_dfs['X']
- y = processed_dfs['y']
- # Get cross-validated predictions and probabilities
- y_pred_proba = cross_val_predict(best_model, X, y, cv=3, method="predict_proba")
- y_pred = (y_pred_proba[:, 1] >= 0.5).astype(int)
- y_proba = y_pred_proba[:, 1]
- # Calculate metrics
- roc_auc = roc_auc_score(y, y_proba)
- ap = average_precision_score(y, y_proba)
- precision_score_value = precision_score(y, y_pred)
- recall_score_value = recall_score(y, y_pred)
- f1_score_value = f1_score(y, y_pred)
- metrics = {
- "roc_auc": roc_auc,
- "ap": ap,
- "precision": precision_score_value,
- "recall": recall_score_value,
- "f1_score": f1_score_value,
- }
- return metrics
utils.py at commit 6a397fc, under MIT · 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.
Repositories
Its files are read in the Code ↔ Paper reader above, with 6 matches between paragraphs and lines of code.
Zenodo 19075438
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
- 30 September 2026: the link answers (HTTP 200)
marccanela/cellrake
6a397fcdd5a37f99d4ba272d21cc333d033e0cff, 23 November 2025Availability: 1 check, the latest on 30 September 2026: the link answers
- 30 September 2026: the link answers
9 files
- cellrake/
__init__.py , Python, 4 lines - cellrake/
main.py , Python, 482 lines, 1 match - cellrake/
predicting.py , Python, 305 lines - cellrake/
segmentation.py , Python, 421 lines, 1 match - cellrake/
training.py , Python, 636 lines, 2 matches - cellrake/
utils.py , Python, 693 lines, 2 matches - examples/
analysis_pipeline.ipynb , Jupyter, 147 lines - LICENSE, License, 19 lines
- README.md, Text, 72 lines
Zenodo 19002677
Availability: 1 check, the latest on 30 September 2026: the link answers (HTTP 200)
- 30 September 2026: the link answers (HTTP 200)
9 files
- cellrake/
__init__.py , Python, 4 lines - cellrake/
main.py , Python, 482 lines - cellrake/
predicting.py , Python, 305 lines - cellrake/
segmentation.py , Python, 421 lines - cellrake/
training.py , Python, 636 lines - cellrake/
utils.py , Python, 693 lines - examples/
analysis_pipeline.ipynb , Jupyter, 147 lines - LICENSE, License, 19 lines
- README.md, Text, 72 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 14 scripts, each with its path and the digest of its content;
- 6 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.
Code and data availability statement
The paper has a code and 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 points to the authors' code: marccanela/
cellrake , Zenodo 19002677, Zenodo 19075438 - it says that the data are available on request
- it says that the code is available on request
Read it in the paper: doi.org/10.1016/j.isci.2026.115522.
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, 30 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 6 authors, 3 keywords, 5 funders, 69 references.
Cite
This paper
Canela, M., Adell, J. B., Coll, D. R., González-Parra, J. A., Pinho, J. S., & Busquets-García, A. (2026). Dentate gyrus and CA3 activity mediates light-tone second-order conditioning expression in mice. iScience, 29(4), 115522. https://
BibTeX
@article{canela2026denta
author = {Canela, Marc and Adell, Jordi Bach and Coll, David Roura and González-Parra, Jose Antonio and Pinho, Julia S. and Busquets-García, Arnau},
title = {{Dentate gyrus and CA3 activity mediates light-tone second-order conditioning expression in mice}},
journal = {iScience},
year = {2026},
month = mar,
volume = {29},
number = {4},
pages = {115522},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/
url = {https://
pmid = {42006365},
pmcid = {PMC13091456}
}
RIS
TY - JOUR
AU - Canela, Marc
AU - Adell, Jordi Bach
AU - Coll, David Roura
AU - González-Parra, Jose Antonio
AU - Pinho, Julia S.
AU - Busquets-García, Arnau
TI - Dentate gyrus and CA3 activity mediates light-tone second-order conditioning expression in mice
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/
VL - 29
IS - 4
SP - 115522
SN - 2589-0042
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "Dentate gyrus and CA3 activity mediates light-tone second-order conditioning expression in mice",
"container-title": "iScience",
"author": [
{
"family": "Canela",
"given": "Marc"
},
{
"family": "Adell",
"given": "Jordi Bach"
},
{
"family": "Coll",
"given": "David Roura"
},
{
"family": "González-Parra",
"given": "Jose Antonio"
},
{
"family": "Pinho",
"given": "Julia S."
},
{
"family": "Busquets-García",
"given": "Arnau"
}
],
"container-title-short":
"volume": "29",
"issue": "4",
"page": "115522",
"DOI": "10.1016/
"PMID": "42006365",
"PMCID": "PMC13091456",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
3,
30
]
]
}
}
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.7554/elife.105863 [code]
- Dorsal hippocampus mediates light-tone associations in male mice.Journal: eLifeIn common: pandas, SciPy, Matplotlib, 1 other tool, mouse, 9 references, author Arnau Busquets-García
- [2] doi:10.1016/j.isci.2026.116825 [code]
- Social hierarchy shapes behavioral and transcriptional responses to chronic stress and ketamine in male mice.Journal: iScienceIn common: imbalanced-learn, scikit-image, Pillow, 5 other tools, mouse, 2 references
- [3] doi:10.1038/s41593-023-01281-z [code]
- Ascending neurons convey behavioral state to integrative sensory and action selection brain regions.Journal: Nature neuroscienceIn common: imbalanced-learn, scikit-image, Pillow, 5 other tools, 2 references
- [4] doi:10.7554/elife.95273 [code]
- Unbiased identification of cell identity in dense mixed neural cultures.Journal: eLifeIn common: imbalanced-learn, scikit-image, scikit-learn, 4 other tools, 3 references
- [5] doi:10.1371/journal.pbio.3002646 [code]
- Deep brain stimulation of the Tbr1-deficient mouse model of autism spectrum disorder at the basolateral amygdala alters amygdalar connectivity, whole-brain synchronization, and social behaviors.Journal: PLoS biologyIn common: scikit-image, scikit-learn, pandas, 3 other tools, mouse, 4 references
- [6] doi:10.1126/sciadv.adu9136 [code]
- High-resolution in vivo kinematic tracking with customized injectable fluorescent nanoparticles.Journal: Science advancesIn common: scikit-image, Pillow, scikit-learn, 4 other tools, mouse, 3 references
- [7] doi:10.1016/j.cell.2022.12.010 [code]
- Molecular and spatial signatures of mouse brain aging at single-cell resolution.Journal: CellIn common: imbalanced-learn, scikit-image, Pillow, 5 other tools, mouse, 1 reference
- [8] doi:10.1242/jcs.261950 [code]
- Gut Analysis Toolbox - automating quantitative analysis of enteric neurons.Journal: Journal of cell scienceIn common: scikit-image, Pillow, scikit-learn, 4 other tools, mouse, 3 references
- [9] doi:10.1038/s41586-024-07780-8 [code]
- Inhibitory specificity from a connectomic census of mouse visual cortex.Journal: NatureIn common: imbalanced-learn, scikit-image, Pillow, 5 other tools, mouse, 1 reference
- [10] doi:10.1038/s42003-026-10957-8 [code]
- Brain defence by the extracellular matrix protein Cochlin.Journal: Communications biologyIn common: imbalanced-learn, scikit-image, Pillow, 5 other tools, mouse, 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: 3 repositories of the authors' code, each at its verified commit and with its license, 14 scripts, and 6 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:e7602556ab1a1754…
Add the badge to the code's README
If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.
Markdown
<!-- oscr-badge:start -->
[](https://openscicode.org/badge/doi/10.1016/j.isci.2026.115522)
<!-- oscr-badge:end -->reStructuredText
.. oscr-badge:start
.. image:: https://openscicode.org/badge/doi/10.1016/j.isci.2026.115522.svg
:target: https://openscicode.org/badge/doi/10.1016/j.isci.2026.115522
:alt: OSCR
.. oscr-badge:endHTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/doi/10.1016/j.isci.2026.115522"><img src="https://openscicode.org/badge/doi/10.1016/j.isci.2026.115522.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->On GitHub, open the README, choose Edit (the pencil), paste the snippet under the title, then "Commit changes".
If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.
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: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.
Report a mismatch between the code and the paper · Report a code error (signed in)
Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.
Report a reproduction failure (signed in)
Versions of its code: the releases of its code tied to a version of this paper (the preprint, the accepted manuscript, the version of record…), each with the tracing map versioned with it.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
