1

I'm trying to visualize measured pressures in an annulus in a polar plot. The problem is that I have only 6 measurement points and therefore the plot is star-shaped, while it should be more ellipse shaped due to the vertical pressure gradiënt in a liquid. Note that it doesn't have to be a circle since the injection pressures right and left can differ.

First I tried to make a plot using matplotlib's polar function, resulting in a star-shaped plot. Then I tried to scatter the data but now I'm unable to fit an ellipse through the data points.

loc_deg =(71, 11, 306, 234, 169, 109, 71) #  location of sensors 1, 2, 3, 4, 5, 6, 1 1 is repeated to complete the star/circle
loc_rad = np.radians(loc_deg) # use radians

P = (2.7269999999999999, 3.0019999999999998, 0.39800000000000002, 2.9729999999999999, 2.5099999999999998, 2.5609999999999999, 2.7269999999999999)

fig = plt.figure() 
ax = fig.add_subplot(111,projection = 'polar')

ax.set_ylim(0,10)
ax.set_xticks(loc_rad)

tv = ax.plot(loc_rad, P)# create star
lis = ax.scatter(loc_rad, P, color = '#ff7f00', marker = '.') # create scatter

Now I'm trying to fit an ellipse through the scatter plot, or the star should change in an ellipse.

EDIT This is a plot of the three solutions, including the one proposed by Ardweaden

Upon trying Ardweadens solution I realize that a fit was not exactly the thing I was looking for and therefore my question was not clear. I'm looking for a way to connect the dots over the polar surface instead of just a straight line.

e.g.: If one would have 2 measuring points: 1 on 1 degree and 1 on 179 degrees and both of these measurements are the value 10. By using the plot function a straight line would show a value of almost 0 at 90 degrees, while interpolating between 10 and 10 you would expect the value be 10 there as well. So more like a half circle.

Michiel
  • 27
  • 8
  • You could try some interpolation such as here; https://stackoverflow.com/questions/48875339/smooth-curved-line-between-3-points-in-plot – Ardweaden Jul 31 '19 at 10:09
  • The problem with a solution like this is that you would expect a lineair gradient like: P = dp/dh * h + P0. However since the polar plot is not horizontal symmetric you would have to do so for the right side and left side separately. This would result in 2 half circles, which causes a problem on the top and bottom, where they should touch. You expect the graph to be continuous but this solution gives 2 discontinuities, at 90 deg/.5pi and 270 deg/1.5 pi. – Michiel Jul 31 '19 at 11:13
  • So, what I'm looking for is some kind of least squares fit which takes into account that the result should be a circle/ellipse connecting 0 degrees with 360 degrees. – Michiel Jul 31 '19 at 11:39
  • Why can't you fit an ellipse? Where would you want the ellipse to go through? Can you provide an image perhaps. I added simple fitting of an ellipse in the answer as it's more readable. – Ardweaden Jul 31 '19 at 13:18

1 Answers1

0

Just fitting an ellipse.

from scipy.optimize import curve_fit

def ellipse(phi,b,e,f):
    return b/(np.sqrt(1 - e * np.cos(phi + f)**2))

popt, pcov = curve_fit(ellipse, loc_rad, P)
x = np.arange(0,2*np.pi,0.01)

ax = fig.add_subplot(111,projection = 'polar')
ax.plot(x,ellipse(x,popt[0],popt[1],popt[2]))

Hardcoding your data and plotting gradients:

loc_deg =(306, 234, 169, 109,71,11) #  location of sensors 1, 2, 3, 4, 5, 6, 1 1 is repeated to complete the star/circle
loc_rad = np.radians(loc_deg) # use radians

P = (0.39800000000000002, 2.9729999999999999, 2.5099999999999998, 2.5609999999999999,3.0019999999999998,2.7269999999999999)

fig = plt.figure() 
ax = fig.add_subplot(111,projection = 'polar')

ax.set_ylim(0,10)
ax.set_xticks(loc_rad)

def generate_fit(deg,P,deg_f=1):
    x,y = [],[]

    for i in range(1,len(P)):
        x.extend(np.arange(deg[i-1],deg[i],-1))
        incy = abs(deg[i]-deg[i-1])
        y.extend(np.linspace(P[i-1],P[i],incy))

    x.extend(np.arange(11,0,-1))
    x.extend(np.arange(360,306,-1))
    y.extend(np.linspace(P[-1],P[0],360-306 + 11))
    return np.radians(x),y

x,y = generate_fit(loc_deg,P)
ax.plot(x,y)

ax.scatter(loc_rad, P, color = '#ff7f00', marker = '.')
Ardweaden
  • 857
  • 9
  • 23
  • This does not plot as an ellipse on a polar plot per the question. Please edit the answer to do so. – James Phillips Jul 31 '19 at 14:37
  • I am not sure what you mean. This is only an extension of the code provided by the OP, where he sets `ax`. I only posted this awaiting his response, as you can see in the comments to his question. I now added that line from his code if that's what you meant. – Ardweaden Jul 31 '19 at 14:53
  • This solution fits an ellipse through the points without taking into account the actual values of the plot. The problem with a polar plot is that the measured value is shown from the center of the plot, so by the radius. So what I'm looking for is a function that lineally changes the radius from one point to the other. – Michiel Aug 01 '19 at 06:41
  • To be frank, the request is still quite unclear. Do you want something along the lines of this? https://i.imgur.com/mFlwKq8.png – Ardweaden Aug 01 '19 at 09:09
  • See my example in the edit of the main question. I would like to connect the dots in a way that you would expect the value to be in between the dots, not just a straight line. So if the gap is 20 degrees and the pressure at said points is 20 and 40 kPa I would like to display at every degree 1 kPa off. A straight line would, as the extreme example in the main question shows not give the right values at the right locations. – Michiel Aug 01 '19 at 13:31
  • Sorry, I didn't see your image at first. But yes, I would expect something like that. The left side looks really good. The right side probably needs some tweaking, not going to 0. Can you show how you did this? – Michiel Aug 01 '19 at 14:26
  • Now I get it! Well, in the first pic I simply fitted a higher-order polynomial, so the gradient isn't always 1kPa per degree. This plot is correct: https://i.imgur.com/csaPht6.png You can simply calculate the values of straight lines between the points. – Ardweaden Aug 01 '19 at 14:47
  • 1
    Thanks a lot! This is what I was looking for. – Michiel Aug 02 '19 at 07:29