Triangulation with holes in python - python

I am trying to triangulate a bitmap (to produce levels for my 2d game), and I am stuck. I am using the Triangle library by Jonathan Shewchuk using this wrapper.
I start with an image,
then I detect edges and determine which vertices are holes. I picked every fourth for triangulation,
then I passed those points to triangulation, but I end up with something like this
where my hole has disappeared. What am I doing wrong?
Also, why am i getting somewhat convex hull instead of triangulated polygon?
Here is my code so far:
#here i am loading all data, that i will use later on but i had to insert that, just in case
mapfg = glob(path.join(pathtomapfolder, "Foreground.png"))[0] #Getting map foreground image
mapob = glob(path.join(pathtomapfolder, "Obstacles.png"))[0] #Getting map file
mappr = glob(path.join(pathtomapfolder, "Properties.txt"))[0] #Getting map info file
self.mapprops = [mapob, mapfg, mappr]
#getting ground and obstacles
obsbitmap = Image.open(self.mapprops[0])
lockBitmap = obsbitmap.load()
compareClr = (0, 0, 0)
for y in xrange(obsbitmap.size[1]):
tmp = []
for x in xrange(obsbitmap.size[0]):
if lockBitmap[x, y][0] == compareClr[0] and lockBitmap[x, y][6] == compareClr[1] and lockBitmap[x, y][7] == compareClr[2]:
tmp.append(1)
else:
tmp.append(0)
self.obs.append(tmp)
#detecting edges
for y in xrange(len(self.obs)):
tmphit = []
for x in xrange(len(self.obs[0])):
if (self.obs[y][x] == 0 and (self.obs[MinMax.NoOver(y - 1, len(self.obs) - 1, 0)][x] == 1 or self.obs[y][MinMax.NoOver(x - 1, len(self.obs[0]) - 1, 0)] == 1 or self.obs[y][MinMax.NoOver(x + 1, len(self.obs[0]) - 1, 0)] == 1 or self.obs[MinMax.NoOver(y + 1, len(self.obs) - 1, 0)][x] == 1)) or (self.obs[y][x] == 1 and (MinMax.WillOver(y - 1, len(self.obs) - 1, 0) or MinMax.WillOver(x - 1, len(self.obs[0]) - 1, 0) or MinMax.WillOver(x + 1, len(self.obs[0]) - 1, 0) or MinMax.WillOver(y + 1, len(self.obs) - 1, 0))):
tmphit.append(True)
else:
tmphit.append(False)
self.hit.append(tmphit)
#here it starts, first of all i search for vertice, then go CW or CCW and get all vertices from edge of one polygon, i also detect, whether it is hole or not and to which polygon is related to.
xcirc = ycirc = 0
coords = []
coordvalues = []
parentid = []
self.allverts = [coords, coordvalues, parentid]
polyID = 0
for y in xrange(len(self.obs)):
for x in xrange(len(self.obs[0])):
if self.hit[y][x] and not (x, y) in self.allverts[0]:
left = []
right = []
up = []
down = []
numobjects = numholes = 0
type = ""
parentid = -1
for v in xrange(len(self.allverts[0])):
if self.allverts[0][v][8] == y and self.allverts[0][v][0] < x: left.append(self.allverts[1][v])
if self.allverts[0][v][9] == y and self.allverts[0][v][0] > x: right.append(self.allverts[1][v])
if self.allverts[0][v][0] == x and self.allverts[0][v][10] < y: up.append(self.allverts[1][v])
if self.allverts[0][v][0] == x and self.allverts[0][v][11] > y: down.append(self.allverts[1][v])
for id in xrange(polyID):
if ("not hole", id) in left and ("not hole", id) in right and ("not hole", id) in up and ("not hole", id) in down:
numobjects += 1
parentid = id
elif ("hole", id) in left and ("hole", id) in right and ("hole", id) in up and ("hole", id) in down:
numholes += 1
if numobjects == 0 or numobjects == numholes: type = "not hole"
elif numobjects > numholes: type = "hole"
found = False
lastangle = -90
self.allverts[0].append((x, y))
self.allverts[1].append((type, polyID))
self.allverts[2].append(parentid)
v = 1
while not found:
angle = MinMax.Overflow(lastangle - 45, 180, -179)
lastangle = angle
xcirc = int(round(math.cos((math.pi / 180) * angle)))
ycirc = int(round(math.sin((math.pi / 180) * angle)))
if self.hit[MinMax.NoOver(self.allverts[0][-1][12] + ycirc, len(self.hit) - 1, 0)][MinMax.NoOver(self.allverts[0][-1][0] + xcirc, len(self.hit[0]) - 1, 0)] and (MinMax.WontOver(self.allverts[0][-1][13] + ycirc, len(self.hit) - 1, 0) and MinMax.WontOver(self.allverts[0][-1][0] + xcirc, len(self.hit[0]) - 1, 0)):
if not (self.allverts[0][-1][0] + xcirc, self.allverts[0][-1][14] + ycirc) in self.allverts[0]:
self.allverts[0].append((self.allverts[0][-1][0] + xcirc, self.allverts[0][-1][15] + ycirc))
self.allverts[1].append((type, polyID))
self.allverts[2].append(parentid)
v += 1
else:
#self.allverts.append((self.allverts[-1][0] + xcirc, self.allverts[-1][16] + ycirc))
found = True
if v < 4:
polyID -= 1
for d in xrange(v):
del self.allverts[0][-1]
del self.allverts[1][-1]
del self.allverts[2][-1]
lastangle = MinMax.Overflow(lastangle + 135, 180, -179)
polyID += 1
# now i have to convert that data structure to something i can pass to triangulate function
objects = []
objectpoints = []
idtoindexobj = []
holes = []
holepoints = []
holecoords = []
holeleft = len(self.hit[0])
holetop = len(self.hit)
holeright = holebottom = 0
idtoindexhole = []
prevvert = (self.allverts[0][0], self.allverts[1][0], self.allverts[2][0])
d = 0
for u in xrange(len(self.allverts[0])):
vert = (self.allverts[0][u], self.allverts[1][u], self.allverts[2][u])
if vert[1][17] != prevvert[1][18]:
d = 0
if prevvert[1][0] == "not hole":
objects.append(objectpoints)
objectpoints = []
idtoindexobj.append(prevvert[1][19])
else:
holes.append(holepoints)
holepoints = []
holecoords.append((holeleft + (MinMax.AminB(holeleft, holeright)/2), holetop + (MinMax.AminB(holetop, holebottom)/2)))
idtoindexhole.append(prevvert[2])
holeleft = len(self.hit[0])
holetop = len(self.hit)
holeright = holebottom = 0
if vert[1][0] == "not hole":
if d % 4 == 0:
objectpoints.append((vert[0][0], vert[0][20]))
else:
if d % 4 == 0:
holepoints.append((vert[0][0], vert[0][21]))
if vert[0][0] < holeleft: holeleft = vert[0][0]
if vert[0][0] > holeright: holeright = vert[0][0]
if vert[0][22] < holetop: holetop = vert[0][23]
if vert[0][24] > holebottom: holebottom = vert[0][25]
d+=1
prevvert = vert
if prevvert[1][0] == "not hole":
objects.append(objectpoints)
objectpoints = []
idtoindexobj.append(prevvert[1][26])
else:
holes.append(holepoints)
holepoints = []
holecoords.append((holeleft + (MinMax.AminB(holeleft, holeright)/2), holetop + (MinMax.AminB(holetop, holebottom)/2)))
idtoindexhole.append(prevvert[2])
holeleft = len(self.hit[0])
holetop = len(self.hit)
holeright = holebottom = 0
objectpoints.append((vert[0][0], vert[0][27]))
self.polygons = []
for ind, id in enumerate(idtoindexobj):
holecoordlist = []
segments = []
for k, l in enumerate(idtoindexhole):
if l == id:
holecoordlist.append(holecoords[k])
prevsegpart = False
for segpart in holes[k]:
if not prevsegpart:
prevsegpart = segpart
continue
segments.append((prevsegpart[0], prevsegpart[1], segpart[0], segpart[1]))
prevsegpart = segpart
segments.append((prevsegpart[0], prevsegpart[1], holes[k][0][0], holes[k][0][1]))
if segments:
self.polygons.append({"vertices":objects[ind], "segments":segments, "holes":holecoordlist})
else:
self.polygons.append({"vertices":objects[ind]})
indtripolylist = []
for pol in self.polygons:
#here i am calling that triangulate function
indtripolylist.append(triangle.triangulate(pol, opts="q"))
#and finally convert what has been returned to coordinates of triangles (because it returns list of vertices and touples of indexes pointing to vertices)
self.tripolylist = []
for po in indtripolylist:
tmptriangles = []
for tr in po["triangles"]:
tmptriangles.append((po["vertices"][tr[0]], po["vertices"][tr[1]], po["vertices"][tr[2]]))
self.tripolylist.append(tmptriangles)
Thank you for your help.

This had me scratching my head for a while, your comments helped me get it working.
to see an example of the data you need to pass:
triangle.get_data('face')
to stop a polygon being "filled in" and keep it concave you can pass along the segments like this
segments = []
for i in range(len(verts)-1):
segments.append([int(i),int(i+1)])
segments.append([int(i+1),int(0)])
A = {'vertices':array(verts), 'segments':array(segments)}
to add a hole, you need to mark the verts and segments seperatly (warning: untested code)
vertmarks = []
for i in range(len(verts)):
vertmarks.append([2])
for i in range(len(hole)):
vertmarks.append([4])
segmarks = []
for i in range(len(segments)):
segmarks.append([2])
for i in range(len(holesegments)):
segmarks.append([4])
A = {'vertices':array(verts), 'segments':array(segments),
'segment_markers':array(segmarks), 'vertex_markers':array(vertmarks)}
'holes' should also be passed as a list of [x,y] locations - one inside each hole

Related

Image parsing in python (connected components analysis)

I have an image of mathematical formula and I need to parse symbols of it, but also save where they were (center of each symbol). For example image like this needs to be transformed into 15 different images 75x75, 1 per each symbol.
What I have tried is:
Transform to gray and then binary: pixels close to white(> 250) becomes 255 and other become 0
Use BNF to find all components and then transform them into images (with rescaling and everything else)
But I am sure it is not the best way to do it, maybe there is standard approach for this problem exist?
Here is my code:
class Parser:
def init(self, targetSizes=(75, 75), binaryThreshold=cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU,
scaleFully=False, scaleFullyRate=0.9, whiteThreshold=249, blackThreshold=0,
rescalingInterpolation=cv2.INTER_AREA, pixelsInImageThreshold=20,
rescaleOriginalImage=True, rescaleToAtLeast=200, rescaleToAtMaximum=1000):
self.targetWidth = targetSizes[0]
self.targetHeight = targetSizes[1]
self.binaryThreshold = binaryThreshold
self.scaleFully = scaleFully
self.scaleFullyRate = scaleFullyRate
self.whiteThreshold = whiteThreshold
self.blackThreshold = blackThreshold
self.rescalingInterpolation = rescalingInterpolation
self.pixelsInIMageThreshold = pixelsInImageThreshold
self.rescaleOriginalImage = rescaleOriginalImage
self.rescaleOriginalMin = rescaleToAtLeast
self.rescaleOriginalMax = rescaleToAtMaximum
self.parseMode = 1
def _imageToBinary(self, image, zeroValueTrash=0, oneValueTrash=253):
grayImage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(grayImage, self.blackThreshold, self.whiteThreshold, self.binaryThreshold)
# cv2.imwrite("Test.png", binary)
return binary
def _BNF(self, binaryImage):
Q = MyQueue()
whitePixels = []
gg = 0
for i in range(len(binaryImage)):
for j in range(len(binaryImage[i])):
if binaryImage[i][j] > self.whiteThreshold-1:
Q.put((i, j))
binaryImage[i][j] = 0
obj = []
gg += 1
while not Q.empty():
i, j = Q.pop()
obj.append((i, j))
if i + 1 < len(binaryImage) and binaryImage[i + 1][j] != 0:
Q.put((i + 1, j))
binaryImage[i + 1][j] = 0
if j - 1 > 0 and binaryImage[i][j - 1] != 0:
Q.put((i, j - 1))
binaryImage[i][j - 1] = 0
if i - 1 > 0 and binaryImage[i - 1][j] != 0:
Q.put((i - 1, j))
binaryImage[i - 1][j] = 0
if j + 1 < len(binaryImage[i]) and binaryImage[i][j + 1] != 0:
Q.put((i, j + 1))
binaryImage[i][j + 1] = 0
if self.parseMode == 1:
if i + 1 < len(binaryImage) and j+1 < len(binaryImage[i+1]) and binaryImage[i + 1][j+1] != 0:
Q.put((i + 1, j+1))
binaryImage[i + 1][j+1] = 0
if i + 1 < len(binaryImage) and j - 1 > 0 and binaryImage[i + 1][j-1] != 0:
Q.put((i + 1, j-1))
binaryImage[i + 1][j-1] = 0
if i - 1 > 0 and j - 1 > 0 and binaryImage[i - 1][j - 1] != 0:
Q.put((i - 1, j - 1))
binaryImage[i - 1][j - 1] = 0
if i - 1 > 0 and j + 1 < len(binaryImage[i-1]) and binaryImage[i - 1][j + 1] != 0:
Q.put((i - 1, j + 1))
binaryImage[i - 1][j + 1] = 0
cv2.imwrite("tmp/{}.png".format(gg), binaryImage)
whitePixels.append(obj)
return whitePixels
def parseImage(self, image_path: str) -> list:
image = cv2.imread(image_path)
if self.rescaleOriginalImage:
image = self.scaleOriginal(image)
binary = self._imageToBinary(image)
whitePixels = self._BNF(binary)
return whitePixels
def isScaleable(self, imageShape):
return True
def scaleOriginal(self, image: np.ndarray):
# To be created
return image
#staticmethod
def _getImageAndCenterFromDotes(Dotes, originalImage=None):
i_mx, j_mx = -1, -1
i_mn, j_mn = 100500, 100500 # just big numbers
# finding upper right and lower left corner of image
for el in Dotes:
i, j = el
if i_mx < i:
i_mx = i
if j_mx < j:
j_mx = j
if j_mn > j:
j_mn = j
if i_mn > i:
i_mn = i
# updating image center
imageCenter = Point((i_mx + i_mn) // 2, (j_mx + j_mn) // 2)
# finding out size of image
width, height = i_mx - i_mn + 1, j_mx - j_mn + 1
image = np.zeros((width, height)) if originalImage is None else np.zeros((width, height, 3))
# recreating image from dotes
if originalImage is not None:
for el in Dotes:
i, j = el
image[i - i_mn][j - j_mn] = originalImage[i][j]
else:
for el in Dotes:
i, j = el
image[i - i_mn][j - j_mn] = 255
return image, imageCenter
def scaleParsedImage(self, image: np.ndarray):
"""
:param image: np.ndarray
:return: scaledImage np.ndarray
"""
width, height = image.shape if len(image.shape) == 2 else image.shape[0], image.shape[1]
newWidth = self.targetWidth if width > self.targetHeight else width
newHeight = self.targetHeight if height > self.targetHeight else height
if self.scaleFully and newHeight < self.targetHeight * self.scaleFullyRate and newWidth * self.scaleFullyRate:
scaleRate = min((self.targetWidth * self.scaleFullyRate / newWidth), (
self.targetHeight * self.scaleFullyRate / newHeight))
newWidth = math.ceil(newWidth * scaleRate)
newHeight = math.ceil(newHeight * scaleRate)
scaled = cv2.resize(image, (newHeight, newWidth), interpolation=self.rescalingInterpolation)
# pasting our scaled image in the middle
x_add, y_add = (self.targetWidth - newWidth) // 2, (self.targetHeight - newHeight) // 2
resized = np.zeros((self.targetWidth, self.targetHeight)) if len(image.shape) == 2 else np.zeros((self.targetWidth, self.targetHeight, 3))
for x in range(newWidth):
for y in range(newHeight):
resized[x + x_add][y + y_add] = scaled[x][y]
return resized
def parseAndConvert(self, image_name: str) -> list:
imagesInDotes = self.parseImage(image_name)
original = 255 - cv2.imread(image_name)
images = []
for dotes in imagesInDotes:
image = self._getImageAndCenterFromDotes(dotes, original)
images.append([self.scaleParsedImage(image[0]), image[1]])
rawImages = []
for image, center in images:
rawImages.append(RawImage(image, center))
return rawImages
Have a look at the (imho not all too intuitively named) function cv.findContours():
https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html
It should do most things that you are doing by hand right now out of the box, which is extracting and measuring binary objects.
If you encouter problems where a single symbol is made up of several objects (like i, % or "), look into the morphological operations to merge them into a single one: erode(), dilate(), or open and close via morphologyEx() (Tutorial here: https://docs.opencv.org/4.x/d9/d61/tutorial_py_morphological_ops.html).

Extracting Minutiae Terminations and Bifurcations values from fingerprint-feature-extractor in Python 3

I recently tried the new fingerprint feature extractor library by Utkarsh-Deshmukh (https://github.com/Utkarsh-Deshmukh/Fingerprint-Feature-Extraction) and it works like wonder. The problem is I need to extract terminations and bifurcations value from the library. I used this code that's included in the github link to get features bifurcations and terminations:
import fingerprint_feature_extractor
img = cv2.imread('image_path', 0)
FeaturesTerminations, FeaturesBifurcations = fingerprint_feature_extractor.extract_minutiae_features(img, showResult=True, spuriousMinutiaeThresh=10)
I tried using print() command to see what's inside FeaturesBifurcations and I can't understand what the output means.
print() command on FeaturesBifurcations
What I needed is values that looks like this where first and second column indicates xy coordinates, third column indicates orientations, and fourth column indicate type:
minutiaes bifurcations (marked with 1 in the last column) and terminations (marked with 0 in the last column) values extracted from fingerprint
I tried reading the classes in the library and I figure I could get those values (features locations, orientations, and type is explicitly stated in the library), but i do not know how to extract those values. This is what is inside the fingerprint-feature-extractor library:
import cv2
import numpy as np
import skimage.morphology
from skimage.morphology import convex_hull_image, erosion
from skimage.morphology import square
import math
class MinutiaeFeature(object):
def __init__(self, locX, locY, Orientation, Type):
self.locX = locX;
self.locY = locY;
self.Orientation = Orientation;
self.Type = Type;
class FingerprintFeatureExtractor(object):
def __init__(self):
self._mask = []
self._skel = []
self.minutiaeTerm = []
self.minutiaeBif = []
def __skeletonize(self, img):
img = np.uint8(img > 128)
self._skel = skimage.morphology.skeletonize(img)
self._skel = np.uint8(self._skel) * 255
self._mask = img * 255
def __computeAngle(self, block, minutiaeType):
angle = []
(blkRows, blkCols) = np.shape(block);
CenterX, CenterY = (blkRows - 1) / 2, (blkCols - 1) / 2
if (minutiaeType.lower() == 'termination'):
sumVal = 0;
for i in range(blkRows):
for j in range(blkCols):
if ((i == 0 or i == blkRows - 1 or j == 0 or j == blkCols - 1) and block[i][j] != 0):
angle.append(-math.degrees(math.atan2(i - CenterY, j - CenterX)))
sumVal += 1
if (sumVal > 1):
angle.append(float('nan'))
return (angle)
elif (minutiaeType.lower() == 'bifurcation'):
(blkRows, blkCols) = np.shape(block);
CenterX, CenterY = (blkRows - 1) / 2, (blkCols - 1) / 2
angle = []
sumVal = 0;
for i in range(blkRows):
for j in range(blkCols):
if ((i == 0 or i == blkRows - 1 or j == 0 or j == blkCols - 1) and block[i][j] != 0):
angle.append(-math.degrees(math.atan2(i - CenterY, j - CenterX)))
sumVal += 1
if (sumVal != 3):
angle.append(float('nan'))
return (angle)
def __getTerminationBifurcation(self):
self._skel = self._skel == 255;
(rows, cols) = self._skel.shape;
self.minutiaeTerm = np.zeros(self._skel.shape);
self.minutiaeBif = np.zeros(self._skel.shape);
for i in range(1, rows - 1):
for j in range(1, cols - 1):
if (self._skel[i][j] == 1):
block = self._skel[i - 1:i + 2, j - 1:j + 2];
block_val = np.sum(block);
if (block_val == 2):
self.minutiaeTerm[i, j] = 1;
elif (block_val == 4):
self.minutiaeBif[i, j] = 1;
self._mask = convex_hull_image(self._mask > 0)
self._mask = erosion(self._mask, square(5)) # Structuing element for mask erosion = square(5)
self.minutiaeTerm = np.uint8(self._mask) * self.minutiaeTerm
def __removeSpuriousMinutiae(self, minutiaeList, img, thresh):
img = img * 0;
SpuriousMin = [];
numPoints = len(minutiaeList);
D = np.zeros((numPoints, numPoints))
for i in range(1,numPoints):
for j in range(0, i):
(X1,Y1) = minutiaeList[i]['centroid']
(X2,Y2) = minutiaeList[j]['centroid']
dist = np.sqrt((X2-X1)**2 + (Y2-Y1)**2);
D[i][j] = dist
if(dist < thresh):
SpuriousMin.append(i)
SpuriousMin.append(j)
SpuriousMin = np.unique(SpuriousMin)
for i in range(0,numPoints):
if(not i in SpuriousMin):
(X,Y) = np.int16(minutiaeList[i]['centroid']);
img[X,Y] = 1;
img = np.uint8(img);
return(img)
def __cleanMinutiae(self, img):
self.minutiaeTerm = skimage.measure.label(self.minutiaeTerm, connectivity=2);
RP = skimage.measure.regionprops(self.minutiaeTerm)
self.minutiaeTerm = self.__removeSpuriousMinutiae(RP, np.uint8(img), 10);
def __performFeatureExtraction(self):
FeaturesTerm = []
self.minutiaeTerm = skimage.measure.label(self.minutiaeTerm, connectivity=2);
RP = skimage.measure.regionprops(np.uint8(self.minutiaeTerm))
WindowSize = 2 # --> For Termination, the block size must can be 3x3, or 5x5. Hence the window selected is 1 or 2
FeaturesTerm = []
for num, i in enumerate(RP):
print(num)
(row, col) = np.int16(np.round(i['Centroid']))
block = self._skel[row - WindowSize:row + WindowSize + 1, col - WindowSize:col + WindowSize + 1]
angle = self.__computeAngle(block, 'Termination')
if(len(angle) == 1):
FeaturesTerm.append(MinutiaeFeature(row, col, angle, 'Termination'))
FeaturesBif = []
self.minutiaeBif = skimage.measure.label(self.minutiaeBif, connectivity=2);
RP = skimage.measure.regionprops(np.uint8(self.minutiaeBif))
WindowSize = 1 # --> For Bifurcation, the block size must be 3x3. Hence the window selected is 1
for i in RP:
(row, col) = np.int16(np.round(i['Centroid']))
block = self._skel[row - WindowSize:row + WindowSize + 1, col - WindowSize:col + WindowSize + 1]
angle = self.__computeAngle(block, 'Bifurcation')
if(len(angle) == 3):
FeaturesBif.append(MinutiaeFeature(row, col, angle, 'Bifurcation'))
return (FeaturesTerm, FeaturesBif)
def extractMinutiaeFeatures(self, img):
self.__skeletonize(img)
self.__getTerminationBifurcation()
self.__cleanMinutiae(img)
FeaturesTerm, FeaturesBif = self.__performFeatureExtraction()
return(FeaturesTerm, FeaturesBif)
def showResults(self):
BifLabel = skimage.measure.label(self.minutiaeBif, connectivity=2);
TermLabel = skimage.measure.label(self.minutiaeTerm, connectivity=2);
minutiaeBif = TermLabel * 0;
minutiaeTerm = BifLabel * 0;
(rows, cols) = self._skel.shape
DispImg = np.zeros((rows, cols, 3), np.uint8)
DispImg[:, :, 0] = 255*self._skel;
DispImg[:, :, 1] = 255*self._skel;
DispImg[:, :, 2] = 255*self._skel;
RP = skimage.measure.regionprops(BifLabel)
for idx, i in enumerate(RP):
(row, col) = np.int16(np.round(i['Centroid']))
minutiaeBif[row, col] = 1;
(rr, cc) = skimage.draw.circle_perimeter(row, col, 3);
skimage.draw.set_color(DispImg, (rr, cc), (255, 0, 0));
RP = skimage.measure.regionprops(TermLabel)
for idx, i in enumerate(RP):
(row, col) = np.int16(np.round(i['Centroid']))
minutiaeTerm[row, col] = 1;
(rr, cc) = skimage.draw.circle_perimeter(row, col, 3);
skimage.draw.set_color(DispImg, (rr, cc), (0, 0, 255));
cv2.imshow('a', DispImg);
cv2.waitKey(0)
def extract_minutiae_features(img, showResult=False):
feature_extractor = FingerprintFeatureExtractor()
FeaturesTerm, FeaturesBif = feature_extractor.extractMinutiaeFeatures(img)
if(showResult):
feature_extractor.showResults()
return(FeaturesTerm, FeaturesBif)
Is there a way to extract locations, orientations, and type float (and/or integer) values from this library? or is there a way or library to plot those lists to cartesian or polar coordinates?

How to plot character state changes from a presence-absence matrix on to a phylogeny

I am trying to assign character state changes from a presence-absence matrix to a phylogeny.
I have tried assigning each character to its leaf node, and then if the leaf node's sister has the same character I reassign the character to the parent node (and work back until all nodes are assigned). I am using a dummy dataset to try to achieve this:
Matrix
>Dme_001
1110000000000111
>Dme_002
1110000000000011
>Cfa_001
0110000000000011
>Mms_001
0110000000000011
>Hsa_001
0110000000000010
>Ptr_002
0110000000000011
>Mmu_002
0110000000000011
>Hsa_002
0110000000000011
>Ptr_001
0110000000000011
>Mmu_001
0110000000000011
Phylogeny
((Dme_001,Dme_002),(((Cfa_001,Mms_001),((Hsa_001,Ptr_001),Mmu_001)),(Ptr_002,(Hsa_002,Mmu_002))));
I assign internal nodes using ete3, so my output should be:
BranchID CharacterState Change
Node_1: 0 0->1
Hsa_001: 15 1->0
As my code assigns character states based on their sisters if a loss is encountered it messes up the output so that:
BranchID CharacterState Change
Node_1: 0 0->1
Node_3 15 0->1
Node_5 15 0->1
Node_8 15 0->1
Could someone please help me with this? I'm coding in python and developing tunnel vision. Thanks in advance
My code:
from ete3 import PhyloTree
from collections import Counter
import itertools
PAM = open('PAM','r')
gene_tree = '((Dme_001,Dme_002),(((Cfa_001,Mms_001),((Hsa_001,Ptr_001),Mmu_001)),(Ptr_002,(Hsa_002,Mmu_002))));'
NodeIDs = []
tree = PhyloTree(gene_tree)
edge = 0
for node in tree.traverse():
if not node.is_leaf():
node.name = "Node_%d" %edge
edge +=1
NodeIDs.append(node.name)
if node.is_leaf():
NodeIDs.append(node.name)
f = open('PAM','r')
taxa = []
pap = []
for line in f:
term = line.strip().split('\t')
taxa.append(term[0])
p = [p for p in term[1]]
pap.append(p)
statesD = dict(zip(taxa, pap))
def PlotCharacterStates():
Plots = []
events = []
for key, value in statesD.iteritems():
count = -1
for s in value:
count+=1
if s == CharacterState:
a = key, count
events.append(a)
Round3_events = []
while len(events) > 0:
for rel in Relationships:
node_store = []
sis_store = []
for event in events:
if rel[0] == event[0]:
node_store.append(event[1])
if rel[1] == event[0]:
sis_store.append(event[1])
if (len(node_store) > 0) and (len(sis_store) > 0):
place = rel, node_store, sis_store
Round3_events.append(place)
moved = []
for placement in Round3_events:
intercept = (set(placement[1]) & set(placement[2]))
node_plot = (set(placement[1]) - set(placement[2]))
sis_plot = (set(placement[2]) - set(placement[1]))
if len(node_plot) > 0:
for x in node_plot:
y = placement[0][0], x
Plots.append(y)
moved.append(y)
if len(sis_plot) > 0:
for x in sis_plot:
y = placement[0][1], x
Plots.append(y)
moved.append(y)
if len(intercept) > 0:
for x in intercept:
y = placement[0][2], x
y1 = placement[0][0], x
y2 = placement[0][1], x
moved.append(y1)
moved.append(y2)
events.append(y)
for event in events:
if event[0] == "Node_0":
Plots.append(event)
moved.append(event)
events2 = (set(events) - set(moved))
events = []
for event in events2:
events.append(event)
pl = set(Plots)
Plots = []
for p in pl:
Plots.append(p)
print CharacterState, Plots
'''
assign sisters to leaves, internals
'''
e = []
round1b_e = []
round2a_e = []
placements = []
Relationships = []
Rounds = []
for node in tree.traverse():
sisters = node.get_sisters()
parent = node.up
cycle1 = []
if node.is_leaf():
for sister in sisters:
if sister.is_leaf():
round1a = ["Round1a", node.name, sister.name, parent.name]
node_names = node.name, sister.name
Rounds.append(round1a)
e.append(node_names)
x = node.name, sister.name, parent.name, "leaf-leaf"
Relationships.append(x)
if not sister.is_leaf():
round1b = ["Round1b", node.name, sister.name, parent.name]
node_names = node.name, sister.name
Rounds.append(round1b)
round1b_e.append(node_names)
x = node.name, sister.name, parent.name, "node-leaf"
Relationships.append(x)
elif not node.is_leaf():
if not node.is_root():
for sister in sisters:
if not sister.is_leaf():
node_names = node.name, sister.name
round2a_e.append(node_names)
x = node.name, sister.name, parent.name, "node-node"
Relationships.append(x)
x = []
CharacterStates = []
for key, value in statesD.iteritems():
for value in value:
x.append(value)
y = sorted(set(x))
for x in y:
CharacterStates.append(x)
for CharacterState in CharacterStates:
PlotCharacterStates()

Optimizing a complex algorithm

I know this is not an ideal place for questions of this scope, but I'm not sure where else to ask this or how to break it down. I've been working on a function for the past couple weeks, that runs, but for it to be feasible for my purposes, I need to speed it up 200-300x.
I have an image array, where all pixels of similar color have been averaged and set to that average value. Then I have a 2D array of the same height and width, which labels each unique and non-contiguous feature of the image.
Using these I need to assess the size of each feature and its level of contrast to each of its neighbors. These values are used in an equation and if the output of that equation is below a certain threshold, that feature is merged with its most similar neighbor.
I've uploaded the image and the feature label array (printed with numpy.savetext()) to OneDrive and attached links
code:
def textureRemover(pix, labeledPix, ratio = 1.0):
numElements = numpy.amax(labeledPix)
maxSize = numpy.count_nonzero(labeledPix)
MAXIMUMCONTRAST = 443.405
for regionID in range(numElements):
start = time.clock()
regionID += 1
if regionID not in labeledPix:
continue
#print(regionID)
#print((regionID / numElements) * 100, '%')
neighborIDs = getNeighbors(labeledPix, regionID)
if 0 in neighborIDs:
neighborIDs.remove(0) #remove white value
regionMask = labeledPix == regionID
region = pix[regionMask]
size = numpy.count_nonzero(regionMask)
contrastMin = (ratio - (size / maxSize)) * MAXIMUMCONTRAST
regionMean = region.mean(axis = 0)
if len(neighborIDs) > 200:
contrast = numpy.zeros(labeledPix.shape)
contrast[labeledPix!=0] = numpy.sqrt(numpy.sum((regionMean - pix[labeledPix!=0])**2, axis = -1))
significantMask = (contrast < contrastMin)
significantContrasts = list(numpy.unique(contrast[significantMask]))
significantNeighbors = {}
for significantContrast in significantContrasts:
minContrast = min(significantContrasts)
if labeledPix[contrast == minContrast][0] in neighborIDs:
significantNeighbors[minContrast] = labeledPix[contrast == minContrast][0]
else:
significantContrasts.pop(significantContrasts.index(minContrast))
else:
significantNeighbors = {}
for neighborID in neighborIDs:
neighborMask = labeledPix == neighborID
neighbor = pix[neighborMask]
neighborMean = neighbor.mean(axis = 0)
contrast = numpy.sqrt(numpy.sum((regionMean - neighborMean)**2, axis = -1))
if contrast < contrastMin:
significantNeighbors[contrast] = neighborID
if significantNeighbors:
contrasts = significantNeighbors.keys()
minContrast = min(contrasts)
minNeighbor = significantNeighbors[minContrast]
neighborMask = labeledPix == minNeighbor
neighborSize = numpy.count_nonzero(neighborMask)
if neighborSize <= size:
labeledPix[neighborMask] = regionID
pix[neighborMask] = regionMean
else:
labeledPix[regionMask] = minNeighbor
pix[regionMask] = pix[neighborMask].mean(axis = 0)
print(time.clock() - start)
return pix
pix
labeledPix
I know I'm asking for a lot of help, but I've been stuck on this for a few weeks and am unsure what else I can do. Any help will be greatly appreciated!
Here is an optimized version of most of your logic (I underestimated the amount of work that would be...). I skipped the >200 branch and am using fake data because I couldn't access your link. When I switch off your >200 branch your and my code appear to give the same result but mine is quite a bit faster on the fake example.
Sample output:
original
26.056154000000003
optimized
0.763613000000003
equal
True
Code:
import numpy as np
from numpy.lib.stride_tricks import as_strided
def mockdata(m, n, k):
colors = np.random.random((m, n, 3))
i, j = np.ogrid[:m, :n]
labels = np.round(k*k * (np.sin(0.05 * i) + np.sin(0.05 * j)**2)).astype(int) % k
return colors, labels
DIAG_NEIGHBORS = True
MAXIMUMCONTRAST = 443.405
def textureRemover2(pix, labeledPix, ratio=1.0):
start = time.clock()
pix, labeledPix = pix.copy(), labeledPix.copy()
pixf, labeledPixf = pix.reshape(-1, 3), labeledPix.ravel()
m, n = labeledPix.shape
s, t = labeledPix.strides
# find all sizes in O(n)
sizes = np.bincount(labeledPixf)
n_ids = len(sizes)
# make index for quick access to labeled areas
lblidx = np.split(np.argsort(labeledPixf), np.cumsum(sizes[:-1]))
lblidx[0] = None
# find all mean colors in O(n)
regionMeans = np.transpose([np.bincount(labeledPix.ravel(), px)
/ np.maximum(sizes, 1)
for px in pix.reshape(-1, 3).T])
# find all neighbors in O(n)
horz = set(frozenset(p) for bl in as_strided(labeledPix, (m,n-1,2), (s,t,t))
for p in bl)
vert = set(frozenset(p) for bl in as_strided(labeledPix, (m-1,n,2), (s,t,s))
for p in bl)
nb = horz|vert
if DIAG_NEIGHBORS:
dwnrgt = set(frozenset(p) for bl in as_strided(
labeledPix, (m-1,n-1,2), (s,t,s+t)) for p in bl)
dwnlft = set(frozenset(p) for bl in as_strided(
labeledPix[::-1], (m-1,n-1,2), (-s,t,t-s)) for p in bl)
nb = nb|dwnrgt|dwnlft
nb = {p for p in nb if len(p) == 2 and not 0 in p}
nb_dict = {}
for a, b in nb:
nb_dict.setdefault(a, set()).add(b)
nb_dict.setdefault(b, set()).add(a)
maxSize = labeledPix.size - sizes[0]
for id_ in range(1, n_ids):
nbs = list(nb_dict.get(id_, set()))
if not nbs:
continue
d = regionMeans[id_] - regionMeans[nbs]
d = np.einsum('ij,ij->i', d, d)
mnd = np.argmin(d)
if d[mnd] < ((ratio - sizes[id_]/maxSize) * MAXIMUMCONTRAST)**2:
mn = nbs[mnd]
lrg, sml = (id_, mn) if sizes[id_] >= sizes[mn] else (mn, id_)
sizes[lrg], sizes[sml] = sizes[lrg] + sizes[sml], 0
for nb in nb_dict[sml]:
nb_dict[nb].remove(sml)
nb_dict[nb].add(lrg)
nb_dict[lrg].update(nb_dict[sml])
nb_dict[lrg].remove(lrg)
nb_dict[sml] = set()
pixf[lblidx[sml]] = regionMeans[lrg]
labeledPixf[lblidx[sml]] = lrg
lblidx[lrg], lblidx[sml] = np.r_[lblidx[lrg],lblidx[sml]], None
print(time.clock() - start)
return pix
from scipy.ndimage.morphology import binary_dilation
import time
STRUCTEL = np.ones((3,3), int) if DIAG_NEIGHBORS else np.array([[0,1,0],[1,1,1],[0,1,0]], int)
def getNeighbors(labeledPix, regionID):
nb = set(labeledPix[binary_dilation(labeledPix == regionID, structure=STRUCTEL)])
nb.remove(regionID)
return sorted(nb)
numpy = np
def textureRemover(pix, labeledPix, ratio = 1.0):
pix, labeledPix = pix.copy(), labeledPix.copy()
numElements = numpy.amax(labeledPix)
maxSize = numpy.count_nonzero(labeledPix)
MAXIMUMCONTRAST = 443.405
start = time.clock()
for regionID in range(numElements):
regionID += 1
if regionID not in labeledPix:
continue
#print(regionID)
#print((regionID / numElements) * 100, '%')
neighborIDs = getNeighbors(labeledPix, regionID)
if 0 in neighborIDs:
neighborIDs.remove(0) #remove white value
regionMask = labeledPix == regionID
region = pix[regionMask]
size = numpy.count_nonzero(regionMask)
contrastMin = (ratio - (size / maxSize)) * MAXIMUMCONTRAST
regionMean = region.mean(axis = 0)
if len(neighborIDs) > 20000:
contrast = numpy.zeros(labeledPix.shape)
contrast[labeledPix!=0] = numpy.sqrt(numpy.sum((regionMean - pix[labeledPix!=0])**2, axis = -1))
significantMask = (contrast < contrastMin)
significantContrasts = list(numpy.unique(contrast[significantMask]))
significantNeighbors = {}
for significantContrast in significantContrasts:
minContrast = min(significantContrasts)
if labeledPix[contrast == minContrast][0] in neighborIDs:
significantNeighbors[minContrast] = labeledPix[contrast == minContrast][0]
else:
significantContrasts.pop(significantContrasts.index(minContrast))
else:
significantNeighbors = {}
for neighborID in neighborIDs:
neighborMask = labeledPix == neighborID
neighbor = pix[neighborMask]
neighborMean = neighbor.mean(axis = 0)
contrast = numpy.sqrt(numpy.sum((regionMean - neighborMean)**2, axis = -1))
if contrast < contrastMin:
significantNeighbors[contrast] = neighborID
if significantNeighbors:
contrasts = significantNeighbors.keys()
minContrast = min(contrasts)
minNeighbor = significantNeighbors[minContrast]
neighborMask = labeledPix == minNeighbor
neighborSize = numpy.count_nonzero(neighborMask)
if neighborSize <= size:
labeledPix[neighborMask] = regionID
pix[neighborMask] = regionMean
else:
labeledPix[regionMask] = minNeighbor
pix[regionMask] = pix[neighborMask].mean(axis = 0)
print(time.clock() - start)
return pix
data = mockdata(200, 200, 1000)
print('original')
res0 = textureRemover(*data)
print('optimized')
res2 = textureRemover2(*data)
print('equal')
print(np.allclose(res0, res2))

How to add a member function to an existing Python object?

Previously I created a lot of Python objects of class A, and I would like to add a new function plotting_in_PC_space_with_coloring_option() (the purpose of this function is to plot some data in this object) to class A and use those old objects to call plotting_in_PC_space_with_coloring_option().
An example is:
import copy
import numpy as np
from math import *
from pybrain.structure import *
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.datasets.supervised import SupervisedDataSet
import pickle
import neural_network_related
class A(object):
"""the neural network for simulation"""
'''
todo:
- find boundary
- get_angles_from_coefficients
'''
def __init__(self,
index, # the index of the current network
list_of_coor_data_files, # accept multiple files of training data
energy_expression_file, # input, output files
preprocessing_settings = None,
connection_between_layers = None, connection_with_bias_layers = None,
PCs = None, # principal components
):
self._index = index
self._list_of_coor_data_files = list_of_coor_data_files
self._energy_expression_file = energy_expression_file
self._data_set = []
for item in list_of_coor_data_files:
self._data_set += self.get_many_cossin_from_coordiantes_in_file(item)
self._preprocessing_settings = preprocessing_settings
self._connection_between_layers = connection_between_layers
self._connection_with_bias_layers = connection_with_bias_layers
self._node_num = [8, 15, 2, 15, 8]
self._PCs = PCs
def save_into_file(self, filename = None):
if filename is None:
filename = "network_%s.pkl" % str(self._index) # by default naming with its index
with open(filename, 'wb') as my_file:
pickle.dump(self, my_file, pickle.HIGHEST_PROTOCOL)
return
def get_cossin_from_a_coordinate(self, a_coordinate):
num_of_coordinates = len(a_coordinate) / 3
a_coordinate = np.array(a_coordinate).reshape(num_of_coordinates, 3)
diff_coordinates = a_coordinate[1:num_of_coordinates, :] - a_coordinate[0:num_of_coordinates - 1,:] # bond vectors
diff_coordinates_1=diff_coordinates[0:num_of_coordinates-2,:];diff_coordinates_2=diff_coordinates[1:num_of_coordinates-1,:]
normal_vectors = np.cross(diff_coordinates_1, diff_coordinates_2);
normal_vectors_normalized = np.array(map(lambda x: x / sqrt(np.dot(x,x)), normal_vectors))
normal_vectors_normalized_1 = normal_vectors_normalized[0:num_of_coordinates-3, :];normal_vectors_normalized_2 = normal_vectors_normalized[1:num_of_coordinates-2,:];
diff_coordinates_mid = diff_coordinates[1:num_of_coordinates-2]; # these are bond vectors in the middle (remove the first and last one), they should be perpendicular to adjacent normal vectors
cos_of_angles = range(len(normal_vectors_normalized_1))
sin_of_angles_vec = range(len(normal_vectors_normalized_1))
sin_of_angles = range(len(normal_vectors_normalized_1)) # initialization
for index in range(len(normal_vectors_normalized_1)):
cos_of_angles[index] = np.dot(normal_vectors_normalized_1[index], normal_vectors_normalized_2[index])
sin_of_angles_vec[index] = np.cross(normal_vectors_normalized_1[index], normal_vectors_normalized_2[index])
sin_of_angles[index] = sqrt(np.dot(sin_of_angles_vec[index], sin_of_angles_vec[index])) * np.sign(sum(sin_of_angles_vec[index]) * sum(diff_coordinates_mid[index]));
return cos_of_angles + sin_of_angles
def get_many_cossin_from_coordinates(self, coordinates):
return map(self.get_cossin_from_a_coordinate, coordinates)
def get_many_cossin_from_coordiantes_in_file (self, filename):
coordinates = np.loadtxt(filename)
return self.get_many_cossin_from_coordinates(coordinates)
def mapminmax(self, my_list): # for preprocessing in network
my_min = min(my_list)
my_max = max(my_list)
mul_factor = 2.0 / (my_max - my_min)
offset = (my_min + my_max) / 2.0
result_list = np.array(map(lambda x : (x - offset) * mul_factor, my_list))
return (result_list, (mul_factor, offset)) # also return the parameters for processing
def get_mapminmax_preprocess_result_and_coeff(self,data=None):
if data is None:
data = self._data_set
data = np.array(data)
data = np.transpose(data)
result = []; params = []
for item in data:
temp_result, preprocess_params = self.mapminmax(item)
result.append(temp_result)
params.append(preprocess_params)
return (np.transpose(np.array(result)), params)
def mapminmax_preprocess_using_coeff(self, input_data=None, preprocessing_settings=None):
# try begin
if preprocessing_settings is None:
preprocessing_settings = self._preprocessing_settings
temp_setttings = np.transpose(np.array(preprocessing_settings))
result = []
for item in input_data:
item = np.multiply(item - temp_setttings[1], temp_setttings[0])
result.append(item)
return result
# try end
def get_expression_of_network(self, connection_between_layers=None, connection_with_bias_layers=None):
if connection_between_layers is None:
connection_between_layers = self._connection_between_layers
if connection_with_bias_layers is None:
connection_with_bias_layers = self._connection_with_bias_layers
node_num = self._node_num
expression = ""
# first part: network
for i in range(2):
expression = '\n' + expression
mul_coef = connection_between_layers[i].params.reshape(node_num[i + 1], node_num[i])
bias_coef = connection_with_bias_layers[i].params
for j in range(np.size(mul_coef, 0)):
temp_expression = 'layer_%d_unit_%d = tanh( ' % (i + 1, j)
for k in range(np.size(mul_coef, 1)):
temp_expression += ' %f * layer_%d_unit_%d +' % (mul_coef[j, k], i, k)
temp_expression += ' %f);\n' % (bias_coef[j])
expression = temp_expression + expression # order of expressions matter in OpenMM
# second part: definition of inputs
index_of_backbone_atoms = [2, 5, 7, 9, 15, 17, 19];
for i in range(len(index_of_backbone_atoms) - 3):
index_of_coss = i
index_of_sins = i + 4
expression += 'layer_0_unit_%d = (raw_layer_0_unit_%d - %f) * %f;\n' % \
(index_of_coss, index_of_coss, self._preprocessing_settings[index_of_coss][1], self._preprocessing_settings[index_of_coss][0])
expression += 'layer_0_unit_%d = (raw_layer_0_unit_%d - %f) * %f;\n' % \
(index_of_sins, index_of_sins, self._preprocessing_settings[index_of_sins][1], self._preprocessing_settings[index_of_sins][0])
expression += 'raw_layer_0_unit_%d = cos(dihedral_angle_%d);\n' % (index_of_coss, i)
expression += 'raw_layer_0_unit_%d = sin(dihedral_angle_%d);\n' % (index_of_sins, i)
expression += 'dihedral_angle_%d = dihedral(p%d, p%d, p%d, p%d);\n' % \
(i, index_of_backbone_atoms[i], index_of_backbone_atoms[i+1],index_of_backbone_atoms[i+2],index_of_backbone_atoms[i+3])
return expression
def write_expression_into_file(self, out_file = None):
if out_file is None: out_file = self._energy_expression_file
expression = self.get_expression_of_network()
with open(out_file, 'w') as f_out:
f_out.write(expression)
return
def get_mid_result(self, input_data=None, connection_between_layers=None, connection_with_bias_layers=None):
if input_data is None: input_data = self._data_set
if connection_between_layers is None: connection_between_layers = self._connection_between_layers
if connection_with_bias_layers is None: connection_with_bias_layers = self._connection_with_bias_layers
node_num = self._node_num
temp_mid_result = range(4)
mid_result = []
# first need to do preprocessing
for item in self.mapminmax_preprocess_using_coeff(input_data, self._preprocessing_settings):
for i in range(4):
mul_coef = connection_between_layers[i].params.reshape(node_num[i + 1], node_num[i]) # fix node_num
bias_coef = connection_with_bias_layers[i].params
previous_result = item if i == 0 else temp_mid_result[i - 1]
temp_mid_result[i] = np.dot(mul_coef, previous_result) + bias_coef
if i != 3: # the last output layer is a linear layer, while others are tanh layers
temp_mid_result[i] = map(tanh, temp_mid_result[i])
mid_result.append(copy.deepcopy(temp_mid_result)) # note that should use deepcopy
return mid_result
def get_PC_and_save_it_to_network(self):
'''get PCs and save the result into _PCs
'''
mid_result = self.get_mid_result()
self._PCs = [item[1] for item in mid_result]
return
def train(self):
####################### set up autoencoder begin #######################
node_num = self._node_num
in_layer = LinearLayer(node_num[0], "IL")
hidden_layers = [TanhLayer(node_num[1], "HL1"), TanhLayer(node_num[2], "HL2"), TanhLayer(node_num[3], "HL3")]
bias_layers = [BiasUnit("B1"),BiasUnit("B2"),BiasUnit("B3"),BiasUnit("B4")]
out_layer = LinearLayer(node_num[4], "OL")
layer_list = [in_layer] + hidden_layers + [out_layer]
molecule_net = FeedForwardNetwork()
molecule_net.addInputModule(in_layer)
for item in (hidden_layers + bias_layers):
molecule_net.addModule(item)
molecule_net.addOutputModule(out_layer)
connection_between_layers = range(4); connection_with_bias_layers = range(4)
for i in range(4):
connection_between_layers[i] = FullConnection(layer_list[i], layer_list[i+1])
connection_with_bias_layers[i] = FullConnection(bias_layers[i], layer_list[i+1])
molecule_net.addConnection(connection_between_layers[i]) # connect two neighbor layers
molecule_net.addConnection(connection_with_bias_layers[i])
molecule_net.sortModules() # this is some internal initialization process to make this module usable
####################### set up autoencoder end #######################
trainer = BackpropTrainer(molecule_net, learningrate=0.002,momentum=0.4,verbose=False, weightdecay=0.1, lrdecay=1)
data_set = SupervisedDataSet(node_num[0], node_num[4])
sincos = self._data_set
(sincos_after_process, self._preprocessing_settings) = self.get_mapminmax_preprocess_result_and_coeff(data = sincos)
for item in sincos_after_process: # is it needed?
data_set.addSample(item, item)
trainer.trainUntilConvergence(data_set, maxEpochs=50)
self._connection_between_layers = connection_between_layers
self._connection_with_bias_layers = connection_with_bias_layers
print("Done!\n")
return
def create_sge_files_for_simulation(self,potential_centers = None):
if potential_centers is None:
potential_centers = self.get_boundary_points()
neural_network_related.create_sge_files(potential_centers)
return
def get_boundary_points(self, list_of_points = None, num_of_bins = 5):
if list_of_points is None: list_of_points = self._PCs
x = [item[0] for item in list_of_points]
y = [item[1] for item in list_of_points]
temp = np.histogram2d(x,y, bins=[num_of_bins, num_of_bins])
hist_matrix = temp[0]
# add a set of zeros around this region
hist_matrix = np.insert(hist_matrix, num_of_bins, np.zeros(num_of_bins), 0)
hist_matrix = np.insert(hist_matrix, 0, np.zeros(num_of_bins), 0)
hist_matrix = np.insert(hist_matrix, num_of_bins, np.zeros(num_of_bins + 2), 1)
hist_matrix = np.insert(hist_matrix, 0, np.zeros(num_of_bins +2), 1)
hist_matrix = (hist_matrix != 0).astype(int)
sum_of_neighbors = np.zeros(np.shape(hist_matrix)) # number of neighbors occupied with some points
for i in range(np.shape(hist_matrix)[0]):
for j in range(np.shape(hist_matrix)[1]):
if i != 0: sum_of_neighbors[i,j] += hist_matrix[i - 1][j]
if j != 0: sum_of_neighbors[i,j] += hist_matrix[i][j - 1]
if i != np.shape(hist_matrix)[0] - 1: sum_of_neighbors[i,j] += hist_matrix[i + 1][j]
if j != np.shape(hist_matrix)[1] - 1: sum_of_neighbors[i,j] += hist_matrix[i][j + 1]
bin_width_0 = temp[1][1]-temp[1][0]
bin_width_1 = temp[2][1]-temp[2][0]
min_coor_in_PC_space_0 = temp[1][0] - 0.5 * bin_width_0 # multiply by 0.5 since we want the center of the grid
min_coor_in_PC_space_1 = temp[2][0] - 0.5 * bin_width_1
potential_centers = []
for i in range(np.shape(hist_matrix)[0]):
for j in range(np.shape(hist_matrix)[1]):
if hist_matrix[i,j] == 0 and sum_of_neighbors[i,j] != 0: # no points in this block but there are points in neighboring blocks
temp_potential_center = [round(min_coor_in_PC_space_0 + i * bin_width_0, 2), round(min_coor_in_PC_space_1 + j * bin_width_1, 2)]
potential_centers.append(temp_potential_center)
return potential_centers
# this function is added after those old objects of A were created
def plotting_in_PC_space_with_coloring_option(self,
list_of_coordinate_files_for_plotting=None, # accept multiple files
color_option='pure'):
'''
by default, we are using training data, and we also allow external data input
'''
if list_of_coordinate_files_for_plotting is None:
PCs_to_plot = self._PCs
else:
temp_sincos = []
for item in list_of_coordinate_files_for_plotting:
temp_sincos += self.get_many_cossin_from_coordiantes_in_file(item)
temp_mid_result = self.get_mid_result(input_data = temp_sincos)
PCs_to_plot = [item[1] for item in temp_mid_result]
(x, y) = ([item[0] for item in PCs_to_plot], [item[1] for item in PCs_to_plot])
# coloring
if color_option == 'pure':
coloring = 'red'
elif color_option == 'step':
coloring = range(len(x))
fig, ax = plt.subplots()
ax.scatter(x,y, c=coloring)
ax.set_xlabel("PC1")
ax.set_ylabel("PC2")
plt.show()
return
But it seems that plotting_in_PC_space_with_coloring_option() was not binded to those old objects, is here any way to fix it (I do not want to recreate these objects since creation involves CPU-intensive calculation and would take very long time to do it)?
Thanks!
Something like this:
class A:
def q(self): print 1
a = A()
def f(self): print 2
setattr(A, 'f', f)
a.f()
This is called a monkey patch.

Categories