ASKSAGE: Sage Q&A Forum - Individual question feedhttps://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Tue, 03 May 2011 05:54:29 -0500Plotting in 3D in spherical coordinateshttps://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/My problem is that I am trying to plot (in full 3D spherical coordinates) a set of values stored in a 2D lookup table or LUT. The LUT is actually stored as a numpy 1801*3601 2D array indexed by theta and phi respectively in 0.1 degree steps. The LUT in fact represents an antenna radiation pattern (i.e. antenna gain/ radiation intensity as a function of theta and phi). However, my problem generalises to any one of plotting a function in spherical coordinates.
My first attempt at plotting this in Sage was to use the 'spherical_plot3d()' function. First I defined a function called:
getGain(phiInRadians, thetaInRadians)
which returned a value from the lookup table (LUT) representing antenna gain (a positive number in decibels). Then I tried plotting this as follows:
sage: spherical_plot3d(getGain,(-3.142,3.142),(0,3.142)).show(aspect_ratio=(1,1,1))
Now this *almost* does what I want, but not quite. My LUT has a high resolution with 0.1 degree intervals. However, the 3D plot which the above command delivers (via Jmol) seems to smooth the pattern where I don't want it to be smoothed (because it has abrupt edges), and is too 'blocky' where I would like the pattern to be smooth. Is there any way I can have fine control of the step-size in phi and theta (u and v in Sage-speak), or must I leave it to Sage to control these?
I also tried a different approach, which is to use list_plot3d, but to transform the coordinates from spherical to rectangular when building up my list to plot. To discuss this case we can simplify the problem to say that we wish to plot the radiation pattern of an isotropic antenna, i.e. one which has equal gain in all directions. Thus what we are simply trying to do is to plot a sphere in 3 dimensions from a list of 3-tuples, where each tuple represents an (x,y,z) coordinate in Cartesian space. However, when generating the points to plot I transform from spherical to cartesian coordinates when setting up the list of points to plot, thus:
sage: import numpy as np
sage: r=1 # Representing the gain of an isotropic antenna
sage: listOfPointsOnSurfaceOfSphere = [ (r* sin(theta) * cos(phi), r* sin(theta)* sin(phi), r* getGain(phi,theta)* cos(theta)) for theta in np.arange(0.1,pi,0.1) for phi in np.arange(-pi,pi,0.1) ]
sage: myPlot1 = list_plot3d(listOfPointsOnSurfaceOfSphere).show()
Now what I find is that my plot is all 'spiky', whereas I was hoping to see a smooth sphere. Of course, what is happening is that I have multiple points with the same (or similar) (x,y) coordinates, but very different z coordinates, since every point on the sphere 'above the equator' (i.e. above the x,y plane) has effective neighbours as mirror images below. This seems to be screwing up the interpolation routine, which isn't able to identify that it is actually nearby points ON THE SURFACE OF THE SPHERE which should be treated as neighbours. I can (sort of) solve this problem by only plotting my antenna radiation pattern over the range of theta for 0..pi/2 rather than 0..pi. This means that my pattern now interpolates nicely, and I can choose whatever resolution I desire (within reason). However, I can now only plot the upper (or lower) half of my radiation pattern plot at a time, and not the whole 3D pattern all together.
So, in summary, I have an almost but not quite satisfactory situation whereby I can choose between:
a) A full 3D plot, but can't control the resolution, so I get unwanted blockiness/smoothing in the wrong places, or
b) A plot where I get the resolution I desire, but I can only show either above or below the x,y plane, but not all at the same time
So if anyone could help me by advising me how I could achieve the best of both worlds (i.e. full 3D plot with full control of resolution) I would be most grateful. Thanks.
Tue, 19 Apr 2011 01:28:25 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/Answer by Jason Grout for <div class="snippet"><p>My problem is that I am trying to plot (in full 3D spherical coordinates) a set of values stored in a 2D lookup table or LUT. The LUT is actually stored as a numpy 1801*3601 2D array indexed by theta and phi respectively in 0.1 degree steps. The LUT in fact represents an antenna radiation pattern (i.e. antenna gain/ radiation intensity as a function of theta and phi). However, my problem generalises to any one of plotting a function in spherical coordinates.</p>
<p>My first attempt at plotting this in Sage was to use the 'spherical_plot3d()' function. First I defined a function called:</p>
<p>getGain(phiInRadians, thetaInRadians)</p>
<p>which returned a value from the lookup table (LUT) representing antenna gain (a positive number in decibels). Then I tried plotting this as follows:</p>
<p>sage: spherical_plot3d(getGain,(-3.142,3.142),(0,3.142)).show(aspect_ratio=(1,1,1))</p>
<p>Now this <em>almost</em> does what I want, but not quite. My LUT has a high resolution with 0.1 degree intervals. However, the 3D plot which the above command delivers (via Jmol) seems to smooth the pattern where I don't want it to be smoothed (because it has abrupt edges), and is too 'blocky' where I would like the pattern to be smooth. Is there any way I can have fine control of the step-size in phi and theta (u and v in Sage-speak), or must I leave it to Sage to control these?</p>
<p>I also tried a different approach, which is to use list_plot3d, but to transform the coordinates from spherical to rectangular when building up my list to plot. To discuss this case we can simplify the problem to say that we wish to plot the radiation pattern of an isotropic antenna, i.e. one which has equal gain in all directions. Thus what we are simply trying to do is to plot a sphere in 3 dimensions from a list of 3-tuples, where each tuple represents an (x,y,z) coordinate in Cartesian space. However, when generating the points to plot I transform from spherical to cartesian coordinates when setting up the list of points to plot, thus:</p>
<p>sage: import numpy as np</p>
<p>sage: r=1 # Representing the gain of an isotropic antenna</p>
<p>sage: listOfPointsOnSurfaceOfSphere = [ (r* sin(theta) * cos(phi), r* sin(theta)* sin(phi), r* getGain(phi,theta)* cos(theta)) for theta in np.arange(0.1,pi,0.1) for phi in np.arange(-pi,pi,0.1) ]</p>
<p>sage: myPlot1 = list_plot3d(listOfPointsOnSurfaceOfSphere).show()</p>
<p>Now what I find is that my plot is all 'spiky', whereas I was hoping to see a smooth sphere. Of course, what is happening is that I have multiple points with the same (or similar) (x,y) coordinates, but very different z coordinates, since every point on the sphere 'above the equator' (i.e. above the x,y plane) has effective neighbours as mirror images below. This seems to be screwing up the interpolation routine, which isn't able to identify that it ...<span class="expander"> <a>(more)</a></span></p></div> https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?answer=12310#post-id-12310Can you use the plot_points option in spherical_plot3d to get a finer u,v grid?Thu, 21 Apr 2011 10:08:37 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?answer=12310#post-id-12310Comment by deebs67 for <p>Can you use the plot_points option in spherical_plot3d to get a finer u,v grid?</p>
https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21765#post-id-21765Another great answer! Yes, this worked a treat, and avoids the residual 'shaded plane' problem I found with the 'list_plot3d()' approach described above. So this solves my problem entirely. Thanks.Tue, 03 May 2011 05:54:29 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21765#post-id-21765Comment by Jason Grout for <p>Can you use the plot_points option in spherical_plot3d to get a finer u,v grid?</p>
https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21808#post-id-21808To follow up: you can do something like spherical_plot3d(getGain,(-3.142,3.142),(0,3.142), plot_points=[200,100]).show(aspect_ratio=(1,1,1)) to plot 200 grid points in the azimuth angle and 100 points in the inclination angle. You can also just pass in a plot_points=<number> to set both numbers of points to the same value.Thu, 21 Apr 2011 10:13:05 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21808#post-id-21808Answer by niles for <div class="snippet"><p>My problem is that I am trying to plot (in full 3D spherical coordinates) a set of values stored in a 2D lookup table or LUT. The LUT is actually stored as a numpy 1801*3601 2D array indexed by theta and phi respectively in 0.1 degree steps. The LUT in fact represents an antenna radiation pattern (i.e. antenna gain/ radiation intensity as a function of theta and phi). However, my problem generalises to any one of plotting a function in spherical coordinates.</p>
<p>My first attempt at plotting this in Sage was to use the 'spherical_plot3d()' function. First I defined a function called:</p>
<p>getGain(phiInRadians, thetaInRadians)</p>
<p>which returned a value from the lookup table (LUT) representing antenna gain (a positive number in decibels). Then I tried plotting this as follows:</p>
<p>sage: spherical_plot3d(getGain,(-3.142,3.142),(0,3.142)).show(aspect_ratio=(1,1,1))</p>
<p>Now this <em>almost</em> does what I want, but not quite. My LUT has a high resolution with 0.1 degree intervals. However, the 3D plot which the above command delivers (via Jmol) seems to smooth the pattern where I don't want it to be smoothed (because it has abrupt edges), and is too 'blocky' where I would like the pattern to be smooth. Is there any way I can have fine control of the step-size in phi and theta (u and v in Sage-speak), or must I leave it to Sage to control these?</p>
<p>I also tried a different approach, which is to use list_plot3d, but to transform the coordinates from spherical to rectangular when building up my list to plot. To discuss this case we can simplify the problem to say that we wish to plot the radiation pattern of an isotropic antenna, i.e. one which has equal gain in all directions. Thus what we are simply trying to do is to plot a sphere in 3 dimensions from a list of 3-tuples, where each tuple represents an (x,y,z) coordinate in Cartesian space. However, when generating the points to plot I transform from spherical to cartesian coordinates when setting up the list of points to plot, thus:</p>
<p>sage: import numpy as np</p>
<p>sage: r=1 # Representing the gain of an isotropic antenna</p>
<p>sage: listOfPointsOnSurfaceOfSphere = [ (r* sin(theta) * cos(phi), r* sin(theta)* sin(phi), r* getGain(phi,theta)* cos(theta)) for theta in np.arange(0.1,pi,0.1) for phi in np.arange(-pi,pi,0.1) ]</p>
<p>sage: myPlot1 = list_plot3d(listOfPointsOnSurfaceOfSphere).show()</p>
<p>Now what I find is that my plot is all 'spiky', whereas I was hoping to see a smooth sphere. Of course, what is happening is that I have multiple points with the same (or similar) (x,y) coordinates, but very different z coordinates, since every point on the sphere 'above the equator' (i.e. above the x,y plane) has effective neighbours as mirror images below. This seems to be screwing up the interpolation routine, which isn't able to identify that it ...<span class="expander"> <a>(more)</a></span></p></div> https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?answer=12300#post-id-12300There may be an easy fix, using two copies of your solution (b): If you add two plots, and show the result, you will see both plotted on the same axes. If I understand correctly, this will resolve your issues with (b), no?
sage: N = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi))
sage: S = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: -sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi), color='red')
sage: (N+S).show()Tue, 19 Apr 2011 02:22:40 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?answer=12300#post-id-12300Comment by deebs67 for <p>There may be an easy fix, using two copies of your solution (b): If you add two plots, and show the result, you will see both plotted on the same axes. If I understand correctly, this will resolve your issues with (b), no?</p>
<pre><code>sage: N = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi))
sage: S = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: -sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi), color='red')
sage: (N+S).show()
</code></pre>
https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21825#post-id-21825Great answer! The only slight issue is that using parametric_plot3d() as you did above works fine for the sphere, but I still get the 'blocky/smoothed' problems as per a) when I try to plot my full (complicated) antenna radiation pattern in this way. This is presumably because Sage takes care of controlling the resolution, without giving me the option (??). But I can still use your 'North'+'South' trick with list_plot3d(). However, this does have the drawback that the plots also shade the x,y plane. So when I plot my full antenna radiation pattern in this way (or the sphere described above) it is bisected by a coloured plane at z=0. But other than that the problem is solved. Thanks.Tue, 19 Apr 2011 03:34:04 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21825#post-id-21825Comment by niles for <p>There may be an easy fix, using two copies of your solution (b): If you add two plots, and show the result, you will see both plotted on the same axes. If I understand correctly, this will resolve your issues with (b), no?</p>
<pre><code>sage: N = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi))
sage: S = parametric_plot3d((lambda u,v: cos(u)*sin(v), lambda u,v: -sin(u)*sin(v), lambda u,v: cos(v)),(0,pi),(0,pi), color='red')
sage: (N+S).show()
</code></pre>
https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21822#post-id-21822yes, I just didn't have a bunch of data to give an example with list_plot3d(). Sorry it's still not ideal -- maybe there's a keyword which will remove the shaded plane? For this, you might have to trace through the source code of list_plot3d() to see what keywords are accepted by the other functions it calls.Tue, 19 Apr 2011 04:17:34 -0500https://ask.sagemath.org/question/8081/plotting-in-3d-in-spherical-coordinates/?comment=21822#post-id-21822