Skip to content

Commit

Permalink
add Cartesian class for coordinate operations
Browse files Browse the repository at this point in the history
  • Loading branch information
xiuliren committed Jan 5, 2022
1 parent 3439037 commit 6b4fc22
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 15 deletions.
4 changes: 2 additions & 2 deletions chunkflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# -*- coding: utf-8 -*-

# Using Green Threads
import gevent.monkey
gevent.monkey.patch_all(thread=False)
# import gevent.monkey
# gevent.monkey.patch_all(thread=False)
10 changes: 9 additions & 1 deletion chunkflow/chunk/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ def to_h5(self, file_name: str, with_offset: bool=True,
f.create_dataset('/unique_nonzeros', data = unique)
return file_name

def __len__(self):
return len(self.array)

def __array__(self):
return self.array

Expand Down Expand Up @@ -550,13 +553,18 @@ def add_overlap(self, other):
overlap_slices = self._get_overlap_slices(other.slices)
self.array[overlap_slices] += other.array[overlap_slices]

def cutout(self, slices: tuple):
def cutout(self, x: Union[tuple, BoundingBox, Bbox]):
"""
cutout a region of interest from this chunk
:param slices: the global slices of region of interest
:return: another chunk of region of interest
"""
if isinstance(x, BoundingBox) or isinstance(x, Bbox):
slices = x.to_slices()
else:
slices = x

if len(slices) == self.ndim - 1:
slices = (slice(0, self.shape[0]), ) + slices
internalSlices = self._get_internal_slices(slices)
Expand Down
67 changes: 63 additions & 4 deletions chunkflow/lib/bounding_boxes.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,64 @@
# support the class method with parameter type of itself
from __future__ import annotations

import logging
import os
from itertools import product
from collections import UserList
from collections import UserList, namedtuple
from math import ceil
from typing import Union
from copy import deepcopy

import numpy as np
import h5py
import h5py
from numpy.lib.arraysetops import isin

from cloudvolume import CloudVolume
from cloudvolume.lib import Vec, Bbox


class Cartesian(namedtuple('Cartesian', ['z', 'y', 'x'])):
"""Cartesian coordinate or offset."""
__slots__ = ()

def __sub__(self, offset: Union[Cartesian, int]):
"""subtract to another voxel coordinate
Args:
offset (Cartesian, int): another voxel coordinate
"""
if isinstance(offset, int):
offset = (offset, offset, offset)
return Cartesian(*[x-o for x, o in zip(self, offset)])

def __add__(self, offset: Union[Cartesian, int]):
"""add another coordinate
Args:
offset (Cartesian, int): offset
"""
if isinstance(offset, int):
offset = (offset, offset, offset)
return Cartesian(*[x+o for x, o in zip(self, offset)])

@property
def vec(self):
return Vec(*self)


class BoundingBox(Bbox):
def __init__(self, min_corner: list, max_corner: list, dtype=None, voxel_size: tuple = None):
super().__init__(min_corner, max_corner, dtype=dtype)
self._voxel_size = voxel_size

@classmethod
def from_corners(cls, minpt: Cartesian, maxpt: Cartesian):
if isinstance(minpt, Cartesian):
minpt = minpt.vec

if isinstance(maxpt, Cartesian):
maxpt = maxpt.vec
return cls(minpt, maxpt)

@classmethod
def from_bbox(cls, bbox: Bbox, voxel_size: tuple = None):
return cls(bbox.minpt, bbox.maxpt, voxel_size=voxel_size)
Expand All @@ -32,6 +73,24 @@ def from_list(cls, x: list):
bbox = Bbox.from_list(x)
return cls.from_bbox(bbox)

@classmethod
def from_points(cls, x: np.ndarray):
bbox = Bbox.from_points(x)
return cls.from_bbox(bbox)

@classmethod
def from_center(cls, center: Cartesian, extent: int):
"""Create bounding box from center and extent
Args:
center (Cartesian): center coordinate
extent (int): the range to extent, like radius
"""
minpt = center - extent
maxpt = center - extent
return cls.from_corners(minpt, maxpt)


def clone(self):
bbox = Bbox(self.minpt, self.maxpt, dtype=self.dtype)
bbox = bbox.clone()
Expand All @@ -48,7 +107,7 @@ def adjust(self, size: Union[int, tuple, list, Vec]):
self.maxpt += size
return self

def union(self, bbox2: Union[BoundingBox, Bbox]):
def union(self, bbox2):
"""Merge another bounding box
Args:
Expand Down
8 changes: 4 additions & 4 deletions chunkflow/lib/synapses.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ def __init__(self, pre: np.ndarray, pre_confidence: np.ndarray = None,
np.testing.assert_array_less(0, resolution)

self.resolution = resolution
self.pre = pre
# unsigned integer will have minus issues
self.pre = pre.astype(np.int32)
self.pre_confidence = pre_confidence
self.post = post
self.post = post.astype(np.int32)
self.post_confidence = post_confidence

@classmethod
Expand Down Expand Up @@ -217,8 +218,7 @@ def distances_from_pre_to_post(self):
for post_idx in range(self.post_num):
post = self.post[post_idx, 1:]
pre_idx = self.post[post_idx, 0]
pre = self.pre[pre_idx]
pre = self.pre[pre_idx, :]
distances[post_idx] = np.linalg.norm(pre - post)
return distances


4 changes: 2 additions & 2 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# -*- coding: utf-8 -*-

# Using Green Threads
import gevent.monkey
gevent.monkey.patch_all(thread=False)
# # import gevent.monkey
# gevent.monkey.patch_all(thread=False)
21 changes: 19 additions & 2 deletions tests/lib/test_bounding_box.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
from cloudvolume.lib import Bbox
from cloudvolume.lib import Bbox, Vec

from chunkflow.lib.bounding_boxes import BoundingBox
from chunkflow.lib.bounding_boxes import BoundingBox, Cartesian


def test_cartesian():
ct = Cartesian(1,2,3)
ct += 2
ct == Cartesian(3,4,5)

ct -= 2
ct == Cartesian(1,2,3)

ct.vec == Vec(1,2,3)

def test_bounding_box():
bbox = Bbox.from_delta((1,3,2), (64, 32, 8))
bbox = BoundingBox.from_bbox(bbox)

bbox = bbox.clone()
assert isinstance(bbox, BoundingBox)

minpt = Cartesian(1,2,3)
maxpt = Cartesian(2,3,4)
bbox = BoundingBox.from_corners(minpt, maxpt)

bbox = BoundingBox.from_center(Cartesian(1,2,3), 3)
bbox == BoundingBox.from_list([-2, -1, 0, 4, 5, 6])


0 comments on commit 6b4fc22

Please sign in to comment.