Source code for pycellfit.cell

import math
from itertools import combinations

import matplotlib.pyplot as plt

from .edge import Edge
from .path_finder import breadth_first_search


[docs]class Cell: def __init__(self, pixel_value): """ constructor for a Cell object :param pixel_value: value of all of pixels that make up this Cell in the array :type pixel_value: float """ # identify each cell based on its pixel value self._label = pixel_value # set of tuples of points in cell boundary # each element looks like ((x, y), neighboring_cell_label) self._edge_point_set = set() self._cell_boundary_segments = [] self.junctions = set() @property def neighboring_cell_labels(self): neighboring_cell_labels = set() for j in self.junctions: neighboring_cell_labels.update(j.cell_labels) return neighboring_cell_labels
[docs] def add_edge_point(self, edge_point, neighboring_cell_label): self._edge_point_set.add((edge_point, neighboring_cell_label))
[docs] def generate_maze(self, neighboring_cell_label): xmin = 512 ymin = 512 xmax = 0 ymax = 0 for (x, y), neighboring_cell in self._edge_point_set: if x > xmax: xmax = x if x < xmin: xmin = x if y > ymax: ymax = y if y < ymin: ymin = y rows, cols = (int(ymax - ymin + 1), int(xmax - xmin + 1)) arr = [[0 for i in range(cols)] for j in range(rows)] for (x, y), neighboring_cell in self._edge_point_set: if neighboring_cell == neighboring_cell_label: row = int(y - ymin) col = int(x - xmin) arr[row][col] = 1 for junction in self.junctions: if neighboring_cell_label in junction.cell_labels: x, y = junction.coordinates row = int(y - ymin) col = int(x - xmin) arr[row][col] = 1 return arr, xmin, ymin
[docs] def make_edges(self, master_set): for start, end in combinations(self.junctions, 2): already_created_edge = False for edge in master_set: if edge.start_node == start and edge.end_node == end: already_created_edge = True if edge.start_node == end and edge.end_node == start: already_created_edge = True if not already_created_edge: start_cells = start.cell_labels end_cells = end.cell_labels shared_cell_labels = start_cells.intersection(end_cells) if len(shared_cell_labels) == 2: (neighboring_cell_label,) = shared_cell_labels - {self.label} maze, xmin, ymin = self.generate_maze(neighboring_cell_label) x1, y1 = start.coordinates point1 = (int(y1 - ymin), int(x1 - xmin)) x2, y2 = end.coordinates point2 = (int(y2 - ymin), int(x2 - xmin)) path = breadth_first_search(maze, point1, point2) path_new = [] for point in path: y, x = tuple(map(lambda i, j: i + j, point, (ymin, xmin))) path_new.append((x, y)) self._cell_boundary_segments.append(path_new) e = Edge(start, end, path_new, {self.label, neighboring_cell_label}) master_set.add(e)
@property def number_of_edge_points(self): """ returns the number of edge points in edge_point_list :return: number of edge points """ return len(self._edge_point_set) @property def label(self): """ the label of a Cell is it's unique pixel value. It is assigned when the Cell object is created. :return: """ return self._label
[docs] def approximate_cell_center(self): """ approximates the coordinates of the center of the cell by averaging the coordinates of points on the perimeter (edge) of the cell :return: approximate center of the cell :rtype: tuple """ xsum = 0 ysum = 0 for point, neighbor in self._edge_point_set: xsum += point[0] ysum += point[1] xc = xsum / len(self._edge_point_set) yc = ysum / len(self._edge_point_set) return xc, yc
[docs] def plot(self): plt.text(self.approximate_cell_center()[0], self.approximate_cell_center()[1], str(self._label), color='green', fontsize=3, horizontalalignment='center', verticalalignment='center')
def __str__(self): return str('Cell {}'.format(self._label)) def __repr__(self): return repr('Cell {}'.format(self._label)) def __eq__(self, other): return math.isclose(self.label, other.label) def __hash__(self): return hash(str(self))