sclab 0.2.3__tar.gz → 0.2.4__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.

Potentially problematic release.


This version of sclab might be problematic. Click here for more details.

Files changed (45) hide show
  1. {sclab-0.2.3 → sclab-0.2.4}/PKG-INFO +1 -1
  2. {sclab-0.2.3 → sclab-0.2.4}/pyproject.toml +5 -1
  3. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/__init__.py +1 -1
  4. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/_io.py +0 -6
  5. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/_sclab.py +1 -1
  6. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/__init__.py +4 -0
  7. sclab-0.2.4/src/sclab/examples/processor_steps/_gene_expression.py +125 -0
  8. sclab-0.2.4/src/sclab/examples/processor_steps/_integration.py +86 -0
  9. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_preprocess.py +2 -4
  10. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/methods/__init__.py +6 -0
  11. sclab-0.2.4/src/sclab/scanpy/plotting/__init__.py +0 -0
  12. {sclab-0.2.3 → sclab-0.2.4}/LICENSE +0 -0
  13. {sclab-0.2.3 → sclab-0.2.4}/README.md +0 -0
  14. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/_methods_registry.py +0 -0
  15. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/__init__.py +0 -0
  16. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/_dataset.py +0 -0
  17. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/_exceptions.py +0 -0
  18. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/plotter/__init__.py +0 -0
  19. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/plotter/_controls.py +0 -0
  20. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/plotter/_plotter.py +0 -0
  21. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/plotter/_utils.py +0 -0
  22. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/__init__.py +0 -0
  23. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/_processor.py +0 -0
  24. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/_results_panel.py +0 -0
  25. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/step/__init__.py +0 -0
  26. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/step/_basic_processor_step.py +0 -0
  27. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/dataset/processor/step/_processor_step_base.py +0 -0
  28. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/event/__init__.py +0 -0
  29. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/event/_broker.py +0 -0
  30. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/event/_client.py +0 -0
  31. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/event/_utils.py +0 -0
  32. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/__init__.py +0 -0
  33. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_cluster.py +0 -0
  34. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_differential_expression.py +0 -0
  35. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_neighbors.py +0 -0
  36. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_pca.py +0 -0
  37. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_qc.py +0 -0
  38. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/examples/processor_steps/_umap.py +0 -0
  39. {sclab-0.2.3/src/sclab/scanpy/plotting → sclab-0.2.4/src/sclab/scanpy}/__init__.py +0 -0
  40. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/_compat.py +0 -0
  41. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/_settings.py +0 -0
  42. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/logging.py +0 -0
  43. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/plotting/_rcmod.py +0 -0
  44. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/plotting/palettes.py +0 -0
  45. {sclab-0.2.3 → sclab-0.2.4}/src/sclab/scanpy/readwrite.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sclab
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: sclab
5
5
  Author-email: Argenis Arriojas <ArriojasMaldonado001@umb.edu>
6
6
  Requires-Python: >=3.10,<3.13
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sclab"
3
- version = "0.2.3"
3
+ version = "0.2.4"
4
4
  description = "sclab"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -48,6 +48,9 @@ build-backend = "flit_core.buildapi"
48
48
  name = "sclab"
49
49
  source = "src/sclab"
50
50
 
51
+ [tool.uv.sources]
52
+ sclab-tools = { path = "../sclab-tools" }
53
+
51
54
  [dependency-groups]
52
55
  dev = [
53
56
  "bump-my-version>=0.31.1",
@@ -60,4 +63,5 @@ dev = [
60
63
  "mkdocs-jupyter>=0.25.1",
61
64
  "scanpy[leiden]>=1.10.4",
62
65
  "jupyterlab>=4.3.6",
66
+ "sclab-tools",
63
67
  ]
@@ -6,4 +6,4 @@ __all__ = [
6
6
  "SCLabDashboard",
7
7
  ]
8
8
 
9
- __version__ = "0.2.3"
9
+ __version__ = "0.2.4"
@@ -58,12 +58,6 @@ def load_adata_from_url(
58
58
  assert is_valid_url(url), "URL is not valid"
59
59
  url_path = Path(urlparse(url).path)
60
60
 
61
- if url_path.suffix == ".h5":
62
- try:
63
- import scanpy as sc
64
- except ImportError:
65
- raise ImportError("Please install scanpy: `pip install scanpy`")
66
-
67
61
  file_content = fetch_file(url, progress=progress)
68
62
  match url_path.suffix:
69
63
  case ".h5":
@@ -187,7 +187,7 @@ class DataLoader(VBox):
187
187
  user_f_locals = inspect.stack()[2].frame.f_locals
188
188
  self.defined_adatas_dict = {}
189
189
  for name, variable_type in [(k, type(v)) for k, v in user_f_locals.items()]:
190
- if variable_type is AnnData:
190
+ if variable_type is AnnData and not name.startswith("_"):
191
191
  self.defined_adatas_dict[name] = user_f_locals[name]
192
192
 
193
193
  self.defined_adatas_label = Label(
@@ -1,5 +1,7 @@
1
1
  from ._cluster import Cluster
2
2
  from ._differential_expression import DifferentialExpression
3
+ from ._gene_expression import GeneExpression
4
+ from ._integration import Integration
3
5
  from ._neighbors import Neighbors
4
6
  from ._pca import PCA
5
7
  from ._preprocess import Preprocess
@@ -10,8 +12,10 @@ __all__ = [
10
12
  "QC",
11
13
  "Preprocess",
12
14
  "PCA",
15
+ "Integration",
13
16
  "Neighbors",
14
17
  "UMAP",
15
18
  "Cluster",
19
+ "GeneExpression",
16
20
  "DifferentialExpression",
17
21
  ]
@@ -0,0 +1,125 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import plotly.colors as pc
4
+ import plotly.express as px
5
+ from ipywidgets import Combobox, Dropdown
6
+
7
+ from sclab.dataset.processor import Processor
8
+ from sclab.dataset.processor.step import ProcessorStepBase
9
+
10
+ colorscales = list(
11
+ filter(lambda s: "swatch" not in s and not s.startswith("_"), dir(pc.sequential))
12
+ )
13
+
14
+
15
+ class GeneExpression(ProcessorStepBase):
16
+ parent: Processor
17
+ name: str = "gene_expression"
18
+ description: str = "Gene Expression"
19
+
20
+ run_button_description = "Plot Expression"
21
+
22
+ def __init__(self, parent: Processor) -> None:
23
+ df = parent.dataset.metadata.select_dtypes("number")
24
+ df = parent.dataset.metadata
25
+ axis_key_options = {"": None, **{c: c for c in df.columns}}
26
+
27
+ gene_input_options = parent.dataset.adata.var_names
28
+ genes_df = parent.dataset.adata.var
29
+ info_cols = ["name", "symbol", "description"]
30
+ for col in [
31
+ c for c in genes_df.columns if any([s.lower() in c for s in info_cols])
32
+ ]:
33
+ new_info = genes_df[col].astype(str).str.replace("nan", "")
34
+ gene_input_options = gene_input_options + " - " + new_info
35
+
36
+ variable_controls = dict(
37
+ gene_input=Combobox(
38
+ placeholder="Type gene name",
39
+ options=gene_input_options.to_list(),
40
+ description="Gene",
41
+ ensure_option=True,
42
+ ),
43
+ layer=Dropdown(
44
+ options=tuple(parent.dataset.adata.layers.keys()),
45
+ value=None,
46
+ description="Layer",
47
+ ),
48
+ time_key=Dropdown(
49
+ options=axis_key_options,
50
+ value=None,
51
+ description="Horiz. axis",
52
+ ),
53
+ colorscale=Dropdown(
54
+ options=colorscales, value="Oryel", description="Col. scale"
55
+ ),
56
+ )
57
+
58
+ super().__init__(
59
+ parent=parent,
60
+ fixed_params={},
61
+ variable_controls=variable_controls,
62
+ )
63
+
64
+ self.variable_controls["gene_input"].observe(self.send_plot, names="value")
65
+ self.variable_controls["layer"].observe(self.send_plot, names="value")
66
+ self.variable_controls["time_key"].observe(self.send_plot, names="value")
67
+ self.variable_controls["colorscale"].observe(self.send_plot, names="value")
68
+
69
+ def function(self, *pargs, **kwargs):
70
+ self.send_plot({})
71
+
72
+ def send_plot(self, change: dict):
73
+ adata = self.parent.dataset.adata
74
+ metadata = self.parent.dataset.metadata
75
+ selected_cells = self.parent.dataset.selected_rows
76
+
77
+ gene_input: str = self.variable_controls["gene_input"].value
78
+ layer: str = self.variable_controls["layer"].value
79
+ time_key: str = self.variable_controls["time_key"].value
80
+ colorscale: str = self.variable_controls["colorscale"].value
81
+
82
+ if gene_input is None or gene_input == "":
83
+ self.update_output("")
84
+ return
85
+
86
+ if layer is None or layer == "":
87
+ self.update_output("")
88
+ return
89
+
90
+ gene_id = gene_input.split(" ")[0]
91
+
92
+ if layer == "X":
93
+ X = adata[:, gene_id].X
94
+ else:
95
+ X = adata[:, gene_id].layers[layer]
96
+
97
+ E = np.asarray(X.sum(axis=1)).flatten()
98
+
99
+ self.update_output(f"Showing gene: {gene_id}")
100
+ # self.variable_controls["gene_input"].value = ""
101
+
102
+ df = pd.DataFrame({gene_id: E}, index=adata.obs.index)
103
+ metadata = metadata.join(df)
104
+ if selected_cells.size > 0:
105
+ metadata = metadata.loc[selected_cells]
106
+
107
+ if time_key is None:
108
+ self.broker.publish(
109
+ "dplt_plot_figure_request",
110
+ metadata=metadata,
111
+ colorby=gene_id,
112
+ color_continuous_scale=colorscale,
113
+ )
114
+ return
115
+
116
+ fig = px.scatter(
117
+ metadata,
118
+ x=time_key,
119
+ y=gene_id,
120
+ color=gene_id,
121
+ color_continuous_scale=colorscale,
122
+ hover_name=adata.obs.index,
123
+ title=f"Gene: {gene_id}, Layer: {layer}",
124
+ )
125
+ self.broker.publish("dplt_plot_figure_request", figure=fig)
@@ -0,0 +1,86 @@
1
+ from ipywidgets import Dropdown
2
+
3
+ from sclab.dataset.processor import Processor
4
+ from sclab.dataset.processor.step import ProcessorStepBase
5
+
6
+
7
+ class Integration(ProcessorStepBase):
8
+ parent: Processor
9
+ name: str = "integration"
10
+ description: str = "Integration"
11
+
12
+ def __init__(self, parent: Processor) -> None:
13
+ try:
14
+ from scanpy.external.pp import harmony_integrate # noqa
15
+ except ImportError:
16
+ try:
17
+ from scanpy.external.pp import scanorama_integrate # noqa
18
+ except ImportError:
19
+ raise ImportError(
20
+ "Integration requires scanorama or harmony to be installed.\n"
21
+ "\nInstall with one of:\n"
22
+ "\npip install harmony"
23
+ "\npip install scanorama"
24
+ "\n"
25
+ )
26
+
27
+ cat_metadata = parent.dataset._metadata.select_dtypes(
28
+ include=["object", "category"]
29
+ )
30
+ cat_options = {"": None, **{c: c for c in cat_metadata.columns}}
31
+
32
+ variable_controls = dict(
33
+ use_rep=Dropdown(
34
+ options=tuple(parent.dataset.adata.obsm.keys()),
35
+ value=None,
36
+ description="Use rep.",
37
+ ),
38
+ group_by=Dropdown(
39
+ options=cat_options,
40
+ value="batch" if "batch" in cat_options else None,
41
+ description="GroupBy",
42
+ ),
43
+ flavor=Dropdown(
44
+ options=["harmony", "scanorama"],
45
+ value="harmony",
46
+ description="Flavor",
47
+ ),
48
+ )
49
+
50
+ super().__init__(
51
+ parent=parent,
52
+ fixed_params={},
53
+ variable_controls=variable_controls,
54
+ )
55
+
56
+ def function(self, use_rep: str, group_by: str, flavor: str):
57
+ adata = self.parent.dataset.adata
58
+
59
+ key_added = f"{use_rep}_{flavor}"
60
+ kvargs = {
61
+ "adata": adata,
62
+ "key": group_by,
63
+ "basis": use_rep,
64
+ "adjusted_basis": key_added,
65
+ }
66
+
67
+ self.broker.std_output.clear_output(wait=False)
68
+ with self.broker.std_output:
69
+ match flavor:
70
+ case "harmony":
71
+ from scanpy.external.pp import harmony_integrate
72
+
73
+ harmony_integrate(**kvargs)
74
+
75
+ case "scanorama":
76
+ from scanpy.external.pp import scanorama_integrate
77
+
78
+ scanorama_integrate(**kvargs)
79
+ case _:
80
+ raise ValueError(f"Unknown flavor: {flavor}")
81
+
82
+ self.broker.publish(
83
+ "dset_data_dict_change",
84
+ self.parent.dataset.data_dict,
85
+ key_added,
86
+ )
@@ -129,7 +129,6 @@ class Preprocess(ProcessorStepBase):
129
129
  if normalize_total:
130
130
  new_layer += "_normt"
131
131
  sc.pp.normalize_total(adata, target_sum=1e4)
132
- adata.layers[new_layer] = adata.X.copy()
133
132
 
134
133
  pbar.update(10)
135
134
  pbar.update(10)
@@ -138,7 +137,6 @@ class Preprocess(ProcessorStepBase):
138
137
  new_layer += "_log1p"
139
138
  adata.uns.pop("log1p", None)
140
139
  sc.pp.log1p(adata)
141
- adata.layers[new_layer] = adata.X.copy()
142
140
  pbar.update(10)
143
141
 
144
142
  vars_to_regress = []
@@ -154,13 +152,13 @@ class Preprocess(ProcessorStepBase):
154
152
  if vars_to_regress:
155
153
  new_layer += "_regr"
156
154
  sc.pp.regress_out(adata, keys=vars_to_regress, n_jobs=1)
157
- adata.layers[new_layer] = adata.X.copy()
158
155
  pbar.update(10)
159
156
 
160
157
  if scale:
161
158
  new_layer += "_scale"
162
159
  sc.pp.scale(adata, zero_center=False)
163
- adata.layers[new_layer] = adata.X.copy()
160
+
161
+ adata.layers[new_layer] = adata.X.copy()
164
162
 
165
163
  pbar.update(10)
166
164
 
@@ -5,6 +5,8 @@ from ..examples.processor_steps import (
5
5
  UMAP,
6
6
  Cluster,
7
7
  DifferentialExpression,
8
+ GeneExpression,
9
+ Integration,
8
10
  Neighbors,
9
11
  Preprocess,
10
12
  )
@@ -13,16 +15,20 @@ __all__ = [
13
15
  "QC",
14
16
  "Preprocess",
15
17
  "PCA",
18
+ "Integration",
16
19
  "Neighbors",
17
20
  "UMAP",
18
21
  "Cluster",
22
+ "GeneExpression",
19
23
  "DifferentialExpression",
20
24
  ]
21
25
 
22
26
  register_sclab_method("Processing")(QC)
23
27
  register_sclab_method("Processing")(Preprocess)
24
28
  register_sclab_method("Processing")(PCA)
29
+ register_sclab_method("Processing")(Integration)
25
30
  register_sclab_method("Processing")(Neighbors)
26
31
  register_sclab_method("Processing")(UMAP)
27
32
  register_sclab_method("Processing")(Cluster)
33
+ register_sclab_method("Analysis")(GeneExpression)
28
34
  register_sclab_method("Analysis")(DifferentialExpression)
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