Skip to content

Conversation

@EZoni
Copy link
Member

@EZoni EZoni commented Jul 23, 2025

Overview

With the implementation in the main branch, if we add a name attribute to the line object created in the FODO example, the attribute is ignored and the output is

kind: Line
line:
- drift1:
    kind: Drift
    length: 0.25
- quad1:
    MagneticMultipoleP:
      Bn1: 1.0
    kind: Quadrupole
    length: 1.0
- drift2:
    kind: Drift
    length: 0.5
- quad2:
    MagneticMultipoleP:
      Bn1: -1.0
    kind: Quadrupole
    length: 1.0
- drift3:
    kind: Drift
    length: 0.5

This is not consistent with the example in https://github.com/campa-consortium/pals/blob/main/examples/fodo.pals.yaml.

With the implementation in this branch, if we add a name attribute to the line object created in the FODO example, the attribute is stored and the output is

fodo_cell:
  kind: BeamLine
  line:
  - drift1:
      kind: Drift
      length: 0.25
  - quad1:
      MagneticMultipoleP:
        Bn1: 1.0
      kind: Quadrupole
      length: 1.0
  - drift2:
      kind: Drift
      length: 0.5
  - quad2:
      MagneticMultipoleP:
        Bn1: -1.0
      kind: Quadrupole
      length: 1.0
  - drift3:
      kind: Drift
      length: 0.5

which is consistent with the example in https://github.com/campa-consortium/pals/blob/main/examples/fodo.pals.yaml.

This is achieved primarily by deriving the Line (BeamLine after #15) class from the base element class BaseElement instead of deriving it from Pydantic's base model class BaseModel.

I also merged the custom field validation of the line field with the custom model validation, since we needed one anyways to fix the deserialization. I don't see why they should be separate.

I wonder if the right way to do this is using @model_serializer instead of @model_validator...

To do

  • Serialization (fixed with c391e43, very few lines changed)
  • Deserialization (fixed with the custom model validator, many more lines changed)
  • Cleaning

@EZoni EZoni changed the title Fix (Beam)Line name attribute [WIP] Fix (Beam)Line name attribute Jul 23, 2025
examples/fodo.py Outdated
yaml_data = yaml.safe_load(file)
# Parse YAML data
loaded_line = Line(**yaml_data)
loaded_line = Line(**yaml_data[0])
Copy link
Member Author

@EZoni EZoni Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yaml_data was a dictionary before, now it's a one-element list. Keeping the previous API for the Line constructor requires more work, which could be done in this PR or in a separate PR. I have not tried it yet (i.e., I don't know yet if I can find a way to make it work).

@EZoni EZoni changed the title [WIP] Fix (Beam)Line name attribute Fix (Beam)Line name attribute Jul 23, 2025
@EZoni EZoni mentioned this pull request Jul 24, 2025
@EZoni EZoni requested a review from ax3l July 24, 2025 00:12
@ax3l
Copy link
Member

ax3l commented Aug 7, 2025

@EZoni does this need a rebase?

@EZoni
Copy link
Member Author

EZoni commented Aug 7, 2025

Probably yes, after the last few commits in main. I will get to it asap.

@EZoni
Copy link
Member Author

EZoni commented Aug 7, 2025

@ax3l

Conflicts fixed.

@ax3l ax3l self-assigned this Aug 18, 2025
examples/fodo.py Outdated
yaml_data = yaml.safe_load(file)
# Parse YAML data
loaded_line = BeamLine(**yaml_data)
loaded_line = BeamLine(**yaml_data[0])
Copy link
Member

@ax3l ax3l Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me think, also for our current layout/draft:

  • should a PALS file support having multiple beamlines (segments: yes)?
  • if not, which one is the "entry point" to use by default? The 0-th element might be a lattice element and not a kind: BeamLine once we support inheritance

Ignoring the entry point question, we might need a "wrapping" LatticeElements class here in Python that can load a list of elements (instead of only loading [0] and assuming it is of kind BeamLine)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a change in 464020d to return a dict instead of a single-element list.

I cannot remember where the single-element list came from, but the new change seems to avoid the API issue. Am I overlooking something?

I'm not sure I understand what the LatticeElements class should be, but maybe it could be done in a separate PR, unless it turns out that it's necessary here.

Copy link
Member Author

@EZoni EZoni Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the problem was with the serialization of single elements, maybe it should be fixed separately as well.

@EZoni EZoni changed the title Fix (Beam)Line name attribute Fix BeamLine name attribute Oct 3, 2025
@ax3l
Copy link
Member

ax3l commented Oct 15, 2025

From the PR description:

I wonder if the right way to do this is using @model_serializer instead of @model_validator...

This is what I found:

The pydantic serializer is how we go from pydantic classes to dicts / json and back. This is needed when we want to rename fields or do custom conversions that are serialized slightly different than the internal representation. It looks to me like this is primarily for output formatting changes, not input.

The pydantic validator is used for custom validation logic, e.g., when someone sets a field/value/property, and can optionally modify values. But it seems this is also used for input changes...

Copy link
Member

@ax3l ax3l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent, thank you!

@ax3l ax3l added bug Something isn't working breaking and removed bug Something isn't working labels Oct 15, 2025
@ax3l ax3l merged commit 0bc4878 into pals-project:main Oct 15, 2025
11 checks passed
@EZoni EZoni deleted the beamline_name branch October 15, 2025 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants