Skip to content

PreferredUnits

PreferredUnits dataclass

Configuration class for default units used throughout ballistic calculations.

This class defines the default units that will be used when creating measurements without explicitly specifying units, and for displaying results in user interfaces. It provides a centralized way to configure unit preferences for an entire ballistic calculation session. This allows users to set their preferred unit system once and have it apply to all subsequent calculations.

Default Configuration
  • angular: Degree (for look-angle and barrel elevation)
  • distance: Yard (traditional ballistic range unit)
  • velocity: FPS (feet per second)
  • pressure: InHg (inches of mercury, for barometric pressure)
  • temperature: Fahrenheit
  • diameter: Inch (bullet and bore diameter)
  • length: Inch (bullet length, barrel length)
  • weight: Grain (bullet weight, powder charge)
  • adjustment: Mil (scope adjustment increments)
  • drop: Inch (trajectory vertical measurements)
  • energy: FootPound (kinetic energy)
  • ogw: Pound (optimal game weight)
  • sight_height: Inch (scope height above bore)
  • target_height: Inch (target dimensions)
  • twist: Inch (barrel twist rate)
  • time: Second (flight time)

Examples:

>>> # Set metric preferences
>>> PreferredUnits.distance = Unit.Meter
>>> PreferredUnits.velocity = Unit.MPS
>>> # Reset to defaults
>>> PreferredUnits.restore_defaults()
>>> # Bulk configuration
>>> PreferredUnits.set(
...     distance='meter',
...     velocity='mps',
...     temperature='celsius'
... )
Note

Changing preferred units affects all subsequent unit creation and display.

Methods:

Name Description
restore_defaults

Reset all preferred units to their default values.

set

Set preferred units from keyword arguments.

Functions

restore_defaults classmethod

Reset all preferred units to their default values.

Examples:

>>> # Changing default distance units:
>>> PreferredUnits.distance = Unit.Meter
>>> # Reset to defaults
>>> PreferredUnits.restore_defaults()
>>> PreferredUnits.distance
yard
Source code in py_ballisticcalc/unit.py
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
@classmethod
def restore_defaults(cls):
    """Reset all preferred units to their default values.

    Examples:
        >>> # Changing default distance units:
        >>> PreferredUnits.distance = Unit.Meter
        >>> # Reset to defaults
        >>> PreferredUnits.restore_defaults()
        >>> PreferredUnits.distance
        yard
    """
    for f in fields(cls):
        if f.default is not MISSING:
            setattr(cls, f.name, f.default)
        elif getattr(f, "default_factory", MISSING) is not MISSING:
            setattr(cls, f.name, f.default_factory())  # type: ignore
set classmethod

Set preferred units from keyword arguments.

Allows bulk configuration of preferred units using either Unit enum values or string aliases. Invalid attributes or values are logged as warnings but do not raise exceptions.

Parameters:

Name Type Description Default
**kwargs Union[Unit, str, bool]

Keyword arguments where keys are attribute names and values are either Unit enum values or (string) UnitAliases.

{}

Examples:

>>> # Set using Unit enums
>>> PreferredUnits.set(
...     distance=Unit.Meter,
...     velocity=Unit.MPS,
...     temperature=Unit.Celsius
... )
>>> # Set using string aliases
>>> PreferredUnits.set(
...     distance='meter',
...     velocity='mps',
...     weight='gram'
... )
>>> # Mixed types
>>> PreferredUnits.set(
...     distance=Unit.Yard,
...     velocity='fps',
...     adjustment='mil'
... )
Source code in py_ballisticcalc/unit.py
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
@classmethod
def set(cls, **kwargs: Union[Unit, str, bool]):
    """Set preferred units from keyword arguments.

    Allows bulk configuration of preferred units using either Unit enum values or string aliases.
    Invalid attributes or values are logged as warnings but do not raise exceptions.

    Args:
        **kwargs: Keyword arguments where keys are attribute names and values
                  are either Unit enum values or (string) UnitAliases.

    Examples:
        >>> # Set using Unit enums
        >>> PreferredUnits.set(
        ...     distance=Unit.Meter,
        ...     velocity=Unit.MPS,
        ...     temperature=Unit.Celsius
        ... )

        >>> # Set using string aliases
        >>> PreferredUnits.set(
        ...     distance='meter',
        ...     velocity='mps',
        ...     weight='gram'
        ... )

        >>> # Mixed types
        >>> PreferredUnits.set(
        ...     distance=Unit.Yard,
        ...     velocity='fps',
        ...     adjustment='mil'
        ... )
    """
    for attribute, value in kwargs.items():
        if hasattr(PreferredUnits, attribute):
            if isinstance(value, Unit):
                setattr(PreferredUnits, attribute, value)
            elif isinstance(value, str):
                if _unit := Unit._parse_unit(value):
                    setattr(PreferredUnits, attribute, _unit)
                else:
                    logger.warning(f"{value=} not a member of Unit")
            elif isinstance(value, bool):
                setattr(PreferredUnits, attribute, value)
            else:
                logger.warning(f"type of {value=} have not been converted to a member of Unit")
        else:
            logger.warning(f"{attribute=} not found in preferred_units")

Unit Presets

You can define and load PreferredUnits presets from toml files. There are three such preset files in /assets that have predefined loader functions that can be invoked as follows:

from py_ballisticcalc import loadImperialUnits, loadMetricUnits, loadMixedUnits

loadImperialUnits()
loadMetricUnits()
loadMixedUnits()

(Use just one of these methods – only the last one called counts.)

Imperial Units

From assets/.pybc-imperial.toml:

angular = 'Degree'
distance = 'Foot'
velocity = 'FPS'
pressure = 'InHg'
temperature = 'Fahrenheit'
diameter = 'Inch'
length = 'Inch'
weight = 'Grain'
adjustment = 'Mil'
drop = 'Inch'
energy = 'FootPound'
ogw = 'Pound'
sight_height = 'Inch'
target_height = 'Inch'
twist = 'Inch'
time = 'Second'

Metric Units

From assets/.pybc-metrics.toml:

angular = 'Degree'
distance = 'Meter'
velocity = 'MPS'
pressure = 'hPa'
temperature = 'Celsius'
diameter = 'Centimeter'
length = 'Centimeter'
weight = 'Gram'
adjustment = 'Mil'
drop = 'Centimeter'
energy = 'Joule'
ogw = 'Kilogram'
sight_height = 'Centimeter'
target_height = 'Meter'
twist = 'Centimeter'
time = 'Second'

Mixed Units

Mixed sets:

  • metric units for distance, velocity, target, atmosphere
  • imperial for bullet and gun dimensions.

From assets/.pybc-mixed.toml:

angular = 'Degree'
distance = 'Meter'
velocity = 'MPS'
pressure = 'Bar'
temperature = 'Celsius'
diameter = 'Inch'
length = 'Inch'
weight = 'Grain'
adjustment = 'Mil'
drop = 'Centimeter'
energy = 'FootPound'
ogw = 'Kilogram'
sight_height = 'Inch'
target_height = 'Meter'
twist = 'Inch'
time = 'Second'

UnitProps

Bases: NamedTuple

Properties and display characteristics for unit measurements.

Attributes:

Name Type Description
name str

Human-readable name of the unit (e.g., 'meter', 'foot-pound').

accuracy int

Number of decimal places for formatting values for display.

symbol str

Standard symbol or abbreviation for the unit (e.g., 'm', 'ft·lb').

Examples:

>>> d = Distance.Yard(600)
>>> print(d << Distance.Kilometer)
0.549km
>>> UnitPropsDict[Unit.Kilometer] = UnitProps("kilometer", 5, " kilometers")
>>> print(d << Distance.Kilometer)
0.54864 kilometers

UnitPropsDict = {Unit.Radian: UnitProps('radian', 6, 'rad'), Unit.Degree: UnitProps('degree', 4, '°'), Unit.MOA: UnitProps('MOA', 2, 'MOA'), Unit.Mil: UnitProps('mil', 3, 'mil'), Unit.MRad: UnitProps('mrad', 2, 'mrad'), Unit.Thousandth: UnitProps('thousandth', 2, 'ths'), Unit.InchesPer100Yd: UnitProps('inch/100yd', 2, 'in/100yd'), Unit.CmPer100m: UnitProps('cm/100m', 2, 'cm/100m'), Unit.OClock: UnitProps('hour', 2, 'h'), Unit.Inch: UnitProps('inch', 1, 'inch'), Unit.Foot: UnitProps('foot', 2, 'ft'), Unit.Yard: UnitProps('yard', 1, 'yd'), Unit.Mile: UnitProps('mile', 3, 'mi'), Unit.NauticalMile: UnitProps('nautical mile', 3, 'nm'), Unit.Millimeter: UnitProps('millimeter', 3, 'mm'), Unit.Centimeter: UnitProps('centimeter', 3, 'cm'), Unit.Meter: UnitProps('meter', 1, 'm'), Unit.Kilometer: UnitProps('kilometer', 3, 'km'), Unit.Line: UnitProps('line', 3, 'ln'), Unit.FootPound: UnitProps('foot-pound', 0, 'ft·lb'), Unit.Joule: UnitProps('joule', 0, 'J'), Unit.MmHg: UnitProps('mmHg', 0, 'mmHg'), Unit.InHg: UnitProps('inHg', 6, 'inHg'), Unit.Bar: UnitProps('bar', 2, 'bar'), Unit.hPa: UnitProps('hPa', 4, 'hPa'), Unit.PSI: UnitProps('psi', 4, 'psi'), Unit.Fahrenheit: UnitProps('fahrenheit', 1, '°F'), Unit.Celsius: UnitProps('celsius', 1, '°C'), Unit.Kelvin: UnitProps('kelvin', 1, '°K'), Unit.Rankin: UnitProps('rankin', 1, '°R'), Unit.MPS: UnitProps('mps', 0, 'm/s'), Unit.KMH: UnitProps('kmh', 1, 'km/h'), Unit.FPS: UnitProps('fps', 1, 'ft/s'), Unit.MPH: UnitProps('mph', 1, 'mph'), Unit.KT: UnitProps('knot', 1, 'kt'), Unit.Grain: UnitProps('grain', 1, 'gr'), Unit.Ounce: UnitProps('ounce', 1, 'oz'), Unit.Gram: UnitProps('gram', 1, 'g'), Unit.Pound: UnitProps('pound', 0, 'lb'), Unit.Kilogram: UnitProps('kilogram', 3, 'kg'), Unit.Newton: UnitProps('newton', 3, 'N'), Unit.Minute: UnitProps('minute', 0, 'min'), Unit.Second: UnitProps('second', 1, 's'), Unit.Millisecond: UnitProps('millisecond', 3, 'ms'), Unit.Microsecond: UnitProps('microsecond', 6, 'µs'), Unit.Nanosecond: UnitProps('nanosecond', 9, 'ns'), Unit.Picosecond: UnitProps('picosecond', 12, 'ps')} module-attribute

UnitPropsDict: Mapping[Unit, UnitProps] = {
    Unit.Radian: UnitProps('radian', 6, 'rad'),
    Unit.Degree: UnitProps('degree', 4, '°'),
    Unit.MOA: UnitProps('MOA', 2, 'MOA'),
    Unit.Mil: UnitProps('mil', 3, 'mil'),
    Unit.MRad: UnitProps('mrad', 2, 'mrad'),
    Unit.Thousandth: UnitProps('thousandth', 2, 'ths'),
    Unit.InchesPer100Yd: UnitProps('inch/100yd', 2, 'in/100yd'),
    Unit.CmPer100m: UnitProps('cm/100m', 2, 'cm/100m'),
    Unit.OClock: UnitProps('hour', 2, 'h'),

    Unit.Inch: UnitProps("inch", 1, "inch"),
    Unit.Foot: UnitProps("foot", 2, "ft"),
    Unit.Yard: UnitProps("yard", 1, "yd"),
    Unit.Mile: UnitProps("mile", 3, "mi"),
    Unit.NauticalMile: UnitProps("nautical mile", 3, "nm"),
    Unit.Millimeter: UnitProps("millimeter", 3, "mm"),
    Unit.Centimeter: UnitProps("centimeter", 3, "cm"),
    Unit.Meter: UnitProps("meter", 1, "m"),
    Unit.Kilometer: UnitProps("kilometer", 3, "km"),
    Unit.Line: UnitProps("line", 3, "ln"),

    Unit.FootPound: UnitProps('foot-pound', 0, 'ft·lb'),
    Unit.Joule: UnitProps('joule', 0, 'J'),

    Unit.MmHg: UnitProps('mmHg', 0, 'mmHg'),
    Unit.InHg: UnitProps('inHg', 6, 'inHg'),
    Unit.Bar: UnitProps('bar', 2, 'bar'),
    Unit.hPa: UnitProps('hPa', 4, 'hPa'),
    Unit.PSI: UnitProps('psi', 4, 'psi'),

    Unit.Fahrenheit: UnitProps('fahrenheit', 1, '°F'),
    Unit.Celsius: UnitProps('celsius', 1, '°C'),
    Unit.Kelvin: UnitProps('kelvin', 1, '°K'),
    Unit.Rankin: UnitProps('rankin', 1, '°R'),

    Unit.MPS: UnitProps('mps', 0, 'm/s'),
    Unit.KMH: UnitProps('kmh', 1, 'km/h'),
    Unit.FPS: UnitProps('fps', 1, 'ft/s'),
    Unit.MPH: UnitProps('mph', 1, 'mph'),
    Unit.KT: UnitProps('knot', 1, 'kt'),

    Unit.Grain: UnitProps('grain', 1, 'gr'),
    Unit.Ounce: UnitProps('ounce', 1, 'oz'),
    Unit.Gram: UnitProps('gram', 1, 'g'),
    Unit.Pound: UnitProps('pound', 0, 'lb'),
    Unit.Kilogram: UnitProps('kilogram', 3, 'kg'),
    Unit.Newton: UnitProps('newton', 3, 'N'),

    Unit.Minute: UnitProps('minute', 0, 'min', ),
    Unit.Second: UnitProps('second', 1, 's'),
    Unit.Millisecond: UnitProps('millisecond', 3, 'ms', ),
    Unit.Microsecond: UnitProps('microsecond', 6, 'µs'),
    Unit.Nanosecond: UnitProps('nanosecond', 9, 'ns'),
    Unit.Picosecond: UnitProps('picosecond', 12, 'ps')
}