Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: How to increase colormap/linewidth quality in streamplot?

I have the following code to generate a streamplot based on an interp1d-Interpolation of discrete data:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from scipy.interpolate import interp1d

# CSV Import
a1array=pd.read_csv('a1.csv', sep=',',header=None).values
rv=a1array[:,0]
a1v=a1array[:,1]
da1vM=a1array[:,2]
a1 = interp1d(rv, a1v)
da1M = interp1d(rv, da1vM)

# Bx and By vector components
def bx(x ,y):
    rad = np.sqrt(x**2+y**2)
    if rad == 0:
        return 0
    else:
        return x*y/rad**4*(-2*a1(rad)+rad*da1M(rad))/2.87445E-19*1E-12

def by(x ,y):
    rad = np.sqrt(x**2+y**2)
    if rad == 0:
        return 4.02995937E-04/2.87445E-19*1E-12
    else:
        return -1/rad**4*(2*a1(rad)*y**2+rad*da1M(rad)*x**2)/2.87445E-19*1E-12

Bx = np.vectorize(bx, otypes=[np.float])
By = np.vectorize(by, otypes=[np.float])

# Grid
num_steps = 11
Y, X = np.mgrid[-25:25:(num_steps * 1j), 0:25:(num_steps * 1j)]
Vx = Bx(X, Y)
Vy = By(X, Y)
speed = np.sqrt(Bx(X, Y)**2+By(X, Y)**2)
lw = 2*speed / speed.max()+.5

# Star Radius
circle3 = plt.Circle((0, 0), 16.3473140, color='black', fill=False)

# Plot
fig0, ax0 = plt.subplots(num=None, figsize=(11,9), dpi=80, facecolor='w', edgecolor='k')
strm = ax0.streamplot(X, Y, Vx, Vy, color=speed, linewidth=lw,density=[1,2], cmap=plt.cm.jet)
ax0.streamplot(-X, Y, -Vx, Vy, color=speed, linewidth=lw,density=[1,2], cmap=plt.cm.jet)
ax0.add_artist(circle3)
cbar=fig0.colorbar(strm.lines,fraction=0.046, pad=0.04)
cbar.set_label('B[GT]', rotation=270, labelpad=8)
cbar.set_clim(0,1500)
cbar.draw_all()
ax0.set_ylim([-25,25])
ax0.set_xlim([-25,25])
ax0.set_xlabel('x [km]')
ax0.set_ylabel('z [km]')
ax0.set_aspect(1)
plt.title('polyEos(0.05,2), M/R=0.2, B_r(0,0)=1402GT', y=1.01)
plt.savefig('MR02Br1402.pdf',bbox_inches=0)
plt.show(fig0)

I uploaded the csv-file here if you want to try some stuff https://www.dropbox.com/s/4t7jixpglt0mkl5/a1.csv?dl=0. Which generates the following plot: StreamPlot

I am actually pretty happy with the result except for one small detail, which I can not figure out: If one looks closely the linewidth and the color change in rather big steps, which is especially visible at the center:

Problem

Is there some way/option with which I can decrease the size of this steps to especially make the colormap smother?

like image 866
N0va Avatar asked Sep 02 '16 14:09

N0va


2 Answers

I had another look at this and it wasnt as painful as I thought it might be.

Add:

    subdiv = 15
    points = np.arange(len(t[0]))
    interp_points = np.linspace(0, len(t[0]), subdiv * len(t[0]))
    tgx = np.interp(interp_points, points, tgx)
    tgy = np.interp(interp_points, points, tgy)
    tx = np.interp(interp_points, points, tx)
    ty = np.interp(interp_points, points, ty)

after ty is initialised in the trajectories loop (line 164 in my version). Just substitute whatever number of subdivisions you want for subdiv = 15. All the segments in the streamplot will be subdivided into as many equally sized segments as you choose. The colors and linewidths for each will still be properly obtained from interpolating the data.

Its not as neat as changing the integration step but it does plot exactly the same trajectories.

subdiv = 15

like image 162
TobyD Avatar answered Oct 11 '22 02:10

TobyD


If you don't mind changing the streamplot code (matplotlib/streamplot.py), you could simply decrease the size of the integration steps. Inside _integrate_rk12() the maximum step size is defined as:

maxds = min(1. / dmap.mask.nx, 1. / dmap.mask.ny, 0.1)

If you decrease that, lets say:

maxds = 0.1 * min(1. / dmap.mask.nx, 1. / dmap.mask.ny, 0.1)

I get this result (left = new, right = original):

enter image description here

Of course, this makes the code about 10x slower, and I haven't thoroughly tested it, but it seems to work (as a quick hack) for this example.

About the density (mentioned in the comments): I personally don't see the problem of that. It's not like we are trying to visualize the actual path line of (e.g.) a particle; the density is already some arbitrary (controllable) choice, and yes it is influenced by choices in the integration, but I don't thing that it changes the (not quite sure how to call this) required visualization we're after.

The results (density) do seem to converge a bit for decreasing step sizes, this shows the results for decreasing the integration step with a factor {1,5,10,20}:

enter image description here

like image 37
Bart Avatar answered Oct 11 '22 01:10

Bart