"""
This module administrates the contours
8 June 2018.
"""import numpy as np
from collections import OrderedDict
import csv
defload_contours(name):
""" Open a cotours csv file and read it """
contours = OrderedDict()
# Load the contourswithopen(name, "r") as f:
fr = csv.reader(f)
frl = list(fr)
for line in frl:
try:
values = [float(item) for item in line]
except ValueError:
key = line[0]
contours[key] = []
else:
contours[key].append(values)
return contours
defread_poly(file_name):
"""
Simple poly-file reader, that creates a python dictionary
with information about vertices, edges and holes.
It assumes that vertices have no attributes or boundary markers.
It assumes that edges have no boundary markers.
No regional attributes or area constraints are parsed.
Taken and adapted from: ...
"""
output = {'vertices': None, 'holes': None, 'segments': None}
# open file and store lines in a list
file = open(file_name, 'r')
lines = file.readlines()
file.close()
lines = [x.strip('\n').split() for x in lines]
# Store vertices
vertices= []
N_vertices, dimension, attr, bdry_markers = [int(x) for x in lines[0]]
# We assume attr = bdrt_markers = 0for k inrange(N_vertices):
label, x, y = [items for items in lines[k+1]]
vertices.append([float(x), float(y)])
output['vertices']=np.array(vertices)
# Store segments
segments = []
N_segments, bdry_markers = [int(x) for x in lines[N_vertices+1]]
for k inrange(N_segments):
label, pointer_1, pointer_2 = [items for items in lines[N_vertices+k+2]]
segments.append([int(pointer_1)-1, int(pointer_2)-1])
output['segments'] = np.array(segments)
# Store holes
N_holes = int(lines[N_segments+N_vertices+2][0])
holes = []
for k inrange(N_holes):
label, x, y = [items for items in lines[N_segments + N_vertices + 3 + k]]
holes.append([float(x), float(y)])
output['holes'] = np.array(holes)
return output
defmove_element(dic, key, newpos):
""" Move the element with key 'key' of a dictionary 'dic' to the
position 'newpos' """
newdic = OrderedDict()
for i, (k, v) inenumerate(dic.items()):
if k != key:
newdic[k] = v
if i == newpos:
newdic[key] = dic[key]
return newdic
deffill_random(c, n):
""" Fill a contour given by the array c with a maximum of n random
points """# Contour's enclosing box
left, right = c[:, 0].min(), c[:, 0].max()
bottom, top = c[:, 1].min(), c[:, 1].max()
# Dimensions
width = right - left
height = top - bottom
# Generate random points in the box
x = np.random.uniform(low=left, high=right, size=n)
y = np.random.uniform(low=bottom, high=top, size=n)
points = np.array([x, y]).T
# 'Planar' polygon object for the contour
polygon = pl.Polygon(c.tolist())
# Check if the points are inside the polygon
good_points = []
for p in points:
if polygon.contains_point(p):
good_points.append(p)
return polygon, np.array(good_points)
defremove_points(points):
""" Remove points from 'points' that fall inside fascicles """
survivors = []
# Iterate over input pointsfor p in points:
discard = False# Iterate over fasciclesfor k, fp in polygons.items():
if"Fascicle"in k:
# Discard it and end this sub-loop if the point is inside the# fascicle's polygonif fp.contains_point(p):
discard = Truebreak# If it survived the loop, save itifnot discard:
survivors.append(p)
return np.array(survivors)
defreduce_points(c, n):
""" Reduce the number of points of contours 'c' by a factor of n in
order to reduce the computational burden. Only for contours with
more than n points """for k, a in c.items():
iflen(a) > n:
c[k] = a[::n]
return c
defc2pslg(c):
""" Convert the contours of a nerve stored in the dictionary 'c' to a
dictionary describing a Planar Straight Line Graph (PSLG) """# newc = {'vertices': None, 'holes': None, 'segments': None}
newc = {}
# Total number of points
nt = np.array([len(a) for a in c.values()]).sum()
# Counter of processed points
npr = 0# Generate the information
vertices = []
holes = []
segments = []
# Iterate over all the contoursfor k, a in c.items():
n = len(a)
i = 0# Append vertices and segmentsfor (x, y) in a:
vertices.append([x, y])
# Only if there's more than one point here, add segmentsif n > 1:
if i < n-1:
segments.append([npr+i, npr+i+1])
i += 1else:
segments.append([npr+i, npr])
# Update npr
npr += n
# Holesif"Fascicle"in k:
# Add the centroid (hand-maded for speed-up)
a = np.array(a)
holes.append([a[:, 0].mean(), a[:, 1].mean()])
newc['vertices'] = np.array(vertices)
# Condition: for there to be a 'holes' entry, there must be holesiflen(holes) > 0:
newc['holes'] = np.array(holes)
newc['segments'] = np.array(segments)
return newc