Matplotlib中的箭头图箭头太可笑了

时间:2017-07-15 22:00:24

标签: python matplotlib physics

我正在创建一个可以对电场线进行建模的python脚本,但箭头图中出现的箭头太大了。我尝试过改变单位和比例,但是matplotlib上的文档对我来说也没有意义......当系统中只有一次充电时,这似乎只是一个主要问题,但箭头仍然略有任意数量的收费超大。箭头往往在所有情况下都过大,但最明显的只有一个粒子。

Over sized arrows

import matplotlib.pyplot as plt
import numpy as np
import sympy as sym
import astropy as astro

k = 9 * 10 ** 9


def get_inputs():
    inputs_loop = False
    while inputs_loop is False:
        """"
        get inputs
        """
        inputs_loop = True
        particles_loop = False
        while particles_loop is False:
            try:
                particles_loop = True
                """
                get n particles with n charges.
                """
                num_particles = int(raw_input('How many particles are in the system? '))
                parts = []
                for i in range(num_particles):
                    parts.append([float(raw_input("What is the charge of particle %s in Coulombs? " % (str(i + 1)))),
                                  [float(raw_input("What is the x position of particle %s? " % (str(i + 1)))),
                                   float(raw_input('What is the y position of particle %s? ' % (str(i + 1))))]])
            except ValueError:
                print 'Could not convert input to proper data type. Please try again.'
                particles_loop = False
    return parts
def vec_addition(vectors):
    x_sum = 0
    y_sum = 0
    for b in range(len(vectors)):
        x_sum += vectors[b][0]
        y_sum += vectors[b][1]
    return [x_sum,y_sum]

def electric_field(particle, point):
    if particle[0] > 0:
        """
        Electric field exitation is outwards

        If the x position of the particle is > the point, then a different calculation must be made than in not.
        """
        field_vector_x = k * (
        particle[0] / np.sqrt((particle[1][0] - point[0]) ** 2 + (particle[1][1] - point[1]) ** 2) ** 2) * \
                         (np.cos(np.arctan2((point[1] - particle[1][1]), (point[0] - particle[1][0]))))
        field_vector_y = k * (
        particle[0] / np.sqrt((particle[1][0] - point[0]) ** 2 + (particle[1][1] - point[1]) ** 2) ** 2) * \
                         (np.sin(np.arctan2((point[1] - particle[1][1]), (point[0] - particle[1][0]))))
        """
        Defining the direction of the components
        """
        if point[1] < particle[1][1] and field_vector_y > 0:
            print field_vector_y
            field_vector_y *= -1
        elif point[1] > particle[1][1] and field_vector_y < 0:
            print field_vector_y
            field_vector_y *= -1
        else:
            pass
        if point[0] < particle[1][0] and field_vector_x > 0:
            print field_vector_x
            field_vector_x *= -1
        elif point[0] > particle[1][0] and field_vector_x < 0:
            print field_vector_x
            field_vector_x *= -1
        else:
            pass
        """
        If the charge is negative
        """
    elif particle[0] < 0:
        field_vector_x = k * (
            particle[0] / np.sqrt((particle[1][0] - point[0]) ** 2 + (particle[1][1] - point[1]) ** 2) ** 2) * (
                             np.cos(np.arctan2((point[1] - particle[1][1]), (point[0] - particle[1][0]))))
        field_vector_y = k * (
            particle[0] / np.sqrt((particle[1][0] - point[0]) ** 2 + (particle[1][1] - point[1]) ** 2) ** 2) * (
                             np.sin(np.arctan2((point[1] - particle[1][1]), (point[0] - particle[1][0]))))
        """
        Defining the direction of the components
        """
        if point[1] > particle[1][1] and field_vector_y > 0:
            print field_vector_y
            field_vector_y *= -1
        elif point[1] < particle[1][1] and field_vector_y < 0:
            print field_vector_y
            field_vector_y *= -1
        else:
            pass
        if point[0] > particle[1][0] and field_vector_x > 0:
            print field_vector_x
            field_vector_x *= -1
        elif point[0] < particle[1][0] and field_vector_x < 0:
            print field_vector_x
            field_vector_x *= -1
        else:
            pass
    return [field_vector_x, field_vector_y]

def main(particles):
    """
    Graphs the electrical field lines.
    :param particles:
    :return:
    """
    """
    plot particle positions
    """
    particle_x = 0
    particle_y = 0
    for i in range(len(particles)):
        if particles[i][0]<0:
            particle_x = particles[i][1][0]
            particle_y = particles[i][1][1]
            plt.plot(particle_x,particle_y,'r+',linewidth=1.5)
        else:
            particle_x = particles[i][1][0]
            particle_y = particles[i][1][1]
            plt.plot(particle_x,particle_y,'r_',linewidth=1.5)
    """
    Plotting out the quiver plot.
    """
    parts_x = [particles[i][1][0] for i in range(len(particles))]
    graph_x_min = min(parts_x)
    graph_x_max = max(parts_x)
    x,y = np.meshgrid(np.arange(graph_x_min-(graph_x_max-graph_x_min),graph_x_max+(graph_x_max-graph_x_min)),
                      np.arange(graph_x_min-(graph_x_max-graph_x_min),graph_x_max+(graph_x_max-graph_x_min)))
    if len(particles)<2:
        for x_pos in range(int(particles[0][1][0]-10),int(particles[0][1][0]+10)):
            for y_pos in range(int(particles[0][1][0]-10),int(particles[0][1][0]+10)):
                vecs = []
                for particle_n in particles:
                    vecs.append(electric_field(particle_n, [x_pos, y_pos]))
                final_vector = vec_addition(vecs)
                distance = np.sqrt((final_vector[0] - x_pos) ** 2 + (final_vector[1] - y_pos) ** 2)
                plt.quiver(x_pos, y_pos, final_vector[0], final_vector[1], distance, angles='xy', scale_units='xy',
                           scale=1, width=0.05)
        plt.axis([particles[0][1][0]-10,particles[0][1][0]+10,
                  particles[0][1][0] - 10, particles[0][1][0] + 10])
    else:
        for x_pos in range(int(graph_x_min-(graph_x_max-graph_x_min)),int(graph_x_max+(graph_x_max-graph_x_min))):
            for y_pos in range(int(graph_x_min-(graph_x_max-graph_x_min)),int(graph_x_max+(graph_x_max-graph_x_min))):
                vecs = []
                for particle_n in particles:
                    vecs.append(electric_field(particle_n,[x_pos,y_pos]))
                final_vector = vec_addition(vecs)
                distance = np.sqrt((final_vector[0]-x_pos)**2+(final_vector[1]-y_pos)**2)
                plt.quiver(x_pos,y_pos,final_vector[0],final_vector[1],distance,angles='xy',units='xy')
        plt.axis([graph_x_min-(graph_x_max-graph_x_min),graph_x_max+(graph_x_max-graph_x_min),graph_x_min-(graph_x_max-graph_x_min),graph_x_max+(graph_x_max-graph_x_min)])
    plt.grid()
    plt.show()



g = get_inputs()
main(g)}

1 个答案:

答案 0 :(得分:5)

您可以将比例设置为大致对应sequ向量。

v

这会导致类似这样的事情:

enter image description here

如果我正确解释它,你想绘制点电荷的场矢量。人们发现例如其他人如何做到这一点。 Christian Hill的this blog entry。他使用plt.quiver(x_pos, y_pos, final_vector[0], final_vector[1], scale=1e9, units="xy") 代替streamplot但我们可能会使用代码来计算字段并替换图。

在任何情况下,我们都不需要并且不需要100个不同的箭头图,如问题的代码,但只有一个箭头图绘制整个场。如果我们想让场矢量的长度表示场强,我们当然会遇到一个问题,因为幅度随着粒子与3的幂的距离而变化。解决方案可能是在绘制之前以对数方式缩放场,使得箭头长度仍然以某种方式可见,即使在距离粒子一定距离处也是如此。然后可以使用quiver绘图的比例参数来调整箭头的长度,使它们以某种方式适合其他绘图参数。

quiver

enter image description here

(请注意,这里的字段没有以任何方式标准化,这应该是可视化的。)

另一种选择是看例如this code也从点费中提取字段线。