Skip to content

Commit

Permalink
Merge 5e1ca87 into ef1a4a6
Browse files Browse the repository at this point in the history
  • Loading branch information
srivarra committed Aug 25, 2022
2 parents ef1a4a6 + 5e1ca87 commit e8c9833
Show file tree
Hide file tree
Showing 19 changed files with 103 additions and 76 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ Pipfile
Pipfile.lock
.coverage
.python-version
.coverage.*
2 changes: 1 addition & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ sphinx:
fail_on_warning: true

python:
version: "3.7"
version: "3.8"
install:
- requirements: docs/rtd-requirements.txt
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ git:
language: python

python:
- 3.7
- 3.8

# Install the updated versions of importlib-metadata and setuptools, as Travis 3.7 environments
# contains a very old version of importlib-metadata which is incompatible for 3.7+
# Install the updated versions of importlib-metadata and setuptools, as Travis 3.8 environments
# contains a very old version of importlib-metadata which is incompatible for 3.8+
# We add python path to enable testing jupyter notebooks
install:
- pip install -U importlib_metadata setuptools
Expand All @@ -30,7 +30,7 @@ script:
jobs:
include:
- stage: pypi_deploy
python: 3.7
python: 3.8
deploy:
provider: pypi
user: $PYPI_USERNAME
Expand All @@ -39,7 +39,7 @@ jobs:
tags: true
- stage: docker_deploy
if: tag IS present
python: 3.7
python: 3.8
script:
- "travis_wait 120 sleep 7200 &"
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.7
FROM python:3.8

# system maintenance
RUN apt-get update
Expand Down
2 changes: 1 addition & 1 deletion ark/analysis/dimensionality_reduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import seaborn as sns
import umap.umap_ as umap
import umap
import os

from ark.utils import misc_utils
Expand Down
2 changes: 1 addition & 1 deletion ark/phenotyping/cell_cluster_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from matplotlib.colors import ListedColormap
import numpy as np
import pandas as pd
from skimage.draw import circle
from skimage.draw import disk
import skimage.io as io
import scipy.ndimage as ndimage
from sklearn.utils import shuffle
Expand Down
6 changes: 3 additions & 3 deletions ark/phenotyping/pixel_cluster_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from matplotlib.colors import ListedColormap
import numpy as np
import pandas as pd
from skimage.draw import circle
from skimage.draw import disk
import skimage.io as io
import scipy.ndimage as ndimage
from sklearn.utils import shuffle
Expand Down Expand Up @@ -519,8 +519,8 @@ def test_filter_with_nuclear_mask(sub_dir, exclude, capsys):
rand_img = np.random.randint(1, 16, size=(1, 10, 10))

# draw a dummy nucleus and store the coords
nuclear_x, nuclear_y = circle(
base_center[0] + offset, base_center[1] + offset, base_radius
nuclear_x, nuclear_y = disk(
(base_center[0] + offset, base_center[1] + offset), base_radius
)
rand_img[0, nuclear_x, nuclear_y] = 0
nuclear_coords[fov] = (nuclear_x, nuclear_y)
Expand Down
2 changes: 1 addition & 1 deletion ark/segmentation/regionprops_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def num_concavities(prop, **kwargs):
diff_img = convex_image ^ cell_image

if np.sum(diff_img) > 0:
labeled_diff_img = label(diff_img)
labeled_diff_img = label(diff_img, connectivity=1)
hull_prop_df = pd.DataFrame(regionprops_table(labeled_diff_img,
properties=['area', 'perimeter']))
hull_prop_df['compactness'] = np.square(hull_prop_df['perimeter']) / hull_prop_df['area']
Expand Down
15 changes: 10 additions & 5 deletions ark/segmentation/regionprops_extraction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def test_major_minor_axis_ratio():
prop_info = regionprops(sample_arr)[0]

major_minor_rat = regionprops_extraction.major_minor_axis_ratio(prop_info)
assert np.round(major_minor_rat, 4) == 1.1524
desired_value = 1.1524
np.testing.assert_allclose(actual=major_minor_rat, desired=desired_value, rtol=0.1, atol=1e-5)

class Regionprop(object):
pass
Expand All @@ -42,7 +43,8 @@ def test_perim_square_over_area():
prop_info = regionprops(sample_arr)[0]

perim_area_rat = regionprops_extraction.perim_square_over_area(prop_info)
assert np.round(perim_area_rat, 4) == 39.3630
desired_value = 39.3630
np.testing.assert_allclose(actual=perim_area_rat, desired=desired_value, rtol=0.1, atol=1e-5)


def test_major_axis_equiv_diam_ratio():
Expand All @@ -54,7 +56,8 @@ def test_major_axis_equiv_diam_ratio():
prop_info = regionprops(sample_arr)[0]

major_diam_rat = regionprops_extraction.major_axis_equiv_diam_ratio(prop_info)
assert np.round(major_diam_rat, 4) == 1.7664
desired_value = 1.7664
np.testing.assert_allclose(actual=major_diam_rat, desired=desired_value, rtol=0.1, atol=1e-5)


def test_convex_hull_resid():
Expand All @@ -66,7 +69,8 @@ def test_convex_hull_resid():
prop_info = regionprops(sample_arr)[0]

convex_res = regionprops_extraction.convex_hull_resid(prop_info)
assert np.round(convex_res, 4) == 0.6605
desired_value = 0.6605
np.testing.assert_allclose(actual=convex_res, desired=desired_value, rtol=0.1, atol=1e-5)


def test_nc_ratio():
Expand Down Expand Up @@ -115,7 +119,8 @@ def test_centroid_dif():
prop_info = regionprops(sample_arr)[0]

centroid_dist = regionprops_extraction.centroid_dif(prop_info)
assert np.round(centroid_dist, 4) == 0.3562
desired_value = 0.3562
np.testing.assert_allclose(actual=centroid_dist, desired=desired_value, rtol=0.1, atol=1e-5)


def test_num_concavities():
Expand Down
7 changes: 4 additions & 3 deletions ark/utils/deepcell_service_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import RetryError
from requests.packages.urllib3.util.retry import Retry
from requests.packages.urllib3.util import Retry
import time
from tqdm.notebook import tqdm
from urllib.parse import unquote_plus
import warnings
from concurrent.futures import ThreadPoolExecutor
import numpy as np
from scipy import stats
from skimage import io, external
from skimage import io
from tifffile import imread
from io import BytesIO
from ark.utils import misc_utils
from zipfile import ZipFile, ZIP_DEFLATED
Expand Down Expand Up @@ -323,7 +324,7 @@ def _convert_deepcell_seg_masks(seg_mask: bytes) -> np.ndarray:
np.ndarray: The segmentation masks, converted from floating point 64-bit to integer
16-bit via `scipy.stats.rankdata`
"""
float_mask = external.tifffile.imread(BytesIO(seg_mask))
float_mask = imread(BytesIO(seg_mask))

# Reshape as ranked_mask returns a 1D numpy array, dims: n^2 x 1 -> 1 x n x n
shape = float_mask.shape
Expand Down
4 changes: 2 additions & 2 deletions ark/utils/plot_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pytest

from ark.utils import plot_utils, test_utils
from skimage.draw import circle
from skimage.draw import disk

from pathlib import Path
import natsort
Expand All @@ -23,7 +23,7 @@ def _generate_segmentation_labels(img_dims, num_cells=20):

for i in range(num_cells):
r, c = np.random.randint(radius, img_dims[0] - radius, 2)
rr, cc = circle(r, c, radius)
rr, cc = disk((r, c), radius)
labels[rr, cc] = i

return labels
Expand Down
26 changes: 13 additions & 13 deletions ark/utils/synthetic_spatial_datagen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import xarray as xr

from copy import deepcopy
from skimage.draw import circle
from skimage.draw import disk


def generate_test_dist_matrix(num_A=100, num_B=100, num_C=100,
Expand Down Expand Up @@ -263,10 +263,9 @@ def generate_two_cell_seg_mask(size_img=(1024, 1024), cell_radius=10):
center_2 = (size_img[0] // 2, size_img[0] // 2 + cell_radius * 2 - 1)

# generate the coordinates of each nuclear disk
cell_region_1_x, cell_region_1_y = circle(center_1[0], center_1[1], cell_radius,
shape=size_img)
cell_region_2_x, cell_region_2_y = circle(center_2[0], center_2[1], cell_radius,
shape=size_img)
cell_region_1_x, cell_region_1_y = disk(center=center_1, radius=cell_radius, shape=size_img)

cell_region_2_x, cell_region_2_y = disk(center=center_2, radius=cell_radius, shape=size_img)

# assign the respective cells value according to their label
sample_segmentation_mask[cell_region_1_x, cell_region_1_y] = 1
Expand Down Expand Up @@ -314,8 +313,9 @@ def generate_two_cell_nuc_signal(segmentation_mask, cell_centers,
center = cell_centers[cell]

# generate nuclear region
nuc_region_x, nuc_region_y = circle(center[0], center[1],
nuc_radius + nuc_uncertainty_length, shape=size_img)
nuc_region_x, nuc_region_y = disk(center=center,
radius=nuc_radius + nuc_uncertainty_length,
shape=size_img)

# set nuclear signal
sample_nuclear_signal[nuc_region_x, nuc_region_y] = nuc_signal_strength
Expand Down Expand Up @@ -364,14 +364,14 @@ def generate_two_cell_memb_signal(segmentation_mask, cell_centers,
center = cell_centers[cell]

# generate coordinates of the cell region
cell_region_x, cell_region_y = circle(center[0], center[1],
cell_radius + memb_uncertainty_length,
shape=size_img)
cell_region_x, cell_region_y = disk(center=center,
radius=cell_radius + memb_uncertainty_length,
shape=size_img)

# generate coordinates of the non-membrane region
non_memb_region_x, non_memb_region_y = circle(center[0], center[1],
cell_radius - memb_thickness,
shape=size_img)
non_memb_region_x, non_memb_region_y = disk(center=center,
radius=cell_radius - memb_thickness,
shape=size_img)

# perform circle subtraction to generate membrane region
sample_membrane_signal[cell_region_x, cell_region_y] = memb_signal_strength
Expand Down
35 changes: 24 additions & 11 deletions ark/utils/tiff_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from fractions import Fraction
import numpy as np
from skimage.external.tifffile import TiffFile, TiffWriter
from tifffile import TiffFile, TiffWriter
import json
import datetime
from itertools import compress
Expand Down Expand Up @@ -33,7 +33,8 @@ def read_mibitiff(file, channels=None):

# get tags as json
description = json.loads(
page.tags['image_description'].value.decode('utf-8')
# `ImageDescription` tag code is 270
page.tags[270].value
)

# only load supplied channels
Expand Down Expand Up @@ -69,8 +70,8 @@ def _check_version(file):
Raises:
ValueError
"""
filetype = file.pages[0].tags.get('software')
if not (filetype and filetype.value.decode('utf-8').startswith('IonpathMIBI')):
filetype = file.pages[0].tags.get('Software')
if not (filetype and filetype.value.startswith('IonpathMIBI')):
raise ValueError('File is not of type IonpathMIBI...')


Expand Down Expand Up @@ -106,16 +107,22 @@ def write_mibitiff(filepath, img_data, channel_tuples, metadata):
(286, '2i', 1, _micron_to_cm(metadata['coordinates'][0])),
(287, '2i', 1, _micron_to_cm(metadata['coordinates'][1]))
]
resolution = (img_data.shape[0] * 1e4 / float(metadata['size']),
img_data.shape[1] * 1e4 / float(metadata['size']),
'cm')
_resolution = (img_data.shape[0] * 1e4 / float(metadata['size']),
img_data.shape[1] * 1e4 / float(metadata['size']))

# resolutionunit / RESUNIT = 3 is "CENTIMETER"
_resolutionunit = 3

# Compression uses ZLIB, with level 6
_compression = "zlib"
_compressionargs = {"level": 6}

description = {}
for key, value in metadata.items():
if key in _PREFIXED_METADATA_ATTRIBUTES:
description[f'mibi.{key}'] = value

with TiffWriter(filepath, software="IonpathMIBIv1.0") as infile:
with TiffWriter(filepath) as infile:
for index, channel_tuple in enumerate(channel_tuples):
mass, target = channel_tuple
_metadata = description.copy()
Expand All @@ -132,9 +139,15 @@ def write_mibitiff(filepath, img_data, channel_tuples, metadata):
max_value = (341, range_dtype, 1, ranges[index][1])
page_tags = coordinates + [page_name, min_value, max_value]

infile.save(
img_data[:, :, index], compress=6, resolution=resolution,
extratags=page_tags, metadata=_metadata,
infile.write(
data=img_data[:, :, index],
compression=_compression,
compressionargs=_compressionargs,
resolution=_resolution,
resolutionunit=_resolutionunit,
software="IonpathMIBIv1.0",
extratags=page_tags,
metadata=_metadata,
datetime=datetime.datetime.strptime(metadata['date'], '%Y-%m-%dT%H:%M:%S')
)

Expand Down
19 changes: 11 additions & 8 deletions docs/_rtd/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you wish to do higher-level development on top of `ark`, we recommend setting up a virtual environment. We highly recommend using `conda` virtual environments. To be able to set one up, you will need to install the Anaconda package.

### Setting up Your Virtual Environment
### Setting up Your Virtual Environment - Anaconda

#### Installing Anaconda

Expand All @@ -11,7 +11,8 @@ For a step-by-step guide of how to install Anaconda, please refer to these links
* https://github.com/conda-forge/miniforge/releases for Mac (arm64 / Apple Silicon) users
* https://docs.anaconda.com/anaconda/install/windows/ for Windows users

##### Notes for Mac users

**Notes for Mac users**

We recommend following the command line installer instructions as users have reported recent issues with the graphical installer.

Expand Down Expand Up @@ -43,23 +44,25 @@ Miniforge contains conda with native Apple Silicon support. There are a few inst

Now that Anaconda is installed, you can now create a `conda` environment.

To do so, on your command line, type `conda create -n <my_env> python=3.7`, where `<my_env>` is a name you set. Our codebase only supports Python 3.7, so please do not change the `python=3.7` flag when creating your environment.
To do so, on your command line, type `conda create -n <my_env> python=3.8`, where `<my_env>` is a name you set. Our codebase currently supports up to Python 3.8.

Say yes to any prompts and your `conda` environment will be created!

To verify installation, activate your `conda` environment with `conda activate <my_env>`. If you see `(<my_env>)` on the far left of the command prompt, you have successfully created and activated your environment. Type `conda deactivate` to exit at any time.

**Apple Silicon Installation**

`Ark` now supports development with Apple Silicon.

Currently there is not a native M1 implementation of ark-analysis for development, so it will need to go through Rosetta 2 (the Intel to Arm transition layer). Luckily, this isn't something you'll have to deal with, as `conda` makes it straightforward.

1. Create a Python 3.6 `conda` environment called `my_env` using osx-64 (compiled binaries for Intel Macs as the default installation type)
1. Create a Python 3.8 `conda` environment called `my_env`.
```sh
CONDA_SUBDIR=osx-64 conda create -n <my_env> python=3.6
conda create -n <my_env> python=3.8
```

2. Test to make sure the `platform.machine()` function reports `x86_64` in the terminal.
```
2. Test to make sure the `platform.machine()` function reports `arm64` in the terminal.
```sh
conda activate <my_env>
python -c "import platform;print(platform.machine())"
```
Expand All @@ -70,7 +73,7 @@ Currently there is not a native M1 implementation of ark-analysis for developmen
```
4. The prompt may ask you to deactivate and reactivate the environment as well.

Now any package that is installed in `my_env` will targeted for `x86_64`.
Now any package that is installed in `my_env` will targeted for `arm64`.

### Setting up ark-analysis for development

Expand Down
Loading

0 comments on commit e8c9833

Please sign in to comment.