sclab 0.2.4__py3-none-any.whl → 0.3.0__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.

Files changed (51) hide show
  1. sclab/__init__.py +1 -1
  2. sclab/_sclab.py +10 -3
  3. sclab/dataset/_dataset.py +1 -1
  4. sclab/examples/processor_steps/__init__.py +2 -0
  5. sclab/examples/processor_steps/_doublet_detection.py +68 -0
  6. sclab/examples/processor_steps/_integration.py +37 -4
  7. sclab/examples/processor_steps/_neighbors.py +24 -4
  8. sclab/examples/processor_steps/_pca.py +5 -5
  9. sclab/examples/processor_steps/_preprocess.py +14 -1
  10. sclab/examples/processor_steps/_qc.py +22 -6
  11. sclab/gui/__init__.py +0 -0
  12. sclab/gui/components/__init__.py +5 -0
  13. sclab/gui/components/_guided_pseudotime.py +482 -0
  14. sclab/methods/__init__.py +25 -1
  15. sclab/preprocess/__init__.py +18 -0
  16. sclab/preprocess/_cca.py +154 -0
  17. sclab/preprocess/_cca_integrate.py +77 -0
  18. sclab/preprocess/_filter_obs.py +42 -0
  19. sclab/preprocess/_harmony.py +421 -0
  20. sclab/preprocess/_harmony_integrate.py +50 -0
  21. sclab/preprocess/_normalize_weighted.py +61 -0
  22. sclab/preprocess/_subset.py +208 -0
  23. sclab/preprocess/_transfer_metadata.py +137 -0
  24. sclab/preprocess/_transform.py +82 -0
  25. sclab/preprocess/_utils.py +96 -0
  26. sclab/tools/__init__.py +0 -0
  27. sclab/tools/cellflow/__init__.py +0 -0
  28. sclab/tools/cellflow/density_dynamics/__init__.py +0 -0
  29. sclab/tools/cellflow/density_dynamics/_density_dynamics.py +349 -0
  30. sclab/tools/cellflow/pseudotime/__init__.py +0 -0
  31. sclab/tools/cellflow/pseudotime/_pseudotime.py +332 -0
  32. sclab/tools/cellflow/pseudotime/timeseries.py +226 -0
  33. sclab/tools/cellflow/utils/__init__.py +0 -0
  34. sclab/tools/cellflow/utils/density_nd.py +136 -0
  35. sclab/tools/cellflow/utils/interpolate.py +334 -0
  36. sclab/tools/cellflow/utils/smoothen.py +124 -0
  37. sclab/tools/cellflow/utils/times.py +55 -0
  38. sclab/tools/differential_expression/__init__.py +5 -0
  39. sclab/tools/differential_expression/_pseudobulk_edger.py +304 -0
  40. sclab/tools/differential_expression/_pseudobulk_helpers.py +277 -0
  41. sclab/tools/doublet_detection/__init__.py +5 -0
  42. sclab/tools/doublet_detection/_scrublet.py +64 -0
  43. sclab/tools/labeling/__init__.py +6 -0
  44. sclab/tools/labeling/sctype.py +233 -0
  45. sclab/utils/__init__.py +5 -0
  46. sclab/utils/_write_excel.py +510 -0
  47. {sclab-0.2.4.dist-info → sclab-0.3.0.dist-info}/METADATA +7 -2
  48. sclab-0.3.0.dist-info/RECORD +81 -0
  49. sclab-0.2.4.dist-info/RECORD +0 -45
  50. {sclab-0.2.4.dist-info → sclab-0.3.0.dist-info}/WHEEL +0 -0
  51. {sclab-0.2.4.dist-info → sclab-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,510 @@
1
+ import math
2
+ import re
3
+ from collections import defaultdict
4
+ from pathlib import Path
5
+ from typing import Literal, Sequence
6
+
7
+ import numpy as np
8
+ import pandas as pd
9
+
10
+ _column_format_type = Literal[
11
+ "text", "bold", "number", "scientific", "percentage", "nodecimal", "boolean"
12
+ ]
13
+
14
+
15
+ def write_excel(
16
+ dataframes: pd.DataFrame | dict[str, pd.DataFrame],
17
+ file_path: str | Path,
18
+ sortby: str | list[str] | None = None,
19
+ sort_ascending: bool | list[bool] = None,
20
+ autofilter: bool = True,
21
+ guess_formats: bool = True,
22
+ guess_widths: bool = True,
23
+ column_formats: dict[str, _column_format_type] | None = None,
24
+ column_widths: dict[str, int] | None = None,
25
+ verbose: bool = False,
26
+ ) -> None:
27
+ """
28
+ Write pandas DataFrame(s) to an Excel file with enhanced formatting and styling.
29
+
30
+ This function provides advanced Excel writing capabilities including automatic format detection,
31
+ column width adjustment, conditional formatting, and table headers with autofilter.
32
+
33
+ Parameters
34
+ ----------
35
+ dataframes : pandas.DataFrame or dict[str, pandas.DataFrame]
36
+ Single DataFrame or dictionary of DataFrames where keys are sheet names.
37
+ file_path : str or pathlib.Path
38
+ Path where the Excel file will be saved.
39
+ sortby : str or None, optional
40
+ Column name to sort the data by. If specified, applies 3-color scale conditional formatting
41
+ to the sorted column. Default is None.
42
+ sort_ascending : bool, optional
43
+ Sort order when sortby is specified. Default is True.
44
+ autofilter : bool, optional
45
+ Whether to add filter buttons to column headers. Default is True.
46
+ guess_formats : bool, optional
47
+ Whether to automatically detect and apply appropriate formats based on column data types.
48
+ Default is True.
49
+ guess_widths : bool, optional
50
+ Whether to automatically estimate and apply column widths based on column name/contents.
51
+ Default is True.
52
+ column_formats : dict[str, str] or None, optional
53
+ Custom format specifications for columns. Keys are column names, values are format types:
54
+ "text", "bold", "number", "scientific", "percentage", "nodecimal", or "boolean".
55
+ Default is None.
56
+ column_widths : dict[str, int] or None, optional
57
+ Custom width specifications for columns. Keys are column names, values are widths in
58
+ Excel units. Default is None.
59
+ verbose : bool, optional
60
+ Whether to print detailed information about column formatting. Default is False.
61
+
62
+ Returns
63
+ -------
64
+ None
65
+
66
+ Notes
67
+ -----
68
+ - If a single DataFrame is provided, it will be written to 'Sheet1'
69
+ - Percentage columns get conditional formatting based on their values
70
+ - The function validates file writability and format specifications before proceeding
71
+ - Column formats and widths are either explicitly specified or automatically detected
72
+ """
73
+ if not isinstance(sortby, list):
74
+ sortby = [sortby]
75
+
76
+ if sort_ascending is None:
77
+ sort_ascending = [True]
78
+
79
+ if not isinstance(sort_ascending, list):
80
+ sort_ascending = [sort_ascending]
81
+
82
+ if column_formats is None:
83
+ column_formats = {}
84
+ else:
85
+ _validate_column_formats(column_formats)
86
+
87
+ if column_widths is None:
88
+ column_widths = {}
89
+ else:
90
+ _validate_column_widths(column_widths)
91
+
92
+ if not isinstance(dataframes, dict):
93
+ dataframes = {"Sheet1": dataframes}
94
+
95
+ file_path = Path(file_path)
96
+
97
+ if not _is_writable(file_path):
98
+ print(f"File {file_path} is not writable. Please make sure it's not in use.")
99
+ return
100
+
101
+ with pd.ExcelWriter(file_path) as writer:
102
+ for sheet_name, df in dataframes.items():
103
+ df = df.reset_index()
104
+
105
+ _sortby = [c for c in sortby if c in df.columns]
106
+ _sort_ascending = [a for a in sort_ascending if a]
107
+ if not _sort_ascending:
108
+ _sort_ascending = True
109
+ if _sortby:
110
+ df = df.sort_values(by=_sortby, ascending=_sort_ascending)
111
+
112
+ df.to_excel(
113
+ writer, sheet_name=sheet_name, index=False, startrow=1, header=False
114
+ )
115
+ max_row, max_col = df.shape
116
+
117
+ workbook = writer.book
118
+ formats = _get_formats_dict(workbook)
119
+
120
+ worksheet = writer.sheets[sheet_name]
121
+
122
+ for i, col in enumerate(df.columns):
123
+ if col in column_formats:
124
+ column_format = column_formats[col]
125
+ elif guess_formats:
126
+ column_format = _guess_column_format(df[col])
127
+ else:
128
+ column_format = "noformat"
129
+
130
+ if col in column_widths:
131
+ column_width = column_widths[col]
132
+ elif guess_widths:
133
+ try:
134
+ column_width = _guess_column_width(df[col], column_format)
135
+ except ValueError:
136
+ column_width = 10
137
+ else:
138
+ column_width = 10
139
+
140
+ fmt = formats[column_format]
141
+ worksheet.set_column(i, i, column_width, fmt)
142
+
143
+ if verbose:
144
+ _print_column_info(
145
+ i, sheet_name, col, column_format, column_width, max_col
146
+ )
147
+
148
+ if column_format == "percentage":
149
+ fmt = _make_percentage_conditional_format()
150
+ worksheet.conditional_format(0, i, max_row, i, fmt)
151
+
152
+ if column_format == "boolean":
153
+ fmt = _make_cell_color_conditional_format(
154
+ "==", "TRUE", formats["cellGreen"]
155
+ )
156
+ worksheet.conditional_format(0, i, max_row, i, fmt)
157
+
158
+ # if col in sortby:
159
+ # fmt = _make_3_color_scale_conditional_format(df[col])
160
+ # worksheet.conditional_format(0, i, max_row, i, fmt)
161
+
162
+ if m := re.match(
163
+ r"^number_(Blue|Green|Red)(Blue|Green|Red)\|?([\-\+\d.]+)?,?([\-\+\d.]+)?,?([\-\+\d.]+)?$",
164
+ column_format,
165
+ ):
166
+ min_color = m.group(1)
167
+ max_color = m.group(2)
168
+
169
+ if m.group(3):
170
+ min_value = float(m.group(3))
171
+ else:
172
+ min_value = None
173
+
174
+ if m.group(4):
175
+ mid_value = float(m.group(4))
176
+ else:
177
+ mid_value = None
178
+
179
+ if m.group(5):
180
+ max_value = float(m.group(5))
181
+ else:
182
+ max_value = None
183
+
184
+ fmt = _make_3_color_scale_conditional_format(
185
+ df[col],
186
+ min_color=min_color,
187
+ mid_color="White",
188
+ max_color=max_color,
189
+ min_value=min_value,
190
+ mid_value=mid_value,
191
+ max_value=max_value,
192
+ )
193
+ worksheet.conditional_format(0, i, max_row, i, fmt)
194
+
195
+ if m := re.match(
196
+ r"^number_(Blue|Green|Red)(_desc)?\|?([\-\+\d.]+)?,?([\-\+\d.]+)?$",
197
+ column_format,
198
+ ):
199
+ desc = m.group(2) == "_desc"
200
+ if desc:
201
+ min_color = "White"
202
+ max_color = m.group(1)
203
+ else:
204
+ min_color = m.group(1)
205
+ max_color = "White"
206
+
207
+ if m.group(3):
208
+ min_value = float(m.group(3))
209
+ else:
210
+ min_value = None
211
+
212
+ if m.group(4):
213
+ max_value = float(m.group(4))
214
+ else:
215
+ max_value = None
216
+
217
+ fmt = _make_2_color_scale_conditional_format(
218
+ df[col],
219
+ min_color=min_color,
220
+ max_color=max_color,
221
+ min_value=min_value,
222
+ max_value=max_value,
223
+ )
224
+ # print(col, df[col].dtype, df[col].iloc[:5].to_list(), fmt)
225
+ worksheet.conditional_format(0, i, max_row, i, fmt)
226
+
227
+ if column_format == "3color":
228
+ fmt = _make_3_color_scale_conditional_format(df[col])
229
+ worksheet.conditional_format(0, i, max_row, i, fmt)
230
+
231
+ _write_table_header(df.columns, worksheet, formats["header_format"])
232
+
233
+ if autofilter:
234
+ worksheet.autofilter(0, 0, max_row - 1, max_col - 1)
235
+
236
+
237
+ def _color(color: str):
238
+ match color:
239
+ case "Blue":
240
+ return "#B3CDE3"
241
+ case "Green":
242
+ return "#B3E3B3"
243
+ case "Red":
244
+ return "#FFB3B3"
245
+ case "White":
246
+ return "#F7F7F7"
247
+ case _:
248
+ raise ValueError(f"Invalid color: {color}")
249
+
250
+
251
+ def _validate_column_formats(column_formats: dict[str, str]):
252
+ assert isinstance(column_formats, dict), "column_formats must be a dict"
253
+ for col, fmt in column_formats.items():
254
+ if re.match(
255
+ r"^number_(Blue|Green|Red)(Blue|Green|Red)?(_desc)?\|?([\-\+\d.]+)?,?([\-\+\d.]+)?,?([\-\+\d.]+)?$",
256
+ fmt,
257
+ ):
258
+ continue
259
+ else:
260
+ assert fmt in (
261
+ "text",
262
+ "bold",
263
+ "number",
264
+ "scientific",
265
+ "percentage",
266
+ "nodecimal",
267
+ "boolean",
268
+ ), f"Unknown format: {fmt}"
269
+
270
+
271
+ def _validate_column_widths(column_widths: dict[str, int]):
272
+ assert isinstance(column_widths, dict), "column_widths must be a dict"
273
+ for col, width in column_widths.items():
274
+ assert isinstance(width, int | float), f"Invalid column width: {width}"
275
+ assert width > 0, f"Invalid column width: {width}"
276
+
277
+
278
+ def _is_writable(file_path: str | Path) -> None:
279
+ file_path = Path(file_path)
280
+
281
+ if file_path.exists() and file_path.is_file():
282
+ try:
283
+ with open(file_path, "a"):
284
+ return True
285
+ except PermissionError:
286
+ return False
287
+
288
+ return True
289
+
290
+
291
+ def _get_formats_dict(workbook):
292
+ return defaultdict(
293
+ lambda: workbook.add_format(),
294
+ **{
295
+ "noformat": workbook.add_format(),
296
+ "header_format": workbook.add_format(
297
+ {
298
+ "bold": True,
299
+ "text_wrap": True,
300
+ "valign": "top",
301
+ "fg_color": "#FCFCFC",
302
+ "border": 1,
303
+ }
304
+ ),
305
+ "text": workbook.add_format({"font_name": "Calibri", "font_size": 11}),
306
+ "bold": workbook.add_format({"bold": True}),
307
+ "number": workbook.add_format({"num_format": "0.00"}),
308
+ "scientific": workbook.add_format({"num_format": "0.00E+00"}),
309
+ "percentage": workbook.add_format({"num_format": "0.00%"}),
310
+ "nodecimal": workbook.add_format({"num_format": "0"}),
311
+ "boolean": workbook.add_format(
312
+ {
313
+ "bold": True,
314
+ "valign": "center",
315
+ "align": "center",
316
+ "font_name": "Monospace",
317
+ "font_size": 11,
318
+ }
319
+ ),
320
+ **{
321
+ f"cell{color}": workbook.add_format(
322
+ {
323
+ "bg_color": _color(color),
324
+ }
325
+ )
326
+ for color in ["Blue", "Green", "Red", "White"]
327
+ },
328
+ },
329
+ )
330
+
331
+
332
+ def _guess_column_format(column: pd.Series) -> str:
333
+ if pd.api.types.is_bool_dtype(column):
334
+ return "boolean"
335
+
336
+ if pd.api.types.is_numeric_dtype(column):
337
+ if pd.api.types.is_float_dtype(column):
338
+ eps = np.finfo(column.dtype).eps
339
+
340
+ if (column % 1 == 0).all():
341
+ return "nodecimal"
342
+
343
+ if np.log10(column.abs() + eps).max() > 6:
344
+ return "scientific"
345
+
346
+ if np.log10(column.abs() + eps).min() < -3:
347
+ return "scientific"
348
+
349
+ return "number"
350
+
351
+ return "nodecimal"
352
+
353
+ return "text"
354
+
355
+
356
+ def _guess_column_width(
357
+ column: pd.Series,
358
+ column_format: str,
359
+ step: int = 6,
360
+ min_width: int = 10,
361
+ max_width: int = 75,
362
+ ) -> int:
363
+ # widths should be multiple of 5, minimum 10 and maximum 75
364
+ colname = str(column.name)
365
+ colname_len = len(colname)
366
+ if len(column) == 0:
367
+ return _round_width(colname_len, step, min_width, max_width)
368
+
369
+ match column_format:
370
+ case "text":
371
+ max_len = int(column.str.len().max())
372
+ return _round_width(max(max_len, colname_len), step, min_width, max_width)
373
+
374
+ case "number" | "nodecimal" | "scientific" | "boolean":
375
+ return _round_width(colname_len, step, min_width, max_width)
376
+
377
+ case x if re.match("^number_.*", x):
378
+ return _round_width(colname_len, step, min_width, max_width)
379
+
380
+ case "percentage":
381
+ return _round_width(max(min_width, colname_len), step, min_width, max_width)
382
+
383
+ case _:
384
+ raise ValueError(f"Unknown format: {column_format}")
385
+
386
+
387
+ def _round_width(value: float, step: int, min_width: int, max_width: int) -> int:
388
+ out = math.ceil(value * 1.4)
389
+ return int(max(min_width, min(max_width, out)))
390
+
391
+
392
+ def _print_column_info(i, sheet_name, col, column_format, column_width, max_col):
393
+ if i == 0:
394
+ print()
395
+ print("-" * 55)
396
+ print(f"| Sheet Name: {sheet_name:<39} |")
397
+ print("-" * 55)
398
+ print(f"| {'Column':<20} | {'Format':<20} | {'Width':>5} |")
399
+ print("-" * 55)
400
+ print(f"| {col[:20]:>20} | {column_format:>20} | {column_width:>5} |")
401
+ if i == max_col - 1:
402
+ print("-" * 55)
403
+
404
+
405
+ def _make_percentage_conditional_format():
406
+ return {
407
+ "type": "data_bar",
408
+ "bar_color": "#76C1E1", # Light blue for the bar color
409
+ "min_type": "num", # Define minimum as a numeric value
410
+ "min_value": 0, # Minimum percentage (0%)
411
+ "max_type": "num", # Define maximum as a numeric value
412
+ "max_value": 1, # Maximum percentage (100%)
413
+ }
414
+
415
+
416
+ def _make_cell_color_conditional_format(criteria, value, fmt):
417
+ return {
418
+ "type": "cell",
419
+ "criteria": criteria,
420
+ "value": value,
421
+ "format": fmt,
422
+ }
423
+
424
+
425
+ def _make_3_color_scale_conditional_format(
426
+ series: pd.Series,
427
+ scale: float = 1.5,
428
+ min_color: str = "Blue", # soft blue
429
+ mid_color: str = "White", # off-white
430
+ max_color: str = "Red", # soft red
431
+ min_value: int | float | None = None,
432
+ mid_value: int | float | None = None,
433
+ max_value: int | float | None = None,
434
+ ):
435
+ values = series.loc[np.isfinite(series)]
436
+
437
+ if min_value is None and mid_value is None and max_value is None:
438
+ bound = values.quantile([0, 1]).abs().max() * scale
439
+ min_value = -bound
440
+ mid_value = 0
441
+ max_value = bound
442
+
443
+ if min_value is None:
444
+ min_value = values.min()
445
+
446
+ if max_value is None:
447
+ max_value = values.max()
448
+
449
+ if mid_value is None:
450
+ mid_value = (values.max() + values.min()) / 2
451
+
452
+ if not min_color.startswith("#"):
453
+ min_color = _color(min_color)
454
+
455
+ if not mid_color.startswith("#"):
456
+ mid_color = _color(mid_color)
457
+
458
+ if not max_color.startswith("#"):
459
+ max_color = _color(max_color)
460
+
461
+ return {
462
+ "type": "3_color_scale",
463
+ "min_type": "num", # Can be "num", "percent", or "percentile"
464
+ "min_value": min_value,
465
+ "min_color": min_color,
466
+ "mid_type": "num",
467
+ "mid_value": mid_value,
468
+ "mid_color": mid_color,
469
+ "max_type": "num",
470
+ "max_value": max_value,
471
+ "max_color": max_color,
472
+ }
473
+
474
+
475
+ def _make_2_color_scale_conditional_format(
476
+ series: pd.Series,
477
+ min_color: str = "#F7F7F7",
478
+ max_color: str = "#B3E3B3",
479
+ min_value: int | float | None = None,
480
+ max_value: int | float | None = None,
481
+ ):
482
+ values = series.loc[np.isfinite(series)]
483
+
484
+ if min_value is None:
485
+ min_value = values.quantile(0.05)
486
+
487
+ if max_value is None:
488
+ max_value = values.quantile(0.95)
489
+
490
+ if not min_color.startswith("#"):
491
+ min_color = _color(min_color)
492
+
493
+ if not max_color.startswith("#"):
494
+ max_color = _color(max_color)
495
+
496
+ return {
497
+ "type": "2_color_scale",
498
+ "min_type": "num",
499
+ "min_value": min_value,
500
+ "min_color": min_color,
501
+ "max_type": "num",
502
+ "max_value": max_value,
503
+ "max_color": max_color,
504
+ }
505
+
506
+
507
+ def _write_table_header(column_names: Sequence[str], worksheet, header_format):
508
+ # Write the column headers with the defined format.
509
+ for col_num, value in enumerate(column_names):
510
+ worksheet.write(0, col_num, value, header_format)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sclab
3
- Version: 0.2.4
3
+ Version: 0.3.0
4
4
  Summary: sclab
5
5
  Author-email: Argenis Arriojas <ArriojasMaldonado001@umb.edu>
6
6
  Requires-Python: >=3.10,<3.13
@@ -14,15 +14,19 @@ License-File: LICENSE
14
14
  Requires-Dist: anndata
15
15
  Requires-Dist: anywidget
16
16
  Requires-Dist: ipywidgets
17
- Requires-Dist: itables
17
+ Requires-Dist: itables<2.4
18
+ Requires-Dist: matplotlib
18
19
  Requires-Dist: numpy<2.2
19
20
  Requires-Dist: pandas
20
21
  Requires-Dist: plotly<6.0
21
22
  Requires-Dist: requests
23
+ Requires-Dist: ripser>=0.6.12
22
24
  Requires-Dist: scikit-learn
23
25
  Requires-Dist: svgpathtools
24
26
  Requires-Dist: tqdm
25
27
  Requires-Dist: jupyterlab>=4.3.6 ; extra == "jupyter"
28
+ Requires-Dist: anndata2ri>=1.3 ; extra == "r"
29
+ Requires-Dist: rpy2>=3.5 ; extra == "r"
26
30
  Requires-Dist: scanpy[leiden, skmisc]>=1.10 ; extra == "scanpy"
27
31
  Requires-Dist: pytest>=8.3.4 ; extra == "test"
28
32
  Project-URL: Bug Tracker, https://github.com/umbibio/sclab/issues
@@ -31,6 +35,7 @@ Project-URL: Documentation, https://github.com/umbibio/sclab/docs
31
35
  Project-URL: Homepage, https://github.com/umbibio/sclab
32
36
  Project-URL: Repository, https://github.com/umbibio/sclab.git
33
37
  Provides-Extra: jupyter
38
+ Provides-Extra: r
34
39
  Provides-Extra: scanpy
35
40
  Provides-Extra: test
36
41
 
@@ -0,0 +1,81 @@
1
+ sclab/__init__.py,sha256=c1t2JlHvk3gNl7hJgMnqPYJ0157TYvTSnk4sqnqqOXg,132
2
+ sclab/_io.py,sha256=5ISxIPbE233UiOt3QEs9fkLO8DLLEe5HrMnZoR-KLYE,2662
3
+ sclab/_methods_registry.py,sha256=RcffyRuuLzHqsnAdbBL4W1GmZx80d9AxdGjUnx1mbNg,1704
4
+ sclab/_sclab.py,sha256=-ukFb0bWX5MPZsKnoXBJ9SvKyQpuTK4VUCzmWYnAVNM,9062
5
+ sclab/dataset/__init__.py,sha256=f9PoXIMAPnC3Var1ODr3mXkotW6u6NRPQvlgcWYXk54,143
6
+ sclab/dataset/_dataset.py,sha256=wsbWnBHnlGJ779RV1Vv7RfxlEzHCfUZKNT3FTI1mu9g,14248
7
+ sclab/dataset/_exceptions.py,sha256=g8RJL8PiRmD4--PkOs5CZth_qeaduvieMlKJNkrUIYA,45
8
+ sclab/dataset/plotter/__init__.py,sha256=pdWhAywnoc1_nnIcD-qNW0U364-yo4k5DwP79y9NVgA,129
9
+ sclab/dataset/plotter/_controls.py,sha256=NBDdtY1wQbIEvE_WToigR5bEEoi3z30_67T_dLSOSIo,20295
10
+ sclab/dataset/plotter/_plotter.py,sha256=EXwk6KSM7FOyLLJ8HCgIB_2m730t0kHsVKWfQOxL6kA,37023
11
+ sclab/dataset/plotter/_utils.py,sha256=ANm_R9PJd33-QJtZzqXCN5pJ_XrJ7AA4AvSHaDRbOMA,11595
12
+ sclab/dataset/processor/__init__.py,sha256=v8Qbusb6h8oSndv9q-12vzHrz5BDF3N2LCkQG9KC19I,104
13
+ sclab/dataset/processor/_processor.py,sha256=H8smeuHPnJVToSxEgGNHUpyNwKYqP-Itp5jMVIgnjbc,41104
14
+ sclab/dataset/processor/_results_panel.py,sha256=p2xmHgoYfpkPXj-SjRGTmAPAwL1VC8I70iFD_o-90AE,2342
15
+ sclab/dataset/processor/step/__init__.py,sha256=j8j4oU9NMdWHn6kVjft7Klm6xme8M6wzebxJj_zNehg,179
16
+ sclab/dataset/processor/step/_basic_processor_step.py,sha256=7NKC4W-I_EU3QBPi5BL9-NwAF_h6_oWl1l_kEk6gSAg,3640
17
+ sclab/dataset/processor/step/_processor_step_base.py,sha256=DpbL4F53W1YPI_xHuQ0T3gcvDGwwKG2Xp-n8DkMUf90,4133
18
+ sclab/event/__init__.py,sha256=unkfpmoxitPVZvWcc9YhkUwcXODdcd9cw_toVXVIDMU,126
19
+ sclab/event/_broker.py,sha256=W4GgoBhJS1LxGQv8TYFg71o5jUQPO8BDLrKzahDUyEM,7121
20
+ sclab/event/_client.py,sha256=Kx7pza-CzLySR0JBBneiZQAjtllUnjWKNKSfw3K2ZQE,2362
21
+ sclab/event/_utils.py,sha256=LehiFhn7dopNEaTFERJhs6fiVgXCBvseRxWTSWc6u-k,456
22
+ sclab/examples/__init__.py,sha256=uSu4DMfF2K7xlZbLC_CmANyS3D56khGLMSVt6x9XXiI,68
23
+ sclab/examples/processor_steps/__init__.py,sha256=_b9nLeZhyVex17lk8Vvy44eXbvKhygrPOZXpaM1jfSo,575
24
+ sclab/examples/processor_steps/_cluster.py,sha256=olbri3HWPBU8p__r9kP9tgWaJoUJ2bK48pmHfdvf11c,1120
25
+ sclab/examples/processor_steps/_differential_expression.py,sha256=uEToPiACCgo42oZidAw5DFgWVcDnChWzVRlVzn53K34,11567
26
+ sclab/examples/processor_steps/_doublet_detection.py,sha256=eFQtRsdvBWJ_v3HH08v-KbjYius-fj1pg1HBm0mjADg,2114
27
+ sclab/examples/processor_steps/_gene_expression.py,sha256=io_U53TQ3bpclGZ7xjuQHws4Lei5_nMpWTKbvD2zqs0,4216
28
+ sclab/examples/processor_steps/_integration.py,sha256=3WtkMZQTn0VNnLn0q5iVaOa3tmC-L_CsBSAM_YlMDzQ,3733
29
+ sclab/examples/processor_steps/_neighbors.py,sha256=jGpoPtlN8nlcsOqUOiqTPQgGzbpToLAVR1By2SHBo5U,2949
30
+ sclab/examples/processor_steps/_pca.py,sha256=a0-d-ayEM2uywgtU6uGAhaoQVW-blTTLjP7h0veSCfE,4566
31
+ sclab/examples/processor_steps/_preprocess.py,sha256=kKqOQWyBC3BFLYVsCWRPwaXHeuWG1s69puvwhDQK5Eg,6809
32
+ sclab/examples/processor_steps/_qc.py,sha256=3e5TTGPNWbGPJBX0Sx18np8qcrgPznUuJJ-DwCrRZ0U,3684
33
+ sclab/examples/processor_steps/_umap.py,sha256=Mzxj4LiZfh3WT5lS_BO_lTleC5jMoUm5_km_gvzU_I8,1402
34
+ sclab/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ sclab/gui/components/__init__.py,sha256=RaCj_yEgWhdxNKDf0mBgQ3qy3VWJ0UB7hF0AkSs2_OI,88
36
+ sclab/gui/components/_guided_pseudotime.py,sha256=sxI0jmZxD4fxV9CsTJONhINWzIL--YF3nDg0nku2yp8,17670
37
+ sclab/methods/__init__.py,sha256=4FbLhU2gKciC6h5HpTbE4AcOjs07NaxspsabHp6V2dY,1237
38
+ sclab/preprocess/__init__.py,sha256=3gJJsndE50nvO3xE58o24UdJjmFXPtap2CFr7Czpwsc,511
39
+ sclab/preprocess/_cca.py,sha256=_JKFaIRG80HKq8OV867iyK7ozaqMDawAu7PI3CI0JGc,4364
40
+ sclab/preprocess/_cca_integrate.py,sha256=D4nymYZNurmVAMUUBi4hBL-nLjGuEL310cvISnWTUVk,1863
41
+ sclab/preprocess/_filter_obs.py,sha256=uYlcljuaq85G44Si8oxrNRcCCX2nFRdT3RN3ArqnwaY,1166
42
+ sclab/preprocess/_harmony.py,sha256=wpFQXpr13BvljT04I_Rw5JdBvhzvAuinkrRs152CfvQ,13747
43
+ sclab/preprocess/_harmony_integrate.py,sha256=75FxdGNDn6D7rsoXWpORxoc8_x-8o4dE9ePV0zh6JC4,1665
44
+ sclab/preprocess/_normalize_weighted.py,sha256=h86rQakNoXoRKOepAEoBbBtHV_F-VMG2-uW_LcaSdWs,1587
45
+ sclab/preprocess/_subset.py,sha256=8Vc5jty8WzIf8NZ1mleqNJLAp5CRWvEXGVevlT6ekNk,7066
46
+ sclab/preprocess/_transfer_metadata.py,sha256=HA11JHHpq4ueFTeXlU4K3kHDDUzcUjyvfxpzdPBRNTo,4307
47
+ sclab/preprocess/_transform.py,sha256=n2xHJR3T-rRxZneCFH2oMw9RaQcGGBfHpOu1-YP1c1E,2312
48
+ sclab/preprocess/_utils.py,sha256=dLeS_fIvQGZZfesEtbJKtnPmqjqy3fmyTC4GewRD3Fc,3078
49
+ sclab/scanpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ sclab/scanpy/_compat.py,sha256=VEdW4lWLtKmgLSrikRnfvYOz9EOa7e_iDt4Q88X9JKQ,2109
51
+ sclab/scanpy/_settings.py,sha256=UVcJExVHsf_nvyZ5kTrBHPkddHCz7ARCzqAdZAM_A5E,16736
52
+ sclab/scanpy/logging.py,sha256=VwSPeKjpXeopdcgEAlWDz2Wv4IGAAUv8GyMNpMART-0,8453
53
+ sclab/scanpy/readwrite.py,sha256=yixHonShUZ2Ms3Sv3UXw_VXlY00XDApvmyN2mZWFAcs,37025
54
+ sclab/scanpy/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ sclab/scanpy/plotting/_rcmod.py,sha256=pc53dasHh2RFfTHVTbTb8v1z8vW032zjvum-WQLgjXA,1970
56
+ sclab/scanpy/plotting/palettes.py,sha256=zHTM_CVfKazb32YreRx0-INllFssZP5rY_B7JTeaBhA,4782
57
+ sclab/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
+ sclab/tools/cellflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ sclab/tools/cellflow/density_dynamics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ sclab/tools/cellflow/density_dynamics/_density_dynamics.py,sha256=dle_pYTWPXXM7O45i_snnOVaxfbZlgPLQg-CmatNNYA,11000
61
+ sclab/tools/cellflow/pseudotime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
+ sclab/tools/cellflow/pseudotime/_pseudotime.py,sha256=RiwbOduu0InNdh2Rp8DUXG6-r5wL_vVUGTyTkwnYhTY,9842
63
+ sclab/tools/cellflow/pseudotime/timeseries.py,sha256=ZuMAm9LOKksJy2FzsQg3rdYKtLm1G0rbgO6dOdQuIV0,6326
64
+ sclab/tools/cellflow/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ sclab/tools/cellflow/utils/density_nd.py,sha256=BEh5o19u1fd2l15ZMzTHXHJePfo4fjsCbdQmPimdcow,3852
66
+ sclab/tools/cellflow/utils/interpolate.py,sha256=HnpYEBdc4KSPC4QYOglJ2MpipLx3a5ENJQ8uhMnuwRc,9755
67
+ sclab/tools/cellflow/utils/smoothen.py,sha256=yg2_zBrYKGRmXZY8C3pKmX3xGm0GGMI365IKqhgCmP0,3738
68
+ sclab/tools/cellflow/utils/times.py,sha256=lV5ZRjCdBaYELGJ1pGdEBeA0w-WD77lOzPC6R7_kUxo,1811
69
+ sclab/tools/differential_expression/__init__.py,sha256=KKaDzeGGgE1LxnC5aBcPQYcVX_e2h8qAbfMPQVvYlSA,87
70
+ sclab/tools/differential_expression/_pseudobulk_edger.py,sha256=WWqKEA8I1I_YsgjafeznX3tyZoXyu0HV13QkxiYGFgQ,10538
71
+ sclab/tools/differential_expression/_pseudobulk_helpers.py,sha256=raQ0DBBrmrxBbGTKhOyZpZLmeJRX_tWcn3_mzuQctkw,8424
72
+ sclab/tools/doublet_detection/__init__.py,sha256=zWyAPScrHVRaBqWaizVsm2H3oi6yr0OQ5gF-fGY2ZrA,63
73
+ sclab/tools/doublet_detection/_scrublet.py,sha256=koi6MRUS1lWVvdpeNbzpR8njqVFrWEuWoKNMFXQLFec,1953
74
+ sclab/tools/labeling/__init__.py,sha256=o-FJWonGNr2h_pB0o3YfnGl_y1kKU06_rYLmTt8ktlQ,57
75
+ sclab/tools/labeling/sctype.py,sha256=jCsCFnqUgb_s1nTSK-N_5pEL_ZvZw-zUo12fUy9RLfs,8164
76
+ sclab/utils/__init__.py,sha256=Py3dPN9ptMs6D-f7IGYisoxOS2YuX0O1oyw75nci3Os,72
77
+ sclab/utils/_write_excel.py,sha256=DBZg9Kx7Ex6VqFrZFDZbSgvzMtu84iEwKo4nI3I2AT0,17017
78
+ sclab-0.3.0.dist-info/licenses/LICENSE,sha256=LO7qldZoHIo9hc-HMBqclBh5800kZ9US9xTbLAQdHpg,1523
79
+ sclab-0.3.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
80
+ sclab-0.3.0.dist-info/METADATA,sha256=3nl-smhJCgBue7Q9XoCMXUzlU9UpQesGMJYZa_3gLFE,4437
81
+ sclab-0.3.0.dist-info/RECORD,,
@@ -1,45 +0,0 @@
1
- sclab/__init__.py,sha256=0XdhioNKeydnAhDycQGD86UAWtEWc9IgYWY4PQKEWPE,132
2
- sclab/_io.py,sha256=5ISxIPbE233UiOt3QEs9fkLO8DLLEe5HrMnZoR-KLYE,2662
3
- sclab/_methods_registry.py,sha256=RcffyRuuLzHqsnAdbBL4W1GmZx80d9AxdGjUnx1mbNg,1704
4
- sclab/_sclab.py,sha256=kgjChI0h9fVI3sg8O32CJp57KTmoRQ53jGt8eu-_hCQ,8717
5
- sclab/dataset/__init__.py,sha256=f9PoXIMAPnC3Var1ODr3mXkotW6u6NRPQvlgcWYXk54,143
6
- sclab/dataset/_dataset.py,sha256=dJeiEfo-f6eM866-d53H6FUF9IR-OK4vwDojSq_og0Q,14248
7
- sclab/dataset/_exceptions.py,sha256=g8RJL8PiRmD4--PkOs5CZth_qeaduvieMlKJNkrUIYA,45
8
- sclab/dataset/plotter/__init__.py,sha256=pdWhAywnoc1_nnIcD-qNW0U364-yo4k5DwP79y9NVgA,129
9
- sclab/dataset/plotter/_controls.py,sha256=NBDdtY1wQbIEvE_WToigR5bEEoi3z30_67T_dLSOSIo,20295
10
- sclab/dataset/plotter/_plotter.py,sha256=EXwk6KSM7FOyLLJ8HCgIB_2m730t0kHsVKWfQOxL6kA,37023
11
- sclab/dataset/plotter/_utils.py,sha256=ANm_R9PJd33-QJtZzqXCN5pJ_XrJ7AA4AvSHaDRbOMA,11595
12
- sclab/dataset/processor/__init__.py,sha256=v8Qbusb6h8oSndv9q-12vzHrz5BDF3N2LCkQG9KC19I,104
13
- sclab/dataset/processor/_processor.py,sha256=H8smeuHPnJVToSxEgGNHUpyNwKYqP-Itp5jMVIgnjbc,41104
14
- sclab/dataset/processor/_results_panel.py,sha256=p2xmHgoYfpkPXj-SjRGTmAPAwL1VC8I70iFD_o-90AE,2342
15
- sclab/dataset/processor/step/__init__.py,sha256=j8j4oU9NMdWHn6kVjft7Klm6xme8M6wzebxJj_zNehg,179
16
- sclab/dataset/processor/step/_basic_processor_step.py,sha256=7NKC4W-I_EU3QBPi5BL9-NwAF_h6_oWl1l_kEk6gSAg,3640
17
- sclab/dataset/processor/step/_processor_step_base.py,sha256=DpbL4F53W1YPI_xHuQ0T3gcvDGwwKG2Xp-n8DkMUf90,4133
18
- sclab/event/__init__.py,sha256=unkfpmoxitPVZvWcc9YhkUwcXODdcd9cw_toVXVIDMU,126
19
- sclab/event/_broker.py,sha256=W4GgoBhJS1LxGQv8TYFg71o5jUQPO8BDLrKzahDUyEM,7121
20
- sclab/event/_client.py,sha256=Kx7pza-CzLySR0JBBneiZQAjtllUnjWKNKSfw3K2ZQE,2362
21
- sclab/event/_utils.py,sha256=LehiFhn7dopNEaTFERJhs6fiVgXCBvseRxWTSWc6u-k,456
22
- sclab/examples/__init__.py,sha256=uSu4DMfF2K7xlZbLC_CmANyS3D56khGLMSVt6x9XXiI,68
23
- sclab/examples/processor_steps/__init__.py,sha256=ymEOSOlQANfMcyjUQxFEzzzjoZFv8IejfnEFUfPqwKg,500
24
- sclab/examples/processor_steps/_cluster.py,sha256=olbri3HWPBU8p__r9kP9tgWaJoUJ2bK48pmHfdvf11c,1120
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
28
- sclab/examples/processor_steps/_neighbors.py,sha256=sEhLuuY-dCdwzqIarHpFVgM4tE1bW9Qa18xHOWA84Bk,2206
29
- sclab/examples/processor_steps/_pca.py,sha256=vit15FqHhWC-VSLSViduFt9V7dwakVvdnDOHxzJHiw0,4585
30
- sclab/examples/processor_steps/_preprocess.py,sha256=pDPAzcqbHyX2zKrGY7HHNYCzrM-wI6VL7YGwUrkq9os,6172
31
- sclab/examples/processor_steps/_qc.py,sha256=KPWKxytu5YLXQ42uXe3ARKE36jqj5uidLhtyR-_TVBY,3238
32
- sclab/examples/processor_steps/_umap.py,sha256=Mzxj4LiZfh3WT5lS_BO_lTleC5jMoUm5_km_gvzU_I8,1402
33
- sclab/methods/__init__.py,sha256=gqqKIvai7E30IA5f4OnYZcyu5xUDF03GzYDkAZNhzr4,823
34
- sclab/scanpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- sclab/scanpy/_compat.py,sha256=VEdW4lWLtKmgLSrikRnfvYOz9EOa7e_iDt4Q88X9JKQ,2109
36
- sclab/scanpy/_settings.py,sha256=UVcJExVHsf_nvyZ5kTrBHPkddHCz7ARCzqAdZAM_A5E,16736
37
- sclab/scanpy/logging.py,sha256=VwSPeKjpXeopdcgEAlWDz2Wv4IGAAUv8GyMNpMART-0,8453
38
- sclab/scanpy/readwrite.py,sha256=yixHonShUZ2Ms3Sv3UXw_VXlY00XDApvmyN2mZWFAcs,37025
39
- sclab/scanpy/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- sclab/scanpy/plotting/_rcmod.py,sha256=pc53dasHh2RFfTHVTbTb8v1z8vW032zjvum-WQLgjXA,1970
41
- sclab/scanpy/plotting/palettes.py,sha256=zHTM_CVfKazb32YreRx0-INllFssZP5rY_B7JTeaBhA,4782
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