# Common

Dependency-free primitives every stage shares: config areas, tags, vectors, protocols, logging, progress and console formatting.

## femforge.common

Dependency-free primitives shared by every stage: config areas, tags, vectors, protocols, logging, progress UI, and console formatting.

Modules:

- **`cli`** –

  The failure every `femforge` subcommand raises, shared so a command module needs no import back into the entry point.
- **`config`** –

  The shared base of the config area models.
- **`files`** –

  The run-bundle filename vocabulary every writer and the retention sweep share, plus the file primitives they use.
- **`frame`** –

  The solve frame: how an authored model maps onto the frame Elmer solves in.
- **`introspect`** –

  Source-level reflection: the attribute docstrings an IDE shows on hover, read back at runtime.
- **`log`** –

  The only logging config site; every Rich output path (RichSink, StepTimer, tree prints) must share the one stderr Console from get\_console().
- **`names`** –

  Memorable bundle names derived deterministically from the content hash: `<adjective>-<noun>-<hash8>`.
- **`progress`** –

  Progress UI: live per-step elapsed-time rows rendered on the shared console.
- **`protocols`** –

  Structural typing contracts shared across pipeline stages.
- **`pydantic`** –

  Field-level `Annotated` markers read back by reflection: `Map()` ties a field to an external key name and `HashExclude()` keeps it out of a content hash.
- **`rich_sink`** –

  Rich-powered Loguru sink that renders each record as a fixed-column row via a Rich Console.
- **`tags`** –

  Tags: the shared key vocabulary, tagged objects and the grouping of tagged items into hierarchies.
- **`utils`** –

  Console formatting helpers: Rich color styles, Title Case labels and markup handling.
- **`vector`** –

  Small geometric value types: 2D and 3D vectors, unit directions, boxes, quaternions and coordinate frames.

Type Aliases:

- **`Levels`** –

  The tag keys to group by at each level, outermost first.
- **`Nested`** –

  A leaf `X` or a `TagGroup` of nested nodes.
- **`TagDict`** –

  Tag key=value pairs; a key is a `TagKey` or a user-defined name.

Classes:

- **`ConfigArea`** –

  Shared base for the config area models: `arbitrary_types_allowed` plus `use_attribute_docstrings`.
- **`StepTimer`** –

  Context manager showing a live elapsed-time line for one pipeline step.
- **`TimerRenderable`** –

  Live-updating timer row; Rich calls `__rich__` on every refresh tick.
- **`ElmerEmitter`** –

  Something that emits its own Elmer sif keywords; materials, conditions, and boundaries all satisfy it.
- **`MeshGroupSource`** –

  Something that resolves to one or more gmsh physical groups.
- **`Map`** –

  `Annotated` metadata marker tying a model field to an external key name.
- **`RichSink`** –

  Loguru sink callable; add with `format="{message}"` and `colorize=False` so Rich owns all styling.
- **`CurrentDir`** –

  Values of `TagKey.CURRENT_DIR`: whether an electrode part is a current entry or exit.
- **`HasTags`** –

  A mixin that holds an object's tag key=value pairs.
- **`TagGroup`** –

  A list of tagged items or nested groups that carries its own tags.
- **`TagGrouper`** –

  Groups tagged items into a `TagGroup` hierarchy, one level per list of tag keys.
- **`TagKey`** –

  The shared tag-key vocabulary: geometry authors these on parts, meshing/FEA select by them.
- **`COLORS`** –

  For use in rich console output. Not for physical materials.
- **`Box`** –

  An axis-aligned 3D box spanned by its min and max corners.
- **`CoordinateFrame`** –

  A position and orientation that maps local coordinates to global ones.
- **`Direction`** –

  A unit-length orientation, normalized and rounded on construction; arithmetic on it returns a plain Vec3.
- **`Quaternion`** –

  A rotation quaternion `w + xi + yj + zk`.
- **`Rect`** –

  An axis-aligned 2D rectangle spanned by its min and max corners.
- **`Vec2`** –

  A mutable 2D vector.
- **`Vec3`** –

  An immutable 3D vector; `==` and `hash` compare its exact components.

Functions:

- **`get_console`** –

  Return the process-wide stderr Console shared by logging and all progress/tree rendering.
- **`run_log_context`** –

  Bind `run_id` into the log context and write every record at DEBUG or above that carries it to `run_dir/run.log`.
- **`setup_logging`** –

  Install the terminal RichSink plus stdlib/warnings interception; repeat calls only adjust the sink level, library gates and telemetry root.
- **`fmt_time`** –

  Format a duration in seconds as `m:ss.s` or `s.s`, right-justified to `width`.
- **`get_map_key`** –

  The external key from a field's `Map()` metadata, or None if the field carries no `Map()`.
- **`mapped_items`** –

  Yield `(external_key, value)` for each field carrying a `Map()` whose current value is not None.
- **`map_group_leaves`** –

  Collapse each deepest bucket of sibling leaves (a list\[X\]) into one Y,
- **`map_leaves`** –

  Transform every leaf X -\> Y, keeping the hierarchy identical.
- **`parse_tags`** –

  The `key=value` pairs found in a label / STEP-name path; a repeated key keeps its last (deepest) value.
- **`contains_rich_markup`** –

  Whether `text` looks like it carries Rich markup.
- **`preserve_and_format`** –

  Preserves existing string formatting and applies a new style safely.
- **`title`** –

  A label or identifier in Title Case: underscores and camelCase humps become spaces, acronyms are capitalized, joining words stay lower case.

Attributes:

- **`DirectionField`** –

  A `Direction` pydantic field, normalized on load.
- **`Vec3Field`** –

  A `Vec3` pydantic field, loaded from a Vec3, `[x, y, z]` or `{x, y, z}`.

### DirectionField

```python
DirectionField = Direction
```

A `Direction` pydantic field, normalized on load.

### Vec3Field

```python
Vec3Field = Vec3
```

A `Vec3` pydantic field, loaded from a Vec3, `[x, y, z]` or `{x, y, z}`.

### Levels

```python
Levels = list[list[str]]
```

The tag keys to group by at each level, outermost first.

### Nested

```python
Nested = X | TagGroup[Nested[X]]
```

A leaf `X` or a `TagGroup` of nested nodes.

### TagDict

```python
TagDict = dict[TagKey | str, str]
```

Tag key=value pairs; a key is a `TagKey` or a user-defined name.

### ConfigArea

Bases: `BaseModel`

Shared base for the config area models: `arbitrary_types_allowed` plus `use_attribute_docstrings`.

### StepTimer

```python
StepTimer(title: str, msg: str = '', console: Console | None = None)
```

Bases: `Live`

Context manager showing a live elapsed-time line for one pipeline step.

Parameters:

- **`title`** (`str`) –

  The step name.
- **`msg`** (`str`, default: `''` ) –

  A status message shown after the step name.
- **`console`** (`Console | None`, default: `None` ) –

  The console to render on; None uses the shared one.

### TimerRenderable

```python
TimerRenderable(title: str, msg: str)
```

Bases: `RichCast`

Live-updating timer row; Rich calls `__rich__` on every refresh tick.

Methods:

- **`elapsed`** –

  Seconds since the timer started.
- **`elapsed_str`** –

  The elapsed time as `fmt_time` formats it.

#### elapsed

```python
elapsed() -> float
```

Seconds since the timer started.

#### elapsed\_str

```python
elapsed_str() -> str
```

The elapsed time as `fmt_time` formats it.

### ElmerEmitter

Bases: `Protocol`

Something that emits its own Elmer sif keywords; materials, conditions, and boundaries all satisfy it.

Methods:

- **`to_elmer`** –

  This object's Elmer sif keywords.

#### to\_elmer

```python
to_elmer(**ctx: object) -> dict[str, object]
```

This object's Elmer sif keywords.

### MeshGroupSource

Bases: `Protocol`

Something that resolves to one or more gmsh physical groups.

Methods:

- **`physical_group_name`** –

  The stable group name the Elmer side references the region by.

#### physical\_group\_name

```python
physical_group_name() -> str
```

The stable group name the Elmer side references the region by.

### Map

```python
Map(map: str)
```

`Annotated` metadata marker tying a model field to an external key name.

Example: `Annotated[bool, Map("Geometry.OCCImportLabels"), Field(...)]` -- the gmsh option name lives on the field.

### RichSink

```python
RichSink(console: Console | None = None, *, time_format: str = '%H:%M:%S.%f', show_path: bool = True, path_width: int = 0, rich_tracebacks: bool = True, show_locals: bool = False, markup: bool = False, hide_keys: frozenset[str] = frozenset())
```

Loguru sink callable; add with `format="{message}"` and `colorize=False` so Rich owns all styling.

Parameters:

- **`console`** (`Console | None`, default: `None` ) –

  The console to print to; None prints to a new stderr console.
- **`time_format`** (`str`, default: `'%H:%M:%S.%f'` ) –

  The `strftime` format of the time column.
- **`show_path`** (`bool`, default: `True` ) –

  Show the `module:function` column.
- **`path_width`** (`int`, default: `0` ) –

  Truncate the location column to this width, keeping its tail; 0 sizes it to its content.
- **`rich_tracebacks`** (`bool`, default: `True` ) –

  Render a logged exception as a Rich traceback.
- **`show_locals`** (`bool`, default: `False` ) –

  Include local variables in Rich tracebacks.
- **`markup`** (`bool`, default: `False` ) –

  Parse Rich markup in messages.
- **`hide_keys`** (`frozenset[str]`, default: `frozenset()` ) –

  The bound `extra` keys to leave out of the context column.

### CurrentDir

Bases: `StrEnum`

Values of `TagKey.CURRENT_DIR`: whether an electrode part is a current entry or exit.

Attributes:

- **`ENTRY`** –

  The electrode where current enters.
- **`EXIT`** –

  The electrode where current leaves.

#### ENTRY

```python
ENTRY = 'Entry'
```

The electrode where current enters.

#### EXIT

```python
EXIT = 'Exit'
```

The electrode where current leaves.

### HasTags

```python
HasTags(tags: TagDict | None = None)
```

A mixin that holds an object's tag key=value pairs.

Methods:

- **`set_tag`** –

  Set `key` to the cleaned `value`.
- **`add_tag`** –

  Set `key` to the cleaned `value`, like `set_tag`.
- **`get_tag`** –

  The value of `key`, or `default` when it is unset.
- **`get_tags`** –

  A copy of the tags, or of only `keys` with an unset key as an empty string.
- **`get_key_string`** –

  Return a string representation of the tags for the given keys.
- **`remove_tag`** –

  Drop `key` when it is set.
- **`clear_tags`** –

  Drop every tag.
- **`set_tags`** –

  Replace every tag with `tags`, each value cleaned.
- **`tags_str`** –

  The tags as comma-separated `key=value` pairs.

Attributes:

- **`current_tags`** (`TagDict`) –

  A copy of the tags.

#### current\_tags

```python
current_tags: TagDict
```

A copy of the tags.

#### set\_tag

```python
set_tag(key: str, value: str)
```

Set `key` to the cleaned `value`.

#### add\_tag

```python
add_tag(key: str, value: str)
```

Set `key` to the cleaned `value`, like `set_tag`.

#### get\_tag

```python
get_tag(key: str, default: str | None = None) -> str | None
```

The value of `key`, or `default` when it is unset.

#### get\_tags

```python
get_tags(keys: list[str] | None = None) -> TagDict
```

A copy of the tags, or of only `keys` with an unset key as an empty string.

#### get\_key\_string

```python
get_key_string(keys: list[str], default: str = 'default') -> str
```

Return a string representation of the tags for the given keys.

#### remove\_tag

```python
remove_tag(key: str)
```

Drop `key` when it is set.

#### clear\_tags

```python
clear_tags()
```

Drop every tag.

#### set\_tags

```python
set_tags(tags: TagDict)
```

Replace every tag with `tags`, each value cleaned.

#### tags\_str

```python
tags_str() -> str
```

The tags as comma-separated `key=value` pairs.

### TagGroup

```python
TagGroup(tags: TagDict, items: Iterable[T] = ())
```

Bases: `HasTags`, `list[T]`

A list of tagged items or nested groups that carries its own tags.

Methods:

- **`flatten`** –

  Roll the hierarchy up into a flat list of leaves, merging each path's tags onto the item (its own tags win only for keys the hierarchy doesn't set). Mutates `.tags` in place.
- **`tree`** –

  Return a tree representation of the tag group.

#### flatten

```python
flatten() -> list[X]
```

Roll the hierarchy up into a flat list of leaves, merging each path's tags onto the item (its own tags win only for keys the hierarchy doesn't set). Mutates `.tags` in place.

#### tree

```python
tree(parent: Tree | None = None) -> Tree
```

Return a tree representation of the tag group.

### TagGrouper

```python
TagGrouper(keys: list[str] | str | None = None, *, _levels: Levels | None = None)
```

Bases: `HasTags`

Groups tagged items into a `TagGroup` hierarchy, one level per list of tag keys.

Methods:

- **`then_by`** –

  A grouper with `keys` added as the next level.
- **`apply`** –

  Group items into a single root TagGroup (root has empty tags).
- **`map`** –

  Group `items` and transform each leaf with `fn`.
- **`map_groups`** –

  Group `items` and collapse each deepest bucket of leaves with `fn`.

#### then\_by

```python
then_by(keys: list[str] | str) -> TagGrouper
```

A grouper with `keys` added as the next level.

#### apply

```python
apply(items: list[X]) -> TagGroup[Nested[X]]
```

Group items into a single root TagGroup (root has empty tags).

#### map

```python
map(items: list[X], fn: Callable[[X], Y]) -> TagGroup[Nested[Y]]
```

Group `items` and transform each leaf with `fn`.

#### map\_groups

```python
map_groups(items: list[X], fn: Callable[[list[X]], Y]) -> TagGroup[Nested[Y]]
```

Group `items` and collapse each deepest bucket of leaves with `fn`.

### TagKey

Bases: `StrEnum`

The shared tag-key vocabulary: geometry authors these on parts, meshing/FEA select by them.

Attributes:

- **`MATERIAL`** –

  The registry tag of the body's material.
- **`PHASE`** –

  The winding phase a conductor belongs to.
- **`CURRENT_DIR`** –

  Whether an electrode is a current entry or exit, a `CurrentDir` value.
- **`SEGMENT`** –

  The winding segment a conductor belongs to.
- **`LAYER`** –

  The layer a conductor lies on, such as a PCB copper layer.
- **`TYPE`** –

  The kind of part, such as `Trace` or `Via`.
- **`MAGNETIZATION`** –

  A magnet's magnetization label, such as `N` or `S`.
- **`SLOT`** –

  The pole or slot position a part occupies.
- **`NAME`** –

  The authored part name; when set it is the body's name everywhere (mesh group, Elmer body, entities.json, viewer).

#### MATERIAL

```python
MATERIAL = 'Material'
```

The registry tag of the body's material.

#### PHASE

```python
PHASE = 'Phase'
```

The winding phase a conductor belongs to.

#### CURRENT\_DIR

```python
CURRENT_DIR = 'CurrentDir'
```

Whether an electrode is a current entry or exit, a `CurrentDir` value.

#### SEGMENT

```python
SEGMENT = 'Segment'
```

The winding segment a conductor belongs to.

#### LAYER

```python
LAYER = 'Layer'
```

The layer a conductor lies on, such as a PCB copper layer.

#### TYPE

```python
TYPE = 'Type'
```

The kind of part, such as `Trace` or `Via`.

#### MAGNETIZATION

```python
MAGNETIZATION = 'Magnetization'
```

A magnet's magnetization label, such as `N` or `S`.

#### SLOT

```python
SLOT = 'Slot'
```

The pole or slot position a part occupies.

#### NAME

```python
NAME = 'Name'
```

The authored part name; when set it is the body's name everywhere (mesh group, Elmer body, entities.json, viewer).

### COLORS

For use in rich console output. Not for physical materials.

Methods:

- **`gradient`** –

  Generate `steps` hex colors interpolating from `start_color` to `end_color`.
- **`Prop`** –

  Format a property name/value pair with colors for rich console output.
- **`PropName`** –

  A property name in the property-name style.
- **`PropValue`** –

  A property value in the property-value style.
- **`H1`** –

  A top-level heading.
- **`H2`** –

  A second-level heading.
- **`H3`** –

  A third-level heading.
- **`Units`** –

  A unit label in the units style.

#### gradient

```python
gradient(start_color: str, end_color: str, steps: int) -> list[str]
```

Generate `steps` hex colors interpolating from `start_color` to `end_color`.

Parameters:

- **`start_color`** (`str`) –

  The first color, as `#RRGGBB`.
- **`end_color`** (`str`) –

  The last color, as `#RRGGBB`.
- **`steps`** (`int`) –

  How many colors to generate.

#### Prop

```python
Prop(name: str, value: str) -> Text
```

Format a property name/value pair with colors for rich console output.

#### PropName

```python
PropName(name: str) -> Text
```

A property name in the property-name style.

#### PropValue

```python
PropValue(value: str) -> Text
```

A property value in the property-value style.

#### H1

```python
H1(text: str) -> Text
```

A top-level heading.

#### H2

```python
H2(text: str) -> Text
```

A second-level heading.

#### H3

```python
H3(text: str) -> Text
```

A third-level heading.

#### Units

```python
Units(text: str) -> Text
```

A unit label in the units style.

### Box

```python
Box(min: Vec3, max: Vec3)
```

An axis-aligned 3D box spanned by its min and max corners.

Attributes:

- **`center`** (`Vec3`) –

  The midpoint; setting it moves the box.
- **`size`** (`Vec3`) –

  The edge lengths; setting them resizes the box about its center.

#### center

```python
center: Vec3
```

The midpoint; setting it moves the box.

#### size

```python
size: Vec3
```

The edge lengths; setting them resizes the box about its center.

### CoordinateFrame

```python
CoordinateFrame(origin: Vec3, orientation: Quaternion)
```

A position and orientation that maps local coordinates to global ones.

Methods:

- **`transform_position`** –

  Transform a position from local to global coordinates
- **`inverse_transform_position`** –

  Transform a position from global to local coordinates
- **`transform_direction`** –

  Transform a direction vector (ignoring translation) from local to global coordinates
- **`inverse_transform_direction`** –

  Transform a direction vector (ignoring translation) from global to local coordinates
- **`__mul__`** –

  Combine two coordinate frames by applying this transformation followed by the other
- **`__rmul__`** –

  Allow left multiplication to combine coordinate frames
- **`__imul__`** –

  In-place combination of coordinate frames

#### transform\_position

```python
transform_position(position: Vec3) -> Vec3
```

Transform a position from local to global coordinates

#### inverse\_transform\_position

```python
inverse_transform_position(position: Vec3) -> Vec3
```

Transform a position from global to local coordinates

#### transform\_direction

```python
transform_direction(direction: Vec3) -> Vec3
```

Transform a direction vector (ignoring translation) from local to global coordinates

#### inverse\_transform\_direction

```python
inverse_transform_direction(direction: Vec3) -> Vec3
```

Transform a direction vector (ignoring translation) from global to local coordinates

#### \_\_mul\_\_

```python
__mul__(other: CoordinateFrame) -> CoordinateFrame
```

Combine two coordinate frames by applying this transformation followed by the other

#### \_\_rmul\_\_

```python
__rmul__(other: CoordinateFrame) -> CoordinateFrame
```

Allow left multiplication to combine coordinate frames

#### \_\_imul\_\_

```python
__imul__(other: CoordinateFrame) -> CoordinateFrame
```

In-place combination of coordinate frames

### Direction

```python
Direction(x: float, y: float, z: float)
```

Bases: `Vec3`

A unit-length orientation, normalized and rounded on construction; arithmetic on it returns a plain Vec3.

Parameters:

- **`x`** (`float`) –

  The x component of any non-zero vector along the direction.
- **`y`** (`float`) –

  The y component.
- **`z`** (`float`) –

  The z component.

### Quaternion

```python
Quaternion(w: float, x: float, y: float, z: float)
```

A rotation quaternion `w + xi + yj + zk`.

Parameters:

- **`w`** (`float`) –

  The scalar part.
- **`x`** (`float`) –

  The i component.
- **`y`** (`float`) –

  The j component.
- **`z`** (`float`) –

  The k component.

Methods:

- **`__mul__`** –

  Hamilton product of two quaternions
- **`conjugate`** –

  Conjugate of the quaternion
- **`magnitude`** –

  The Euclidean norm of the quaternion.
- **`normalized`** –

  The unit quaternion with the same orientation; raises `ValueError` for a zero quaternion.
- **`rotate_vector`** –

  Rotate a vector by this quaternion
- **`to_rotation_matrix`** –

  Convert the quaternion to a 3x3 rotation matrix
- **`to_euler_angles`** –

  Convert the quaternion to Euler angles (yaw, pitch, roll) in degrees
- **`from_euler_angles`** –

  Create a quaternion from Euler angles in degrees.
- **`from_axis_angle`** –

  Create a quaternion from an axis and angle in degrees
- **`slerp`** –

  Spherical linear interpolation between two quaternions.

#### \_\_mul\_\_

```python
__mul__(other: Quaternion) -> Quaternion
```

Hamilton product of two quaternions

#### conjugate

```python
conjugate() -> Quaternion
```

Conjugate of the quaternion

#### magnitude

```python
magnitude() -> float
```

The Euclidean norm of the quaternion.

#### normalized

```python
normalized() -> Quaternion
```

The unit quaternion with the same orientation; raises `ValueError` for a zero quaternion.

#### rotate\_vector

```python
rotate_vector(vec: Vec3) -> Vec3
```

Rotate a vector by this quaternion

#### to\_rotation\_matrix

```python
to_rotation_matrix() -> list[list[float]]
```

Convert the quaternion to a 3x3 rotation matrix

#### to\_euler\_angles

```python
to_euler_angles() -> tuple[float, float, float]
```

Convert the quaternion to Euler angles (yaw, pitch, roll) in degrees

#### from\_euler\_angles

```python
from_euler_angles(yaw: float, pitch: float, roll: float)
```

Create a quaternion from Euler angles in degrees.

Parameters:

- **`yaw`** (`float`) –

  The rotation about Z, in degrees.
- **`pitch`** (`float`) –

  The rotation about Y, in degrees.
- **`roll`** (`float`) –

  The rotation about X, in degrees.

#### from\_axis\_angle

```python
from_axis_angle(axis: Vec3, angle_degrees: float) -> Quaternion
```

Create a quaternion from an axis and angle in degrees

#### slerp

```python
slerp(q1: Quaternion, q2: Quaternion, t: float) -> Quaternion
```

Spherical linear interpolation between two quaternions.

Parameters:

- **`q1`** (`Quaternion`) –

  The orientation at `t = 0`.
- **`q2`** (`Quaternion`) –

  The orientation at `t = 1`.
- **`t`** (`float`) –

  The interpolation fraction.

### Rect

```python
Rect(min: Vec2, max: Vec2)
```

An axis-aligned 2D rectangle spanned by its min and max corners.

Attributes:

- **`center`** (`Vec2`) –

  The midpoint; setting it moves the rectangle.
- **`size`** (`Vec2`) –

  The width and height; setting them resizes the rectangle about its center.

#### center

```python
center: Vec2
```

The midpoint; setting it moves the rectangle.

#### size

```python
size: Vec2
```

The width and height; setting them resizes the rectangle about its center.

### Vec2

```python
Vec2(x: float, y: float)
```

A mutable 2D vector.

Methods:

- **`rotate`** –

  Rotate the vector by a given angle in degrees around a center point
- **`magnitude`** –

  Euclidean length of the vector.
- **`to_list`** –

  The components as `[x, y]`.
- **`to_tuple`** –

  The components as `(x, y)`.

#### rotate

```python
rotate(angle: float, center: Vec2 | None = None) -> Vec2
```

Rotate the vector by a given angle in degrees around a center point

#### magnitude

```python
magnitude() -> float
```

Euclidean length of the vector.

#### to\_list

```python
to_list() -> list[float]
```

The components as `[x, y]`.

#### to\_tuple

```python
to_tuple() -> tuple[float, float]
```

The components as `(x, y)`.

### Vec3

```python
Vec3(x: float, y: float, z: float)
```

An immutable 3D vector; `==` and `hash` compare its exact components.

Methods:

- **`isclose`** –

  Whether every component matches `other` within `tolerance`, relative or absolute.
- **`magnitude`** –

  Euclidean length |v| of the vector.
- **`dot`** –

  The scalar product with `other`.
- **`normalized`** –

  A unit vector in the same direction; raises `ValueError` for a zero-length vector.
- **`to_list`** –

  The components as `[x, y, z]`.
- **`to_tuple`** –

  The components as `(x, y, z)`.

Attributes:

- **`x`** (`float`) –

  `x` `[?]`: The x component.
- **`y`** (`float`) –

  `y` `[?]`: The y component.
- **`z`** (`float`) –

  `z` `[?]`: The z component.

#### x

```python
x: float
```

`x` `[?]`: The x component.

#### y

```python
y: float
```

`y` `[?]`: The y component.

#### z

```python
z: float
```

`z` `[?]`: The z component.

#### isclose

```python
isclose(other: Vec3, tolerance: float = 1e-09) -> bool
```

Whether every component matches `other` within `tolerance`, relative or absolute.

#### magnitude

```python
magnitude() -> float
```

Euclidean length |v| of the vector.

#### dot

```python
dot(other: Vec3) -> float
```

The scalar product with `other`.

#### normalized

```python
normalized() -> Vec3
```

A unit vector in the same direction; raises `ValueError` for a zero-length vector.

#### to\_list

```python
to_list() -> list[float]
```

The components as `[x, y, z]`.

#### to\_tuple

```python
to_tuple() -> tuple[float, float, float]
```

The components as `(x, y, z)`.

### get\_console

```python
get_console() -> Console
```

Return the process-wide stderr Console shared by logging and all progress/tree rendering.

### run\_log\_context

```python
run_log_context(run_id: str, run_dir: Path) -> Iterator[None]
```

Bind `run_id` into the log context and write every record at DEBUG or above that carries it to `run_dir/run.log`.

### setup\_logging

```python
setup_logging(*, level: LogLevel | str | None = None, console: Console | None = None, library_levels: Mapping[str, LogLevel | str] | None = None, telemetry: Path | None = None, process: str | None = None) -> None
```

Install the terminal RichSink plus stdlib/warnings interception; repeat calls only adjust the sink level, library gates and telemetry root.

Parameters:

- **`level`** (`LogLevel | str | None`, default: `None` ) –

  Terminal sink threshold; `None` falls back to the `FEMFORGE_LOG_LEVEL` env var, then `INFO`.
- **`console`** (`Console | None`, default: `None` ) –

  Console the sink renders into; `None` uses the shared stderr console from `get_console()`.
- **`library_levels`** (`Mapping[str, LogLevel | str] | None`, default: `None` ) –

  Stdlib logger name to minimum level, gating chatty libraries at the source; `None` applies `DEFAULT_LIBRARY_LEVELS`.
- **`telemetry`** (`Path | None`, default: `None` ) –

  Telemetry root the parquet sink writes to; `None` falls back to `FEMFORGE_TELEMETRY`, and telemetry stays off when that is unset too.
- **`process`** (`str | None`, default: `None` ) –

  Name the telemetry rows are partitioned under; `None` uses the sanitized `sys.argv[0]` stem.

### fmt\_time

```python
fmt_time(seconds: float, width: int = 6) -> str
```

Format a duration in seconds as `m:ss.s` or `s.s`, right-justified to `width`.

### get\_map\_key

```python
get_map_key(field: FieldInfo) -> str | None
```

The external key from a field's `Map()` metadata, or None if the field carries no `Map()`.

### mapped\_items

```python
mapped_items(model: BaseModel) -> Iterator[tuple[str, object]]
```

Yield `(external_key, value)` for each field carrying a `Map()` whose current value is not None.

### map\_group\_leaves

```python
map_group_leaves(root: TagGroup[Nested[X]], fn: Callable[[list[X]], Y]) -> TagGroup[Nested[Y]]
```

Collapse each deepest bucket of sibling leaves (a list\[X\]) into one Y, keeping its enclosing group and tags.

### map\_leaves

```python
map_leaves(root: TagGroup[Nested[X]], fn: Callable[[X], Y]) -> TagGroup[Nested[Y]]
```

Transform every leaf X -\> Y, keeping the hierarchy identical.

### parse\_tags

```python
parse_tags(text: str) -> TagDict
```

The `key=value` pairs found in a label / STEP-name path; a repeated key keeps its last (deepest) value.

### contains\_rich\_markup

```python
contains_rich_markup(text: str) -> bool
```

Whether `text` looks like it carries Rich markup.

### preserve\_and\_format

```python
preserve_and_format(content: object, new_style: str = 'bold') -> Text
```

Preserves existing string formatting and applies a new style safely.

### title

```python
title(value: str) -> str
```

A label or identifier in Title Case: underscores and camelCase humps become spaces, acronyms are capitalized, joining words stay lower case.
