I have a dictionary called Rsize which have number-List as key-value pair. The dictionary is like this
{10: [0.6621485767296484, 0.6610747762560114, 0.659607022086639, 0.6567761845867727, 0.6535392433801197, 0.6485977028504701, 0.6393024556394106, 0.6223866436257335, 0.5999232392636733, 0.5418403536642005, 0.4961461379219235, 0.4280278015788386, 0.35462315989740956, 0.2863017237662875, 0.2312185739351389, 0.18306363413831017], 12: [0.6638977494825118, 0.663295576452323, 0.662262804664348, 0.6610413916318628, 0.6590939627030634, 0.655212304186114, 0.6492141689834672, 0.6380632834031537, 0.6096663492242224, 0.5647498006858608, 0.4983281599318278, 0.3961350546063216, 0.32119092575707087, 0.2257230704567207, 0.1816695139119151, 0.14363448808684576], 14: [0.6649598494971014, 0.6644370245269158, 0.6638578972784479, 0.6630511299276417, 0.6615070373022596, 0.6596206155163766, 0.6560628158033714, 0.6487119276511941, 0.6343385358239866, 0.5792725000508062, 0.49799837531709923, 0.42482204326408324, 0.26633662071414366, 0.2028085235063155, 0.12411214668987203, 0.09336935548451253]}
[0.6621485767296484, 0.6610747762560114, 0.659607022086639, 0.6567761845867727, 0.6535392433801197, 0.6485977028504701, 0.6393024556394106, 0.6223866436257335, 0.5999232392636733, 0.5418403536642005, 0.4961461379219235, 0.4280278015788386, 0.35462315989740956, 0.2863017237662875, 0.2312185739351389, 0.18306363413831017]
The keys are 10,14,16. I have used each list for plotting and want to find out their pairwise intersection points. I have written the following script for that and used shapely intersection function for the intersection points detection.
from shapely.geometry import LineString
Rsize={10: [0.6621485767296484, 0.6610747762560114, 0.659607022086639, 0.6567761845867727, 0.6535392433801197, 0.6485977028504701, 0.6393024556394106, 0.6223866436257335, 0.5999232392636733, 0.5418403536642005, 0.4961461379219235, 0.4280278015788386, 0.35462315989740956, 0.2863017237662875, 0.2312185739351389, 0.18306363413831017], 12: [0.6638977494825118, 0.663295576452323, 0.662262804664348, 0.6610413916318628, 0.6590939627030634, 0.655212304186114, 0.6492141689834672, 0.6380632834031537, 0.6096663492242224, 0.5647498006858608, 0.4983281599318278, 0.3961350546063216, 0.32119092575707087, 0.2257230704567207, 0.1816695139119151, 0.14363448808684576], 14: [0.6649598494971014, 0.6644370245269158, 0.6638578972784479, 0.6630511299276417, 0.6615070373022596, 0.6596206155163766, 0.6560628158033714, 0.6487119276511941, 0.6343385358239866, 0.5792725000508062, 0.49799837531709923, 0.42482204326408324, 0.26633662071414366, 0.2028085235063155, 0.12411214668987203, 0.09336935548451253]}
[0.6621485767296484, 0.6610747762560114, 0.659607022086639, 0.6567761845867727, 0.6535392433801197, 0.6485977028504701, 0.6393024556394106, 0.6223866436257335, 0.5999232392636733, 0.5418403536642005, 0.4961461379219235, 0.4280278015788386, 0.35462315989740956, 0.2863017237662875, 0.2312185739351389, 0.18306363413831017]
listkT = np.arange(4.0,4.8,0.05)
print(Rsize[10])
plt.figure(figsize=(18, 10))
plt.title ('Binder cumulant for critical point')
plt.plot(listkT, Rsize[10], '-',label='Lattice sie 10')
plt.plot(listkT, Rsize[12], '-',label='Lattice sie 12')
plt.plot(listkT, Rsize[14], '-',label='Lattice sie 14')
plt.legend()
plt.show()
curve_10=LineString(np.column_stack((listkT, Rsize[10])))
curve_12=LineString(np.column_stack((listkT, Rsize[12])))
curve_14=LineString(np.column_stack((listkT, Rsize[14])))
intersection12 = curve_10.intersection(curve_12)
intersection14 = curve_10.intersection(curve_14)
plt.plot(*LineString(intersection12).xy, 'o')
plt.plot(*LineString(intersection14).xy, 'o')
x12, y = LineString(intersection12).xy
x14, y = LineString(intersection14).xy
print(np.intersect1d(x12, x14))
print(x12,x14)
But shapely throws an AssertionError.
File "C:\Users\Endeavour\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
execfile(filename, namespace)
File "C:\Users\Endeavour\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "E:/Project/Codes/3D.py", line 118, in <module>
plt.plot(*LineString(intersection12).xy, 'o')
File "C:\Users\Endeavour\Anaconda3\lib\site-packages\shapely\geometry\linestring.py", line 48, in __init__
self._set_coords(coordinates)
File "C:\Users\Endeavour\Anaconda3\lib\site-packages\shapely\geometry\linestring.py", line 97, in _set_coords
ret = geos_linestring_from_py(coordinates)
File "shapely/speedups/_speedups.pyx", line 87, in shapely.speedups._speedups.geos_linestring_from_py
AssertionError
The plots are drawn correctly by matplotlib though.
I am using shapely for first time with no prior experience in it. Any help will be much appreciated. Thank you.
Note: The final goal is to get the intersection of 3 curves. If no intersection found the point where they come closest is good enough. Any suggestion or library function to find that will be of great help.
Thank you in advance.
Following the assertion error, I checked shapely/speedups/_speedups.pyx, line 87. geos_linestring_from_py function expects you to either pass a LineString or a LinearRing. When I print your intersection12 and intersection14 I get:
POINT (4.503201814825258 0.4917840919384173)
POINT (4.51830999373466 0.4712012116887737)
So you are passing a Point instance to create a LineString, which creates an AssertionError.
Aside from the error you have, your approach is also wrong because it assumes that (1) there will be multiple intersections between two curves, and (2) there will be one absolute point where three curves intersect. If you zoom into your plot, you can see that neither is the case.
The red circle corresponds to your intersection12 and the purple one is intersection14. If you are looking for an approximate solution, maybe finding the mean of these points can help in this situation, but for more complex curves with multiple intersections per pair, it is also not recommended.
Related
So I'm trying to get some data from a set of equations in the code below. The equations are correct and I've checked them. I'm trying to loop the data over the array set as x in the hopes of scanning or looping across it later, but when I try to run the code I get the ValueError: Maximum allowed size exceeded. The problem appeared when I tried to loop the array of x in reverse. The non-working code is below:
from numpy import *
r=1.0 #radius
d=0.01 #separation of lines
L=1.0 #Length
i=0.01
n=1/d #number of lines
b=-r #position of each line with respect to the radial component
xs=[]
ys=[]
zs=[]
while b<=r:
x=arange(0,L,i) #sets up the x-coordinate system needed for each data point
for i in x:
y=0*x+b
z1=sqrt((r**2)-(y**2)) #plotting the straight lines
xs.append(x)
ys.append(y)
zs.append(z1)
for i in reversed(x):
u=d*x+b
z2=sqrt((r**2)-(u**2)) #plotting the diagonal lines
xs.append(x)
ys.append(u)
zs.append(z2)
b=b+d
print(xs,ys,zs)
And the error I get is:Traceback (most recent call last):
File "", line 1, in
runfile('/Users/Alex/Desktop/fibre_data.py', wdir='/Users/Alex/Desktop')
File "/anaconda/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 880, in runfile
execfile(filename, namespace)
File "/anaconda/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "/Users/Alex/Desktop/fibre_data.py", line 22, in
x=arange(0,L,i) #sets up the x-coordinate system needed for each data point
ValueError: Maximum allowed size exceeded
When you write a program with lots of code, its difficult to find out which values have a big influence of your final result.
In my case i have got a few differential equations which I solve with odeint.
It would take a lot of time to find out which values have a big influence on my result (velocity).
Is there any Tool in python to analyze your values or does someone have any idea?
Thanks for your help.
[Edit]
MathBio: "In general a sensitivity analysis is what you would do. "
#MathBio I read a few blogs about SALib now(SALib Guide) and tried to write a "easier" test program to solve differential equations.
Below you see my written program:
I get the error-message:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 71, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "C:/Users/Tim_s/Desktop/Workspace/test/TrySALib.py", line 44, in <module>
Y = Odefunk(param_values)
File "C:/Users/Tim_s/Desktop/Workspace/test/TrySALib.py", line 24, in Odefunk
dT=odeint(dTdt,T0,t,args=(P,))
File "C:\Python27\lib\site-packages\scipy\integrate\odepack.py", line 148, in odeint
ixpr, mxstep, mxhnil, mxordn, mxords)
File "C:/Users/Tim_s/Desktop/Workspace/test/TrySALib.py", line 17, in dTdt
dT[0]=P[0]*(T[1]-T[0])+P[2]
IndexError: tuple index out of range
Here the code:
from SALib.sample import saltelli
from SALib.analyze import sobol
import numpy as np
from pylab import *
from scipy.integrate import odeint
Tu=20.
t=linspace(0,180,90)
def dTdt(T,t,P):# DGL
dT=zeros(2)
dT[0]=P[0]*(T[1]-T[0])+P[2]
dT[1]=P[1]*(Tu-T[1])+P[0]*(T[0]-T[1])
return dT
T0=[Tu,Tu]
def Odefunk(values):
for P in enumerate(values):
dT=odeint(dTdt,T0,t,args=(P,))
return dT
# Define the model inputs
problem = {
'num_vars': 3,
'names': ['P0', 'P1', 'P2'],
'bounds': [[ 0.1, 0.2],
[ 0.01, 0.02],
[ 0.5, 1]]
}
# Generate samples
param_values = saltelli.sample(problem, 1000, calc_second_order=True)
# Run model (example)
Y = Odefunk(param_values)
# Perform analysis
Si = sobol.analyze(problem, Y, print_to_console=False)
# Print the first-order sensitivity indices
print Si['S1']
You really should include your odes, so we can see the parameters and the initial condition. Code would be nice also.
In general a sensitivity analysis is what you would do. Performing a nondimentionalization is standard also. Look up these tips and try to implement them to see how varying a parameter a small amount will effect your solution.
I suggest you look up these concepts, and include your code. You should try the first steps yourself, and then I'd be happy to help with anything technical once you've clearly made an effort. Best wishes.
I used fsolve to find the zeros of an example sinus function, and worked great. However, I wanted to do the same with a dataset. Two lists of floats, later converted to arrays with numpy.asarray(), containing the (x,y) values, namely 't' and 'ys'.
Although I found some related questions, I failed to implement the code provided in them, as I try to show here. Our arrays of interest are stored in a 2D list (data[i][j], where 'i' corresponds to a variable (e.g. data[0]==t==time==x values) and 'j' are the values of said variable along the x axis (e.g. data[1]==Force). Keep in mind that each data[i] is an array of floats.
Could you offer an example code that takes two inputs (the two mentioned arrays) and returns its intersecting points with a defined function (e.g. 'y=0').
I include some testing I made regarding the other related question. ( #HYRY 's answer)
I do not think it is relevant, but I'm using Spyder through Anaconda.
Thanks in advance!
"""
Following the answer provided by #HYRY in the 'related questions' (see link above).
At this point of the code, the variable 'data' has already been defined as stated before.
"""
from scipy.optimize import fsolve
def tfun(x):
return data[0][x]
def yfun(x):
return data[14][x]
def findIntersection(fun1, fun2, x0):
return [fsolve(lambda x:fun1(x)-fun2(x, y), x0) for y in range(1, 10)]
print findIntersection(tfun, yfun, 0)
Which returns the next error
File "E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py", line 36, in tfun
return data[0][x]
IndexError: arrays used as indices must be of integer (or boolean) type
The full output is as it follows:
Traceback (most recent call last):
File "<ipython-input-16-105803b235a9>", line 1, in <module>
runfile('E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py', wdir='E:/Data/Anaconda/[...]/00-Latest')
File "C:\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 580, in runfile
execfile(filename, namespace)
File "E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py", line 44, in <module>
print findIntersection(tfun, yfun, 0)
File "E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py", line 42, in findIntersection
return [fsolve(lambda x:fun1(x)-fun2(x, y), x0) for y in range(1, 10)]
File "C:\Anaconda\lib\site-packages\scipy\optimize\minpack.py", line 140, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "C:\Anaconda\lib\site-packages\scipy\optimize\minpack.py", line 209, in _root_hybr
ml, mu, epsfcn, factor, diag)
File "E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py", line 42, in <lambda>
return [fsolve(lambda x:fun1(x)-fun2(x, y), x0) for y in range(1, 10)]
File "E:/Data/Anaconda/[...]/00-Latest/fsolvestacktest001.py", line 36, in tfun
return data[0][x]
IndexError: arrays used as indices must be of integer (or boolean) type
You can 'convert' a datasets (arrays) to continuous functions by means of interpolation. scipy.interpolate.interp1d is a factory that provides you with the resulting function, which you could then use with your root finding algorithm.
--edit-- an example for computing an intersection of sin and cos from 20 samples (I've used cubic spline interpolation, as piecewise linear gives warnings about the smoothness):
>>> import numpy, scipy.optimize, scipy.interpolate
>>> x = numpy.linspace(0,2*numpy.pi, 20)
>>> x
array([ 0. , 0.33069396, 0.66138793, 0.99208189, 1.32277585,
1.65346982, 1.98416378, 2.31485774, 2.64555171, 2.97624567,
3.30693964, 3.6376336 , 3.96832756, 4.29902153, 4.62971549,
4.96040945, 5.29110342, 5.62179738, 5.95249134, 6.28318531])
>>> y1sampled = numpy.sin(x)
>>> y2sampled = numpy.cos(x)
>>> y1int = scipy.interpolate.interp1d(x,y1sampled,kind='cubic')
>>> y2int = scipy.interpolate.interp1d(x,y2sampled,kind='cubic')
>>> scipy.optimize.fsolve(lambda x: y1int(x) - y2int(x), numpy.pi)
array([ 3.9269884])
>>> scipy.optimize.fsolve(lambda x: numpy.sin(x) - numpy.cos(x), numpy.pi)
array([ 3.92699082])
Note that interpolation will give you 'guesses' about what data should be between the sampling points. No way to tell how good these guesses are. (but for my example, you can see it's a pretty good estimation)
I'm getting a ZeroDivisionError from the following code:
#stacking the array into a complex array allows np.unique to choose
#truely unique points. We also keep a handle on the unique indices
#to allow us to index `self` in the same order.
unique_points,index = np.unique(xdata[mask]+1j*ydata[mask],
return_index=True)
#Now we break it into the data structure we need.
points = np.column_stack((unique_points.real,unique_points.imag))
xx1,xx2 = self.meta['rcm_xx1'],self.meta['rcm_xx2']
yy1 = self.meta['rcm_yy2']
gx = np.arange(xx1,xx2+dx,dx)
gy = np.arange(-yy1,yy1+dy,dy)
GX,GY = np.meshgrid(gx,gy)
xi = np.column_stack((GX.ravel(),GY.ravel()))
gdata = griddata(points,self[mask][index],xi,method='linear',
fill_value=np.nan)
Here, xdata,ydata and self are all 2D numpy.ndarrays (or subclasses thereof) with the same shape and dtype=np.float32. mask is a 2d ndarray with the same shape and dtype=bool. Here's a link for those wanting to peruse the scipy.interpolate.griddata documentation.
Originally, xdata and ydata are derived from a non-uniform cylindrical grid that has a 4 point stencil -- I thought that the error might be coming from the fact that the same point was defined multiple times, so I made the set of input points unique as suggested in this question. Unfortunately, that hasn't seemed to help. The full traceback is:
Traceback (most recent call last):
File "/xxxxxxx/rcm.py", line 428, in <module>
x[...,1].to_pz0()
File "/xxxxxxx/rcm.py", line 285, in to_pz0
fill_value=fill_value)
File "/usr/local/lib/python2.7/site-packages/scipy/interpolate/ndgriddata.py", line 183, in griddata
ip = LinearNDInterpolator(points, values, fill_value=fill_value)
File "interpnd.pyx", line 192, in scipy.interpolate.interpnd.LinearNDInterpolator.__init__ (scipy/interpolate/interpnd.c:2935)
File "qhull.pyx", line 996, in scipy.spatial.qhull.Delaunay.__init__ (scipy/spatial/qhull.c:6607)
File "qhull.pyx", line 183, in scipy.spatial.qhull._construct_delaunay (scipy/spatial/qhull.c:1919)
ZeroDivisionError: float division
For what it's worth, the code "works" (No exception) if I use the "nearest" method.
For a subplot (self.intensity), I want to shade the area under the graph.
I tried this, hoping it was the correct syntax:
self.intensity.fill_between(arange(l,r), 0, projection)
Which I intend as to do shading for projection numpy array within (l,r) integer limits.
But it gives me an error. How do I do it correctly?
Heres the traceback:
Traceback (most recent call last):
File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_wx.py", line 1289, in _onLeftButtonDown
FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt)
File "/usr/lib/pymodules/python2.7/matplotlib/backend_bases.py", line 1576, in button_press_event
self.callbacks.process(s, mouseevent)
File "/usr/lib/pymodules/python2.7/matplotlib/cbook.py", line 265, in process
proxy(*args, **kwargs)
File "/usr/lib/pymodules/python2.7/matplotlib/cbook.py", line 191, in __call__
return mtd(*args, **kwargs)
File "/root/dev/spectrum/spectrum/plot_handler.py", line 55, in _onclick
self._call_click_callback(event.xdata)
File "/root/dev/spectrum/spectrum/plot_handler.py", line 66, in _call_click_callback
self.__click_callback(data)
File "/root/dev/spectrum/spectrum/plot_handler.py", line 186, in _on_plot_click
band_data = self._band_data)
File "/root/dev/spectrum/spectrum/plot_handler.py", line 95, in draw
self.intensity.fill_between(arange(l,r), 0, projection)
File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 6457, in fill_between
raise ValueError("Argument dimensions are incompatible")
ValueError: Argument dimensions are incompatible
It seems like you are trying to fill the part of the projection from l to r. fill_between expects the x and y arrays to be of equal lengths, so you can not expect to fill part of the curve only.
To get what you want, you can do either of the following:
1. send only part of the projection that needs to be filled to the command; and draw the rest of the projection separately.
2. send a separate boolean array as argument that defines the sections to fill in. See the documentation!
For the former method, see the example code below:
from pylab import *
a = subplot(111)
t = arange(1, 100)/50.
projection = sin(2*pi*t)
# Draw the original curve
a.plot(t, projection)
# Define areas to fill in
l, r = 10, 50
# Fill the areas
a.fill_between(t[l:r], projection[l:r])
show()