Skip to content

Commit 1bae350

Browse files
Merge pull request #1 from HiDiHlabs/dev
Dev
2 parents 72bc558 + b8798f0 commit 1bae350

File tree

18 files changed

+500463
-1073
lines changed

18 files changed

+500463
-1073
lines changed

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exclude test/*
2+
exclude tutorial/*

bld.bat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"%PYTHON%" setup.py install
2+
if errorlevel 1 exit 1

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$PYTHON setup.py install

meta.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{% set name = "plankton" %}
2+
{% set version = "0.0.1" %}
3+
4+
package:
5+
name: "{{ name|lower }}"
6+
version: "{{ version }}"
7+
8+
source:
9+
git_url: "https://github.com/HiDiHlabs/planktonpy"
10+
url: "https://pypi.org/project/planktonspace/"
11+
12+
requirements:
13+
build:
14+
- python
15+
- setuptools
16+
17+
run:
18+
- python
19+
- numpy
20+
- jupyter
21+
- matplotlib
22+
- numpy
23+
- pandas
24+
- plotly
25+
- scipy
26+
- scikit-image
27+
- scikit-learn
28+
- umap-learn
29+
# - anndata
30+
# - scanpy
31+
32+
# test:
33+
# imports:
34+
# -
35+
36+
# about:
37+
# home:

plankton/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# from plankton import *
22
# from stats import *
3-
import plankton
3+
# from plankton import *

plankton/graph.py

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class SpatialGraph():
2828
:param n_neighbors: number of nearset neighbors to infer, defaults to 10
2929
:type n_neighbors: int, optional
3030
"""
31+
3132
def __init__(self, sdata, n_neighbors=10) -> None:
3233

3334
self.sdata = sdata
@@ -74,6 +75,14 @@ def neighbor_types(self):
7475
self.n_neighbors)
7576
return self._neighbor_types[:, :self.n_neighbors]
7677

78+
@property
79+
def umap_0(self):
80+
return self._umap[:, 0]
81+
82+
@property
83+
def umap_1(self):
84+
return self._umap[:, 1]
85+
7786
@property
7887
def umap(self):
7988
"""umap: Returns the coordinates of the UMAP representation of the source data.
@@ -216,7 +225,7 @@ def plot_entropy(self, n_neighbors=4):
216225
linestyle='dotted')
217226
fig.add_artist(con)
218227

219-
def _determine_counts(self, bandwidth=1, kernel=None):
228+
def _determine_counts(self, bandwidth=1, regularization=0, kernel=None):
220229
"""_determine_counts: Determines the count distributions of genes around each molecule, thus effectively generating models of the immediate environment.
221230
222231
:param bandwidth: Bandwidth of the default Gaussian kernel, defaults to 1
@@ -234,9 +243,14 @@ def kernel(x): return np.exp(-x**2/(2*bandwidth**2))
234243
for i in range(0, self.n_neighbors):
235244
counts[np.arange(len(self.sdata)), self.neighbor_types[:, i]
236245
] += kernel(self.distances[:, i])
246+
247+
assert (all(counts.sum(1)) > 0)
248+
counts[np.arange(len(self.sdata)),
249+
self.sdata.gene_ids] += regularization-1
250+
237251
return counts
238252

239-
def run_umap(self, bandwidth=1, kernel=None, metric='euclidean', zero_weight=1.0, cutoff = None, *args, **kwargs):
253+
def run_umap(self, bandwidth=1, kernel=None, metric='euclidean', zero_weight=1.0, cutoff=None, *args, **kwargs):
240254
"""run_umap: Creates a UMAP representation of recurring local contexts in the source data.
241255
242256
:param bandwidth: Bandwidth of the default Gaussian kernel used to build local environment models, defaults to 1
@@ -249,10 +263,8 @@ def run_umap(self, bandwidth=1, kernel=None, metric='euclidean', zero_weight=1.0
249263
:type zero_weight: float, optional
250264
"""
251265
# print(kwargs)
252-
counts = self._determine_counts(bandwidth=bandwidth, kernel=kernel)
253-
assert (all(counts.sum(1)) > 0)
254-
counts[np.arange(len(self.sdata)),
255-
self.sdata.gene_ids] += zero_weight-1
266+
counts = self._determine_counts(
267+
bandwidth=bandwidth, kernel=kernel, regularization=zero_weight)
256268

257269
if cutoff is not None:
258270

@@ -272,7 +284,6 @@ def run_umap(self, bandwidth=1, kernel=None, metric='euclidean', zero_weight=1.0
272284
# del facs,ica
273285
print('Calculating UMAP embedding.')
274286
# counts[:,-1]=facs[:,cutoff:].sum(1)
275-
276287

277288
umap = UMAP(metric=metric, *args, **kwargs)
278289
self._umap = umap.fit_transform(counts)
@@ -364,16 +375,7 @@ def umap_js(self, color_prop='c_genes'):
364375

365376
n_bars = 20
366377

367-
if False:
368-
f_scatter = go.FigureWidget(px.imshow(np.repeat(self.sdata.background.data[:, :, None], 3, axis=-1,),
369-
x=np.linspace(
370-
self.sdata.background.extent[0], self.sdata.background.extent[1], self.sdata.background.data.shape[0]),
371-
y=np.linspace(
372-
self.sdata.background.extent[2], self.sdata.background.extent[3], self.sdata.background.data.shape[1])
373-
),
374-
layout=Layout(border='solid 4px', width='100%'))
375-
376-
trace_scatter = go.Scattergl(x=self.sdata.x,
378+
trace_scatter = go.Scattergl(x=self.sdata.x,
377379
y=self.sdata.y,
378380
mode='markers',
379381
marker=dict(
@@ -383,20 +385,7 @@ def umap_js(self, color_prop='c_genes'):
383385
'color': 'black', 'opacity': 0.2}},
384386
)
385387

386-
f_scatter.add_trace(trace_scatter)
387-
else:
388-
trace_scatter = go.Scattergl(x=self.sdata.x,
389-
y=self.sdata.y,
390-
mode='markers',
391-
marker=dict(
392-
color=self.sdata.obsc.project(color_prop)),
393-
hoverinfo='none', meta={'name': 'tissue-scatter'},
394-
unselected={'marker': {
395-
'color': 'black', 'opacity': 0.2}},
396-
)
397-
398-
f_scatter = go.FigureWidget(trace_scatter,)
399-
388+
f_scatter = go.FigureWidget(trace_scatter,)
400389

401390
f_umap = go.FigureWidget(go.Scattergl(x=self.sdata.graph.umap[:, 0],
402391
y=self.sdata.graph.umap[:, 1],
@@ -417,7 +406,9 @@ def umap_js(self, color_prop='c_genes'):
417406
marker={
418407
'color': ['rgb'+str(tuple((np.array(c)*256).astype(int))) for c in colors]},
419408
)
420-
f_bars = go.FigureWidget(w_bars)
409+
f_bars = go.FigureWidget(w_bars,
410+
layout={'title': 'n (selected):'},
411+
)
421412

422413
f_bars.data[0]['showlegend'] = False
423414

@@ -426,7 +417,8 @@ def umap_js(self, color_prop='c_genes'):
426417
marker={
427418
'color': ['rgb'+str(tuple((np.array(c)*256).astype(int))) for c in colors]},
428419
)
429-
f_bars_ratio_up = go.FigureWidget(w_bars_ratio_up)
420+
f_bars_ratio_up = go.FigureWidget(w_bars_ratio_up,
421+
layout={'title': 'n (selected) / total:'})
430422

431423
f_bars_ratio_up.data[0]['showlegend'] = False
432424

@@ -435,7 +427,9 @@ def umap_js(self, color_prop='c_genes'):
435427
marker={
436428
'color': ['rgb'+str(tuple((np.array(c)*256).astype(int))) for c in colors]},
437429
)
438-
f_bars_binom = go.FigureWidget(w_bars_binom)
430+
f_bars_binom = go.FigureWidget(w_bars_binom,
431+
layout={
432+
'title': 'binomcdf (n (selected),p(total)):'},)
439433

440434
f_bars_binom.data[0]['showlegend'] = False
441435

@@ -521,12 +515,12 @@ def store_selection(event):
521515
return widgets.VBox([widgets.HBox([f_scatter, f_umap], layout=Layout(display='flex', width='100%', height='80%', border='red solid 1px', align_items='stretch', justify_content='space-around', flex_direction='row')),
522516
widgets.HBox([widgets.HBox([f_bars, f_bars_ratio_up, f_bars_binom], layout=Layout(display='flex', width='80%')),
523517
widgets.VBox([widgets.HBox([text_field,
524-
]), widgets.HBox([store_button,reset_button])], layout=Layout(display='flex', width='20%', height='100%', border='red solid 1px', justify_content='space-around', flex_direction='column')
518+
]), widgets.HBox([store_button, reset_button])], layout=Layout(display='flex', width='20%', height='100%', border='red solid 1px', justify_content='space-around', flex_direction='column')
525519
)]
526520
)], layout=Layout(width='100%', height='80vh', background='red', border='solid 1px'))
527521

528522
def map_and_umap(self, color_prop=None, scalebar=True, cmap='jet',
529-
**kwargs):
523+
**kwargs):
530524
"""map_and_umap: Plots a side-by-side representation of the available UMAP- and coordinate data, with styling arguments passed to both plotting functions.
531525
532526
:param color_prop: Property to color the individual markers by. Needs to be a column in self.sdata.obsc, defaults to None
@@ -547,12 +541,11 @@ def map_and_umap(self, color_prop=None, scalebar=True, cmap='jet',
547541

548542
ax1 = plt.subplot2grid((3, 2), (0, 0), 2, 1)
549543

550-
sc2, _, _ = self.sdata.scatter(axd=ax1,scalebar=scalebar,cmap=cmap, ** kwargs)
544+
sc2, _, _ = self.sdata.scatter(
545+
axd=ax1, scalebar=scalebar, cmap=cmap, ** kwargs)
551546

552547
ax2 = plt.subplot2grid((3, 2), (0, 1), 2, 1)
553-
self.sdata.graph.plot_umap(cmap=cmap,**kwargs)
554-
555-
548+
self.sdata.graph.plot_umap(cmap=cmap, **kwargs)
556549

557550
def _untangle_text(self, cogs, untangle_rounds=50, min_distance=0.5):
558551
knn = NearestNeighbors(n_neighbors=2)

plankton/pixelmaps.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@ class PixelMap():
99

1010
def __init__(self,
1111
pixel_data: np.ndarray,
12-
upscale: float = 1.0,
12+
px_p_um: float = 1.0,
1313
x_shift=0.0,
14-
y_shift=0.0) -> None:
14+
y_shift=0.0,
15+
cmap='Greys') -> None:
1516

1617
self.data = pixel_data
1718

1819
self.n_channels = 1 if len(
1920
pixel_data.shape) == 2 else pixel_data.shape[-1]
2021

21-
if not isinstance(upscale, collections.abc.Iterable) or len(upscale) == 1:
22-
self.scale = (upscale, upscale)
22+
if not isinstance(px_p_um, collections.abc.Iterable) or len(px_p_um) == 1:
23+
self.scale = (px_p_um, px_p_um)
2324
else:
24-
self.scale = upscale
25+
self.scale = px_p_um
26+
27+
self.cmap=cmap
2528

2629
self.extent = (x_shift, x_shift+pixel_data.shape[0] / self.scale[0],
2730
y_shift, y_shift + pixel_data.shape[1] / self.scale[1])
@@ -30,7 +33,7 @@ def __init__(self,
3033
def shape(self):
3134
return self.extent[1] - self.extent[0], self.extent[3] - self.extent[2]
3235

33-
def imshow(self, axd=None, **kwargs) -> None:
36+
def imshow(self, cmap=None, axd=None, **kwargs) -> None:
3437
extent = np.array(self.extent)
3538

3639
if (len(self.data.shape) > 2) and (self.data.shape[2] > 4):
@@ -41,10 +44,14 @@ def imshow(self, axd=None, **kwargs) -> None:
4144
if axd is None:
4245
axd = plt.subplot(111)
4346

44-
axd.imshow(data, extent=extent[[0, 3, 1, 2]], **kwargs)
47+
if cmap is None:
48+
cmap = self.cmap
49+
50+
axd.imshow(data, extent=extent[[0, 3, 1, 2]], cmap=cmap,**kwargs)
4551

4652
def __getitem__(self, indices: Union[slice, collections.abc.Iterable[slice]]):
4753

54+
# print(self.extent)
4855
if not isinstance(indices, collections.abc.Iterable):
4956
index_x = indices
5057
index_y = slice(0, None, None)
@@ -62,7 +69,7 @@ def __getitem__(self, indices: Union[slice, collections.abc.Iterable[slice]]):
6269
else:
6370
start_x = index_x.start
6471
if (index_x.stop is None):
65-
stop_x = self.extent[1]
72+
stop_x = self.extent[3]-1
6673
else:
6774
stop_x = index_x.stop
6875

@@ -71,18 +78,19 @@ def __getitem__(self, indices: Union[slice, collections.abc.Iterable[slice]]):
7178
else:
7279
start_y = index_y.start
7380
if (index_y.stop is None):
74-
stop_y = self.extent[3]
81+
stop_y = self.extent[1]-1
7582
else:
7683
stop_y = index_y.stop
7784

85+
# print(self.data.shape, int(stop_x * self.scale[1]), int(stop_y * self.scale[0]), self.scale)
7886
data = self.data[int(start_y * self.scale[1]):int(stop_y *
7987
self.scale[1]),
8088
int(start_x * self.scale[0]):int(stop_x *
8189
self.scale[0]), ]
8290

8391
return PixelMap(
8492
data,
85-
upscale=self.scale,
93+
px_p_um=self.scale,
8694
)
8795

8896
def get_value(self, x, y, padding_value=-1):
@@ -107,16 +115,16 @@ def __init__(self, sd,
107115
bandwidth: float = 3.0,
108116
threshold_vf_norm: float = 1.0,
109117
threshold_p_corr: float = 0.5,
110-
upscale: float = 1) -> None:
118+
px_p_um: float = 1) -> None:
111119

112120
self.sdata = sd
113121
self.bandwidth = bandwidth
114122
self.threshold_vf_norm = threshold_vf_norm
115123
self.threshold_p_corr = threshold_p_corr
116124

117-
self.scale = upscale
125+
self.scale = px_p_um
118126

119-
super().__init__(self.run_kde(), upscale)
127+
super().__init__(self.run_kde(), px_p_um)
120128

121129
def run_kde(self) -> None:
122130

@@ -157,13 +165,13 @@ def __init__(self, data, *args, **kwargs):
157165
class PixelMask(PixelMap):
158166
def __init__(self,
159167
pixel_data: np.ndarray,
160-
upscale: float = 1.0,
168+
px_p_um: float = 1.0,
161169
x_shift=0.0,
162170
y_shift=0.0) -> None:
163171

164172
super(PixelMask, self).__init__(
165173
pixel_data=pixel_data,
166-
upscale=upscale,
174+
px_p_um=px_p_um,
167175
x_shift=x_shift,
168176
y_shift=y_shift
169177
)

0 commit comments

Comments
 (0)