2

I have a surface that looks like Figure A, imagine that is top view. The surface has calculated Z value.

enter image description here

Now I need to find all Z values in new points like figure B. How to do this? I tried scipy.interpolate.interp2d but it gives some weird results like this: enter image description here

I just want to find custom z for custom x and y inside the "figure".

Mimimal code example

func_int = scipy.interpolate.interp2d([point[0] for point in pointsbottom],[point[1] for point in pointsbottom],[point[2] for point in pointsbottom], kind = 'linear')
pointscaption = map(lambda point:(point[0],point[1],func_int(point[0],point[1])),pointscaption)

Where pointsbottom is list of (x,y,z) and pointscaption is list of (x,y,z) but I need to find new z.

Laurel
  • 5,965
  • 14
  • 31
  • 57
sevatster
  • 133
  • 1
  • 3
  • 11
  • 1
    If you would show us a [minimal example of your code](http://stackoverflow.com/help/mcve), we might actually be able to help you. I'm guessing, the `z` coordinate is the vertical one? Could you clarify your question? – jhoepken Mar 16 '16 at 09:43
  • I just want to find custom z for custom x and y inside the "figure". – sevatster Mar 16 '16 at 12:59

1 Answers1

2

Try using griddata instead:

    grid_z1 = griddata(points, values, (grid_x, grid_y), method='linear')

The difference is griddata expects regular data as input (hmm..., I think). It's not that you should have a different result but more that you'll be able to catch the problem faster. You can mask the "regular grid" data easily.

My first guess would be that those input coordinates are not what you are expecting them to be (perhaps with a different scale from the function you are calculating) but it's difficult to say without testing.

In any case it seems you want a surface, which by definition is a type of grid data, so it should be fairly easy to spot the problem using this different framework.

EDIT (further considerations about the doubts of the poster):

Let's say you want some object that you want to input some data inside. After doing this you want to be able to estimate any position using that data. For that purpose you can build a class like this:

    import numpy as np

    class Estimation():
        def __init__(self,datax,datay,dataz):
            self.x = datax
            self.y = datay
            self.v = dataz

        def estimate(self,x,y,using='ISD'):
            """
            Estimate point at coordinate x,y based on the input data for this
            class.
            """
            if using == 'ISD':
                return self._isd(x,y)
        
        def _isd(self,x,y):
            d = np.sqrt((x-self.x)**2+(y-self.y)**2)
            if d.min() > 0:
                v = np.sum(self.v*(1/d**2)/np.sum(1/d**2))
                return v
            else:
                return self.v[d.argmin()]

This example is using Inverse Squared Distance method which is very stable for estimation (if you avoid divisions by zero). It won't be fast but I hope it's understandable. From this point on you can estimate any point in 2D space by doing:

    e = Estimation(datax,datay,dataz)
    newZ = e.estimate(30,55) # the 30 and 55 are just example coordinates

If you were to do this to an entire grid:

    datax,datay = np.random.randint(0,100,10),np.random.randint(0,100,10)
    dataz       = datax/datay

    e = Estimation(datax,datay,dataz)

    surf = np.zeros((100,100))
    for i in range(100):
        for j in range(100):
            surf[i,j] = e.estimate(i,j)

You would obtain an image that you can see using, for instance, matplotlib (in which the color represents the height in your surface):

    import matplotlib.pyplot as plt
    plt.imshow(surf.T,origin='lower',interpolation='nearest')
    plt.scatter(datax,datay,c=dataz,s=90)
    plt.show()

The result of this experiment is this:

Estimated Surface

If you don't want to use ISD (Inverse Squared Distance) just implement a new method on Estimation class. Is this what you are looking for?

Kraigolas
  • 5,121
  • 3
  • 12
  • 37
armatita
  • 12,825
  • 8
  • 48
  • 49
  • It's working better a little bit but still not enough. Here is a screenshot: https://yadi.sk/i/ow8lxLnyqEpzU – sevatster Mar 16 '16 at 15:36
  • It seems you are just changing some locations while leaving other unchecked. Are you sure that the grid object from your code has exactly the same shape as the surface you are viewing? Could you plot it in 2D height map (z a color variable)? It will be easier to understand the geometries. – armatita Mar 16 '16 at 15:42
  • Sorry, I don't know how to do this. I can describe with very simple words - I have some smooth surface with irregular x and y and some z for them and I want to find z for new points that I've added in the surface. – sevatster Mar 18 '16 at 12:15
  • Ok. I edited my post with a few recipes you should be able to adapt to your own code (including 2D visualization, and estimation). See if it fits your problem. – armatita Mar 18 '16 at 12:45
  • Hi, I am getting Error - File "/home/username/anaconda3/lib/python3.7/site-packages/numpy/ma/core.py", line 1018, in __call__ result = self.f(da, db, *args, **kwargs) TypeError: unsupported operand type(s) for *: 'float' and 'SingleBlockManager' – sameer_nubia Feb 07 '20 at 04:48