scFates 1.2.2__tar.gz → 1.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {scfates-1.2.2/scFates.egg-info → scfates-1.2.3}/PKG-INFO +1 -1
  2. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/dendrogram.py +11 -6
  3. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/graph_fitting.py +132 -0
  4. {scfates-1.2.2 → scfates-1.2.3/scFates.egg-info}/PKG-INFO +1 -1
  5. {scfates-1.2.2 → scfates-1.2.3}/LICENSE +0 -0
  6. {scfates-1.2.2 → scfates-1.2.3}/MANIFEST.in +0 -0
  7. {scfates-1.2.2 → scfates-1.2.3}/README.md +0 -0
  8. {scfates-1.2.2 → scfates-1.2.3}/pyproject.toml +0 -0
  9. {scfates-1.2.2 → scfates-1.2.3}/scFates/__init__.py +0 -0
  10. {scfates-1.2.2 → scfates-1.2.3}/scFates/datasets/__init__.py +0 -0
  11. {scfates-1.2.2 → scfates-1.2.3}/scFates/datasets/_datasets.py +0 -0
  12. {scfates-1.2.2 → scfates-1.2.3}/scFates/datasets/test.h5ad +0 -0
  13. {scfates-1.2.2 → scfates-1.2.3}/scFates/get/__init__.py +0 -0
  14. {scfates-1.2.2 → scfates-1.2.3}/scFates/get/get.py +0 -0
  15. {scfates-1.2.2 → scfates-1.2.3}/scFates/logging.py +0 -0
  16. {scfates-1.2.2 → scfates-1.2.3}/scFates/pl.py +0 -0
  17. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/__init__.py +0 -0
  18. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/binned_pseudotime_meta.py +0 -0
  19. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/covariate.py +0 -0
  20. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/dendrogram.py +0 -0
  21. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/features.py +0 -0
  22. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/linearity_deviation.py +0 -0
  23. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/matrix.py +0 -0
  24. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/milestones.py +0 -0
  25. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/module_inclusion.py +0 -0
  26. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/modules.py +0 -0
  27. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/palette_tools.py +0 -0
  28. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/palettes.py +0 -0
  29. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/slide_cors.py +0 -0
  30. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/synchro_path.py +0 -0
  31. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/test_association.py +0 -0
  32. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/test_fork.py +0 -0
  33. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/trajectory.py +0 -0
  34. {scfates-1.2.2 → scfates-1.2.3}/scFates/plot/utils.py +0 -0
  35. {scfates-1.2.2 → scfates-1.2.3}/scFates/pp.py +0 -0
  36. {scfates-1.2.2 → scfates-1.2.3}/scFates/preprocessing/__init__.py +0 -0
  37. {scfates-1.2.2 → scfates-1.2.3}/scFates/preprocessing/diffusion.py +0 -0
  38. {scfates-1.2.2 → scfates-1.2.3}/scFates/preprocessing/pagoda2.py +0 -0
  39. {scfates-1.2.2 → scfates-1.2.3}/scFates/settings.py +0 -0
  40. {scfates-1.2.2 → scfates-1.2.3}/scFates/tests/test_w_plots.py +0 -0
  41. {scfates-1.2.2 → scfates-1.2.3}/scFates/tl.py +0 -0
  42. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/__init__.py +0 -0
  43. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/_test_monocle3.R +0 -0
  44. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/bifurcation_tools.py +0 -0
  45. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/cluster.py +0 -0
  46. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/conversion.py +0 -0
  47. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/correlation_tools.py +0 -0
  48. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/covariate.py +0 -0
  49. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/fit.py +0 -0
  50. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/graph_operations.py +0 -0
  51. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/linearity_deviation.py +0 -0
  52. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/pseudotime.py +0 -0
  53. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/root.py +0 -0
  54. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/slide_cors.py +0 -0
  55. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/test_association.py +0 -0
  56. {scfates-1.2.2 → scfates-1.2.3}/scFates/tools/utils.py +0 -0
  57. {scfates-1.2.2 → scfates-1.2.3}/scFates.egg-info/SOURCES.txt +0 -0
  58. {scfates-1.2.2 → scfates-1.2.3}/scFates.egg-info/dependency_links.txt +0 -0
  59. {scfates-1.2.2 → scfates-1.2.3}/scFates.egg-info/requires.txt +0 -0
  60. {scfates-1.2.2 → scfates-1.2.3}/scFates.egg-info/top_level.txt +0 -0
  61. {scfates-1.2.2 → scfates-1.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scFates
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: scanpy compatible python suite for fast tree inference and advanced pseudotime downstream analysis
5
5
  Author: Louis Faure
6
6
  Project-URL: Repository, https://github.com/LouisFaure/scFates
@@ -82,12 +82,17 @@ def dendrogram(adata: anndata.AnnData, crowdedness: float = 1):
82
82
  df["seg_pos"] = df.seg.astype(str)
83
83
  df["t"] = -df.t
84
84
 
85
- for i, x in enumerate(newseg):
86
- df.loc[df.seg == newseg.index[i], "seg_pos"] = x
87
-
88
- df.seg_pos = df.seg_pos.astype("category").cat.rename_categories(
89
- range(len(df.seg_pos.unique()))
90
- )
85
+ # Sort newseg BEFORE assigning positions to cells
86
+ # This ensures the categorical mapping matches the dendrogram segment order
87
+ newseg_sorted = newseg.iloc[newseg.argsort()]
88
+
89
+ # Create mapping from segment ID to sorted position index
90
+ seg_to_pos = {seg_id: i for i, seg_id in enumerate(newseg_sorted.index)}
91
+
92
+ # Assign positions to cells based on sorted order
93
+ for seg_id, pos_idx in seg_to_pos.items():
94
+ df.loc[df.seg == seg_id, "seg_pos"] = pos_idx
95
+
91
96
  df.seg_pos = df.seg_pos.astype(int).astype("category")
92
97
 
93
98
  dend = stripplot(
@@ -23,6 +23,132 @@ from .. import settings
23
23
  from .utils import get_X
24
24
 
25
25
 
26
+ def _patch_elpigraph_grammar():
27
+ """Monkey-patch elpigraph's AddNode2Node to fix numpy 2.x scalar assignment.
28
+
29
+ In elpigraph 0.3.2, ``ineighbour`` is a 1-element array but is used as a
30
+ scalar index, causing ``ValueError: setting an array element with a sequence``
31
+ on numpy ≥ 2.0 (Linux x86 build) because:
32
+ - ``Mus[ineighbour]`` returns shape ``(1,)`` assigned to a scalar slot
33
+ - ``NodePositions[ineighbour,]`` returns shape ``(1, ndims)`` instead of ``(ndims,)``
34
+ """
35
+ try:
36
+ import elpigraph.src.grammar_operations as _go
37
+ except ImportError:
38
+ return
39
+
40
+ _orig = _go.AddNode2Node
41
+
42
+ def _patched_AddNode2Node(
43
+ X,
44
+ NodePositions,
45
+ ElasticMatrix,
46
+ partition,
47
+ AdjustVect,
48
+ FixNodesAtPoints,
49
+ Max_K=float("inf"),
50
+ MaxNumberOfGraphCandidates=float("inf"),
51
+ PointWeights=None,
52
+ ):
53
+ import numpy as _np
54
+
55
+ nNodes = NodePositions.shape[0]
56
+ Mus = ElasticMatrix.diagonal()
57
+ Lambda = ElasticMatrix.copy()
58
+ _np.fill_diagonal(Lambda, 0)
59
+ indL = Lambda > 0
60
+ Connectivities = indL.sum(axis=0)
61
+
62
+ if PointWeights is not None:
63
+ assoc = _np.bincount(
64
+ partition[partition > -1].ravel(),
65
+ weights=PointWeights[partition > -1].ravel(),
66
+ minlength=nNodes,
67
+ )
68
+ else:
69
+ assoc = _np.bincount(
70
+ partition[partition > -1].ravel(), minlength=nNodes
71
+ )
72
+
73
+ npProt = _np.vstack(
74
+ (NodePositions, _np.zeros((1, NodePositions.shape[1])))
75
+ )
76
+ emProt = _np.vstack(
77
+ (
78
+ _np.hstack((Lambda, _np.zeros((nNodes, 1)))),
79
+ _np.zeros((1, nNodes + 1)),
80
+ )
81
+ )
82
+ niProt = _np.arange(nNodes + 1, dtype=int)
83
+ MuProt = _np.zeros(nNodes + 1)
84
+ MuProt[:-1] = Mus
85
+
86
+ if not _np.isinf(Max_K):
87
+ Degree = _np.sum(ElasticMatrix > 0, axis=1)
88
+ Degree[Degree > 1] = Degree[Degree > 1] - 1
89
+ if _np.sum(Degree <= Max_K) > 1:
90
+ idx_nodes = _np.where(Degree <= Max_K)[0]
91
+ else:
92
+ raise ValueError(
93
+ "AddNode2Node impossible with the current parameters!"
94
+ )
95
+ else:
96
+ idx_nodes = _np.array(range(nNodes))
97
+
98
+ if MaxNumberOfGraphCandidates < len(idx_nodes) and _np.isinf(Max_K):
99
+ idx_nodes = _np.argsort(assoc)[::-1][:MaxNumberOfGraphCandidates]
100
+ elif MaxNumberOfGraphCandidates < len(idx_nodes) and not (
101
+ _np.isinf(Max_K)
102
+ ):
103
+ nGraphs = [
104
+ i
105
+ for i in _np.argsort(assoc)[::-1]
106
+ if i in idx_nodes
107
+ ]
108
+ idx_nodes = _np.array(nGraphs)[:MaxNumberOfGraphCandidates]
109
+
110
+ if FixNodesAtPoints != []:
111
+ idx_nodes = idx_nodes[
112
+ ~_np.isin(idx_nodes, _np.arange(len(FixNodesAtPoints)))
113
+ ]
114
+
115
+ NodePositionsArray = [npProt.copy() for i in range(len(idx_nodes))]
116
+ ElasticMatrices = [emProt.copy() for i in range(len(idx_nodes))]
117
+ NodeIndicesArray = _np.repeat(
118
+ niProt[:, _np.newaxis], len(idx_nodes), axis=1
119
+ )
120
+ AdjustVectArray = [AdjustVect + [False] for i in range(len(idx_nodes))]
121
+
122
+ for j, i in enumerate(idx_nodes):
123
+ MuProt[-1] = 0
124
+ meanL = Lambda[i, indL[i,]].mean(axis=0)
125
+ ElasticMatrices[j][nNodes, i] = ElasticMatrices[j][i, nNodes] = meanL
126
+
127
+ if Connectivities[i] == 1:
128
+ ineighbour = _np.nonzero(indL[i,])[0][0] # scalar, not array
129
+ NewNodePosition = (
130
+ 2 * NodePositions[i,] - NodePositions[ineighbour,]
131
+ )
132
+ MuProt[i] = Mus[ineighbour] # scalar assignment
133
+ else:
134
+ if assoc[i] == 0:
135
+ NewNodePosition = NodePositions[indL[:, i]].mean(axis=0)
136
+ else:
137
+ NewNodePosition = X[(partition == i).ravel()].mean(axis=0)
138
+
139
+ NodePositionsArray[j][nNodes, :] = NewNodePosition
140
+ _np.fill_diagonal(ElasticMatrices[j], MuProt)
141
+
142
+ return (
143
+ NodePositionsArray,
144
+ ElasticMatrices,
145
+ AdjustVectArray,
146
+ NodeIndicesArray,
147
+ )
148
+
149
+ _go.AddNode2Node = _patched_AddNode2Node
150
+
151
+
26
152
  def curve(
27
153
  adata: AnnData,
28
154
  Nodes: int = None,
@@ -466,6 +592,8 @@ def tree_epg(
466
592
 
467
593
  import elpigraph
468
594
 
595
+ _patch_elpigraph_grammar()
596
+
469
597
  logg.hint(
470
598
  "parameters used \n"
471
599
  " "
@@ -528,6 +656,8 @@ def curve_epg(
528
656
  ):
529
657
  import elpigraph
530
658
 
659
+ _patch_elpigraph_grammar()
660
+
531
661
  X, use_rep = get_data(adata, use_rep, ndims_rep)
532
662
  X = X.values
533
663
 
@@ -593,6 +723,8 @@ def circle_epg(
593
723
  ):
594
724
  import elpigraph
595
725
 
726
+ _patch_elpigraph_grammar()
727
+
596
728
  X, use_rep = get_data(adata, use_rep, ndims_rep)
597
729
  X = X.values
598
730
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scFates
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: scanpy compatible python suite for fast tree inference and advanced pseudotime downstream analysis
5
5
  Author: Louis Faure
6
6
  Project-URL: Repository, https://github.com/LouisFaure/scFates
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes