Ejemplo n.º 1
0
def drawDipole(position, moment, angle, axis, SYSSIZE, pyplot):
    """
    Draw a dipole moment arrow.

    Parameters
    ----------
    position : vec3
        position of the dipole
    moment : vec3
        orientation vector of the dipole
    SYSSIZE : float
        size of the display
    pyplot : pyplot
        canvas to draw on

    """
    from magpylib._lib.mathLibPublic import rotatePosition
    P = rotatePosition(position, angle, axis)
    M = rotatePosition(moment, angle, axis)

    pyplot.quiver(
        P[0],
        P[1],
        P[2],  # X,Y,Z position
        M[0],
        M[1],
        M[2],  # Components of the Vector
        normalize=True,
        length=SYSSIZE / 12,
        color='k')
Ejemplo n.º 2
0
def test_rotatePosition():
    expectedResult = [-0.26138058, 0.59373138, 3.28125372]
    position = [1,2,3]
    result = rotatePosition(position,234.5,(0,0.2,1),anchor=[0,1,0])
    rounding = 4
    for i in range(0,3):
        assert round(result[i],rounding)==round(expectedResult[i],rounding)
Ejemplo n.º 3
0
    def getB(self, *sources, dupWarning=True):
        """Extract the magnetic field based on the Sensor orientation

        Parameters
        ----------
        dupWarning : Check if there are any duplicate sources, optional.
            This will prevent duplicates and throw a warning, by default True.

        Returns
        -------
        [vec3]
            B-Field as perceived by the sensor

        Example
        -------
        >>> from magpylib import source, Sensor
        >>> sensor = Sensor([0,0,0],90,(0,0,1)) # This sensor is rotated in respect to space
        >>> cyl = source.magnet.Cylinder([1,2,300],[1,2])
        >>> absoluteReading = cyl.getB([0,0,0])
        >>> print(absoluteReading)
            [  0.552   1.105  268.328 ]
        >>> relativeReading = sensor.getB(cyl)
        >>> print(relativeReading)
            [  1.105  -0.552  268.328 ]
        """
        # Check input, add Collection list
        sourcesList = []
        for s in sources:
            try:
                addListToCollection(sourcesList, s.sources, dupWarning)
            except AttributeError:
                if isinstance(s, list) or isinstance(s, tuple):
                    addListToCollection(sourcesList, s, dupWarning)
                else:
                    assert isSource(s), "Argument " + str(s) + \
                        " in addSource is not a valid source for Collection"
                    if dupWarning is True:
                        addUniqueSource(s, sourcesList)
                    else:
                        sourcesList += [s]

        # Read the field from all nominated sources
        Btotal = sum([s.getB(self.position) for s in sources])
        return rotatePosition(Btotal,
                              -self.angle,  # Rotate in the opposite direction
                              self.axis,
                              [0, 0, 0])
Ejemplo n.º 4
0
def drawMagnetizationVector(position, magnetization, angle, axis, color,
                            SYSSIZE, pyplot):
    """Draw the magnetization vector of a magnet.

    Parameters
    ----------
    position : vec3
        position of the magnet
    magnetization : vec3
        magnetization vector
    angle : float
        angle of rotation
    axis : vec3
        Axis of rotation
    color : matplotlib color
        Color of the axis. No default value specified
    SYSSIZE : float
        Size of the display syste
    pyplot : [pyploy]
        pyplot canvas to draw on

    """
    from magpylib._lib.mathLibPublic import rotatePosition
    M = rotatePosition(magnetization, angle, axis)
    P = position
    # Get a lil different but unique tone
    c = [color[0] / 2, color[1] / 2, color[2] / 2, color[3]]
    pyplot.quiver(
        P[0],
        P[1],
        P[2],  # X,Y,Z position
        M[0],
        M[1],
        M[2],  # Components of the Vector
        normalize=True,
        length=SYSSIZE,
        color=c)
Ejemplo n.º 5
0
    def displaySystem(self, markers=listOfPos, suppress=False, direc=False, 
                            subplotAx=None):
        """
        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
        ----------
        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)]
        """
        
        if subplotAx is None:
            fig = plt.figure(dpi=80, figsize=(8, 8))
            ax = fig.gca(projection='3d')
        else:
            ax = subplotAx

        # count magnets
        Nm = 0
        for s in self.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 = []
        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 self.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(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(s.angle, s.axis, d)+P for d in vertB0])
                vT = array(
                    [angleAxisRotation(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(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(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(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 = rotatePosition(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 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 is False:
            plt.show(block=False)

        return plt.gcf()