예제 #1
0
    def getB(self, pos):  # Particular Line current B field calculation. Check RCS for getB() interface
        
        # vectorized code if input is an Nx3 array
        if type(pos) == ndarray:
            if len(shape(pos))==2: # list of positions - use vectorized code
                # vector size
                NN = shape(pos)[0] 
                # prepare vector inputs
                POSREL = pos - self.position
                ANG = ones(NN)*self.angle
                AX = tile(self.axis,(NN,1))
                # compute rotations and field
                ROTATEDPOS = angleAxisRotationV_priv(ANG, -AX, POSREL)
                BB = Bfield_CurrentLineVV(self.vertices,self.current,ROTATEDPOS)
                BCM = angleAxisRotationV_priv(ANG, AX, BB)

                return BCM
        
        # secure input type and check input format
        p1 = array(pos, dtype=float64, copy=False)
        # relative position between mag and obs
        posRel = p1 - self.position
        # rotate this vector into the CS of the magnet (inverse rotation)
        rotatedPos = angleAxisRotation_priv(self.angle, -self.axis, posRel) # pylint: disable=invalid-unary-operand-type
        # rotate field vector back
        BCm = angleAxisRotation_priv(self.angle, self.axis, Bfield_CurrentLineV(self.vertices, self.current,rotatedPos))
        # BCm is the obtained magnetic field in Cm
        # the field is well known in the magnet coordinates.
        return BCm
예제 #2
0
    def getB(self, pos):

        # vectorized code if input is an Nx3 array
        if type(pos) == ndarray:
            if len(np.shape(
                    pos)) == 2:  # list of positions - use vectorized code
                # vector size
                NN = np.shape(pos)[0]
                # prepare vector inputs
                POSREL = pos - self.position
                ANG = np.ones(NN) * self.angle
                AX = np.tile(self.axis, (NN, 1))
                MAG = np.tile(self.magnetization, (NN, 1))
                DIM = np.ones(NN) * self.dimension
                # compute rotations and field
                ROTATEDPOS = angleAxisRotationV_priv(ANG, -AX, POSREL)
                BB = Bfield_SphereV(MAG, ROTATEDPOS, DIM)
                BCM = angleAxisRotationV_priv(ANG, AX, BB)

                return BCM

        # secure input type and check input format
        p1 = array(pos, dtype=float64, copy=False)
        # relative position between mag and obs
        posRel = p1 - self.position
        # rotate this vector into the CS of the magnet (inverse rotation)
        rotatedPos = angleAxisRotation_priv(self.angle, -self.axis, posRel)  # pylint: disable=invalid-unary-operand-type
        # rotate field vector back
        BCm = angleAxisRotation_priv(
            self.angle, self.axis,
            Bfield_Sphere(self.magnetization, rotatedPos, self.dimension))
        # BCm is the obtained magnetic field in Cm
        # the field is well known in the magnet coordinates.
        return BCm
예제 #3
0
def test_Quaternion():
    Qmult([1, 2, 3, 4], [4, 3, 2, 1]) == [-12, 6, 24, 12]
    Qconj([1, 2, 3, 4]) == [1, -2, -3, -4]
    Qnorm2([1, 2, 3, 4]) == 30

    Q = Qunit([1, 2, 3, 4])
    sol = [0.1826, 0.3651, 0.5477, 0.7303]
    for q, s in zip(Q, sol):
        assert round(q, 4) == s, "bad Qunit"

    Q = getRotQuat(33, [1, 2, 3])
    sol = [0.9588, 0.0759, 0.1518, 0.2277]
    for q, s in zip(Q, sol):
        assert round(q, 4) == s, "bad getRotQuat"

    V = angleAxisRotation_priv(33, [1, 2, 3], [4, 5, 6])
    sol = [3.2868, 5.8042, 5.7016]
    for v, s in zip(V, sol):
        assert round(v, 4) == s, "bad getRotQuat"
예제 #4
0
def displaySystem(sources,
                  markers=listOfPos,
                  subplotAx=None,
                  sensors=listOfSensors,
                  suppress=False,
                  direc=False,
                  figsize=(8, 8)):
    """
    Shows the collection system in an interactive pyplot and returns a matplotlib figure identifier.

    WARNING
    -------
    As a result of an inherent problem in matplotlib the 
    Poly3DCollections z-ordering fails when bounding boxes intersect.


    Parameters
    ----------
    markers : list[scalar,scalar,scalar,[label]]
        List of position vectors to add visual markers to the display, optional label.
        Default: [[0,0,0]]

    Example
    -------
    >>> from magpylib import Collection, source
    >>> c=source.current.Circular(3,7)
    >>> x = Collection(c)
    >>> marker0 = [0,0,0,"Neutral Position"]
    >>> marker1 = [10,10,10]
    >>> x.displaySystem(markers=[ marker0,
    ...                           marker1])

    Parameters
    ----------
    sensors : list[sensor]
        List of :class:`~magpylib.Sensor` objects to add the display.
        Default: None

    Example
    -------
    >>> from magpylib import Collection, source
    >>> c=source.current.Circular(3,7)
    >>> x = Collection(c)
    >>> sensor0 = Sensor()
    >>> sensor1 = Sensor(pos=[1,2,3], angle=180)
    >>> x.displaySystem(sensors=[ sensor0,
    ...                           sensor1])


    Parameters
    ----------
    suppress : bool
        If True, only return Figure information, do not show. Interactive mode must be off.
        Default: False.


    Example
    -------
    >>> ## Suppress matplotlib.pyplot.show() 
    >>> ## and returning figure from showing up
    >>> from matplotlib import pyplot 
    >>> pyplot.ioff()
    >>> figureData = Collection.displayFigure(suppress=True)

    Parameters
    ----------
    direc : bool
        Set to True to show current directions and magnetization vectors.
        Default: False


    Return    
    ------
    matplotlib Figure object
        graphics object is displayed through plt.show()

    Example
    -------
    >>> from magpylib import source, Collection
    >>> pm1 = source.magnet.Box(mag=[0,0,1000],dim=[1,1,1],pos=[-1,-1,-1],angle=45,axis=[0,0,1])
    >>> pm2 = source.magnet.Cylinder(mag=[0,0,1000],dim=[2,2],pos=[0,-1,1],angle=45,axis=[1,0,0])
    >>> pm3 = source.magnet.Sphere(mag=[0,0,1000],dim=3,pos=[-2,1,2],angle=45,axis=[1,0,0])
    >>> C1 = source.current.Circular(curr=100,dim=6)
    >>> col = Collection(pm1,pm2,pm3,C1)
    >>> col.displaySystem()
    
    Parameters
    ----------
    subplotAx : matplotlib subplot axe instance
        Use an existing matplotlib subplot instance to draw the 3D system plot into.
        Default: None
    
    Example
    -------
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from magpylib.source.magnet import Box
    >>> from magpylib import Collection
    >>> #create collection of one magnet
    >>> s1 = Box(mag=[ 500,0, 500], dim=[3,3,3], pos=[ 0,0, 3], angle=45, axis=[0,1,0])
    >>> c = Collection(s1)
    >>> #create positions
    >>> xs = np.linspace(-8,8,100)
    >>> zs = np.linspace(-6,6,100)
    >>> posis = [[x,0,z] for z in zs for x in xs]
    >>> #calculate fields
    >>> Bs = c.getBsweep(posis)
    >>> #reshape array and calculate amplitude
    >>> Bs = np.array(Bs).reshape([100,100,3])
    >>> Bamp = np.linalg.norm(Bs,axis=2)
    >>> X,Z = np.meshgrid(xs,zs)
    >>> # Define figure
    >>> fig = plt.figure()
    >>> ## Define ax for 2D
    >>> ax1 = fig.add_subplot(1, 2, 1, axisbelow=True)
    >>> ## Define ax for 3D displaySystem
    >>> ax2 = fig.add_subplot(1, 2, 2, axisbelow=True,projection='3d')
    >>> ## field plot 2D
    >>> ax1.contourf(X,Z,Bamp,100,cmap='rainbow')
    >>> U,V = Bs[:,:,0], Bs[:,:,2]
    >>> ax1.streamplot(X, Z, U, V, color='k', density=2)
    >>> ## plot Collection system in 3D ax subplot
    >>> c.displaySystem(subplotAx=ax2)
    
    Raises
    ------
    AssertionError
        If Marker position list is poorly defined. i.e. listOfPos=(x,y,z) instead of lisOfPos=[(x,y,z)]
    """

    collection = Collection(sources)

    if subplotAx is None:
        fig = plt.figure(dpi=80, figsize=figsize)
        ax = fig.gca(projection='3d')
    else:
        ax = subplotAx

    # count magnets
    Nm = 0
    for s in collection.sources:
        if type(s) is Box or type(s) is Cylinder or type(s) is Sphere:
            Nm += 1

    cm = plt.cm.hsv  # Linter complains about this but it is working pylint: disable=no-member
    # select colors
    colors = [cm(x) for x in linspace(0, 1, Nm + 1)]

    ii = -1
    SYSSIZE = finfo(float).eps  # Machine Epsilon for moment
    dipolesList = []
    magnetsList = []
    sensorsList = []
    currentsList = []
    markersList = []

    # Check input and Add markers to the Markers list before plotting
    for m in markers:
        assert isDisplayMarker(
            m), "Invalid marker definition in displaySystem:" + str(
                m) + ". Needs to be [vec3] or [vec3,string]"
        markersList += [m]

    for s in sensors:
        if s == sensor1:
            continue
        else:
            assert isSensor(
                s), "Invalid sensor definition in displaySystem:" + str(s)
            sensorsList.append(s)

    for s in collection.sources:
        if type(s) is Box:
            ii += 1  # increase color counter
            P = s.position
            D = s.dimension / 2
            # create vertices in canonical basis
            v0 = array([
                D, D * array([1, 1, -1]), D * array([1, -1, -1]),
                D * array([1, -1, 1]), D * array([-1, 1, 1]),
                D * array([-1, 1, -1]), -D, D * array([-1, -1, 1])
            ])
            # rotate vertices + displace
            v = array(
                [angleAxisRotation_priv(s.angle, s.axis, d) + P for d in v0])
            # create faces
            faces = [[v[0], v[1], v[2], v[3]], [v[0], v[1], v[5], v[4]],
                     [v[4], v[5], v[6], v[7]], [v[2], v[3], v[7], v[6]],
                     [v[0], v[3], v[7], v[4]], [v[1], v[2], v[6], v[5]]]
            # plot
            boxf = Poly3DCollection(faces,
                                    facecolors=colors[ii],
                                    linewidths=0.5,
                                    edgecolors='k',
                                    alpha=1)
            ax.add_collection3d(boxf)
            # check system size
            maxSize = amax(abs(v))
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            if direc is True:
                s.color = colors[ii]
                magnetsList.append(s)
        elif type(s) is Cylinder:
            ii += 1  # increase color counter
            P = s.position
            R, H = s.dimension / 2

            resolution = 20

            # vertices
            phis = linspace(0, 2 * pi, resolution)
            vertB0 = array([[R * cos(p), R * sin(p), -H] for p in phis])
            vertT0 = array([[R * cos(p), R * sin(p), H] for p in phis])
            # rotate vertices+displacement
            vB = array([
                angleAxisRotation_priv(s.angle, s.axis, d) + P for d in vertB0
            ])
            vT = array([
                angleAxisRotation_priv(s.angle, s.axis, d) + P for d in vertT0
            ])
            # faces
            faces = [[vT[i], vB[i], vB[i + 1], vT[i + 1]]
                     for i in range(resolution - 1)]
            faces += [vT, vB]
            # plot
            coll = Poly3DCollection(faces,
                                    facecolors=colors[ii],
                                    linewidths=0.5,
                                    edgecolors='k',
                                    alpha=1)
            ax.add_collection3d(coll)
            # check system size
            maxSize = max([amax(abs(vB)), amax(abs(vT))])
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            if direc is True:
                s.color = colors[ii]
                magnetsList.append(s)

        elif type(s) is Sphere:
            ii += 1  # increase color counter
            P = s.position
            R = s.dimension / 2

            resolution = 12

            # vertices
            phis = linspace(0, 2 * pi, resolution)
            thetas = linspace(0, pi, resolution)
            vs0 = [[[
                R * cos(phi) * sin(th), R * sin(phi) * sin(th), R * cos(th)
            ] for phi in phis] for th in thetas]
            # rotate vertices + displacement
            vs = array(
                [[angleAxisRotation_priv(s.angle, s.axis, v) + P for v in vss]
                 for vss in vs0])
            # faces
            faces = []
            for j in range(resolution - 1):
                faces += [[
                    vs[i, j], vs[i + 1, j], vs[i + 1, j + 1], vs[i, j + 1]
                ] for i in range(resolution - 1)]
            # plot
            boxf = Poly3DCollection(faces,
                                    facecolors=colors[ii],
                                    linewidths=0.5,
                                    edgecolors='k',
                                    alpha=1)
            ax.add_collection3d(boxf)
            # check system size
            maxSize = amax(abs(vs))
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            if direc is True:
                s.color = colors[ii]
                magnetsList.append(s)

        elif type(s) is Line:
            P = s.position
            vs0 = s.vertices
            # rotate vertices + displacement
            vs = array(
                [angleAxisRotation_priv(s.angle, s.axis, v) + P for v in vs0])
            # plot
            ax.plot(vs[:, 0], vs[:, 1], vs[:, 2], lw=1, color='k')
            # check system size
            maxSize = amax(abs(vs))
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            if direc is True:
                # These don't move in the original object,
                sCopyWithVertices = deepcopy(s)
                sCopyWithVertices.vertices = vs  # We just draw the frame rotation, discard changes
                currentsList.append(sCopyWithVertices)

        elif type(s) is Circular:
            P = s.position
            R = s.dimension / 2

            resolution = 20

            # vertices
            phis = linspace(0, 2 * pi, resolution)
            vs0 = array([[R * cos(p), R * sin(p), 0] for p in phis])
            # rotate vertices + displacement
            vs = array(
                [angleAxisRotation_priv(s.angle, s.axis, v) + P for v in vs0])
            # plot
            ax.plot(vs[:, 0], vs[:, 1], vs[:, 2], lw=1, color='k')
            # check system size
            maxSize = amax(abs(vs))
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            if direc is True:
                # Send the Circular vertice information
                sCopyWithVertices = deepcopy(s)
                sCopyWithVertices.vertices = vs  # to the object drawing list
                currentsList.append(sCopyWithVertices)

        elif type(s) is Dipole:
            P = angleAxisRotation(s.position, s.angle, s.axis)
            maxSize = amax(abs(P))
            if maxSize > SYSSIZE:
                SYSSIZE = maxSize

            dipolesList.append(s)

    for m in markersList:  # Draw Markers
        ax.scatter(m[0], m[1], m[2], s=20, marker='x')
        if (len(m) > 3):
            zdir = None
            ax.text(m[0], m[1], m[2], m[3], zdir)
        # Goes up to 3rd Position
        maxSize = max([abs(pos) for pos in m[:3]])
        if maxSize > SYSSIZE:
            SYSSIZE = maxSize

    for s in sensorsList:  # Draw Sensors
        maxSize = max([abs(pos) for pos in s.position])
        if maxSize > SYSSIZE:
            SYSSIZE = maxSize
        drawSensor(s, SYSSIZE, ax)

    for d in dipolesList:
        drawDipole(d.position, d.moment, d.angle, d.axis, SYSSIZE, ax)

    if direc is True:  # Draw the Magnetization axes and current directions
        drawCurrentArrows(currentsList, SYSSIZE, ax)
        drawMagAxis(magnetsList, SYSSIZE, ax)

    #for tick in ax.xaxis.get_ticklabels()+ax.yaxis.get_ticklabels()+ax.zaxis.get_ticklabels():
    #    tick.set_fontsize(12)
    ax.set_xlabel('x[mm]')  #, fontsize=12)
    ax.set_ylabel(
        'y[mm]')  #, fontsize=12)   #change font size through rc parameters
    ax.set_zlabel('z[mm]')  #, fontsize=12)
    ax.set(
        xlim=(-SYSSIZE, SYSSIZE),
        ylim=(-SYSSIZE, SYSSIZE),
        zlim=(-SYSSIZE, SYSSIZE),
    )

    plt.tight_layout()

    if suppress == True:
        return plt.gcf()
    else:
        plt.show()