-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
103 lines (85 loc) · 2.97 KB
/
Copy pathutils.py
File metadata and controls
103 lines (85 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import anndata as ad
from typing import Union, Sequence, Optional, Dict, Tuple
import numpy as np
import pandas as df
def copy_feature_score_to_obs(
patch_table: ad.AnnData,
feature_name: str,
obs_colname: Optional[str] = None,
) -> ad.AnnData:
"""
Copy one feature score from ``patch_table[:, feature_name].X`` into ``patch_table.obs``.
Parameters
----------
patch_table : AnnData
Patch-level AnnData table.
feature_name : str
Feature name in ``patch_table.var_names``.
obs_colname : str, optional
Output column name in ``patch_table.obs``. Defaults to ``feature_name``.
Returns
-------
patch_table : AnnData
The same AnnData object, modified in place.
"""
if feature_name not in patch_table.var_names:
raise KeyError(
f"Feature '{feature_name}' not found in patch_table.var_names."
)
if obs_colname is None:
obs_colname = feature_name
x = patch_table[:, feature_name].X
if hasattr(x, "toarray"):
scores = x.toarray()[:, 0]
else:
scores = np.asarray(x).reshape(-1)
patch_table.obs[obs_colname] = scores
return patch_table
def interpolate_patch_max(
samples: Dict[Tuple[int, int], float],
height: int,
width: int,
patch_size: int,
downsample: int = 1,
) -> np.ndarray:
"""
Rasterize sparse sample scores by painting filled squares of size
``patch_size`` centred on each sample coordinate. Patches are drawn
in ascending score order so the highest score wins on overlap.
Parameters
----------
samples : Dict[Tuple[int, int], float]
Dictionary mapping (x, y) pixel coordinates to scalar scores.
height : int
Full-resolution canvas height.
width : int
Full-resolution canvas width.
patch_size : int
Side length (in full-resolution pixels) of each painted square.
downsample : int, default=1
Factor by which to downsample the canvas before painting.
Coordinates and patch_size are scaled accordingly.
Returns
-------
out : np.ndarray, shape (out_height, out_width), dtype float32
Rasterized score map; background pixels are 0.
"""
out_height = height // downsample
out_width = width // downsample
half = (patch_size // downsample) // 2
out = np.zeros((out_height, out_width), dtype=np.float32)
# Sort ascending so highest score is painted last (wins on overlap)
coords = np.array(list(samples.keys())) # (N, 2) col=x, row=y
scores = np.array(list(samples.values()), dtype=np.float32) # (N,)
order = np.argsort(scores)
for idx in order:
x, y = coords[idx]
score = scores[idx]
xi = int(round(x / downsample))
yi = int(round(y / downsample))
x0 = max(xi - half, 0)
x1 = min(xi + half, out_width - 1)
y0 = max(yi - half, 0)
y1 = min(yi + half, out_height - 1)
out[y0:y1, x0:x1] = score
return out