from __future__ import annotations
import ase
import sqlalchemy as sa
from sqlalchemy.orm import Mapped, mapped_column, relationship
from asedb.abstract import Base
from asedb.atoms_model import CASCADE_DELETE_ALL, AtomsModel
atoms_trajectory_mapping = sa.Table(
"atoms_trajectory_mapping",
Base.metadata,
sa.Column("atoms_id", sa.Integer, sa.ForeignKey("atoms.id")),
sa.Column("trajectory_id", sa.Integer, sa.ForeignKey("trajectory.id")),
sa.UniqueConstraint("trajectory_id", "atoms_id"),
)
[docs]
class Trajectory(Base):
__tablename__ = "trajectory"
id: Mapped[int] = mapped_column(primary_key=True)
project: Mapped[str] = mapped_column(nullable=True, index=True)
atoms_list: Mapped[list[AtomsModel]] = relationship(
secondary=atoms_trajectory_mapping,
cascade=CASCADE_DELETE_ALL,
single_parent=True, # 1 atoms object can only belong to 1 trajectory. TODO: Is this what we want?
)
[docs]
def add_atoms(self, atoms: ase.Atoms) -> AtomsModel:
"""Add an Atoms object to the Trajectory.
Returns the newly created AtomsModel instance, which belongs to the trajectory.
"""
model = AtomsModel.from_atoms(atoms)
self.atoms_list.append(model)
return model
[docs]
def to_atoms_list(self) -> list[ase.Atoms]:
return [model.to_atoms() for model in self.atoms_list]