I was trying to optimize this function using Numba, but I am unable to do it. I think this has no part of the code which can be accelerated. If anyone can help me with an optimized version of this, My program would become blazing fast. Please tell if any dataset or other info is needed. When I apply direct #jit on this, It is not working.
def c_a(x, y, z, counter, p_l):
# start = time.time()
if counter == 1:
l = x
m = y
n = z
path = "c_r.pdb"
global r_a_t
p = Bio.PDB.PDBParser()
structure = p.get_structure('mSN1', path)
c_r = [a.get_coord() for a in structure.get_atoms()]
lengthnew = len(c_r)
m_d = np.array([-45, -45, -45])
a_s_r = np.zeros((128, 128, 128), np.complex)
for i in range(0, lengthnew):
x = int(math.floor((c_r[i][0] - m_d[0]) / 1.2))
y = int(math.floor((c_r[i][1] - m_d[1]) / 1.2))
z = int(math.floor((c_r[i][2] - m_d[2]) / 1.2))
with open("Ei.txt", 'r') as ei_values:
for row in ei_values:
s_v = row.split()
if s_v[0] == r_a_t[i] :
a_s_r[x, y, z] = np.complex(s_v[1])
n_n = lambda x, y, z : [(x2, y2, z2) for x2 in range(x - 5, x + 6)
for y2 in range(y - 5, y + 6)
for z2 in range(z - 5, z + 6)
if (-1 < x < X and
-1 < y < Y and
-1 < z < Z and
(x != x2 or y != y2 or z != z2) and
(0 <= x2 < X) and
(0 <= y2 < Y) and
(0 <= z2 < Z) and
((( abs(x - x2)) ** 2 + (abs(y - y2)) ** 2 + (abs(z - z2)) ** 2 ) <= 25))]
m = n_n(l, m, n)
result = 0
for i in range(0, len(m)):
a = m[i][0]
b = m[i][1]
c = m[i][2]
result = result + a_s_r[a][b][c]
return result
else:
l = x
m = y
n = z
path = p_l
global l_a_t
p = Bio.PDB.PDBParser()
structure = p.get_structure('mSN1', path)
c_l = [a.get_coord() for a in structure.get_atoms()]
lengthnew = len(c_l)
m_d = np.array([-45, -45, -45])
a_s_l = np.zeros((128, 128, 128), np.complex)
for i in range(0, lengthnew):
x = int(math.floor((c_l[i][0] - m_d[0]) / 1.2))
y = int(math.floor((c_l[i][1] - m_d[1]) / 1.2))
z = int(math.floor((c_l[i][2] - m_d[2]) / 1.2))
with open("E.txt", 'r') as e_v:
for row in e_v:
s_v = row.split()
if s_v[0] == l_a_t[i] :
a_s_l[x, y, z] = np.complex(s_v[1])
n_n = lambda x, y, z : [(x2, y2, z2) for x2 in range(x - 5, x + 6)
for y2 in range(y - 5, y + 6)
for z2 in range(z - 5, z + 6)
if (-1 < x < X and
-1 < y < Y and
-1 < z < Z and
(x != x2 or y != y2 or z != z2) and
(0 <= x2 < X) and
(0 <= y2 < Y) and
(0 <= z2 < Z) and
(((abs(x - x2)) ** 2 + (abs(y - y2)) ** 2 + (abs(z - z2)) ** 2 ) <= 25))]
m = n_n(l, m, n)
result = 0
for i in range(0, len(m)):
a = m[i][0]
b = m[i][1]
c = m[i][2]
result = result + a_s_l[a][b][c]
# print "c_a : ", time.time() - start
return result
Solved.
Brought out all the file reading steps outside the function, as they were being executed many times. It gave a 70x boost.
Just left the lambda functions in the function as they are dependent on x, y & z.
Related
I am trying to generate a polynomial dataset. I wrote a code
def generate_dataset1():
n = 500
X = 2 - 3 * np.random.normal(0, 1, n)
y = X - 2 * (X ** 2) + 0.5 * ( X ** 3) + np.random.normal(-3, 3, n)
m = np.random.uniform(0.3, 0.5, (n, ))
b = np.random.uniform(5, 10, (n, ))
plt.scatter(X, y, s=10)
plt.show()
Now, if I want to generate a dataset using the given formula (from Wikipedia), could you tell me what I have to change?
y = B_0 + B_1*x, B_2*x2 + B_3*x3 + ... + e
Here, x2 means x (square), x3 means x (cube), so on and e is the unobserved random error with mean zero.
There are many ways to multiply x with B, such as dot product. But I think for loop should be good enough. Just loop through element of B and x:
def generate_dataset(B, n):
# B is beta, n is number of sample
e = np.random.normal(-3, 3, n)
X = 2 - 3 * np.random.normal(0, 1, n)
y = 0
for i in range(len(B)):
y += B[i] * X**i
y += e
return X, y
def plot_dataset(X, y):
#m = np.random.uniform(0.3, 0.5, (n, )) # not sure why you need this
#b = np.random.uniform(5, 10, (n, )) # not sure why you need this
plt.scatter(X, y, s=10)
plt.show()
n = 500
B = [0, 1, -2, 0.5] # [beta0, beta1, beta2, beta3]
X, y = generate_dataset(B, 500)
plot_dataset(X, y)
I would like to project two (x, y) points C and E normally onto a line defined by two (x, y) points A and B.
I want the projection result as a distance from A towards B (e.g. AD and AF in the below image), not as (x, y) coordinates on the line. Notice the negative distance for AF when it falls outside the A to B line. Please help me out with the below coordinates_to_distances function.
import numpy as np
A = np.array([2, 1]) # (x, y) coordinates of A
B = np.array([6, 2]) # (x, y) coordinates of B
x = np.array([3, 1]) # x-coordinates of C and E
y = np.array([3, 2]) # y-coordinates of C and E
def coordinates_to_distances(A, B, x, y):
# Help
return distances
distances = coordinates_to_distances(A, B, x, y) # expected result: [1.46, -0.73]
I've modified your task a little to work with points as dictionaries ({x, y}).
projection returns a projection point of c to line ab
distance_to_point returns distance of point c to point a, where direction from a is given by point b
NOTE: The sample will not work when the line ab is vertical!
import math
def projection(a,b,c):
n = (b['y'] - a['y']) / (b['x'] - a['x'])
m = a['y'] - n * a['x']
p = c['y'] + c['x'] / n
x = (p - m) / (n + 1 / n)
y = n * x + m
return {'x': x, 'y': y}
def distance_to_point(a, b, c):
dir = 1 if bool(b['x'] > a['x']) == bool(c['x'] > a['x']) else -1
return math.hypot(c['y'] - a['y'], c['x'] - a['x']) * dir
a = {'x': 2, 'y': 1}
b = {'x': 6, 'y': 2}
c = {'x': 3, 'y': 3}
d = projection(a, b, c)
dta = distance_to_point(a, b, d)
print(dta)
NumPy solution:
import numpy as np
A = np.array([2, 1]) # (x, y) coordinates of A
B = np.array([6, 2]) # (x, y) coordinates of B
x = np.array([3, 1]) # x-coordinates of C and E
y = np.array([3, 2]) # y-coordinates of C and E
def coordinates_to_distances(A, B, x, y):
dy = B[1] - A[1]
dx = B[0] - A[0]
x_new, y_new = x * 0 + 1, y * 0 + 1
if dx == 0:
x_new, y_new = x * 0 + A[0], y
if dy == 0:
x_new, y_new = x, y * 0 + A[1]
if dx != 0 and dy != 0:
n = dy / dx
m = A[1] - n * A[0]
p = y + x / n
x_new = (p - m) / (n + 1 / n)
y_new = n * x_new + m
dir = x_new * 0 - 1
dir[(B[0] > A[0]) == (x_new > A[0])] = 1
return dir * np.sqrt((A[0] - x_new)**2 + (A[1] - y_new)**2)
distances = coordinates_to_distances(A, B, x, y)
print(distances) # [1.46, -0.73]
Now that my perlin generator is 'working' I created noise, to find that it is nothing like what I see on the internets...
My noise:
Notice the streaks:
What I am aiming to get (obviously with corresponding colour):
1:
Why does mine look so noisy and nasty?
Code (sorry for no stub, the Perlin noise makes up most of the program so it's important to include the full program):
from PIL import Image
from tkinter import filedialog
from random import randint, random
#Initialise width / height
width = 625
height = 625
#Import gradient picture - 200*1 image used to texture perlin noise
#R,G,B,Alpha
gradient = Image.open("image.png")
gradlist = list(gradient.getdata())
#Create new image
img = Image.new('RGBA', (width, height), color=(255, 255, 255, 255))
#Perlin noise modules --------------------------------------------------------------------------------------------------------
#Modules
from random import sample
from math import floor
p = sample([x for x in range(0, (width * height))], (width * height)) * 2
#Antialising
def fade(t):
retval = 6*(t**5) - 15*(t**4) + 10*(t**3)
return retval
#Linear interpolation
def lerp(t,a,b):
retval = a + (t * (b - a))
return retval
#Clever bitwise hash stuff - picks a unit vector from 12 possible - (1,1,0),(-1,1,0),(1,-1,0),(-1,-1,0),(1,0,1),(-1,0,1),(1,0,-1),(-1,0,-1),(0,1,1),(0,-1,1),(0,1,-1),(0,-1,-1)
def grad(hash, x, y, z):
h = hash % 15
if h < 8:
u = x
else:
u = y
if h < 4:
v = y
elif h in (12, 14):
v = x
else:
v = z
return (u if (h & 1) == 0 else -u) + (v if (h & 2) == 0 else -v)
#Perlin function
def perlin(x,y,z):
ix = int(floor(x)) & 255
iy = int(floor(y)) & 255
iz = int(floor(z)) & 255
x -= int(floor(x))
y -= int(floor(y))
z -= int(floor(z))
u = fade(x)
v = fade(y)
w = fade(z)
#Complicated hash stuff
A = p[ix] + iy
AA = p[A] + iz
AB = p[A + 1] + iz
B = p[ix + 1] + iy
BA = p[B] + iz
BB = p[B + 1] + iz
return -lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),grad(p[BA], x - 1, y, z)),lerp(u, grad(p[AB], x, y - 1, z),grad(p[BB], x - 1, y - 1, z))),lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1),grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1),grad(p[BB + 1], x - 1, y - 1, z - 1))))
def octavePerlin(x,y,z,octaves,persistence):
total = 0
frequency = 1
amplitude = 1
maxValue = 0
for x in range(octaves):
total += perlin(x * frequency, y * frequency, z * frequency) * amplitude
maxValue += amplitude
amplitude *= persistence
frequency *= 2
return total / maxValue
z = random()
img.putdata([gradlist[int(octavePerlin((x + random() - 0.5) / 1000, (y + random() - 0.5) / 1000, z, 4, 2) * 100 + 100)] for x in range(width) for y in range(height)])
img.save(filedialog.asksaveasfilename() + ".png", "PNG")
Right now, I am working on something (in Python) to create an ellipse and display it on the screen (in the console). I have the ellipse creation already, but rotating the ellipse gives me problems.
Ellipse Method:
def ellipse(yc, xc, b, a, rotation=0):
yc_min_b = yc - b
# divide b to account for spacing in console
b = int(round(b / 2 + 0.01)) - 1
yc = yc_min_b + b
points = []
a2 = a*a
b2 = b*b
fa2 = 4 * a2
fb2 = 4 * b2
x = 0
y = b
sigma = 2 * b2 + a2 * (1 - 2 * b)
while b2 * x <= a2 * y:
points.append((xc + x, yc + y))
points.append((xc - x, yc + y))
points.append((xc + x, yc - y))
points.append((xc - x, yc - y))
if sigma >= 0:
sigma += fa2 * (1 - y)
y -= 1
sigma += b2 * ((4 * x) + 6)
x += 1 # INCREMENT
x = a
y = 0
sigma = 2 * a2 + b2 * (1 - 2 * a)
while a2 * y <= b2 * x:
points.append((xc + x, yc + y))
points.append((xc - x, yc + y))
points.append((xc + x, yc - y))
points.append((xc - x, yc - y))
if sigma >= 0:
sigma += fb2 * (1 - x)
x -= 1
sigma += a2 * ((4 * y) + 6)
y += 1 # INCREMENT
# now rotate points
sin = math.sin(rotation)
cos = math.cos(rotation)
rotated = []
for point in points:
x = point[0]
y = point[1]
'''
px -= xc
py -= yc
xnew = px * c - py * s
ynew = px * s + py * c
px = xnew + xc
py = ynew + yc
'''
#XRot := Round(XCenter + (X - XCenter) * CAngle - (Y - YCenter) * SAngle);
#YRot := Round(YCenter + (X - XCenter) * SAngle + (Y - YCenter) * CAngle);
x = round(xc + (x + xc) * cos - (y - yc) * sin)
y = round(yc + (x - xc) * sin + (y - yc) * cos)
rotated.append((int(x), int(y)))
points = rotated
print points
ell_matr = []
# set up empty matrix
maxx = 0
maxy = 0
for point in points:
y = point[1]
x = point[0]
if y > maxy:
maxy = y
if x > maxx:
maxx = x
for i in range(maxy + 1):
ell_matr.append([])
for j in range(maxx + 1):
ell_matr[i].append(' ')
for point in points:
y = point[1]
x = point[0]
ell_matr[y][x] = fill
return ell_matr
I would ignore the matrix part, as it is translating the points into a matrix to display on screen.
Here is the output of an ellipse without rotation.
And when I add a 45 degree rotation (converted to radians)
Is there a better way to rotate the points?
I've taken the Wikipedia Perlin Noise Algorithm and implemented it in Python, here is the code:
import random
import math
from PIL import Image
from decimal import Decimal
IMAGE_SIZE = 200
PERLIN_RESOLUTION = 10
GRADIENT = []
for x in range(PERLIN_RESOLUTION + 1):
GRADIENT.append([])
for y in range(PERLIN_RESOLUTION + 1):
angle = random.random() * 2 * math.pi
vector = (
Decimal(math.cos(angle)),
Decimal(math.sin(angle))
)
GRADIENT[x].append(vector)
def lerp(a0, a1, w):
return (1 - w)*a0 + w*a1
def dotGridGradient(ix, iy, x, y):
dx = x - Decimal(ix)
dy = y - Decimal(iy)
return (dx*GRADIENT[iy][ix][0] + dy*GRADIENT[iy][ix][1])
def perlin(x, y):
if x > 0.0:
x0 = int(x)
else:
x0 = int(x) - 1
x1 = x0 + 1
if y > 0.0:
y0 = int(y)
else:
y0 = int(y) - 1
y1 = y0 + 1
sx = x - Decimal(x0)
sy = y - Decimal(y0)
n0 = dotGridGradient(x0, y0, x, y)
n1 = dotGridGradient(x1, y0, x, y)
ix0 = lerp(n0, n1, sx)
n0 = dotGridGradient(x0, y1, x, y)
n1 = dotGridGradient(x1, y1, x, y)
ix1 = lerp(n0, n1, sx)
value = lerp(ix0, ix1, sy)
return value
image = Image.new('RGB', (IMAGE_SIZE, IMAGE_SIZE))
pixels = image.load()
for i in range(IMAGE_SIZE):
x = Decimal(i) / IMAGE_SIZE
for j in range(IMAGE_SIZE):
y = Decimal(j) / IMAGE_SIZE
value = perlin(x * 10, y * 10)
greyscale = (value + 1) * 255 / 2
pixels[i, j] = (greyscale, greyscale, greyscale)
image.save('artifacts.png', 'PNG')
Here is the resulting image that is created by the script:
I must be missing something here, you can very clearly see the vertices. Can anyone let me know what is going wrong?
You need to use smoothstep instead of linear interpolation.
def smoothstep(a0, a1, w):
value = w*w*w*(w*(w*6 - 15) + 10)
return a0 + value*(a1 - a0)