sclab 0.2.2__py3-none-any.whl → 0.2.4__py3-none-any.whl

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.

sclab/__init__.py CHANGED
@@ -6,4 +6,4 @@ __all__ = [
6
6
  "SCLabDashboard",
7
7
  ]
8
8
 
9
- __version__ = "0.2.2"
9
+ __version__ = "0.2.4"
sclab/_io.py CHANGED
@@ -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":
sclab/_sclab.py CHANGED
@@ -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
 
sclab/methods/__init__.py CHANGED
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sclab
3
- Version: 0.2.2
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
@@ -18,10 +18,10 @@ Requires-Dist: itables
18
18
  Requires-Dist: numpy<2.2
19
19
  Requires-Dist: pandas
20
20
  Requires-Dist: plotly<6.0
21
- Requires-Dist: requests>=2.32.3
21
+ Requires-Dist: requests
22
22
  Requires-Dist: scikit-learn
23
23
  Requires-Dist: svgpathtools
24
- Requires-Dist: tqdm>=4.67.1
24
+ Requires-Dist: tqdm
25
25
  Requires-Dist: jupyterlab>=4.3.6 ; extra == "jupyter"
26
26
  Requires-Dist: scanpy[leiden, skmisc]>=1.10 ; extra == "scanpy"
27
27
  Requires-Dist: pytest>=8.3.4 ; extra == "test"
@@ -1,7 +1,7 @@
1
- sclab/__init__.py,sha256=UaTIrqZIaNx_mwX7RPdk93mDBq1fkZaElCiMA-bvBIM,132
2
- sclab/_io.py,sha256=21EHrUvYV8WFRbBcdeuWXbApUIITHaXbqgDI8lqQgHo,2852
1
+ sclab/__init__.py,sha256=0XdhioNKeydnAhDycQGD86UAWtEWc9IgYWY4PQKEWPE,132
2
+ sclab/_io.py,sha256=5ISxIPbE233UiOt3QEs9fkLO8DLLEe5HrMnZoR-KLYE,2662
3
3
  sclab/_methods_registry.py,sha256=RcffyRuuLzHqsnAdbBL4W1GmZx80d9AxdGjUnx1mbNg,1704
4
- sclab/_sclab.py,sha256=Fq-GrhapzziTzJgkpPjdjYtjeQpBeXWYVUbPY6axg-A,8688
4
+ sclab/_sclab.py,sha256=kgjChI0h9fVI3sg8O32CJp57KTmoRQ53jGt8eu-_hCQ,8717
5
5
  sclab/dataset/__init__.py,sha256=f9PoXIMAPnC3Var1ODr3mXkotW6u6NRPQvlgcWYXk54,143
6
6
  sclab/dataset/_dataset.py,sha256=dJeiEfo-f6eM866-d53H6FUF9IR-OK4vwDojSq_og0Q,14248
7
7
  sclab/dataset/_exceptions.py,sha256=g8RJL8PiRmD4--PkOs5CZth_qeaduvieMlKJNkrUIYA,45
@@ -20,15 +20,18 @@ sclab/event/_broker.py,sha256=W4GgoBhJS1LxGQv8TYFg71o5jUQPO8BDLrKzahDUyEM,7121
20
20
  sclab/event/_client.py,sha256=Kx7pza-CzLySR0JBBneiZQAjtllUnjWKNKSfw3K2ZQE,2362
21
21
  sclab/event/_utils.py,sha256=LehiFhn7dopNEaTFERJhs6fiVgXCBvseRxWTSWc6u-k,456
22
22
  sclab/examples/__init__.py,sha256=uSu4DMfF2K7xlZbLC_CmANyS3D56khGLMSVt6x9XXiI,68
23
- sclab/examples/processor_steps/__init__.py,sha256=KhbgN0-WrIhpgDZhWJOHr2Vxo0FB1ZBvM2bJK2Mjdmg,372
23
+ sclab/examples/processor_steps/__init__.py,sha256=ymEOSOlQANfMcyjUQxFEzzzjoZFv8IejfnEFUfPqwKg,500
24
24
  sclab/examples/processor_steps/_cluster.py,sha256=olbri3HWPBU8p__r9kP9tgWaJoUJ2bK48pmHfdvf11c,1120
25
25
  sclab/examples/processor_steps/_differential_expression.py,sha256=uEToPiACCgo42oZidAw5DFgWVcDnChWzVRlVzn53K34,11567
26
+ sclab/examples/processor_steps/_gene_expression.py,sha256=io_U53TQ3bpclGZ7xjuQHws4Lei5_nMpWTKbvD2zqs0,4216
27
+ sclab/examples/processor_steps/_integration.py,sha256=Vzl2AdLJmnagPWtNYuqW-AmKbQ8jfRSKdui_DpQX1-8,2729
26
28
  sclab/examples/processor_steps/_neighbors.py,sha256=sEhLuuY-dCdwzqIarHpFVgM4tE1bW9Qa18xHOWA84Bk,2206
27
29
  sclab/examples/processor_steps/_pca.py,sha256=vit15FqHhWC-VSLSViduFt9V7dwakVvdnDOHxzJHiw0,4585
28
- sclab/examples/processor_steps/_preprocess.py,sha256=ffg8Vh-rSJPna08__xOlizu65QBBkRPinslnKRaRjbk,6336
30
+ sclab/examples/processor_steps/_preprocess.py,sha256=pDPAzcqbHyX2zKrGY7HHNYCzrM-wI6VL7YGwUrkq9os,6172
29
31
  sclab/examples/processor_steps/_qc.py,sha256=KPWKxytu5YLXQ42uXe3ARKE36jqj5uidLhtyR-_TVBY,3238
30
32
  sclab/examples/processor_steps/_umap.py,sha256=Mzxj4LiZfh3WT5lS_BO_lTleC5jMoUm5_km_gvzU_I8,1402
31
- sclab/methods/__init__.py,sha256=FMxCemY8-TFHl-BUR6NNDUyOGAAGEhysIlXkSBQXV8g,646
33
+ sclab/methods/__init__.py,sha256=gqqKIvai7E30IA5f4OnYZcyu5xUDF03GzYDkAZNhzr4,823
34
+ sclab/scanpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
35
  sclab/scanpy/_compat.py,sha256=VEdW4lWLtKmgLSrikRnfvYOz9EOa7e_iDt4Q88X9JKQ,2109
33
36
  sclab/scanpy/_settings.py,sha256=UVcJExVHsf_nvyZ5kTrBHPkddHCz7ARCzqAdZAM_A5E,16736
34
37
  sclab/scanpy/logging.py,sha256=VwSPeKjpXeopdcgEAlWDz2Wv4IGAAUv8GyMNpMART-0,8453
@@ -36,7 +39,7 @@ sclab/scanpy/readwrite.py,sha256=yixHonShUZ2Ms3Sv3UXw_VXlY00XDApvmyN2mZWFAcs,370
36
39
  sclab/scanpy/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
40
  sclab/scanpy/plotting/_rcmod.py,sha256=pc53dasHh2RFfTHVTbTb8v1z8vW032zjvum-WQLgjXA,1970
38
41
  sclab/scanpy/plotting/palettes.py,sha256=zHTM_CVfKazb32YreRx0-INllFssZP5rY_B7JTeaBhA,4782
39
- sclab-0.2.2.dist-info/licenses/LICENSE,sha256=LO7qldZoHIo9hc-HMBqclBh5800kZ9US9xTbLAQdHpg,1523
40
- sclab-0.2.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
41
- sclab-0.2.2.dist-info/METADATA,sha256=GciGoDxIh9rPs3KVDs8EQqGq3fP_HfSxQxH4zBOuYVg,4289
42
- sclab-0.2.2.dist-info/RECORD,,
42
+ sclab-0.2.4.dist-info/licenses/LICENSE,sha256=LO7qldZoHIo9hc-HMBqclBh5800kZ9US9xTbLAQdHpg,1523
43
+ sclab-0.2.4.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
44
+ sclab-0.2.4.dist-info/METADATA,sha256=QwxGXc6enzoSEuRb1eEsNNzSn25PCgWk6EQK7hj6VRc,4273
45
+ sclab-0.2.4.dist-info/RECORD,,
File without changes