Python library for piecewise linear interpolation in multiple dimensions with multiple, arbitrarily placed, masters.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Foundation classes for multi-dimensional interpolation that work with any arithmetic objects. These objects form the mathematical core of MutatorMath and can be used independently of UFO-specific functionality.
N-dimensional coordinate representation with full arithmetic support. Location objects behave like numbers and can be added, subtracted, multiplied, and divided. They store axis names as keys and coordinate values as values.
class Location(dict):
"""
N-dimensional location object subclassed from dict.
- key is dimension or axis name
- value is the coordinate
- Location objects behave like numbers
- If a dimension is missing, assume it is zero
"""
def __init__(self, **kwargs):
"""Create location with axis=value pairs."""
def isOrigin(self) -> bool:
"""Check if location is at origin (all values are 0)."""
def isOnAxis(self) -> bool:
"""Check if location is on-axis (only one dimension != 0)."""
def isAmbivalent(self, dim=None) -> bool:
"""Check if location has both positive and negative values."""
def expand(self, axisNames):
"""Expand location with zero values for all axes in axisNames not already present."""
def copy(self) -> Location:
"""Return a copy of this location."""
def getActiveAxes(self) -> list:
"""Return list of axis names which are not zero."""
def getType(self, short=False) -> str:
"""Return string describing location type: origin, on-axis, off-axis, etc."""
def asString(self, strict=False) -> str:
"""Return location as formatted string."""
def asDict(self) -> dict:
"""Return location as plain dictionary."""
def asSortedStringDict(self, roundValue=False) -> dict:
"""Return location as sorted string dictionary."""
def asTuple(self) -> tuple:
"""Return location as tuple of (axis, value) pairs, sorted alphabetically."""
def fromTuple(self, locationTuple):
"""Read coordinates from tuple of (axis, value) pairs."""
def strip(self):
"""Remove axes with zero values."""
def common(self, other) -> Location:
"""Return location with axes common to both locations."""
def split(self) -> tuple:
"""Return (x, y) tuple for ambivalent locations."""
def spliceX(self) -> Location:
"""Return location with X values from split coordinates."""
def spliceY(self) -> Location:
"""Return location with Y values from split coordinates."""
def distance(self, other=None) -> float:
"""Calculate distance to other location or origin."""
def sameAs(self, other) -> bool:
"""Check if location is same as other location."""
def transform(self, transformDict):
"""Transform location using transformation dictionary."""def __add__(self, other) -> Location:
"""Add two locations or location and number."""
def __sub__(self, other) -> Location:
"""Subtract two locations or location and number."""
def __mul__(self, other) -> Location:
"""Multiply location by number or another location."""
def __truediv__(self, other) -> Location:
"""Divide location by number or another location (Python 3 division)."""
def __lt__(self, other) -> bool:
"""Compare locations for sorting."""# Create locations
loc1 = Location(weight=100, width=75)
loc2 = Location(weight=900, width=125)
# Arithmetic operations
middle = (loc1 + loc2) / 2 # Location(weight=500, width=100)
offset = loc2 - loc1 # Location(weight=800, width=50)
# Check properties
print(loc1.isOrigin()) # False
print(loc1.onAxis()) # False (has multiple non-zero dimensions)
# Expand to include new dimensions
loc1.expand(Location(contrast=0)) # Adds contrast dimensionCore interpolation engine that calculates instances from masters using piecewise linear interpolation. Mutator objects store master data and provide instance generation capabilities.
class Mutator(dict):
"""
Main interpolation class for calculating instances from masters.
Subclassed from dict to store master data.
"""
def __init__(self, neutral=None):
"""Create mutator with optional neutral master."""
def makeInstance(self, location, bend=True) -> any:
"""
Calculate interpolated instance at given location.
Parameters:
- location: Location object specifying coordinates
- bend: bool, whether to apply bending transformations
Returns:
- Interpolated object of same type as masters
"""
def getInstance(self, aLocation, axisOnly=False, getFactors=False):
"""
Get instance with optional factor information.
Parameters:
- aLocation: Location object
- axisOnly: bool, use only on-axis masters
- getFactors: bool, return factors along with instance
Returns:
- Instance object or (instance, factors) tuple
"""
def setNeutral(self, aMathObject, deltaName="origin"):
"""Set the neutral master object with optional delta name."""
def getNeutral(self) -> any:
"""Get the neutral master object."""
def setBias(self, location):
"""Set the bias location for interpolation."""
def getBias(self) -> Location:
"""Get the bias location."""
def setBender(self, bender):
"""Set bender object for non-linear transformations."""
def addDelta(self, location, aMathObject, deltaName=None, punch=False, axisOnly=True):
"""
Add a delta master at specified location.
Parameters:
- location: Location object for this master
- aMathObject: Master object (must support math operations)
- deltaName: Optional name for this delta
- punch: bool, force addition even if location exists
- axisOnly: bool, restrict to on-axis deltas
"""
def getAxisNames(self) -> list:
"""Get list of all axis names used in this mutator."""
def collectLocations(self) -> list:
"""Collect all locations from masters."""
def getFactors(self, aLocation, axisOnly=False, allFactors=False) -> dict:
"""
Get interpolation factors for given location.
Parameters:
- aLocation: Location object
- axisOnly: bool, use only on-axis masters
- allFactors: bool, return all factors including zero
Returns:
- dict: Mapping of delta names to factors
"""def buildMutator(items, axes=None, bias=None) -> tuple[Location, Mutator]:
"""
Build a mutator with (location, obj) pairs.
Parameters:
- items: List of (Location, object) tuples defining masters
- axes: Optional axis definitions for bending
- bias: Optional bias location (auto-calculated if None)
Returns:
- Tuple of (bias_location, mutator) ready for interpolation
"""from mutatorMath.objects.mutator import buildMutator
from mutatorMath.objects.location import Location
# Define masters with (location, value) pairs
masters = [
(Location(weight=100), 10), # thin master
(Location(weight=900), 100), # bold master
(Location(weight=100, width=75), 8), # thin condensed
(Location(weight=900, width=125), 120) # bold extended
]
# Build mutator
bias, mutator = buildMutator(masters)
# Generate instances
thin_normal = mutator.makeInstance(Location(weight=200, width=100))
bold_condensed = mutator.makeInstance(Location(weight=800, width=80))Non-linear transformation objects that apply warpmaps to locations before interpolation. Benders enable custom axis mappings and non-linear behavior in design spaces.
class Bender(object):
"""
Object for non-linear transformation of locations using warpmaps.
"""
def __init__(self, axes):
"""
Create bender with axis definitions.
Parameters:
- axes: Dict of axis definitions with 'map' arrays for warping
Format: {axisName: {'map': [(input, output), ...], ...}}
"""
def __call__(self, location) -> Location:
"""
Transform location using configured warpmaps.
Parameters:
- location: Location object to transform
Returns:
- Transformed Location object
"""from mutatorMath.objects.bender import Bender
from mutatorMath.objects.location import Location
# Define warp map for non-linear weight axis
axes = {
'weight': {
'map': [(0, 0), (500, 200), (1000, 1000)], # Non-linear mapping
'minimum': 0,
'maximum': 1000,
'default': 0
}
}
# Create bender
bender = Bender(axes)
# Transform locations
original = Location(weight=250)
transformed = bender(original) # Location(weight=100) - mapped via warpHelper functions for location processing and analysis.
def numberToString(value) -> str:
"""
Return nicely formatted string representation of numeric value.
Parameters:
- value: Number, tuple, or None to format
Returns:
- Formatted string representation
"""
def sortLocations(locations) -> list:
"""
Sort locations for optimal processing order.
Parameters:
- locations: List of Location objects
Returns:
- Sorted list of Location objects
"""
def biasFromLocations(locs, preferOrigin=True) -> Location:
"""
Calculate bias location from a set of locations.
Parameters:
- locs: List of Location objects
- preferOrigin: Whether to prefer origin as bias
Returns:
- Calculated bias Location
"""
def getLimits(locations, current, sortResults=True, verbose=False) -> list:
"""
Get limits for locations relative to current position.
Parameters:
- locations: List of Location objects
- current: Current Location
- sortResults: Whether to sort results
- verbose: Enable verbose output
Returns:
- List of limit information
"""
def noBend(loc) -> Location:
"""
Identity function for bending - returns location unchanged.
Parameters:
- loc: Location object
Returns:
- Same location object
"""Install with Tessl CLI
npx tessl i tessl/pypi-mutator-math