Source code for magpylib._lib.classes.collection

# -------------------------------------------------------------------------------
# magpylib -- A Python 3 toolbox for working with magnetic fields.
# Copyright (C) Silicon Austria Labs, https://silicon-austria-labs.com/,
#               Michael Ortner <magpylib@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program.  If not, see <https://www.gnu.org/licenses/>.
# The acceptance of the conditions of the GNU Affero General Public License are
# compulsory for the usage of the software.
#
# For contact information, reach out over at <magpylib@gmail.com> or our issues
# page at https://www.github.com/magpylib/magpylib/issues.
# -------------------------------------------------------------------------------

from magpylib._lib.classes.base import FieldSampler
from magpylib._lib.utility import addListToCollection, isSource,  addUniqueSource

[docs]class Collection(FieldSampler): """ Create a collection of :mod:`magpylib.source` objects for common manipulation. Parameters ---------- sources : source objects python magic variable passes source objects to the collection at initialization. Attributes ---------- sources : list of source objects List of all sources that have been added to the collection. Example ------- >>> from magpylib import source, Collection >>> pm1 = source.magnet.Box(mag=[0,0,1000],dim=[1,1,1]) >>> pm2 = source.magnet.Cylinder(mag=[0,0,1000],dim=[1,1]) >>> pm3 = source.magnet.Sphere(mag=[0,0,1000],dim=1) >>> col = Collection(pm1,pm2,pm3) >>> B = col.getB([1,0,1]) >>> print(B) [9.93360625e+01 1.76697482e-14 3.12727683e+01] """ def __init__(self, *sources, dupWarning=True): self.sources = [] # The following will add Sources to the Collection sources list, # The code is the same as the addsource method. # addSource() is not cast here because it will # put a tuple inside a tuple. # Iterating for this would compromise performance. for s in sources: if type(s) == Collection: addListToCollection(self.sources, s.sources, dupWarning) elif isinstance(s, list) or isinstance(s, tuple): addListToCollection(self.sources, s, dupWarning) else: assert isSource(s), "Argument " + str(s) + \ " in addSource is not a valid source for Collection" if dupWarning is True: addUniqueSource(s, self.sources) else: self.sources += [s]
[docs] def removeSource(self, source_ref=-1): """ Remove a source from the sources list. Parameters ---------- source_ref : source object or int [Optional] Remove the inputted source from the list [Optional] If given an int, remove a source at the given index position. Default: Last position. Return ------ Popped source object. Raises ------ ValueError Will be thrown if you attempt to remove a source that is not in the Collection. AssertionError Will be thrown if inputted index kwarg type is not type int Example ------- >>> from magpylib import Collection, source >>> s = source.magnet.Sphere(mag=[1,2,3],dim=1,pos=[3,3,3]) >>> s2 = source.magnet.Sphere(mag=[1,2,3],dim=2,pos=[-3,-3,-3]) >>> m = source.moment.Dipole(moment=[1,2,3],pos=(0,0,0)) >>> c = Collection(s,s2,m) >>> print(c.sources) [<magpylib._lib.classes.magnets.Sphere object at 0xa31eafcc>, <magpylib._lib.classes.magnets.Sphere object at 0xa31ea1cc>, <magpylib._lib.classes.moments.Dipole object at 0xa31ea06c>] >>> c.removeSource(s) >>> print(c.sources) [<magpylib._lib.classes.magnets.Sphere object at 0xa31ea1cc>, <magpylib._lib.classes.moments.Dipole object at 0xa31ea06c>] >>> c.removeSource(s2) >>> print(c.sources) [<magpylib._lib.classes.moments.Dipole object at 0xa31ea06c>] >>> c.removeSource() >>> print(c.sources) [] """ assert type(source_ref) == int or isSource( source_ref), "Reference in removeSource is not an int nor a source" if type(source_ref) == int: try: return self.sources.pop(source_ref) except IndexError as e: # Give a more helpful error message. raise type(e)(str(e) + ' - Index ' + str(source_ref) + ' in collection source is not accessible for removeSource') else: try: self.sources.remove(source_ref) except ValueError as e: # Give a more helpful error message. raise type(e)(str(e) + ' - ' + str(type(source_ref) ) + ' not in list for removeSource') return source_ref
[docs] def addSources(self, *sources, dupWarning=True): """ This method adds the argument source objects to the collection. May also include other collections. Parameters ---------- source : source object adds the source object `source` to the collection. dupWarning : bool Warn and prevent if there is an attempt to add a duplicate source into the collection. Set to false to disable check and increase performance. Returns ------- None Example ------- >>> from magpylib import source, Collection >>> pm1 = source.magnet.Box(mag=[0,0,1000],dim=[1,1,1]) >>> pm2 = source.magnet.Cylinder(mag=[0,0,1000],dim=[1,1]) >>> pm3 = source.magnet.Sphere(mag=[0,0,1000],dim=1) >>> col = Collection(pm1) >>> print(col.getB([1,0,1])) [4.29223532e+01 1.76697482e-14 1.37461635e+01] >>> col.addSource(pm2) >>> print(col.getB([1,0,1])) [7.72389756e+01 1.76697482e-14 2.39070726e+01] >>> col.addSource(pm3) >>> print( [9.93360625e+01 1.76697482e-14 3.12727683e+01] """ for s in sources: if type(s) == Collection: addListToCollection(self.sources, s.sources, dupWarning) elif isinstance(s, list) or isinstance(s, tuple): addListToCollection(self.sources, s, dupWarning) else: assert isSource(s), "Argument " + str(s) + \ " in addSource is not a valid source for Collection" if dupWarning is True: addUniqueSource(s, self.sources) else: self.sources += [s]
[docs] def getB(self, pos): """ This method returns the magnetic field vector generated by the whole collection at the argument position `pos` in units of [mT] Parameters ---------- pos : vec3 [mm] Position where magnetic field should be determined. Returns ------- magnetic field vector : arr3 [mT] Magnetic field at the argument position `pos` generated by the collection in units of [mT]. """ Btotal = sum([s.getB(pos) for s in self.sources]) return Btotal
[docs] def move(self, displacement): """ This method moves each source in the collection by the argument vector `displacement`. Vector input format can be either list, tuple or array of any data type (float, int). Parameters ---------- displacement : vec3 - [mm] Displacement vector Returns ------- None Example ------- >>> from magpylib import source, Collection >>> pm1 = source.magnet.Box(mag=[0,0,1000],dim=[1,1,1]) >>> pm2 = source.magnet.Cylinder(mag=[0,0,1000],dim=[1,1]) >>> print(pm1.position,pm2.position) [0. 0. 0.] [0. 0. 0.] >>> col = Collection(pm1,pm2) >>> col.move([1,1,1]) >>> print(pm1.position,pm2.position) [1. 1. 1.] [1. 1. 1.] """ for s in self.sources: s.move(displacement)
[docs] def rotate(self, angle, axis, anchor='self.position'): """ This method rotates each source in the collection about `axis` by `angle`. The axis passes through the center of rotation anchor. Scalar input is either integer or float. Vector input format can be either list, tuple or array of any data type (float, int). Parameters ---------- angle : scalar [deg] Angle of rotation in units of [deg] axis : vec3 Axis of rotation anchor : vec3 The Center of rotation which defines the position of the axis of rotation. If not specified all sources will rotate about their respective center. Returns ------- None Example ------- >>> from magpylib import source, Collection >>> pm1 = source.magnet.Box(mag=[0,0,1000],dim=[1,1,1]) >>> pm2 = source.magnet.Cylinder(mag=[0,0,1000],dim=[1,1]) >>> print(pm1.position, pm1.angle, pm1.axis) [0. 0. 0.] 0.0 [0. 0. 1.] >>> print(pm2.position, pm2.angle, pm2.axis) [0. 0. 0.] 0.0 [0. 0. 1.] >>> col = Collection(pm1,pm2) >>> col.rotate(90, [0,1,0], anchor=[1,0,0]) >>> print(pm1.position, pm1.angle, pm1.axis) [1. 0. 1.] 90.0 [0. 1. 0.] >>> print(pm2.position, pm2.angle, pm2.axis) [1. 0. 1.] 90.0 [0. 1. 0.] """ for s in self.sources: s.rotate(angle, axis, anchor=anchor)