Skip to content

Commit

Permalink
Merge pull request #1 from HiDiHlabs/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
sebastiantiesmeyer authored Aug 13, 2022
2 parents 72bc558 + b8798f0 commit 1bae350
Show file tree
Hide file tree
Showing 18 changed files with 500,463 additions and 1,073 deletions.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exclude test/*
exclude tutorial/*
2 changes: 2 additions & 0 deletions bld.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"%PYTHON%" setup.py install
if errorlevel 1 exit 1
1 change: 1 addition & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$PYTHON setup.py install
37 changes: 37 additions & 0 deletions meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{% set name = "plankton" %}
{% set version = "0.0.1" %}

package:
name: "{{ name|lower }}"
version: "{{ version }}"

source:
git_url: "https://github.com/HiDiHlabs/planktonpy"
url: "https://pypi.org/project/planktonspace/"

requirements:
build:
- python
- setuptools

run:
- python
- numpy
- jupyter
- matplotlib
- numpy
- pandas
- plotly
- scipy
- scikit-image
- scikit-learn
- umap-learn
# - anndata
# - scanpy

# test:
# imports:
# -

# about:
# home:
2 changes: 1 addition & 1 deletion plankton/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# from plankton import *
# from stats import *
import plankton
# from plankton import *
73 changes: 33 additions & 40 deletions plankton/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SpatialGraph():
:param n_neighbors: number of nearset neighbors to infer, defaults to 10
:type n_neighbors: int, optional
"""

def __init__(self, sdata, n_neighbors=10) -> None:

self.sdata = sdata
Expand Down Expand Up @@ -74,6 +75,14 @@ def neighbor_types(self):
self.n_neighbors)
return self._neighbor_types[:, :self.n_neighbors]

@property
def umap_0(self):
return self._umap[:, 0]

@property
def umap_1(self):
return self._umap[:, 1]

@property
def umap(self):
"""umap: Returns the coordinates of the UMAP representation of the source data.
Expand Down Expand Up @@ -216,7 +225,7 @@ def plot_entropy(self, n_neighbors=4):
linestyle='dotted')
fig.add_artist(con)

def _determine_counts(self, bandwidth=1, kernel=None):
def _determine_counts(self, bandwidth=1, regularization=0, kernel=None):
"""_determine_counts: Determines the count distributions of genes around each molecule, thus effectively generating models of the immediate environment.
:param bandwidth: Bandwidth of the default Gaussian kernel, defaults to 1
Expand All @@ -234,9 +243,14 @@ def kernel(x): return np.exp(-x**2/(2*bandwidth**2))
for i in range(0, self.n_neighbors):
counts[np.arange(len(self.sdata)), self.neighbor_types[:, i]
] += kernel(self.distances[:, i])

assert (all(counts.sum(1)) > 0)
counts[np.arange(len(self.sdata)),
self.sdata.gene_ids] += regularization-1

return counts

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

if cutoff is not None:

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


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

n_bars = 20

if False:
f_scatter = go.FigureWidget(px.imshow(np.repeat(self.sdata.background.data[:, :, None], 3, axis=-1,),
x=np.linspace(
self.sdata.background.extent[0], self.sdata.background.extent[1], self.sdata.background.data.shape[0]),
y=np.linspace(
self.sdata.background.extent[2], self.sdata.background.extent[3], self.sdata.background.data.shape[1])
),
layout=Layout(border='solid 4px', width='100%'))

trace_scatter = go.Scattergl(x=self.sdata.x,
trace_scatter = go.Scattergl(x=self.sdata.x,
y=self.sdata.y,
mode='markers',
marker=dict(
Expand All @@ -383,20 +385,7 @@ def umap_js(self, color_prop='c_genes'):
'color': 'black', 'opacity': 0.2}},
)

f_scatter.add_trace(trace_scatter)
else:
trace_scatter = go.Scattergl(x=self.sdata.x,
y=self.sdata.y,
mode='markers',
marker=dict(
color=self.sdata.obsc.project(color_prop)),
hoverinfo='none', meta={'name': 'tissue-scatter'},
unselected={'marker': {
'color': 'black', 'opacity': 0.2}},
)

f_scatter = go.FigureWidget(trace_scatter,)

f_scatter = go.FigureWidget(trace_scatter,)

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

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

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

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

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

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

Expand Down Expand Up @@ -521,12 +515,12 @@ def store_selection(event):
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')),
widgets.HBox([widgets.HBox([f_bars, f_bars_ratio_up, f_bars_binom], layout=Layout(display='flex', width='80%')),
widgets.VBox([widgets.HBox([text_field,
]), 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')
]), 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')
)]
)], layout=Layout(width='100%', height='80vh', background='red', border='solid 1px'))

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

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

sc2, _, _ = self.sdata.scatter(axd=ax1,scalebar=scalebar,cmap=cmap, ** kwargs)
sc2, _, _ = self.sdata.scatter(
axd=ax1, scalebar=scalebar, cmap=cmap, ** kwargs)

ax2 = plt.subplot2grid((3, 2), (0, 1), 2, 1)
self.sdata.graph.plot_umap(cmap=cmap,**kwargs)


self.sdata.graph.plot_umap(cmap=cmap, **kwargs)

def _untangle_text(self, cogs, untangle_rounds=50, min_distance=0.5):
knn = NearestNeighbors(n_neighbors=2)
Expand Down
38 changes: 23 additions & 15 deletions plankton/pixelmaps.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@ class PixelMap():

def __init__(self,
pixel_data: np.ndarray,
upscale: float = 1.0,
px_p_um: float = 1.0,
x_shift=0.0,
y_shift=0.0) -> None:
y_shift=0.0,
cmap='Greys') -> None:

self.data = pixel_data

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

if not isinstance(upscale, collections.abc.Iterable) or len(upscale) == 1:
self.scale = (upscale, upscale)
if not isinstance(px_p_um, collections.abc.Iterable) or len(px_p_um) == 1:
self.scale = (px_p_um, px_p_um)
else:
self.scale = upscale
self.scale = px_p_um

self.cmap=cmap

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

def imshow(self, axd=None, **kwargs) -> None:
def imshow(self, cmap=None, axd=None, **kwargs) -> None:
extent = np.array(self.extent)

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

axd.imshow(data, extent=extent[[0, 3, 1, 2]], **kwargs)
if cmap is None:
cmap = self.cmap

axd.imshow(data, extent=extent[[0, 3, 1, 2]], cmap=cmap,**kwargs)

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

# print(self.extent)
if not isinstance(indices, collections.abc.Iterable):
index_x = indices
index_y = slice(0, None, None)
Expand All @@ -62,7 +69,7 @@ def __getitem__(self, indices: Union[slice, collections.abc.Iterable[slice]]):
else:
start_x = index_x.start
if (index_x.stop is None):
stop_x = self.extent[1]
stop_x = self.extent[3]-1
else:
stop_x = index_x.stop

Expand All @@ -71,18 +78,19 @@ def __getitem__(self, indices: Union[slice, collections.abc.Iterable[slice]]):
else:
start_y = index_y.start
if (index_y.stop is None):
stop_y = self.extent[3]
stop_y = self.extent[1]-1
else:
stop_y = index_y.stop

# print(self.data.shape, int(stop_x * self.scale[1]), int(stop_y * self.scale[0]), self.scale)
data = self.data[int(start_y * self.scale[1]):int(stop_y *
self.scale[1]),
int(start_x * self.scale[0]):int(stop_x *
self.scale[0]), ]

return PixelMap(
data,
upscale=self.scale,
px_p_um=self.scale,
)

def get_value(self, x, y, padding_value=-1):
Expand All @@ -107,16 +115,16 @@ def __init__(self, sd,
bandwidth: float = 3.0,
threshold_vf_norm: float = 1.0,
threshold_p_corr: float = 0.5,
upscale: float = 1) -> None:
px_p_um: float = 1) -> None:

self.sdata = sd
self.bandwidth = bandwidth
self.threshold_vf_norm = threshold_vf_norm
self.threshold_p_corr = threshold_p_corr

self.scale = upscale
self.scale = px_p_um

super().__init__(self.run_kde(), upscale)
super().__init__(self.run_kde(), px_p_um)

def run_kde(self) -> None:

Expand Down Expand Up @@ -157,13 +165,13 @@ def __init__(self, data, *args, **kwargs):
class PixelMask(PixelMap):
def __init__(self,
pixel_data: np.ndarray,
upscale: float = 1.0,
px_p_um: float = 1.0,
x_shift=0.0,
y_shift=0.0) -> None:

super(PixelMask, self).__init__(
pixel_data=pixel_data,
upscale=upscale,
px_p_um=px_p_um,
x_shift=x_shift,
y_shift=y_shift
)
Loading

0 comments on commit 1bae350

Please sign in to comment.