Skip to content

[Feature] Simplify displace_along_soft_modes to return a single structure #27

Description

@jarinfrench

What would you like GBOpt to do?

GBManipulator.displace_along_soft_modes() should return a single np.ndarray of atom positions and expose a mode_index parameter so callers can choose which soft phonon mode to displace along.

Environment

  • GBOpt version: 0.0.1
  • Python version: 3.12.11
  • OS / platform: Mac OSX 26.4

Which part of the pipeline does this affect?

  • GBManipulator — atom translations, insertions/deletions, soft-mode displacements, file I/O

Motivation

Usability friction: displace_along_soft_modes() currently always returns a list[np.ndarray] — even when using the default num_children=1. Callers who treat the result as a single structured array (e.g., result["name"]) get a TypeError: list indices must be integers or slices, not str. The num_children parameter is the source of this mismatch: generating multiple children in a single call is better handled by the caller in a loop, since each call already involves significant computation (Delaunay triangulation, dynamical matrix calculation).

Additionally, GBOpt currently provides no way to displace along anything other than the softest mode. Exposing a mode_index parameter would allow callers to explore a range of soft modes without rewriting the internals.

Proposed behavior

# Default: displace along the softest mode, return one structure
displaced = manipulator.displace_along_soft_modes()
displaced["name"]   # np.ndarray — no [0] indexing needed

# Select the second-softest mode
displaced = manipulator.displace_along_soft_modes(mode_index=1)

# Caller-controlled multi-child loop
children = [
    manipulator.displace_along_soft_modes(mode_index=i)
    for i in range(3)
]

Acceptance criteria

  • displace_along_soft_modes() returns np.ndarray, not list[np.ndarray]
  • num_children parameter is removed
  • mode_index: int = 0 parameter is added; 0 selects the softest
    mode, 1 the second-softest, etc.
  • A GBManipulatorValueError is raised if mode_index is out of
    range for the number of soft modes found
  • test_type_preservation_with_numeric_roundtrip passes without
    [0] indexing on the result
  • test_displace_along_soft_modes_base and test_displace_along_soft_modes_with_displacement_threshold
    updated to match the new return type

API / breaking-change impact

  • Breaking change — removes the num_children parameter and changes the return type from list[np.ndarray] to np.ndarray. Any caller using num_children > 1 or indexing the result with [0] must be updated.

Alternatives considered

  • Always return a list, fix the test — consistent return type but forces result[0] for the common single-structure case.
  • Squeeze based on num_children — returns a single array when num_children=1, list otherwise; inconsistent return type makes type hints and callers harder to reason about.
  • Add a squeeze parameter — explicit but adds API surface for a distinction that disappears once num_children is removed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions