How to draw such a picture with Python? [duplicate] - python

I make following Python Code to calculate center and size of Gaussian-like distribution basis of moment method. But, I can't make the code to calculate the angle of gaussian.
Please look at pictures.
First Picture is original data.
Second picture is reconstruct data from the result of moment method.
But, second picture is insufficient reconstruction. Because, original data is inclined distribution.
I have to, I think, calculate the angle of axis for Gaussian-like distribution.
To assume that the original distribution is sufficiently Gaussian-like distribution.
import numpy as np
import matplotlib.pyplot as plt
import json, glob
import sys, time, os
from mpl_toolkits.axes_grid1 import make_axes_locatable
from linecache import getline, clearcache
from scipy.integrate import simps
from scipy.constants import *
def integrate_simps (mesh, func):
nx, ny = func.shape
px, py = mesh[0][int(nx/2), :], mesh[1][:, int(ny/2)]
val = simps( simps(func, px), py )
return val
def normalize_integrate (mesh, func):
return func / integrate_simps (mesh, func)
def moment (mesh, func, index):
ix, iy = index[0], index[1]
g_func = normalize_integrate (mesh, func)
fxy = g_func * mesh[0]**ix * mesh[1]**iy
val = integrate_simps (mesh, fxy)
return val
def moment_seq (mesh, func, num):
seq = np.empty ([num, num])
for ix in range (num):
for iy in range (num):
seq[ix, iy] = moment (mesh, func, [ix, iy])
return seq
def get_centroid (mesh, func):
dx = moment (mesh, func, (1, 0))
dy = moment (mesh, func, (0, 1))
return dx, dy
def get_weight (mesh, func, dxy):
g_mesh = [mesh[0]-dxy[0], mesh[1]-dxy[1]]
lx = moment (g_mesh, func, (2, 0))
ly = moment (g_mesh, func, (0, 2))
return np.sqrt(lx), np.sqrt(ly)
def plot_contour_sub (mesh, func, loc=[0, 0], title="name", pngfile="./name"):
sx, sy = loc
nx, ny = func.shape
xs, ys = mesh[0][0, 0], mesh[1][0, 0]
dx, dy = mesh[0][0, 1] - mesh[0][0, 0], mesh[1][1, 0] - mesh[1][0, 0]
mx, my = int ( (sy-ys)/dy ), int ( (sx-xs)/dx )
fig, ax = plt.subplots()
divider = make_axes_locatable(ax)
ax.set_aspect('equal')
ax_x = divider.append_axes("bottom", 1.0, pad=0.5, sharex=ax)
ax_x.plot (mesh[0][mx, :], func[mx, :])
ax_x.set_title ("y = {:.2f}".format(sy))
ax_y = divider.append_axes("right" , 1.0, pad=0.5, sharey=ax)
ax_y.plot (func[:, my], mesh[1][:, my])
ax_y.set_title ("x = {:.2f}".format(sx))
im = ax.contourf (*mesh, func, cmap="jet")
ax.set_title (title)
plt.colorbar (im, ax=ax, shrink=0.9)
plt.savefig(pngfile + ".png")
def make_gauss (mesh, sxy, rxy, rot):
x, y = mesh[0] - sxy[0], mesh[1] - sxy[1]
px = x * np.cos(rot) - y * np.sin(rot)
py = y * np.cos(rot) + x * np.sin(rot)
fx = np.exp (-0.5 * (px/rxy[0])**2)
fy = np.exp (-0.5 * (py/rxy[1])**2)
return fx * fy
if __name__ == "__main__":
argvs = sys.argv
argc = len(argvs)
print (argvs)
nx, ny = 500, 500
lx, ly = 200, 150
rx, ry = 40, 25
sx, sy = 50, 10
rot = 30
px = np.linspace (-1, 1, nx) * lx
py = np.linspace (-1, 1, ny) * ly
mesh = np.meshgrid (px, py)
fxy0 = make_gauss (mesh, [sx, sy], [rx, ry], np.deg2rad(rot)) * 10
s0xy = get_centroid (mesh, fxy0)
w0xy = get_weight (mesh, fxy0, s0xy)
fxy1 = make_gauss (mesh, s0xy, w0xy, np.deg2rad(0))
s1xy = get_centroid (mesh, fxy1)
w1xy = get_weight (mesh, fxy1, s1xy)
print ([sx, sy], s0xy, s1xy)
print ([rx, ry], w0xy, w1xy)
plot_contour_sub (mesh, fxy0, loc=s0xy, title="Original", pngfile="./fxy0")
plot_contour_sub (mesh, fxy1, loc=s1xy, title="Reconst" , pngfile="./fxy1")

As Paul Panzer said, the flaw of your approach is that you look for "weight" and "angle" instead of covariance matrix. The covariance matrix fits perfectly in your approach: just compute one more moment, mixed xy.
The function get_weight should be replaced with
def get_covariance (mesh, func, dxy):
g_mesh = [mesh[0]-dxy[0], mesh[1]-dxy[1]]
Mxx = moment (g_mesh, func, (2, 0))
Myy = moment (g_mesh, func, (0, 2))
Mxy = moment (g_mesh, func, (1, 1))
return np.array([[Mxx, Mxy], [Mxy, Myy]])
Add one more import,
from scipy.stats import multivariate_normal
for reconstruction purpose. Still using your make_gauss function to create the original PDF, this is how it now gets reconstructed:
s0xy = get_centroid (mesh, fxy0)
w0xy = get_covariance (mesh, fxy0, s0xy)
fxy1 = multivariate_normal.pdf(np.stack(mesh, -1), mean=s0xy, cov=w0xy)
That's it; reconstruction works fine now.
Units on the color bar are not the same, because your make_gauss formula does not normalize the PDF.

Related

Dynamic open-loop optimization with Pyomo

I want to implement a dynamic open-loop optimization. I find that the documentation is not covering these use-case that well, so I found these two examples
https://jckantor.github.io/CBE32338/05.02-Optimization-Control-and-Estimation-using-Pyomo-With-Windows-ipopt.html
https://ndcbe.github.io/CBE60499/02.06-Pyomo-DAE.html
I can get a solution if I use the discretization method dae.finite_difference but not with dae.collocations. It says:
pyomo.common.errors.ApplicationError: Solver (ipopt) did not exit normally
I want to use collocation because I want to constrain the input to pice-wise constant which apparently is possible only with model = discretizer.reduce_collocation_points(...) which does not exist if I do not use the collocation method. Here is my working code ( I use bokeh to visualise the results)
from pyomo.environ import *
from pyomo.dae import *
import numpy as np
from utils.utils import SimSettings
from bokeh.plotting import figure, show
from bokeh.layouts import row, gridplot, grid
from bokeh.io import output_file
from bokeh.palettes import Category20b
results_dir = 'results/ukf_opt'
# Final time
tf = 120
# time vector
t_sim = np.arange(0, tf, 3)
# Define the model
model = ConcreteModel()
model.t = ContinuousSet(bounds=(0, tf)) #time
model.glu = Var(model.t, bounds=(0, None)) # first state
model.bio = Var(model.t, bounds=(0, None))# second state
model.lac = Var(model.t, bounds=(0, None))# Third state
model.v = Var(model.t, bounds=(0, 5)) # forth state
model.fglu = Var(model.t, bounds=(0, 0.5)) # Input
model.dglu = DerivativeVar(model.glu, wrt=model.t)
model.dbio = DerivativeVar(model.bio, wrt=model.t)
model.dlac = DerivativeVar(model.lac, wrt=model.t)
model.dv = DerivativeVar(model.v, wrt=model.t)
model.v_max = Param(initialize=0.08)
model.km = Param(initialize=0.4)
model.v_maxl = Param(initialize=0.04)
model.kml = Param(initialize=0.2)
model.cglu = Param(initialize=5)
# Initial condition
x0 = [1., 2., 0.1, 1.]
# Definition of the odes
def ode_glu(model, t):
vl = (model.v_maxl * model.glu[t]) / (model.kml + model.glu[t])
v = (model.v_max * model.glu[t]) / (model.km + model.glu[t])
return model.dglu[t] == - v * model.bio[t] - vl * model.bio[t] + model.fglu[t] / model.v[t] * (
model.cglu - model.glu[t])
def ode_bio(model, t):
v = (model.v_max * model.glu[t]) / (model.km + model.glu[t])
return model.dbio[t] == v * model.bio[t] - model.fglu[t] / model.v[t] * model.bio[t]
def ode_lac(model, t):
vl = (model.v_maxl * model.glu[t]) / (model.kml + model.glu[t])
return model.dlac[t] == vl * model.bio[t] - model.fglu[t] / model.v[t] * model.lac[t]
def ode_v(model, t):
return model.dv[t] == model.fglu[t]
model.diffeq_glu = Constraint(model.t, rule=ode_glu)
model.diffeq_bio = Constraint(model.t, rule=ode_bio)
model.diffeq_lac = Constraint(model.t, rule=ode_lac)
model.diffeq_v = Constraint(model.t, rule=ode_v)
# Fix initial condition
model.glu[0].fix(x0[0])
model.bio[0].fix(x0[1])
model.lac[0].fix(x0[2])
model.v[0].fix(x0[3])
# I initialize a constant input. This is only to run a simulation to initialize the model. If I don't do it even the finite difference method does not work
model.Usim = Suffix(direction=Suffix.LOCAL)
model.Usim[model.fglu] = {0: 0.01}
# Here is the point where the problem is discretized. If I use dae.collocation instead of dae.finite_difference it does not work
discretizer = TransformationFactory('dae.finite_difference')
discretizer.apply_to(model, nfe=len(t_sim), scheme='FORWARD')
# Simulate the system with a constant input
sim = Simulator(model, package='casadi')
tsim, profiles = sim.simulate(integrator='idas', varying_inputs=model.Usim)
sim.initialize_model()
# Define objective function for the optimiyation
model.ls_control = sum([(model.lac[t]) ** 2 for t in model.t])
model.obj = Objective(expr=model.ls_control, sense=maximize)
# Solve the model. The print_level has basically no effect I do not why
solver = SolverFactory('ipopt')
solver.options['print_level'] = 5
solver.options['output_file'] = f"{ss.results_dir}/my_ipopt_log.txt"
solver.solve(model).write()
# Plot the results
profiles = np.concatenate((np.array([model.glu[t]() for t in t_sim]).reshape(-1, 1),
np.array([model.bio[t]() for t in t_sim]).reshape(-1, 1),
np.array([model.lac[t]() for t in t_sim]).reshape(-1, 1),
np.array([model.v[t]() for t in t_sim]).reshape(-1, 1)),
axis=1)
output_file(f"{results_dir}/simulation.html")
p_states = []
color_list = ['blue', 'green', 'magenta', 'red']
for k, state in enumerate(['glu', 'bio', 'lac', 'v']):
p = figure(background_fill_color='#fafafa', y_range=(0, 3.5))
p.line(t_sim, profiles[:, k],
line_color=color_list[k], line_alpha=0.5, line_width=2)
p_states.append(p)
grid = gridplot([[p_states[0], p_states[1]], [p_states[2], p_states[3]]])
show(grid)

I'm trying to figure out this error " TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'"

I'm running this code any this error keeps popping up "TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'". Most likely this line is causing a problem
----> 2 sols = odeint(VJJmodel,[0,0],ts, args=tuple([params]) )
Please advise.
from scipy.integrate import odeint
import numpy as np
import scipy.constants as const
from matplotlib import pyplot as plt
from scipy.interpolate import interp1d
from scipy.integrate import quad
import collections
Ic = 1e-6
Rsg = 10e3
Rn = Rsg
Cj = 2e-15
Rin = 100e0
Vgap = 4*Ic*Rn/np.pi #Gap voltage linked to IcRn, SIS relation
Vn = 1.1 #0.1*Vgap/Ic/Rin
V0 = Vn*Rin*Ic
phi0 = const.value('mag. flux quantum')
wp = 1/np.sqrt(Cj*phi0/2/np.pi/Ic)
params = {'Vn':Vn, 'Rsg': Rsg, 'Rn':Rn, 'Vgap':Vgap, 'Cj':Cj, 'Rin':Rin, 'wp':wp}
print(Vn)
taustop = 20* wp * Rsg*Cj
params['taustop'] = taustop
print(params)
def Rj(V,params):
Vgap = params['Vgap']
if V>Vgap:
return params['Rn']
elif V<=Vgap:
return params['Rsg']
def Q(V,params):
Cj = params['Cj']
Rin = params['Rin']
wp = params['wp']
return Cj*wp/(1/Rj(V,params)+1/Rin)
def Vs(t,params):
if not hasattr(t,'__len__'):
t = np.array([t])
result = []
for x in t:
if x <params['taustop']/2:
result.append(x/(params['taustop']/2)*params['Vn'])
else:
result.append(params['Vn'])
#return params['Vn']
result = np.ones(len(t))*params['Vn']
return np.array(result)
def VJJmodel(z,t,params):
f = z[0]
g = z[1]
V = phi0/2/np.pi*g
fp = g
gp = Vs(t,params)-(1/Q(V,params)*g+np.sin(f))
return np.array([fp,gp])
ts = np.linspace(0,2*taustop,2000)
sols = odeint(VJJmodel,[0,0],ts, args=tuple([params]) )
solsfunc = interp1d(ts,sols.T)
Vjunc = lambda x: phi0/2/np.pi * wp * solsfunc(x)[1]
taurep = 2*np.pi/np.average(np.diff(sols[:,0])/np.diff(ts))
fig = plt.figure(figsize=(10,10))
plt.clf()
plt.subplot(3, 1, 1)
plt.title('Voltage/Vgap')
plt.plot(ts,Vjunc(ts) / Vgap)
plt.subplot(3, 1, 2)
plt.title('Current')
plt.plot(ts,np.sin(solsfunc(ts)[0]))
plt.plot(ts,(Vs(ts,params)*Ic*Rin-Vjunc(ts))/Rin/Ic)
plt.ylim([-2,2])
plt.subplot(3, 1, 3)
plt.title('Phase')
plt.plot(ts,solsfunc(ts)[0])
plt.show()
plt.close(fig)
I tried to rewrite it but it didn't work.

Ploting a point for each step i

I'm doing a free fall caluculations (really simple) and would like to plot each instance of height of the objects - that is the height of the object to be displayed as it 'falls' down. I tried running it throught a for loop, but i just get the end result plotted. What would i need to do to dislplay the object as it falls, for each individual - not just the end result.
Here is my code:
#Input parameters
y1 = 490 #starting position
y2 = 0 #ground
g = -9.81 #gravity
VY = 0 #starting speed
import math
import numpy as np
import matplotlib.pyplot as plt
sqrt_part = math.sqrt(VY**2-2*g*(y1-y2))
t1 = - VY - sqrt_part/g
t2 = - VY + sqrt_part/g
if t1 > 0:
t = t1
else:
t = t2
print('t = ' + str(t) + ' ' + 's')
t_space = np.linspace(0,t,50)
y_t = y1 + VY * t_space + 0.5 * g * t_space**2
v_t = abs(y_t[1:] - y_t[0:-1])/abs(t_space[0:-1] - t_space[1:])
plt.plot(t_space, y_t, 'go')
plt.plot(t_space[1:], v_t, 'r--')
for i in range(np.size(t_space)):
plt.plot(t_space[i], y_t[i], 'go')
The for loop displays the same as the plot above it, but i would like it to update and show the 'ro' as it moves thorught time. How would i do that?
On the left is what i get, on the right is what i want
enter image description here
Please, take a look at matplotlib animation api.
#Input parameters
y1 = 490 #starting position
y2 = 0 #ground
g = -9.81 #gravity
VY = 0 #starting speed
import math
import numpy as np
import matplotlib.pyplot as plt
sqrt_part = math.sqrt(VY**2-2*g*(y1-y2))
t1 = - VY - sqrt_part/g
t2 = - VY + sqrt_part/g
if t1 > 0:
t = t1
else:
t = t2
print('t = ' + str(t) + ' ' + 's')
t_space = np.linspace(0,t,50)
y_t = y1 + VY * t_space + 0.5 * g * t_space**2
v_t = np.abs((np.roll(y_t, -1) - y_t) / (np.roll(t_space, -1) - t_space))
v_t = np.roll(v_t, 1)
v_t[0] = 0
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
# create two empty lines
ln_y, = plt.plot([], [], 'go', label="y")
ln_v, = plt.plot([], [], 'r--', label="v")
def init():
ax.set_xlim(0, max(t_space))
ax.set_ylim(0, max(y_t))
ax.set_xlabel("t")
ax.legend()
return ln_y, ln_v
def update(i):
# i represents the index of the slice to use at the current frame
ln_y.set_data(t_space[:i], y_t[:i])
ln_v.set_data(t_space[:i], v_t[:i])
return ln_y, ln_v,
ani = FuncAnimation(fig, update, frames=range(len(v_t)),
init_func=init, blit=False, repeat=False)
plt.show()

ACO algorithm on python machine learning

I am trying to understand the code below where it shows the default TSP path on a picture. I understand most of the part except for the polyfit_plot() function. I understand the function in it separately but when combine together I just don't get what it contributes to. I have even tried to delete the function and the result is actually the same, and I don't see where the function is implemented in. Can someone explain it to me?
import numpy as np
import math
import random
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
united_states_map = mpimg.imread(r"C:\Users\user\Downloads\archive\united_states_map.png")
def show_cities(path, w=12, h=8):
if isinstance(path, dict): path = list(path.values())
if isinstance(path[0][0], str): path = [ item[1] for item in path ]
plt.imshow(united_states_map)
for x0, y0 in path:
plt.plot(x0, y0, 'y*', markersize=15) # y* = yellow star for starting point
plt.axis("off")
fig = plt.gcf()
fig.set_size_inches([w, h])
def show_path(path, starting_city=None, w=12, h=8):
if isinstance(path, dict): path = list(path.values())
if isinstance(path[0][0], str): path = [ item[1] for item in path ]
starting_city = starting_city or path[0]
x, y = list(zip(*path))
#_, (x0, y0) = starting_city
(x0, y0) = starting_city
plt.imshow(united_states_map)
#plt.plot(x0, y0, 'y*', markersize=15) # y* = yellow star for starting point
plt.plot(x + x[:1], y + y[:1]) # include the starting point at the end of path
plt.axis("off")
fig = plt.gcf()
fig.set_size_inches([w, h])
def polyfit_plot(x,y,deg, **kwargs):
coefficients = np.polyfit(x,y,deg,**kwargs)
poly = np.poly1d(coefficients)
new_x = np.linspace(x[0], x[-1])
new_y = poly(new_x)
plt.plot(x, y, "o", new_x, new_y)
plt.xlim([x[0]-1, x[-1] + 1 ])
terms = []
for p, c in enumerate(reversed(coefficients)):
term = str(round(c,1))
if p == 1: term += 'x'
if p >= 2: term += 'x^'+str(p)
terms.append(term)
plt.title(" + ".join(reversed(terms)))
cities = { "Oklahoma City": (392.8, 356.4), "Montgomery": (559.6, 404.8), "Saint Paul": (451.6, 186.0), "Trenton": (698.8, 239.6), "Salt Lake City": (204.0, 243.2), "Columbus": (590.8, 263.2), "Austin": (389.2, 448.4), "Phoenix": (179.6, 371.2), "Hartford": (719.6, 205.2), "Baton Rouge": (489.6, 442.0), "Salem": (80.0, 139.2), "Little Rock": (469.2, 367.2), "Richmond": (673.2, 293.6), "Jackson": (501.6, 409.6), "Des Moines": (447.6, 246.0), "Lansing": (563.6, 216.4), "Denver": (293.6, 274.0), "Boise": (159.6, 182.8), "Raleigh": (662.0, 328.8), "Atlanta": (585.6, 376.8), "Madison": (500.8, 217.6), "Indianapolis": (548.0, 272.8), "Nashville": (546.4, 336.8), "Columbia": (632.4, 364.8), "Providence": (735.2, 201.2), "Boston": (738.4, 190.8), "Tallahassee": (594.8, 434.8), "Sacramento": (68.4, 254.0), "Albany": (702.0, 193.6), "Harrisburg": (670.8, 244.0) }
cities = list(sorted(cities.items()))
print(len(cities))
show_cities(cities)
show_path(cities)
It seems that the function polyfit_plot is unused in the code, so it is never run and as you say it does not affect the outcome.

Nested for loop and 3D Plot within Class Object

i am sure this is an easy problem to deal with, but i cant figure it out. I created a Borehole Class and want to compute my pore pressure around each Borehole/Well. Along a single axis, my code looks like this:
from scipy.special import *
import matplotlib.pyplot as plt
import numpy as np
from math import *
## Globale Variablen ##
rhof = 1000 # Dichte Flüssigkeit [kg/m³]
lameu = 11.2*10**9 # Lamé-Parameter, undrained [GPa]
lame = 8.4*10**9 # Lamé-Parameter, drained [GPa]
pi # durch Pythonmodul "math" gegeben
alpha = 0.65 # Biot-Willis-Koeffizient
G = 8.4*10**9 # Schermodul [GPa]
k = 1.0e-15 # Permeabilität [m²] bzw. [Darcy]
eta = 0.001 # Viskosität des Fluids [Pa*s]
## Berechnung der Parameter ##
kappa = k/eta
c = ((kappa*(lameu-lame)*(lame+2*G))/((alpha**2)*(lameu+2*G)))
## Wertebereich ##
xmin = 0
xmax = 100
xsteps = 1.0
x = np.arange(xmin, xmax, xsteps)
## Class ##
class Bohrloch(object):
loch_zaehler = 0
def __init__(self, xlage, tstart, q): # Funktion, um BL zu erzeugen
self.xlage = xlage
#self.ylage = ylage # Lage der Bohrung
self.tstart = tstart # Start der Injektion/Produktion
self.q = q # Fluidmenge
## Druck ##
def getPressure(self, t): # gibt nach Zeit t die zugehörigen Druckwerte aus
if (t-self.tstart<0): # Fehlermeldung, falls Startpunkt nach t liegt
return ()
print "Startpunkt liegt außerhalb des Förderzeitraumes!"
else:
self.r = np.sqrt((x-self.xlage)**2)
self.P = (self.q/(rhof*4*pi*kappa))*(expn(1,self.r**2/(4*c*(t-self.tstart))))
#self.P[self.xlage] = 0 # gibt Bohrlochlage wieder
self.z = self.P/1e6
return self.z # Druckwerte in [MPa]
def pressureTable (self, t, xschritt): # erstellt Wertetabelle
self.getPressure(t)
for i in range (xmin, xmax, xschritt):
print i, " ", self.z[i]
t = 1000*24*3600
b1 = Bohrloch(50,0*24*3600,6.0/1000)
b1.pressureTable(t,1)
With this method i get my desired pressure table. Now i want to have a pressure table for x and y values, including an 3D Plot. This is my code so far:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from scipy.special import *
import matplotlib.pyplot as plt
import numpy as np
from math import *
## Globale Variablen ##
rhof = 1000 # Dichte Flüssigkeit [kg/m³]
lameu = 11.2*10**9 # Lamé-Parameter, undrained [GPa]
lame = 8.4*10**9 # Lamé-Parameter, drained [GPa]
pi # durch Pythonmodul "math" gegeben
alpha = 0.65 # Biot-Willis-Koeffizient
G = 8.4*10**9 # Schermodul [GPa]
k = 1.0e-15 # Permeabilität [m²] bzw. [Darcy]
eta = 0.001 # Viskosität des Fluids [Pa*s]
## Berechnung der Parameter ##
kappa = k/eta
c = ((kappa*(lameu-lame)*(lame+2*G))/((alpha**2)*(lameu+2*G)))
## Wertebereich ##
xmin = 0
xmax = 100
xsteps = 1.0
x = np.arange(xmin,xmax,xsteps)
ymin = 0
ymax = 100
ysteps = 1.0
y = np.arange(ymin,ymax,ysteps)
## Klassendefinition ##
class Bohrloch(object):
loch_zaehler = 0
def __init__(self, xlage, ylage, tstart, q): # Funktion, um BL zu erzeugen
self.xlage = xlage # x-Lage der Bohrung
self.ylage = ylage # y-Lage der Bohrung
self.tstart = tstart # Start der Injektion/Produktion
self.q = q # Fluidmenge
## Druck ##
def getPressure(self, t):
if (t-self.tstart<0):
return ()
print "Startpunkt liegt außerhalb des Förderzeitraumes!"
else:
self.r = np.sqrt((x-self.xlage)**2+(y-self.ylage)**2)
self.P = (self.q/(rhof*4*pi*kappa))*(expn(1,self.r**2/(4*c*(t-self.tstart))))
self.P[self.xlage] = np.nan
self.P[self.ylage] = np.nan
self.z = self.P/1e6
return self.z # Druckwerte in [MPa]
def pressureTable (self, t, xschritt, yschritt):
self.getPressure(t)
for k in range (xmin, xmax, xschritt):
for l in range (ymin, ymax, yschritt):
# my mistake should be here?
print k, " ", l, " ", self.z[k][l]
def pressurePlot3D (self, t):
self.getPressure(t)
Z = self.z
X, Y = np.meshgrid(x,y)
Z[Z == np.inf] = np.nan
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet, linewidth=0,
antialiased=False, vmin=np.nanmin(Z), vmax=np.nanmax(Z))
fig.colorbar(surf, shrink=0.5, aspect=5)
ax.set_xlim(xmin,xmax) # x-Achsenskala vorgeben
ax.set_ylim(ymin,ymax) # y-Achsenskala vorgeben
ax.set_title('Druckverteilung')
ax.set_xlabel('x-Richtung [m]')
ax.set_ylabel('y-Richtung Well [m]')
ax.set_zlabel('Druck in [MPa]')
plt.show()
t = 1000*24*3600
b1 = Bohrloch(50,50,0*24*3600,6.0/1000)
b1.pressureTable(t,1)
b1.pressurePlot3D(t)
Unfortunately, my table doesnt work and the desired 3D Plot looks strange. I am still a total beginner in Python and need some advices.
Can anyone help?
The problem is that self.z is not a two-dimensional array/list. Therefore, trying to access self.z[k][l] results in IndexError: invalid index to scalar variable.
I do not quite understand how you want to implement the second dimension. You introduce the y-position, but then, you just calculate a 1D radius array by using both the x- and y-location in
self.r = np.sqrt((x-self.xlage)**2+(y-self.ylage)**2)
The next question is, what do you intend with:
self.P[self.xlage] = np.nan
self.P[self.ylage] = np.nan
If you change xsteps and ysteps to 10, and call:
b1 = Bohrloch(2,3,0*24*3600,6.0/1000)
print b1.getPressure(t)
Your output will be:
[ 5.44152501 4.40905986 nan nan 2.87481753 2.64950827
2.46756653 2.31503845 2.18379093 2.06866598]
Why would you want to replace the 3rd and 4th elements with nan?
These issues are also at the basis of your plotting routine. Because you now have np.nan values in your array, these won't show in the plot. Because self.z is not two-dimensional, you are probably not getting the surface you may be expecting:
Here's a simple way of coming up with a 2D implementation. I am not familiar enough with what you are trying to do, but it gets the idea across:
def getPressure(self, t):
if (t-self.tstart<0):
return ()
print "Startpunkt liegt außerhalb des Förderzeitraumes!"
else:
# you need to initialize r, P and z as list of lists
# make this dependent on your x coordinates
# the second dimension will grow dynamically
self.r = [[] for ri in range(len(x))]
self.P = [[] for ri in range(len(x))]
self.z = [[] for ri in range(len(x))]
# iterate through both x and y independently
for ii in range(len(x)):
for jj in range(len(y)):
# append to the list that corresponds to the current x -value
# also, use x[ii] and y[jj] to call one x-, y-value at a time
self.r[ii].append(np.sqrt((x[ii]-self.xlage)**2+(y[jj]-self.ylage)**2))
# calling r[ii][-1] ensures you are using the value that was last added to the list:
self.P[ii].append((self.q/(rhof*4*pi*kappa))*(expn(1,self.r[ii][-1]**2/(4*c*(t-self.tstart)))))
self.z[ii].append(self.P[ii][-1]/1e6)
# now, you can use xlage and ylage to blank one value
# do this for both P and z, because z is now calculated inside the loop
self.P[self.xlage][self.ylage] = np.nan
self.z[self.xlage][self.ylage] = np.nan
return self.z
From your plotting routine, remove this line: Z[Z == np.inf] = np.nan, use your original command:
b1 = Bohrloch(50,50,0*24*3600,6.0/1000)
b1.pressurePlot3D(t)
and you will now get this plot:

Categories