OSCR

Spatial isoform sequencing at single-cell resolution reveals cell-type-specific spatial isoform variability in multiple brain cell types.

Code ↔ Paper

25 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 25 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
  1. [1] § Methods › Splicing event classification of expressed isoforms ↔ isoquant_lib/assignment/isoform_assignment.py, lines 128–268 · score 0.89 · Mutually exclusive exons, Alternative donor, acceptor sites, Intron retention, alternative TSS, Exon skipping
  2. [2] § Methods › Splicing event classification of expressed isoforms ↔ isoquant_lib/assignment/isoform_assignment.py, lines 128–268 · score 0.87 · mutually exclusive exons, alternative donor, acceptor site, intron retention, alternative TSS, exon skipping
  3. [3] § Methods › Spatially variable isoform tests using predefined regions ↔ R/DiffSplicingAnalysis.R, the whole file · a weak match · score 0.83 · minNumReads, numIsoforms, DiffSplicingAnalysis, Delta Pi, IsoQuant, ScisorSeqR
  4. [4] § Methods › Barcode detection for other spatial and single-cell protocols ↔ isoquant_lib/barcode_calling/callers/__init__.py, lines 7–68 · score 0.82 · universal barcode calling, linker sequence, custom molecule, barcode detection, Visium HD, single cell
  5. [5] § Methods › Stereo-seq barcode detection ↔ isoquant_lib/barcode_calling/callers/base.py, lines 153–218 · score 0.71 · alignment score, UMI sequence, Stereo seq, detecting barcode, linker, primer
  6. [6] § Methods › Spatially variable isoform tests using predefined regions ↔ tutorials/Tutorial - predefined regions.ipynb, lines 40–91 · score 0.64 · DiffSplicingAnalysis, cortical layers, hippocampal subregions, brain regions, pairwise, ScisorSeqR
  7. [7] § Methods › Read processing and UMI deduplication ↔ isoquant_lib/parallel_workers.py, lines 353–407 · score 0.64 · edit distance, UMI filtered, PCR duplicates, UMIs, transcript, barcode
  8. [8] § Methods › Spatially variable isoform tests using Moran’s I ↔ src/SplIsoFind/spatially_variable.py, lines 134–268 · score 0.64 · nearest neighbors, spatial weights, permutation, moran, variable, isoform
  9. [9] § Methods › Read processing and UMI deduplication ↔ isoquant_lib/dataset_processor.py, lines 546–600 · score 0.63 · edit distance, UMI filtered, PCR duplicates, UMIs, gene
  10. [10] § Methods › Barcode detection for other spatial and single-cell protocols ↔ isoquant_lib/barcode_calling/__init__.py, lines 63–121 · score 0.62 · molecule structure, barcode detection, barcode calling, Visium HD, Curio, linker
  11. [11] § Methods › Stereo-seq barcode detection ↔ isoquant_lib/barcode_calling/detect_barcodes.py, lines 118–258 · score 0.61 · cDNAs, multiple barcoded, complemented, TSO, seq, UMI
  12. [12] § Methods › Stereo-seq barcode detection ↔ isoquant_lib/barcode_calling/callers/curio.py, lines 197–330 · score 0.59 · known barcode, alignment score, candidate, linker, primer, matches
  13. [13] § Methods › Long-read processing ↔ isoquant_lib/utils/read_mapper.py, lines 313–441 · score 0.59 · junc bed, preset, yes, MD, minimap2, alignment
  14. [14] § Methods › Long-read processing ↔ simulation/assess_barcode_quality.py, lines 526–573 · score 0.58 · Visium HD spatial, Stereo seq, barcode calling, single cell, Curio, v3
  15. [15] § Methods › Read processing and UMI deduplication ↔ isoquant_lib/utils/read_mapper.py, lines 313–441 · score 0.58 · junc bed, yes, MD, minimap2, genome, alignment
  16. [16] § Methods › Barcode detection for other spatial and single-cell protocols ↔ simulation/assess_barcode_quality.py, lines 526–573 · score 0.57 · barcode lengths, Visium HD, Stereo seq, barcode calling, bp, Genomics
  17. [17] § Methods › Barcode detection for other spatial and single-cell protocols ↔ misc/assess_barcode_quality.py, lines 526–573 · score 0.56 · barcode lengths, Visium HD, Stereo seq, barcode calling, bp, Genomics
  18. [18] § Methods › Stereo-seq barcode detection ↔ isoquant_lib/barcode_calling/callers/base.py, lines 33–150 · score 0.56 · alignment score, barcode sequence, linker, primer, protocol, filter
  19. [19] § Methods › Long-read processing ↔ isoquant_lib/barcode_calling/callers/__init__.py, lines 7–68 · score 0.55 · universal barcode calling, Visium HD, Stereo seq, single cell, Curio, v3
  20. [20] § Methods › Stereo-seq barcode detection ↔ isoquant_lib/barcode_calling/callers/base.py, lines 153–218 · score 0.54 · UMI sequence, Stereo seq, linker, concatenated, primers, poly
  21. [21] § Methods › Cell-type-constrained permutations ↔ src/SplIsoFind/spatially_variable.py, lines 567–619 · score 0.53 · constrained permutations, doublet_certain, probabilities, singlet, cells
  22. [22] § Methods › Differential exon testing using predefined comparisons ↔ src/SplIsoFind/preprocess.py, lines 21–100 · score 0.53 · AllInfo, intron chain, mapped, spliced, exons, barcoded
  23. [23] § Results › Gene-expression patterns in coronal brain slices ↔ isoquant_lib/barcode_calling/detect_barcodes.py, lines 118–258 · score 0.51 · cDNAs, complementary, stranded, segment, UMI, seq
  24. [24] § Methods › Benchmarking Stereo-seq barcode detection ↔ simulation/assess_barcode_quality.py, lines 278–375 · score 0.51 · NanoSim, barcode calling, recall, precision, simulated, Stereo
  25. [25] § Results › Detecting spatially variable isoforms using predefined brain regions ↔ R/CSIDE.R, lines 283–430 · score 0.50 · Benjamini Hochberg, gene expression, BH, variable

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 · 496 lines · 18 KB · GPL-2.0 · 3 matches

  1. ############################################################################
  2. # Copyright (c) 2023-2026 University of Helsinki
  3. # # All Rights Reserved
  4. # See file LICENSE for details.
  5. ############################################################################
  6. """
  7. Base classes for barcode detection results.
  8. Provides result containers for barcode calling across different platforms.
  9. """
  10. from collections import defaultdict
  11. from typing import List, Optional, Dict, Iterable, Union
  12. def increase_if_valid(val: Optional[int], delta: int) -> Optional[int]:
  13. """
  14. Increment a coordinate value if it's valid.
  15. Args:
  16. val: Position value (-1 or None indicates invalid)
  17. delta: Amount to increment
  18. Returns:
  19. Incremented value if valid, otherwise original value
  20. """
  21. if val and val != -1:
  22. return val + delta
  23. return val
  24. class BarcodeDetectionResult:
  25. """
  26. Base class for barcode detection results.
  27. Stores detected barcode, UMI, and quality scores for a single read.
  28. Implements the BarcodeResult protocol.
  29. """
  30. NOSEQ = "*" # Sentinel for missing/undetected sequence
  31. def __init__(self, read_id: str, barcode: str = NOSEQ, UMI: str = NOSEQ,
  32. BC_score: int = -1, UMI_good: bool = False, strand: str = "."):
  33. """
  34. Initialize barcode detection result.
  35. Args:
  36. read_id: Read identifier
  37. barcode: Detected barcode sequence (NOSEQ if not found)
  38. UMI: Detected UMI sequence (NOSEQ if not found)
  39. BC_score: Barcode alignment score
  40. UMI_good: Whether UMI passes quality filters
  41. strand: Detected strand ('+', '-', or '.')
  42. """
  43. self.read_id: str = read_id
  44. self._barcode: str = barcode if barcode else BarcodeDetectionResult.NOSEQ
  45. self._umi: str = UMI if UMI else BarcodeDetectionResult.NOSEQ
  46. self.BC_score: int = BC_score
  47. self.UMI_good: bool = UMI_good
  48. self.strand: str = strand
  49. # Primary getters (preferred interface)
  50. def get_barcode(self) -> str:
  51. """Get the detected barcode sequence."""
  52. return self._barcode
  53. def get_umi(self) -> str:
  54. """Get the detected UMI sequence."""
  55. return self._umi
  56. # Backward-compatible property accessors
  57. @property
  58. def barcode(self) -> str:
  59. """Barcode sequence. Prefer get_barcode() for new code."""
  60. return self._barcode
  61. @barcode.setter
  62. def barcode(self, value: str) -> None:
  63. self._barcode = value if value else BarcodeDetectionResult.NOSEQ
  64. @property
  65. def UMI(self) -> str:
  66. """UMI sequence. Prefer get_umi() for new code."""
  67. return self._umi
  68. @UMI.setter
  69. def UMI(self, value: str) -> None:
  70. self._umi = value if value else BarcodeDetectionResult.NOSEQ
  71. def is_valid(self) -> bool:
  72. """Check if a valid barcode was detected."""
  73. return self._barcode != BarcodeDetectionResult.NOSEQ
  74. def has_barcode(self) -> bool:
  75. """Check if a barcode was detected (alias for is_valid())."""
  76. return self._barcode != BarcodeDetectionResult.NOSEQ
  77. def has_umi(self) -> bool:
  78. """Check if a valid UMI was detected."""
  79. return self._umi != BarcodeDetectionResult.NOSEQ
  80. def update_coordinates(self, delta: int) -> None:
  81. """
  82. Shift all genomic coordinates by delta.
  83. Used when processing read subsequences.
  84. Args:
  85. delta: Amount to shift coordinates
  86. """
  87. pass
  88. def more_informative_than(self, that: 'BarcodeDetectionResult') -> bool:
  89. """
  90. Compare two results to determine which is more informative.
  91. Args:
  92. that: Another detection result
  93. Returns:
  94. True if this result is more informative
  95. Raises:
  96. NotImplementedError: Must be implemented by subclasses
  97. """
  98. raise NotImplementedError()
  99. def get_additional_attributes(self) -> List[str]:
  100. """
  101. Get list of detected additional features (primer, linker, etc.).
  102. Returns:
  103. List of detected feature names. Empty list for base class.
  104. """
  105. return []
  106. def set_strand(self, strand: str) -> None:
  107. """Set the detected strand."""
  108. self.strand = strand
  109. def __str__(self) -> str:
  110. """Format result as TSV line."""
  111. return "%s\t%s\t%s\t%d\t%s\t%s" % (self.read_id, self._barcode, self._umi,
  112. self.BC_score, self.UMI_good, self.strand)
  113. @staticmethod
  114. def header() -> str:
  115. """Static header for class-level access."""
  116. return "read_id\tbarcode\tUMI\tBC_score\tvalid_UMI\tstrand"
  117. class LinkerBarcodeDetectionResult(BarcodeDetectionResult):
  118. """
  119. Detection result for platforms with double barcodes (e.g., Curio, Stereo-seq).
  120. Extends base result with positions of additional features:
  121. polyT tail, primer, and linker sequences.
  122. """
  123. def __init__(self, read_id: str, barcode: str = BarcodeDetectionResult.NOSEQ,
  124. UMI: str = BarcodeDetectionResult.NOSEQ,
  125. BC_score: int = -1, UMI_good: bool = False, strand: str = ".",
  126. polyT: int = -1, primer: int = -1, linker_start: int = -1, linker_end: int = -1):
  127. """
  128. Initialize double barcode detection result.
  129. Args:
  130. read_id: Read identifier
  131. barcode: Detected barcode (concatenated if split by linker)
  132. UMI: Detected UMI sequence
  133. BC_score: Barcode alignment score
  134. UMI_good: Whether UMI passes quality filters
  135. strand: Detected strand
  136. polyT: Position of polyT tail start (-1 if not found)
  137. primer: Position of primer end (-1 if not found)
  138. linker_start: Position of linker start (-1 if not found)
  139. linker_end: Position of linker end (-1 if not found)
  140. """
  141. BarcodeDetectionResult.__init__(self, read_id, barcode, UMI, BC_score, UMI_good, strand)
  142. self.primer: int = primer
  143. self.linker_start: int = linker_start
  144. self.linker_end: int = linker_end
  145. self.polyT: int = polyT
  146. def update_coordinates(self, delta: int) -> None:
  147. self.primer = increase_if_valid(self.primer, delta)
  148. self.linker_start = increase_if_valid(self.linker_start, delta)
  149. self.linker_end = increase_if_valid(self.linker_end, delta)
  150. self.polyT = increase_if_valid(self.polyT, delta)
  151. def more_informative_than(self, that: 'LinkerBarcodeDetectionResult') -> bool:
  152. if self.BC_score != that.BC_score:
  153. return self.BC_score > that.BC_score
  154. if self.linker_start != that.linker_start:
  155. return self.linker_start > that.linker_start
  156. if self.primer != that.primer:
  157. return self.primer > that.primer
  158. return self.polyT > that.polyT
  159. def get_additional_attributes(self) -> List[str]:
  160. attr = []
  161. if self.polyT != -1:
  162. attr.append("PolyT detected")
  163. if self.primer != -1:
  164. attr.append("Primer detected")
  165. if self.linker_start != -1:
  166. attr.append("Linker detected")
  167. return attr
  168. def __str__(self) -> str:
  169. return (BarcodeDetectionResult.__str__(self) +
  170. "\t%d\t%d\t%d\t%d" % (self.polyT, self.primer, self.linker_start, self.linker_end))
  171. @staticmethod
  172. def header() -> str:
  173. """Static header for class-level access."""
  174. return BarcodeDetectionResult.header() + "\tpolyT_start\tprimer_end\tlinker_start\tlinker_end"
  175. class TSOBarcodeDetectionResult(LinkerBarcodeDetectionResult):
  176. """Detection result for Stereo-seq with TSO detection."""
  177. def __init__(self, read_id: str, barcode: str = BarcodeDetectionResult.NOSEQ,
  178. UMI: str = BarcodeDetectionResult.NOSEQ,
  179. BC_score: int = -1, UMI_good: bool = False, strand: str = ".",
  180. polyT: int = -1, primer: int = -1, linker_start: int = -1,
  181. linker_end: int = -1, tso: int = -1):
  182. LinkerBarcodeDetectionResult.__init__(self, read_id, barcode, UMI, BC_score, UMI_good, strand,
  183. polyT, primer, linker_start, linker_end)
  184. self.tso5: int = tso
  185. def update_coordinates(self, delta: int) -> None:
  186. self.tso5 = increase_if_valid(self.tso5, delta)
  187. LinkerBarcodeDetectionResult.update_coordinates(self, delta)
  188. def __str__(self) -> str:
  189. return (LinkerBarcodeDetectionResult.__str__(self) +
  190. "\t%d" % self.tso5)
  191. def get_additional_attributes(self) -> List[str]:
  192. attr = []
  193. if self.polyT != -1:
  194. attr.append("PolyT detected")
  195. if self.primer != -1:
  196. attr.append("Primer detected")
  197. if self.linker_start != -1:
  198. attr.append("Linker detected")
  199. if self.tso5 != -1:
  200. attr.append("TSO detected")
  201. return attr
  202. def get_fasta_segment_start(self) -> int:
  203. """Start position of the FASTA segment to extract for this molecule."""
  204. return max(0, self.primer - 25, self.polyT - 75)
  205. def get_fasta_segment_end(self, seq_len: int) -> int:
  206. """End position of the FASTA segment to extract for this molecule."""
  207. if self.tso5 == -1:
  208. return seq_len
  209. return min(seq_len, self.tso5 + 25)
  210. def get_tso_position(self) -> int:
  211. """Return TSO position for use in require_tso checks."""
  212. return self.tso5
  213. @staticmethod
  214. def header() -> str:
  215. """Static header for class-level access."""
  216. return LinkerBarcodeDetectionResult.header() + "\tTSO5"
  217. class TenXBarcodeDetectionResult(BarcodeDetectionResult):
  218. """Detection result for 10x Genomics platforms."""
  219. def __init__(self, read_id: str, barcode: str = BarcodeDetectionResult.NOSEQ,
  220. UMI: str = BarcodeDetectionResult.NOSEQ,
  221. BC_score: int = -1, UMI_good: bool = False, strand: str = ".",
  222. polyT: int = -1, r1: int = -1):
  223. BarcodeDetectionResult.__init__(self, read_id, barcode, UMI, BC_score, UMI_good, strand)
  224. self.r1: int = r1
  225. self.polyT: int = polyT
  226. def update_coordinates(self, delta: int) -> None:
  227. self.r1 = increase_if_valid(self.r1, delta)
  228. self.polyT = increase_if_valid(self.polyT, delta)
  229. def more_informative_than(self, that: 'TenXBarcodeDetectionResult') -> bool:
  230. if self.polyT != that.polyT:
  231. return self.polyT > that.polyT
  232. if self.r1 != that.r1:
  233. return self.r1 > that.r1
  234. return self.BC_score > that.BC_score
  235. def get_additional_attributes(self) -> List[str]:
  236. attr = []
  237. if self.polyT != -1:
  238. attr.append("PolyT detected")
  239. if self.r1 != -1:
  240. attr.append("R1 detected")
  241. return attr
  242. def __str__(self) -> str:
  243. return (BarcodeDetectionResult.__str__(self) +
  244. "\t%d\t%d" % (self.polyT, self.r1))
  245. @staticmethod
  246. def header() -> str:
  247. """Static header for class-level access."""
  248. return BarcodeDetectionResult.header() + "\tpolyT_start\tR1_end"
  249. class TenXSplitBarcodeDetectionResult(TenXBarcodeDetectionResult):
  250. """Detection result for 10x split mode — includes TSO position for molecule boundary."""
  251. def __init__(self, read_id: str, barcode: str = BarcodeDetectionResult.NOSEQ,
  252. UMI: str = BarcodeDetectionResult.NOSEQ,
  253. BC_score: int = -1, UMI_good: bool = False, strand: str = ".",
  254. polyT: int = -1, r1: int = -1, tso: int = -1):
  255. TenXBarcodeDetectionResult.__init__(self, read_id, barcode, UMI, BC_score, UMI_good, strand, polyT, r1)
  256. self.tso: int = tso
  257. def update_coordinates(self, delta: int) -> None:
  258. TenXBarcodeDetectionResult.update_coordinates(self, delta)
  259. if self.tso != -1:
  260. self.tso += delta
  261. def get_fasta_segment_start(self) -> int:
  262. """Start position of FASTA segment: just before R1 linker."""
  263. return max(0, self.r1 - 10) if self.r1 != -1 else 0
  264. def get_fasta_segment_end(self, seq_len: int) -> int:
  265. """End position of FASTA segment: just past the TSO, or end of read."""
  266. if self.tso == -1:
  267. return seq_len
  268. return min(seq_len, self.tso + 35)
  269. def get_tso_position(self) -> int:
  270. """Return TSO position for use in require_tso checks."""
  271. return self.tso
  272. def __str__(self) -> str:
  273. return TenXBarcodeDetectionResult.__str__(self) + "\t%d" % self.tso
  274. @staticmethod
  275. def header() -> str:
  276. return TenXBarcodeDetectionResult.header() + "\ttso_start"
  277. class SplittingBarcodeDetectionResult:
  278. """Result container for read splitting modes (multiple barcodes per read)."""
  279. NOSEQ = BarcodeDetectionResult.NOSEQ # For consistency with protocol
  280. def __init__(self, read_id: str):
  281. self.read_id: str = read_id
  282. self.strand: str = "." # For protocol compatibility
  283. self.detected_patterns: List[Union[TSOBarcodeDetectionResult, TenXSplitBarcodeDetectionResult]] = []
  284. def append(self, barcode_detection_result: Union[TSOBarcodeDetectionResult, TenXSplitBarcodeDetectionResult]) -> None:
  285. self.detected_patterns.append(barcode_detection_result)
  286. def empty(self) -> bool:
  287. return not self.detected_patterns
  288. def filter(self) -> None:
  289. if not self.detected_patterns:
  290. return
  291. barcoded_results = []
  292. for r in self.detected_patterns:
  293. if r.is_valid():
  294. barcoded_results.append(r)
  295. if not barcoded_results:
  296. self.detected_patterns = [self.detected_patterns[0]]
  297. else:
  298. self.detected_patterns = barcoded_results
  299. def get_barcode(self) -> str:
  300. """Get barcode from first valid pattern, or NOSEQ if none."""
  301. for r in self.detected_patterns:
  302. if r.is_valid():
  303. return r.get_barcode()
  304. return self.NOSEQ
  305. def get_umi(self) -> str:
  306. """Get UMI from first valid pattern, or NOSEQ if none."""
  307. for r in self.detected_patterns:
  308. if r.is_valid():
  309. return r.get_umi()
  310. return self.NOSEQ
  311. def is_valid(self) -> bool:
  312. """Check if any pattern has a valid barcode."""
  313. return any(r.is_valid() for r in self.detected_patterns)
  314. def has_barcode(self) -> bool:
  315. """Check if any pattern has a valid barcode."""
  316. return any(r.has_barcode() for r in self.detected_patterns)
  317. def has_umi(self) -> bool:
  318. """Check if any pattern has a valid UMI."""
  319. return any(r.has_umi() for r in self.detected_patterns)
  320. def set_strand(self, strand: str) -> None:
  321. """Set strand for all patterns."""
  322. self.strand = strand
  323. for r in self.detected_patterns:
  324. r.set_strand(strand)
  325. def update_coordinates(self, delta: int) -> None:
  326. """Update coordinates for all patterns."""
  327. for r in self.detected_patterns:
  328. r.update_coordinates(delta)
  329. def more_informative_than(self, other: 'SplittingBarcodeDetectionResult') -> bool:
  330. """Compare by number of valid patterns."""
  331. self_valid = sum(1 for r in self.detected_patterns if r.is_valid())
  332. other_valid = sum(1 for r in other.detected_patterns if r.is_valid())
  333. return self_valid > other_valid
  334. def get_additional_attributes(self) -> List[str]:
  335. """Get combined attributes from all patterns."""
  336. attrs = set()
  337. for r in self.detected_patterns:
  338. attrs.update(r.get_additional_attributes())
  339. return list(attrs)
  340. def __str__(self) -> str:
  341. """Format all patterns as TSV lines."""
  342. return "\n".join(str(r) for r in self.detected_patterns)
  343. @staticmethod
  344. def header() -> str:
  345. """Get TSV header for result output."""
  346. return TSOBarcodeDetectionResult.header()
  347. class ReadStats:
  348. """
  349. Statistics tracker for barcode detection results.
  350. Accumulates counts of processed reads, detected barcodes, valid UMIs,
  351. and platform-specific features (primers, linkers, polyT tails, etc.).
  352. """
  353. def __init__(self):
  354. """Initialize empty statistics."""
  355. self.read_count: int = 0
  356. self.bc_count: int = 0
  357. self.umi_count: int = 0
  358. self.additional_attributes_counts: Dict[str, int] = defaultdict(int)
  359. def add_read(self, barcode_detection_result) -> None:
  360. """
  361. Add a read result to statistics.
  362. Args:
  363. barcode_detection_result: Detection result to accumulate (implements BarcodeResult protocol)
  364. """
  365. self.read_count += 1
  366. # Count detected features (primer, linker, etc.)
  367. for a in barcode_detection_result.get_additional_attributes():
  368. self.additional_attributes_counts[a] += 1
  369. # Count valid barcode
  370. if barcode_detection_result.has_barcode():
  371. self.bc_count += 1
  372. # Count valid UMI
  373. if barcode_detection_result.has_umi():
  374. self.umi_count += 1
  375. def add_custom_stats(self, stat_name: str, val: int) -> None:
  376. """
  377. Add custom statistic value.
  378. Args:
  379. stat_name: Name of statistic
  380. val: Count to add
  381. """
  382. self.additional_attributes_counts[stat_name] += val
  383. def __str__(self) -> str:
  384. """Format statistics as human-readable string."""
  385. human_readable_str = ("Total reads\t%d\nBarcode detected\t%d\nReliable UMI\t%d\n" %
  386. (self.read_count, self.bc_count, self.umi_count))
  387. for a in self.additional_attributes_counts:
  388. human_readable_str += "%s\t%d\n" % (a, self.additional_attributes_counts[a])
  389. return human_readable_str
  390. def __iter__(self) -> Iterable[str]:
  391. """Iterate over statistics as formatted strings."""
  392. yield "Total reads: %d" % self.read_count
  393. yield "Barcode detected: %d" % self.bc_count
  394. yield "Reliable UMI: %d" % self.umi_count
  395. for a in self.additional_attributes_counts:
  396. yield "%s: %d" % (a, self.additional_attributes_counts[a])

base.py at commit 4fcbd0d, under GPL-2.0 · at the source

Overview

Authors: Lieke Michielsen1,2,3,4, Andrey D Prjibelski5, Careen Foord1,2, Yelizaveta Spiegelman1,2, Taewoo Kim1,2,6, Wen Hu1,2, Julien Jarroux1,2, Justine Hsu1,2, Rebecca Pfeil7,8,9, Xinyi Zhang1,2, Li Gan1,6, Alexandru I Tomescu5, Iman Hajirasouliha3,4, Hagen U Tilgner1,2
  1. Feil Family Brain and Mind Research Institute, Weill Cornell Medicine, New York, NY USA
  2. Center for Neurogenetics, Weill Cornell Medicine, New York, NY USA
  3. Department of Systems and Computational Biomedicine, Weill Cornell Medicine of Cornell University, New York, NY USA
  4. Caryl and Israel Englander Institute for Precision Medicine, The Meyer Cancer Center, Weill Cornell Medicine, New York, NY USA
  5. Department of Computer Science, University of Helsinki, Helsinki, Finland
  6. Helen and Robert Appel Alzheimer’s Disease Research Institute, Weill Cornell Medicine, New York, NY USA
  7. Department for Endocrinology and Diabetology, Medical Faculty and University Hospital Düsseldorf, Düsseldorf, Germany
  8. German Diabetes Center (DDZ), Leibniz Institute for Diabetes Research, Düsseldorf, Germany
  9. Center for Digital Medicine, Heinrich Heine University Düsseldorf, Düsseldorf, Germany
Journal: Nature methods, volume 23, issue 9, pages 1869-1881
Dates: received 11 September 2025; accepted 22 July 2026; published online 4 September 2026; in print 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1038/s41592-026-03211-w · PMID 42697995 · PMCID PMC13545012 · OpenAlex W7208746201
Open access: hybrid, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), mouse (organism)
Methods: Connectivity, Statistics, Machine learning, fMRI & imaging
Keywords: RNA splicing, Molecular neuroscience, Statistical methods, Software
MeSH: Brain*, Single-Cell Analysis*, Animals, Mice, Neurons, Protein Isoforms, Single-Cell Gene Expression Analysis, Software (* major topic)
Topic: Single-cell and spatial transcriptomics (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: U.S. Department of Health & Human Services | NIH | National Institute on Drug Abuse (NIDA) (2T32DA039080, U01 DA053625-01); NIGMS NIH HHS (R35 GM138152, R35 GM152101); NIDA NIH HHS (U01 DA053625, T32 DA039080); U.S. Department of Health & Human Services | NIH | Center for Information Technology (Center for Information Technology, National Institutes of Health) (Brain Initiative grant 1RF1MH121267-01); U.S. Department of Health & Human Services | NIH | National Institute of General Medical Sciences (NIGMS) (MIRA R35 GM138152, MIRA R35 GM152101-01); National Science Foundation (NSF) (GRFP # 2139291); European Research Council (101169716); NIMH NIH HHS (RF1 MH121267)
Citations: cited by 1 paper (Europe PMC); 81 references in the paper

Abstract

Spatial long-read technologies are increasingly common but usually lack single-cell resolution. This leaves unanswered whether spatially variable isoforms reflect variability within one cell type or differences in region-specific cell-type composition. Here, we developed Spl-ISO-Seq2 (500-nm resolution) and accompanying software, Spl-IsoQuant-2 and Spl-IsoFind, enabling long-read sequencing of >450 million barcodes versus 80,000 previously. Applying this to the adult mouse brain, we compared differential isoform abundance between known regions and spatial isoform patterns independent of predefined regions. Both identified overlapping hits, for example, Rps24 in oligodendrocytes. For known Snap25 spatial isoform variation, we show that it occurs in excitatory neurons. The region-agnostic approach also uncovered patterns missed by region-based comparisons, for example, for Ighm. Notably, many spatial isoform signals are not driven by cell-type composition alone. Finally, our software is applicable to many spatial and single-cell protocols, demonstrating reproducibility between platforms (for example, Visium HD/Stereo-seq). Overall, our experimental/analytical methods enable a submicron-resolution-isoform view and open avenues for spatial isoform disease research.

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 25 matches between paragraphs and lines of code.

dmcable/spacexr

License: GPL-3.0
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: 9f5dc33c8060f946c6072a138b70e189636e1435, 22 January 2026
Languages: R (102)
Size: 294 files, 102 scripts
Software Heritage: archived
Found in: the text, “Cell-type identification”
Holds: README, license file, environment (DESCRIPTION), documentation, 43 notebooks
Not found: CITATION.cff, tests, continuous integration
Tools: ggplot2 (59 files), tidyverse (35 files), reshape2 (29 files), ggpubr (28 files), Seurat (13 files), caret (3 files), mgcv (2 files), broom (1 file), data.table (1 file), metafor (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
104 files

noush-joglekar/scisorseqr

License: MIT
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: a7ce0bbf0b7694f47701249ebca1937453e2454e, 5 December 2022
Languages: R (24), Shell (11), Python (4)
Size: 98 files, 39 scripts
Software Heritage: archived
Found in: the text, “Differential exon testing using predefined compa”
Holds: README, license file, environment (DESCRIPTION), documentation, 2 notebooks
Not found: CITATION.cff, tests, continuous integration
Tools: tidyverse (12 files), data.table (4 files), ggplot2 (4 files), pandas (3 files), SAMtools (3 files), clusterProfiler (2 files), cowplot (2 files), BEDTools (1 file), reshape2 (1 file), Seurat (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
41 files

algbio/spl-IsoQuant

License: GPL-2.0
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: 4fcbd0dff9e0ac068af308b6a99e296a2b5d34a7, 5 August 2026
Languages: Python (171), Shell (3)
Size: 327 files, 174 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (pyproject.toml, requirements.txt, requirements_tests.txt), tests, continuous integration, documentation
Not found: CITATION.cff
Tools: pysam (13 files), NumPy (11 files), pandas (9 files), XGBoost (4 files), Biopython (3 files), Numba (3 files), SciPy (3 files), Matplotlib (2 files), SAMtools (2 files), BEDTools (1 file), h5py (1 file), scikit-learn (1 file), seaborn (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
176 files

tilgnerlab/Spl-IsoFind

License: MIT
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: 8d2f9f7186e36e63991eeabea20a31060aa3438d, 16 March 2026
Languages: Jupyter (6), Python (5)
Size: 22 files, 11 scripts
Software Heritage: not checked
Found in: “Code availability”
Holds: README, license file, environment (pyproject.toml, docs/requirements.txt), documentation, 6 notebooks
Not found: CITATION.cff, tests, continuous integration
Tools: NumPy (7 files), Matplotlib (5 files), pandas (5 files), Pillow (4 files), SciPy (3 files), seaborn (3 files), Scanpy (1 file), scikit-learn (1 file), statsmodels (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
13 files

tilgnerlab/Spl-IsoFind_reproducibility

License: MIT
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: 3523c8de326e884f213a3a412fe36163091f17be, 22 June 2026
Languages: Python (7), Jupyter (4)
Size: 22 files, 11 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, 4 notebooks
Not found: CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Matplotlib (6 files), NumPy (6 files), pandas (4 files), Pillow (3 files), seaborn (3 files), Scanpy (2 files), statsmodels (2 files), Biopython (1 file), pysam (1 file), SciPy (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
13 files

Code availability

Spl-IsoQuant-2 is an open source software available under GNU General Public License, v.2, and is openly available at https://github.com/algbio/spl-IsoQuant. Spl-IsoFind is available under the MIT License at https://github.com/tilgnerlab/Spl-IsoFind. All command lines and supplementary scripts used for the analysis, plot generation, data simulation and benchmarking are available under the MIT License at https://github.com/tilgnerlab/Spl-IsoFind_reproducibility.

Reproduced under the paper's license (CC BY), from the paper cited above.

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:

  • 5 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 337 scripts, each with its path and the digest of its content;
  • 25 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

Data availability

Sequencing data are available at the Sequencing Read Archive under BioProject ID PRJNA1282707 (http://www.ncbi.nlm.nih.gov/bioproject/PRJNA1282707). 10x Visium HD V2 data are publicly available at https://epi2me.nanoporetech.com/visium_hd_2025.06/. 10x Visium HD V3 data are publicly available at https://downloads.pacbcloud.com/public/dataset/Kinnex-single-cell-RNA/DATA-RevioSPRQ-Kinnex-VisiumHD-mouseBrain/1-Sreads/. The human hippocampus data are available at https://knowledge.brain-map.org/data/ASP3B09DZ8PXDUYSHDH (ref. 9). Simulated data are available at https://doi.org/10.5281/zenodo.19616234 (ref. 80). Intermediate analysis files and supplementary files needed for data processing and processed data are available at https://doi.org/10.5281/zenodo.19499423 (ref. 81). Processed data are available for interactive visualization at spatialisoforms.weill.cornell.edu. Source data are provided with this paper.

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 3, 28 September 2026

  • Publisher: n/a → Nature Portfolio

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 14 authors, 4 keywords, 8 MeSH terms, 8 funders, 78 references.

Cite

This paper

Michielsen, L., Prjibelski, A. D., Foord, C., Spiegelman, Y., Kim, T., Hu, W., Jarroux, J., Hsu, J., Pfeil, R., Zhang, X., Gan, L., Tomescu, A. I., Hajirasouliha, I., & Tilgner, H. U. (2026). Spatial isoform sequencing at single-cell resolution reveals cell-type-specific spatial isoform variability in multiple brain cell types. Nature methods, 23(9), 1869-1881. https://doi.org/10.1038/s41592-026-03211-w

BibTeX

@article{michielsen2026spatial,
author = {Michielsen, Lieke and Prjibelski, Andrey D and Foord, Careen and Spiegelman, Yelizaveta and Kim, Taewoo and Hu, Wen and Jarroux, Julien and Hsu, Justine and Pfeil, Rebecca and Zhang, Xinyi and Gan, Li and Tomescu, Alexandru I and Hajirasouliha, Iman and Tilgner, Hagen U},
title = {{Spatial isoform sequencing at single-cell resolution reveals cell-type-specific spatial isoform variability in multiple brain cell types}},
journal = {Nature methods},
year = {2026},
month = sep,
volume = {23},
number = {9},
pages = {1869--1881},
publisher = {Nature Portfolio},
issn = {1548-7091},
doi = {10.1038/s41592-026-03211-w},
url = {https://doi.org/10.1038/s41592-026-03211-w},
pmid = {42697995},
pmcid = {PMC13545012}
}

RIS

TY - JOUR
AU - Michielsen, Lieke
AU - Prjibelski, Andrey D
AU - Foord, Careen
AU - Spiegelman, Yelizaveta
AU - Kim, Taewoo
AU - Hu, Wen
AU - Jarroux, Julien
AU - Hsu, Justine
AU - Pfeil, Rebecca
AU - Zhang, Xinyi
AU - Gan, Li
AU - Tomescu, Alexandru I
AU - Hajirasouliha, Iman
AU - Tilgner, Hagen U
TI - Spatial isoform sequencing at single-cell resolution reveals cell-type-specific spatial isoform variability in multiple brain cell types
T2 - Nature methods
J2 - Nat Methods
PY - 2026
DA - 2026/09/04
VL - 23
IS - 9
SP - 1869
EP - 1881
SN - 1548-7091
PB - Nature Portfolio
DO - 10.1038/s41592-026-03211-w
UR - https://doi.org/10.1038/s41592-026-03211-w
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41592-026-03211-w",
"type": "article-journal",
"title": "Spatial isoform sequencing at single-cell resolution reveals cell-type-specific spatial isoform variability in multiple brain cell types",
"container-title": "Nature methods",
"author": [
{
"family": "Michielsen",
"given": "Lieke"
},
{
"family": "Prjibelski",
"given": "Andrey D"
},
{
"family": "Foord",
"given": "Careen"
},
{
"family": "Spiegelman",
"given": "Yelizaveta"
},
{
"family": "Kim",
"given": "Taewoo"
},
{
"family": "Hu",
"given": "Wen"
},
{
"family": "Jarroux",
"given": "Julien"
},
{
"family": "Hsu",
"given": "Justine"
},
{
"family": "Pfeil",
"given": "Rebecca"
},
{
"family": "Zhang",
"given": "Xinyi"
},
{
"family": "Gan",
"given": "Li"
},
{
"family": "Tomescu",
"given": "Alexandru I"
},
{
"family": "Hajirasouliha",
"given": "Iman"
},
{
"family": "Tilgner",
"given": "Hagen U"
}
],
"container-title-short": "Nat Methods",
"volume": "23",
"issue": "9",
"page": "1869-1881",
"DOI": "10.1038/s41592-026-03211-w",
"PMID": "42697995",
"PMCID": "PMC13545012",
"ISSN": "1548-7091",
"publisher": "Nature Portfolio",
"URL": "https://doi.org/10.1038/s41592-026-03211-w",
"language": "en",
"issued": {
"date-parts": [
[
2026,
9,
4
]
]
}
}

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-76675-1 [code]
Long-read proteogenomic atlas of human neuronal differentiation reveals isoform diversity informing neurodevelopmental risk mechanisms.
Journal: Nature communications
In common: pysam, Biopython, BEDTools, 15 other tools, genetics / omics, 3 references
[2] doi:10.1038/s42003-026-10957-8 [code]
Brain defence by the extracellular matrix protein Cochlin.
Journal: Communications biology
In common: Biopython, caret, XGBoost, 18 other tools, mouse
[3] doi:10.1038/s41593-026-02293-1 [code]
Optics-free spatial genomics for mapping mammalian brain aging by IRISeq.
Journal: Nature neuroscience
In common: Biopython, SAMtools, Numba, 12 other tools, genetics / omics, mouse, 6 references
[4] doi:10.1016/j.celrep.2026.117073 [code]
Single-cell epigenomics uncovers heterochromatin instability and transcription factor dysfunction during mouse brain aging.
Journal: Cell reports
In common: pysam, BEDTools, SAMtools, 15 other tools, genetics / omics, mouse
[5] doi:10.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: Scanpy, Seurat, cowplot, 12 other tools, genetics / omics, 5 references
[6] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: pysam, Numba, clusterProfiler, 16 other tools, genetics / omics
[7] doi:10.21203/rs.3.rs-9676637/v1 [code]
A Comprehensive Benchmarking of Spatial Deconvolution and Domain Detection Methods across Diverse Tissues and Spatial Transcriptomic Technologies
Journal: Research Square (preprint)
In common: Scanpy, Seurat, cowplot, 11 other tools, genetics / omics, 6 references
[8] doi:10.1186/s13059-026-04177-w [code]
Genomic sequence evolution underlying human neocortical interareal diversification.
Journal: Genome biology
In common: pysam, BEDTools, SAMtools, 14 other tools, genetics / omics, mouse, 1 reference
[9] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: clusterProfiler, Scanpy, Seurat, 13 other tools, genetics / omics, mouse, 3 references
[10] doi:10.1038/s41467-026-71803-3 [code]
Charting the transition from in vitro gliogenesis to the in vivo maturation of human glial progenitor cells transplanted into the hypomyelinated mouse brain.
Journal: Nature communications
In common: BEDTools, SAMtools, Numba, 14 other tools, genetics / omics, 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.

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.