Skip to content

glazing.framenet.models

FrameNet core data models.

models

FrameNet core data models.

This module implements the core FrameNet data models including Frame, FrameElement, and supporting models for annotated text processing. Models use Pydantic v2 for validation and support JSON Lines serialization.

CLASS DESCRIPTION
TextAnnotation

Represents an annotation span within text.

AnnotatedText

Text with embedded markup for frame elements and references.

Frame

A FrameNet frame representing a schematic situation.

FrameElement

A participant or prop in a frame.

FrameRelation

Relationship between frames.

FERelation

FE mapping between related frames.

SemanticType

Semantic type in the FrameNet type system.

FrameIndexEntry

Entry in the frame index file.

Examples:

>>> from glazing.framenet.models import Frame, FrameElement
>>> frame = Frame(
...     id=2031,
...     name="Abandonment",
...     definition=AnnotatedText.parse("An <fex>Agent</fex> leaves behind a <fex>Theme</fex>"),
...     frame_elements=[]
... )
>>> print(frame.definition.plain_text)
'An Agent leaves behind a Theme'

Classes

AnnotatedText pydantic-model

Bases: GlazingBaseModel

Text with embedded markup for frame elements and other references.

This model parses FrameNet's embedded markup in definitions, extracting annotations like Agent, Theme, etc.

ATTRIBUTE DESCRIPTION
raw_text

Original text with markup.

TYPE: str

plain_text

Text with markup removed.

TYPE: str

annotations

List of annotations found in the text.

TYPE: list[TextAnnotation]

METHOD DESCRIPTION
parse

Parse text with markup and create AnnotatedText instance.

get_annotations_by_type

Get all annotations of a specific type.

get_fe_references

Get all frame element references.

get_targets

Get all target annotations.

Examples:

>>> text = "An <fex>Agent</fex> leaves behind a <fex name='Theme'>thing</fex>"
>>> annotated = AnnotatedText.parse(text)
>>> print(annotated.plain_text)
'An Agent leaves behind a thing'
>>> print(len(annotated.annotations))
2

Fields:

Attributes
annotations: list[TextAnnotation] pydantic-field

Annotations found in text

plain_text: str pydantic-field

Text with markup removed

raw_text: str pydantic-field

Original text with markup

Functions
get_annotations_by_type(markup_type: MarkupType) -> list[TextAnnotation]

Get all annotations of a specific type.

PARAMETER DESCRIPTION
markup_type

The type of annotations to retrieve.

TYPE: MarkupType

RETURNS DESCRIPTION
list[TextAnnotation]

List of annotations of the specified type.

Source code in src/glazing/framenet/models.py
def get_annotations_by_type(self, markup_type: MarkupType) -> list[TextAnnotation]:
    """Get all annotations of a specific type.

    Parameters
    ----------
    markup_type : MarkupType
        The type of annotations to retrieve.

    Returns
    -------
    list[TextAnnotation]
        List of annotations of the specified type.
    """
    return [ann for ann in self.annotations if ann.type == markup_type]
get_fe_references() -> list[TextAnnotation]

Get all frame element references.

RETURNS DESCRIPTION
list[TextAnnotation]

List of fex and fen annotations.

Source code in src/glazing/framenet/models.py
def get_fe_references(self) -> list[TextAnnotation]:
    """Get all frame element references.

    Returns
    -------
    list[TextAnnotation]
        List of fex and fen annotations.
    """
    return [ann for ann in self.annotations if ann.type in ("fex", "fen")]
get_targets() -> list[TextAnnotation]

Get all target annotations.

RETURNS DESCRIPTION
list[TextAnnotation]

List of target annotations.

Source code in src/glazing/framenet/models.py
def get_targets(self) -> list[TextAnnotation]:
    """Get all target annotations.

    Returns
    -------
    list[TextAnnotation]
        List of target annotations.
    """
    return self.get_annotations_by_type("t")
parse(text: str) -> Self classmethod

Parse text with embedded markup.

Extracts FrameNet markup tags like: - Agent - Frame element example - Theme - Frame element name - abandon - Target word - example - Example text

PARAMETER DESCRIPTION
text

Text containing markup.

TYPE: str

RETURNS DESCRIPTION
Self

Parsed AnnotatedText instance.

Examples:

>>> text = "The <fex>Agent</fex> leaves the <fex name='Theme'>car</fex>"
>>> parsed = AnnotatedText.parse(text)
>>> print(parsed.plain_text)
'The Agent leaves the car'
Source code in src/glazing/framenet/models.py
@classmethod
def parse(cls, text: str) -> Self:
    """Parse text with embedded markup.

    Extracts FrameNet markup tags like:
    - <fex>Agent</fex> - Frame element example
    - <fen>Theme</fen> - Frame element name
    - <t>abandon</t> - Target word
    - <ex>example</ex> - Example text

    Parameters
    ----------
    text : str
        Text containing markup.

    Returns
    -------
    Self
        Parsed AnnotatedText instance.

    Examples
    --------
    >>> text = "The <fex>Agent</fex> leaves the <fex name='Theme'>car</fex>"
    >>> parsed = AnnotatedText.parse(text)
    >>> print(parsed.plain_text)
    'The Agent leaves the car'
    """
    if not text:
        return cls(raw_text=text, plain_text=text, annotations=[])

    annotations: list[TextAnnotation] = []
    plain_text = ""
    offset = 0

    # Pattern to match markup tags with optional attributes
    pattern = r"<(\w+)(?:\s+([^>]*))?>([^<]*?)</\1>"

    for match in re.finditer(pattern, text):
        tag_name = match.group(1)
        attributes = match.group(2) or ""
        content = match.group(3)

        # Add text before this tag to plain text
        before_tag = text[offset : match.start()]
        plain_text += before_tag
        start_pos = len(plain_text)

        # Add the content to plain text
        plain_text += content
        end_pos = len(plain_text)

        # Parse attributes for name and ref_id
        name = None
        ref_id = None

        if attributes:
            # Simple attribute parsing - look for name="value" or name=value
            name_match = re.search(r'name=["\']?([^"\'\s>]+)["\']?', attributes)
            if name_match:
                name = name_match.group(1)

            ref_match = re.search(r'ref(?:_?id)?=["\']?(\d+)["\']?', attributes)
            if ref_match:
                ref_id = int(ref_match.group(1))

        # For fex and fen tags, if no explicit name is provided, use the content as the name
        if tag_name in ("fex", "fen") and name is None:
            name = content

        # Create annotation
        if tag_name in ("fex", "fen", "t", "ex", "m", "gov", "x", "def-root"):
            annotation = TextAnnotation(
                start=start_pos,
                end=end_pos,
                type=tag_name,  # type: ignore[arg-type]
                name=name,
                ref_id=ref_id,
                text=content,
            )
            annotations.append(annotation)

        offset = match.end()

    # Add any remaining text
    if offset < len(text):
        plain_text += text[offset:]

    return cls(
        raw_text=text,
        plain_text=plain_text,
        annotations=annotations,
    )

AnnotationLayer pydantic-model

Bases: GlazingBaseModel

A layer of annotation (FE, GF, PT, Target, etc.).

ATTRIBUTE DESCRIPTION
name

Layer type name.

TYPE: LayerType

rank

Layer rank/priority.

TYPE: int, default=1

labels

Labels in this layer.

TYPE: list[Label]

METHOD DESCRIPTION
get_labels_by_name

Get all labels with a specific name.

has_overlapping_labels

Check if any labels in this layer overlap.

get_label_count

Get the number of labels in this layer.

Examples:

>>> layer = AnnotationLayer(name="FE", labels=[...])
>>> print(layer.get_label_count())
3

Fields:

Attributes
labels: list[Label] pydantic-field

Labels in this layer

name: LayerType pydantic-field

Layer type name

rank: int = 1 pydantic-field

Layer rank/priority

Functions
get_label_count() -> int

Get the number of labels in this layer.

RETURNS DESCRIPTION
int

Number of labels.

Source code in src/glazing/framenet/models.py
def get_label_count(self) -> int:
    """Get the number of labels in this layer.

    Returns
    -------
    int
        Number of labels.
    """
    return len(self.labels)
get_labels_by_name(name: str) -> list[Label]

Get all labels with a specific name.

PARAMETER DESCRIPTION
name

The label name to search for.

TYPE: str

RETURNS DESCRIPTION
list[Label]

List of matching labels.

Source code in src/glazing/framenet/models.py
def get_labels_by_name(self, name: str) -> list[Label]:
    """Get all labels with a specific name.

    Parameters
    ----------
    name : str
        The label name to search for.

    Returns
    -------
    list[Label]
        List of matching labels.
    """
    return [label for label in self.labels if label.name == name]
has_overlapping_labels() -> bool

Check if any labels in this layer overlap.

RETURNS DESCRIPTION
bool

True if any labels overlap.

Source code in src/glazing/framenet/models.py
def has_overlapping_labels(self) -> bool:
    """Check if any labels in this layer overlap.

    Returns
    -------
    bool
        True if any labels overlap.
    """
    for i, label1 in enumerate(self.labels):
        for label2 in self.labels[i + 1 :]:
            if label1.overlaps_with(label2):
                return True
    return False

AnnotationSet pydantic-model

Bases: GlazingBaseModel

A set of annotations on a sentence.

ATTRIBUTE DESCRIPTION
id

Annotation set identifier.

TYPE: AnnotationSetID

status

Annotation completion status.

TYPE: AnnotationStatus

sentence_id

ID of the annotated sentence.

TYPE: SentenceID

layers

Annotation layers in this set.

TYPE: list[AnnotationLayer]

created_by

Creator username.

TYPE: Username | None, default=None

created_date

Creation timestamp.

TYPE: datetime | None, default=None

METHOD DESCRIPTION
get_layer_by_name

Get annotation layer by name.

get_fe_layer

Get the frame element layer.

get_target_layer

Get the target layer.

has_layer

Check if a specific layer exists.

Examples:

>>> anno_set = AnnotationSet(
...     id=123,
...     status="MANUAL",
...     sentence_id=456,
...     layers=[...]
... )

Fields:

Validators:

Attributes
created_by: Username | None = None pydantic-field

Creator username

created_date: datetime | None = None pydantic-field

Creation timestamp

id: AnnotationSetID pydantic-field

Annotation set identifier

layers: list[AnnotationLayer] pydantic-field

Annotation layers

sentence_id: SentenceID pydantic-field

ID of the annotated sentence

status: AnnotationStatus pydantic-field

Annotation completion status

Functions
get_fe_layer() -> AnnotationLayer | None

Get the frame element layer.

RETURNS DESCRIPTION
AnnotationLayer | None

The FE layer, or None if not found.

Source code in src/glazing/framenet/models.py
def get_fe_layer(self) -> AnnotationLayer | None:
    """Get the frame element layer.

    Returns
    -------
    AnnotationLayer | None
        The FE layer, or None if not found.
    """
    return self.get_layer_by_name("FE")
get_layer_by_name(name: LayerType) -> AnnotationLayer | None

Get annotation layer by name.

PARAMETER DESCRIPTION
name

The layer name to find.

TYPE: LayerType

RETURNS DESCRIPTION
AnnotationLayer | None

The layer, or None if not found.

Source code in src/glazing/framenet/models.py
def get_layer_by_name(self, name: LayerType) -> AnnotationLayer | None:
    """Get annotation layer by name.

    Parameters
    ----------
    name : LayerType
        The layer name to find.

    Returns
    -------
    AnnotationLayer | None
        The layer, or None if not found.
    """
    for layer in self.layers:
        if layer.name == name:
            return layer
    return None
get_target_layer() -> AnnotationLayer | None

Get the target layer.

RETURNS DESCRIPTION
AnnotationLayer | None

The Target layer, or None if not found.

Source code in src/glazing/framenet/models.py
def get_target_layer(self) -> AnnotationLayer | None:
    """Get the target layer.

    Returns
    -------
    AnnotationLayer | None
        The Target layer, or None if not found.
    """
    return self.get_layer_by_name("Target")
has_layer(layer_name: LayerType) -> bool

Check if a specific layer exists.

PARAMETER DESCRIPTION
layer_name

The layer name to check.

TYPE: LayerType

RETURNS DESCRIPTION
bool

True if the layer exists.

Source code in src/glazing/framenet/models.py
def has_layer(self, layer_name: LayerType) -> bool:
    """Check if a specific layer exists.

    Parameters
    ----------
    layer_name : LayerType
        The layer name to check.

    Returns
    -------
    bool
        True if the layer exists.
    """
    return self.get_layer_by_name(layer_name) is not None
validate_created_by(v: str | None) -> str | None pydantic-validator

Validate creator username format.

Source code in src/glazing/framenet/models.py
@field_validator("created_by")
@classmethod
def validate_created_by(cls, v: str | None) -> str | None:
    """Validate creator username format."""
    if v is not None:
        return validate_pattern(v, USERNAME_PATTERN, "username")
    return v

FEGroupRealization pydantic-model

Bases: GlazingBaseModel

Realization of grouped FEs in a pattern.

ATTRIBUTE DESCRIPTION
fe_names

Frame element names in this group.

TYPE: list[str]

grammatical_function

Grammatical function for the group.

TYPE: GrammaticalFunction

phrase_type

Phrase type for the group.

TYPE: PhraseType

METHOD DESCRIPTION
contains_fe

Check if group contains a specific FE.

get_fe_count

Get number of FEs in group.

Examples:

>>> group = FEGroupRealization(
...     fe_names=["Agent", "Theme"],
...     grammatical_function="Ext",
...     phrase_type="NP"
... )

Fields:

Validators:

Attributes
fe_names: list[str] pydantic-field

FE names in group

grammatical_function: GrammaticalFunction pydantic-field

Grammatical function

phrase_type: PhraseType pydantic-field

Phrase type

Functions
contains_fe(fe_name: str) -> bool

Check if group contains a specific FE.

PARAMETER DESCRIPTION
fe_name

FE name to check.

TYPE: str

RETURNS DESCRIPTION
bool

True if FE is in this group.

Source code in src/glazing/framenet/models.py
def contains_fe(self, fe_name: str) -> bool:
    """Check if group contains a specific FE.

    Parameters
    ----------
    fe_name : str
        FE name to check.

    Returns
    -------
    bool
        True if FE is in this group.
    """
    return fe_name in self.fe_names
get_fe_count() -> int

Get number of FEs in group.

RETURNS DESCRIPTION
int

Number of FEs.

Source code in src/glazing/framenet/models.py
def get_fe_count(self) -> int:
    """Get number of FEs in group.

    Returns
    -------
    int
        Number of FEs.
    """
    return len(self.fe_names)
validate_fe_names(v: list[str]) -> list[str] pydantic-validator

Validate FE names in group.

Source code in src/glazing/framenet/models.py
@field_validator("fe_names")
@classmethod
def validate_fe_names(cls, v: list[str]) -> list[str]:
    """Validate FE names in group."""
    for fe_name in v:
        if not re.match(FE_NAME_PATTERN, fe_name):
            msg = f"Invalid FE name in group: {fe_name}"
            raise ValueError(msg)
    return v

FERealization pydantic-model

Bases: GlazingBaseModel

How a frame element is realized syntactically.

ATTRIBUTE DESCRIPTION
fe_name

Frame element name.

TYPE: str

total

Total occurrences of this FE.

TYPE: int

patterns

Realization patterns for this FE.

TYPE: list[ValenceRealizationPattern], default=[]

METHOD DESCRIPTION
get_most_frequent_pattern

Get the most frequent realization pattern.

has_patterns

Check if this FE has realization patterns.

get_pattern_count

Get number of realization patterns.

Examples:

>>> fe_real = FERealization(
...     fe_name="Agent",
...     total=10,
...     patterns=[...]
... )

Fields:

Validators:

Attributes
fe_name: str pydantic-field

Frame element name

patterns: list[ValenceRealizationPattern] pydantic-field

Realization patterns

total: int pydantic-field

Total occurrences

Functions
get_most_frequent_pattern() -> ValenceRealizationPattern | None

Get the most frequent realization pattern.

RETURNS DESCRIPTION
ValenceRealizationPattern | None

Most frequent pattern, or None if no patterns.

Source code in src/glazing/framenet/models.py
def get_most_frequent_pattern(self) -> ValenceRealizationPattern | None:
    """Get the most frequent realization pattern.

    Returns
    -------
    ValenceRealizationPattern | None
        Most frequent pattern, or None if no patterns.
    """
    if not self.patterns:
        return None
    return max(self.patterns, key=lambda p: p.total)
get_pattern_count() -> int

Get number of realization patterns.

RETURNS DESCRIPTION
int

Number of patterns.

Source code in src/glazing/framenet/models.py
def get_pattern_count(self) -> int:
    """Get number of realization patterns.

    Returns
    -------
    int
        Number of patterns.
    """
    return len(self.patterns)
has_patterns() -> bool

Check if this FE has realization patterns.

RETURNS DESCRIPTION
bool

True if patterns exist.

Source code in src/glazing/framenet/models.py
def has_patterns(self) -> bool:
    """Check if this FE has realization patterns.

    Returns
    -------
    bool
        True if patterns exist.
    """
    return len(self.patterns) > 0
validate_fe_name(v: str) -> str pydantic-validator

Validate FE name format.

Source code in src/glazing/framenet/models.py
@field_validator("fe_name")
@classmethod
def validate_fe_name(cls, v: str) -> str:
    """Validate FE name format."""
    return validate_pattern(v, FE_NAME_PATTERN, "FE name")

FERelation pydantic-model

Bases: GlazingBaseModel

FE mapping between related frames with alignment metadata.

ATTRIBUTE DESCRIPTION
sub_fe_id

ID of the sub-frame FE.

TYPE: int | None, default=None

sub_fe_name

Name of the sub-frame FE.

TYPE: FEName | None, default=None

super_fe_id

ID of the super-frame FE.

TYPE: int | None, default=None

super_fe_name

Name of the super-frame FE.

TYPE: FEName | None, default=None

relation_type

Type of FE relation.

TYPE: FrameRelationSubType | None, default=None

alignment_confidence

Confidence in the alignment.

TYPE: MappingConfidenceScore | None, default=None

semantic_similarity

Semantic similarity score.

TYPE: MappingConfidenceScore | None, default=None

syntactic_similarity

Syntactic similarity score.

TYPE: MappingConfidenceScore | None, default=None

mapping_notes

Notes about the mapping.

TYPE: str | None, default=None

METHOD DESCRIPTION
is_inheritance

Check if this is an inheritance relation.

is_equivalence

Check if FEs are equivalent.

get_combined_score

Get combined confidence score.

Examples:

>>> fe_rel = FERelation(
...     sub_fe_name="Giver",
...     super_fe_name="Agent",
...     relation_type="Inheritance",
...     alignment_confidence=0.95
... )
>>> print(fe_rel.is_inheritance())
True

Fields:

Validators:

Attributes
alignment_confidence: MappingConfidenceScore | None = None pydantic-field

Alignment confidence

mapping_notes: str | None = None pydantic-field

Mapping notes

relation_type: FrameRelationSubType | None = None pydantic-field

Relation type

semantic_similarity: MappingConfidenceScore | None = None pydantic-field

Semantic similarity score

sub_fe_id: int | None = None pydantic-field

Sub-frame FE ID

sub_fe_name: FEName | None = None pydantic-field

Sub-frame FE name

super_fe_id: int | None = None pydantic-field

Super-frame FE ID

super_fe_name: FEName | None = None pydantic-field

Super-frame FE name

syntactic_similarity: MappingConfidenceScore | None = None pydantic-field

Syntactic similarity score

Functions
get_combined_score() -> float

Get combined confidence score.

Combines alignment confidence with similarity scores.

RETURNS DESCRIPTION
float

Combined confidence score (0.0-1.0).

Source code in src/glazing/framenet/models.py
def get_combined_score(self) -> float:
    """Get combined confidence score.

    Combines alignment confidence with similarity scores.

    Returns
    -------
    float
        Combined confidence score (0.0-1.0).
    """
    scores = []
    if self.alignment_confidence is not None:
        scores.append(self.alignment_confidence)
    if self.semantic_similarity is not None:
        scores.append(self.semantic_similarity)
    if self.syntactic_similarity is not None:
        scores.append(self.syntactic_similarity)

    return sum(scores) / len(scores) if scores else 0.5
is_equivalence() -> bool

Check if FEs are equivalent.

RETURNS DESCRIPTION
bool

True if relation_type is "Equivalence".

Source code in src/glazing/framenet/models.py
def is_equivalence(self) -> bool:
    """Check if FEs are equivalent.

    Returns
    -------
    bool
        True if relation_type is "Equivalence".
    """
    return self.relation_type == "Equivalence"
is_inheritance() -> bool

Check if this is an inheritance relation.

RETURNS DESCRIPTION
bool

True if relation_type is "Inheritance".

Source code in src/glazing/framenet/models.py
def is_inheritance(self) -> bool:
    """Check if this is an inheritance relation.

    Returns
    -------
    bool
        True if relation_type is "Inheritance".
    """
    return self.relation_type == "Inheritance"
validate_fe_names(v: str | None) -> str | None pydantic-validator

Validate FE name format.

Source code in src/glazing/framenet/models.py
@field_validator("sub_fe_name", "super_fe_name")
@classmethod
def validate_fe_names(cls, v: str | None) -> str | None:
    """Validate FE name format."""
    if v is not None:
        return validate_pattern(v, FE_NAME_PATTERN, "FE name")
    return v
validate_fe_relation() -> Self pydantic-validator

Validate FE relation completeness.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_fe_relation(self) -> Self:
    """Validate FE relation completeness."""
    if not any([self.sub_fe_id, self.sub_fe_name]):
        raise ValueError("Either sub_fe_id or sub_fe_name must be provided")
    if not any([self.super_fe_id, self.super_fe_name]):
        raise ValueError("Either super_fe_id or super_fe_name must be provided")
    return self

Frame pydantic-model

Bases: GlazingBaseModel

A FrameNet frame representing a schematic situation.

ATTRIBUTE DESCRIPTION
id

Unique frame identifier.

TYPE: FrameID

name

Human-readable frame name.

TYPE: FrameName

definition

Frame definition with embedded markup.

TYPE: AnnotatedText

frame_elements

Core and non-core frame elements.

TYPE: list[FrameElement]

created_by

Username of frame creator.

TYPE: Username | None, default=None

created_date

Frame creation timestamp.

TYPE: datetime | None, default=None

modified_date

Last modification timestamp.

TYPE: datetime | None, default=None

METHOD DESCRIPTION
get_fe_by_name

Get frame element by name.

get_core_elements

Get all core frame elements.

get_peripheral_elements

Get all peripheral frame elements.

validate_fe_constraints

Validate a set of FEs against constraints.

Examples:

>>> frame = Frame(
...     id=2031,
...     name="Abandonment",
...     definition=AnnotatedText.parse("An <fex>Agent</fex> leaves behind..."),
...     frame_elements=[]
... )
>>> print(frame.name)
'Abandonment'

Fields:

Validators:

Attributes
created_by: Username | None = None pydantic-field

Frame creator username

created_date: datetime | None = None pydantic-field

Creation timestamp

definition: AnnotatedText pydantic-field

Frame definition with markup

frame_elements: list[FrameElement] pydantic-field

Frame elements

frame_relations: list[FrameRelation] pydantic-field

Relations to other frames

id: FrameID pydantic-field

Unique frame identifier

lexical_units: list[LexicalUnit] pydantic-field

Lexical units in this frame

modified_date: datetime | None = None pydantic-field

Modification timestamp

name: FrameName pydantic-field

Human-readable frame name

Functions
get_core_elements() -> list[FrameElement]

Get all core frame elements.

RETURNS DESCRIPTION
list[FrameElement]

Frame elements with core_type "Core" or "Core-Unexpressed".

Source code in src/glazing/framenet/models.py
def get_core_elements(self) -> list[FrameElement]:
    """Get all core frame elements.

    Returns
    -------
    list[FrameElement]
        Frame elements with core_type "Core" or "Core-Unexpressed".
    """
    return [fe for fe in self.frame_elements if fe.is_core()]
get_fe_by_name(name: str) -> FrameElement | None

Get frame element by name.

PARAMETER DESCRIPTION
name

Name of the frame element.

TYPE: str

RETURNS DESCRIPTION
FrameElement | None

The frame element, or None if not found.

Source code in src/glazing/framenet/models.py
def get_fe_by_name(self, name: str) -> FrameElement | None:
    """Get frame element by name.

    Parameters
    ----------
    name : str
        Name of the frame element.

    Returns
    -------
    FrameElement | None
        The frame element, or None if not found.
    """
    for fe in self.frame_elements:
        if fe.name == name:
            return fe
    return None
get_peripheral_elements() -> list[FrameElement]

Get all peripheral frame elements.

RETURNS DESCRIPTION
list[FrameElement]

Frame elements with core_type "Peripheral" or "Extra-Thematic".

Source code in src/glazing/framenet/models.py
def get_peripheral_elements(self) -> list[FrameElement]:
    """Get all peripheral frame elements.

    Returns
    -------
    list[FrameElement]
        Frame elements with core_type "Peripheral" or "Extra-Thematic".
    """
    return [fe for fe in self.frame_elements if not fe.is_core()]
validate_created_by(v: str | None) -> str | None pydantic-validator

Validate creator username format.

Source code in src/glazing/framenet/models.py
@field_validator("created_by")
@classmethod
def validate_created_by(cls, v: str | None) -> str | None:
    """Validate creator username format."""
    if v is not None:
        return validate_pattern(v, USERNAME_PATTERN, "username")
    return v
validate_fe_constraints(fe_names: list[str]) -> dict[str, list[str]]

Validate a set of FEs against dependency constraints.

PARAMETER DESCRIPTION
fe_names

Names of FEs to validate.

TYPE: list[str]

RETURNS DESCRIPTION
dict[str, list[str]]

Dictionary with 'errors' and 'warnings' keys containing lists of constraint violation messages.

Source code in src/glazing/framenet/models.py
def validate_fe_constraints(self, fe_names: list[str]) -> dict[str, list[str]]:
    """Validate a set of FEs against dependency constraints.

    Parameters
    ----------
    fe_names : list[str]
        Names of FEs to validate.

    Returns
    -------
    dict[str, list[str]]
        Dictionary with 'errors' and 'warnings' keys containing
        lists of constraint violation messages.
    """
    errors: list[str] = []
    warnings: list[str] = []
    fe_set = set(fe_names)

    for fe_name in fe_names:
        fe = self.get_fe_by_name(fe_name)
        if not fe:
            errors.append(f"Unknown frame element: {fe_name}")
            continue

        # Check requires constraints
        missing_required = [req for req in fe.requires_fe if req not in fe_set]
        if missing_required:
            errors.append(f"FE '{fe_name}' requires missing FEs: {missing_required}")

        # Check excludes constraints
        conflicting = [exc for exc in fe.excludes_fe if exc in fe_set]
        if conflicting:
            errors.append(f"FE '{fe_name}' conflicts with present FEs: {conflicting}")

    return {"errors": errors, "warnings": warnings}
validate_frame_elements() -> Self pydantic-validator

Validate frame element consistency.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_frame_elements(self) -> Self:
    """Validate frame element consistency."""
    fe_names = [fe.name for fe in self.frame_elements]

    # Check for duplicate FE names
    if len(fe_names) != len(set(fe_names)):
        duplicates = [name for name in fe_names if fe_names.count(name) > 1]
        msg = f"Duplicate frame element names: {set(duplicates)}"
        raise ValueError(msg)

    # Validate FE constraint references
    for fe in self.frame_elements:
        for required_fe in fe.requires_fe:
            if required_fe not in fe_names:
                msg = f"FE '{fe.name}' requires unknown FE '{required_fe}'"
                raise ValueError(msg)
        for excluded_fe in fe.excludes_fe:
            if excluded_fe not in fe_names:
                msg = f"FE '{fe.name}' excludes unknown FE '{excluded_fe}'"
                raise ValueError(msg)

    return self
validate_frame_name(v: str) -> str pydantic-validator

Validate frame name format.

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_frame_name(cls, v: str) -> str:
    """Validate frame name format."""
    return validate_pattern(v, FRAME_NAME_PATTERN, "frame name")

FrameElement pydantic-model

Bases: GlazingBaseModel

A participant or prop in a frame.

ATTRIBUTE DESCRIPTION
id

Unique FE identifier.

TYPE: int

name

Frame element name (validated pattern).

TYPE: FEName

abbrev

FE abbreviation (validated pattern).

TYPE: FEAbbrev

definition

Definition with embedded markup.

TYPE: AnnotatedText

core_type

Core classification of this FE.

TYPE: CoreType

bg_color

Background color (6-digit hex).

TYPE: str

fg_color

Foreground color (6-digit hex).

TYPE: str

requires_fe

FE names that this FE requires.

TYPE: list[FEName], default=[]

excludes_fe

FE names that this FE excludes.

TYPE: list[FEName], default=[]

semtype_refs

Semantic type references.

TYPE: list[SemTypeID]

created_by

Username of creator.

TYPE: Username | None, default=None

created_date

Creation timestamp.

TYPE: datetime | None, default=None

METHOD DESCRIPTION
has_dependencies

Check if this FE has dependency constraints.

is_core

Check if this is a core frame element.

conflicts_with

Check if this FE conflicts with another.

Examples:

>>> fe = FrameElement(
...     id=123,
...     name="Agent",
...     abbrev="Agt",
...     definition=AnnotatedText.parse("The entity that performs an action"),
...     core_type="Core",
...     bg_color="FF0000",
...     fg_color="FFFFFF"
... )
>>> print(fe.is_core())
True

Fields:

Validators:

Attributes
abbrev: FEAbbrev pydantic-field

FE abbreviation

bg_color: str pydantic-field

Background color (6-digit hex)

core_type: CoreType pydantic-field

Core classification

created_by: Username | None = None pydantic-field

Creator username

created_date: datetime | None = None pydantic-field

Creation timestamp

definition: AnnotatedText pydantic-field

Definition with markup

excludes_fe: list[FEName] pydantic-field

FE names this FE excludes

fg_color: str pydantic-field

Foreground color (6-digit hex)

id: int pydantic-field

Unique FE identifier

name: FEName pydantic-field

Frame element name

requires_fe: list[FEName] pydantic-field

FE names this FE requires

semtype_refs: list[SemTypeID] pydantic-field

Semantic type references

Functions
conflicts_with(other_fe_name: str) -> bool

Check if this FE conflicts with another.

PARAMETER DESCRIPTION
other_fe_name

Name of the other FE to check.

TYPE: str

RETURNS DESCRIPTION
bool

True if this FE excludes the other FE.

Source code in src/glazing/framenet/models.py
def conflicts_with(self, other_fe_name: str) -> bool:
    """Check if this FE conflicts with another.

    Parameters
    ----------
    other_fe_name : str
        Name of the other FE to check.

    Returns
    -------
    bool
        True if this FE excludes the other FE.
    """
    return other_fe_name in self.excludes_fe
has_dependencies() -> bool

Check if this FE has dependency constraints.

RETURNS DESCRIPTION
bool

True if the FE has requires or excludes constraints.

Source code in src/glazing/framenet/models.py
def has_dependencies(self) -> bool:
    """Check if this FE has dependency constraints.

    Returns
    -------
    bool
        True if the FE has requires or excludes constraints.
    """
    return len(self.requires_fe) > 0 or len(self.excludes_fe) > 0
is_core() -> bool

Check if this is a core frame element.

RETURNS DESCRIPTION
bool

True if core_type is "Core" or "Core-Unexpressed".

Source code in src/glazing/framenet/models.py
def is_core(self) -> bool:
    """Check if this is a core frame element.

    Returns
    -------
    bool
        True if core_type is "Core" or "Core-Unexpressed".
    """
    return self.core_type in ("Core", "Core-Unexpressed")
validate_abbrev(v: str) -> str pydantic-validator

Validate FE abbreviation format.

Source code in src/glazing/framenet/models.py
@field_validator("abbrev")
@classmethod
def validate_abbrev(cls, v: str) -> str:
    """Validate FE abbreviation format."""
    return validate_pattern(v, FE_ABBREV_PATTERN, "FE abbreviation")
validate_color(v: str) -> str pydantic-validator

Validate hex color format.

Source code in src/glazing/framenet/models.py
@field_validator("bg_color", "fg_color")
@classmethod
def validate_color(cls, v: str) -> str:
    """Validate hex color format."""
    return validate_hex_color(v)
validate_created_by(v: str | None) -> str | None pydantic-validator

Validate creator username format.

Source code in src/glazing/framenet/models.py
@field_validator("created_by")
@classmethod
def validate_created_by(cls, v: str | None) -> str | None:
    """Validate creator username format."""
    if v is not None:
        return validate_pattern(v, USERNAME_PATTERN, "username")
    return v
validate_fe_constraints() -> Self pydantic-validator

Validate FE constraint consistency.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_fe_constraints(self) -> Self:
    """Validate FE constraint consistency."""
    # Check for overlap between requires and excludes
    overlap = set(self.requires_fe) & set(self.excludes_fe)
    if overlap:
        msg = f"FE cannot both require and exclude: {overlap}"
        raise ValueError(msg)

    # Check that FE doesn't require or exclude itself
    if self.name in self.requires_fe:
        msg = f"FE cannot require itself: {self.name}"
        raise ValueError(msg)
    if self.name in self.excludes_fe:
        msg = f"FE cannot exclude itself: {self.name}"
        raise ValueError(msg)

    return self
validate_fe_lists(v: list[str]) -> list[str] pydantic-validator

Validate FE name lists.

Source code in src/glazing/framenet/models.py
@field_validator("requires_fe", "excludes_fe")
@classmethod
def validate_fe_lists(cls, v: list[str]) -> list[str]:
    """Validate FE name lists."""
    for fe_name in v:
        if not re.match(FE_NAME_PATTERN, fe_name):
            msg = f"Invalid FE name in list: {fe_name}"
            raise ValueError(msg)
    return v
validate_fe_name(v: str) -> str pydantic-validator

Validate FE name format.

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_fe_name(cls, v: str) -> str:
    """Validate FE name format."""
    return validate_pattern(v, FE_NAME_PATTERN, "frame element name")

FrameIndexEntry pydantic-model

Bases: GlazingBaseModel

Entry in the frame index file.

ATTRIBUTE DESCRIPTION
id

Frame identifier.

TYPE: FrameID

name

Frame name.

TYPE: FrameName

modified_date

Last modification date.

TYPE: datetime

Examples:

>>> entry = FrameIndexEntry(
...     id=2031,
...     name="Abandonment",
...     modified_date=datetime.now()
... )
>>> print(entry.name)
'Abandonment'

Fields:

Validators:

Attributes
id: FrameID pydantic-field

Frame identifier

modified_date: datetime pydantic-field

Last modification date

name: FrameName pydantic-field

Frame name

Functions
validate_name(v: str) -> str pydantic-validator

Validate frame name format.

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
    """Validate frame name format."""
    return validate_pattern(v, FRAME_NAME_PATTERN, "frame name")

FrameRelation pydantic-model

Bases: GlazingBaseModel

Relationship between frames.

ATTRIBUTE DESCRIPTION
id

Relation identifier.

TYPE: int | None, default=None

type

Type of frame relation.

TYPE: FrameRelationType

sub_frame_id

ID of the sub-frame.

TYPE: FrameID | None, default=None

sub_frame_name

Name of the sub-frame.

TYPE: FrameName | None, default=None

super_frame_id

ID of the super-frame.

TYPE: FrameID | None, default=None

super_frame_name

Name of the super-frame.

TYPE: FrameName | None, default=None

fe_relations

FE-level mappings for this relation.

TYPE: list[FERelation], default=[]

METHOD DESCRIPTION
is_inheritance

Check if this is an inheritance relation.

get_fe_mapping

Get FE mapping for a sub-frame FE.

Examples:

>>> frame_rel = FrameRelation(
...     type="Inherits from",
...     sub_frame_name="Giving",
...     super_frame_name="Transfer",
...     fe_relations=[]
... )
>>> print(frame_rel.is_inheritance())
True

Fields:

Validators:

Attributes
fe_relations: list[FERelation] pydantic-field

FE-level mappings

id: int | None = None pydantic-field

Relation identifier

sub_frame_id: FrameID | None = None pydantic-field

Sub-frame ID

sub_frame_name: FrameName | None = None pydantic-field

Sub-frame name

super_frame_id: FrameID | None = None pydantic-field

Super-frame ID

super_frame_name: FrameName | None = None pydantic-field

Super-frame name

type: FrameRelationType pydantic-field

Frame relation type

Functions
get_fe_mapping(sub_fe_name: str) -> FERelation | None

Get FE mapping for a sub-frame FE.

PARAMETER DESCRIPTION
sub_fe_name

Name of the sub-frame FE.

TYPE: str

RETURNS DESCRIPTION
FERelation | None

The FE relation, or None if not found.

Source code in src/glazing/framenet/models.py
def get_fe_mapping(self, sub_fe_name: str) -> FERelation | None:
    """Get FE mapping for a sub-frame FE.

    Parameters
    ----------
    sub_fe_name : str
        Name of the sub-frame FE.

    Returns
    -------
    FERelation | None
        The FE relation, or None if not found.
    """
    for fe_rel in self.fe_relations:
        if fe_rel.sub_fe_name == sub_fe_name:
            return fe_rel
    return None
is_inheritance() -> bool

Check if this is an inheritance relation.

RETURNS DESCRIPTION
bool

True if type is "Inherits from" or "Is Inherited by".

Source code in src/glazing/framenet/models.py
def is_inheritance(self) -> bool:
    """Check if this is an inheritance relation.

    Returns
    -------
    bool
        True if type is "Inherits from" or "Is Inherited by".
    """
    return self.type in ("Inherits from", "Is Inherited by")
validate_frame_names(v: str | None) -> str | None pydantic-validator

Validate frame name format.

Source code in src/glazing/framenet/models.py
@field_validator("sub_frame_name", "super_frame_name")
@classmethod
def validate_frame_names(cls, v: str | None) -> str | None:
    """Validate frame name format."""
    if v is not None:
        return validate_pattern(v, FRAME_NAME_PATTERN, "frame name")
    return v

Label pydantic-model

Bases: GlazingBaseModel

An annotation label on a text span.

ATTRIBUTE DESCRIPTION
id

Label identifier.

TYPE: LabelID | None, default=None

name

Label name (FE name, GF type, PT type, etc.).

TYPE: str

start

Start position in sentence.

TYPE: int

end

End position in sentence.

TYPE: int

fe_id

Frame element ID for FE labels.

TYPE: int | None, default=None

is_instantiated_null

True for null instantiation labels.

TYPE: bool, default=False

METHOD DESCRIPTION
get_span_length

Get the length of the labeled span.

is_null_instantiation

Check if this is a null instantiation.

overlaps_with

Check if this label overlaps with another.

Examples:

>>> label = Label(name="Agent", start=0, end=5)
>>> print(label.get_span_length())
5

Fields:

Validators:

Attributes
end: int pydantic-field

End position in sentence

fe_id: int | None = None pydantic-field

Frame element ID for FE labels

id: LabelID | None = None pydantic-field

Label identifier

is_instantiated_null: bool = False pydantic-field

Null instantiation flag

name: str pydantic-field

Label name

start: int pydantic-field

Start position in sentence

Functions
get_span_length() -> int

Get the length of the labeled span.

RETURNS DESCRIPTION
int

Length of the span.

Source code in src/glazing/framenet/models.py
def get_span_length(self) -> int:
    """Get the length of the labeled span.

    Returns
    -------
    int
        Length of the span.
    """
    return self.end - self.start
is_null_instantiation() -> bool

Check if this is a null instantiation.

RETURNS DESCRIPTION
bool

True if is_instantiated_null is True.

Source code in src/glazing/framenet/models.py
def is_null_instantiation(self) -> bool:
    """Check if this is a null instantiation.

    Returns
    -------
    bool
        True if is_instantiated_null is True.
    """
    return self.is_instantiated_null
overlaps_with(other: Label) -> bool

Check if this label overlaps with another.

PARAMETER DESCRIPTION
other

The other label to check.

TYPE: Label

RETURNS DESCRIPTION
bool

True if the labels overlap.

Source code in src/glazing/framenet/models.py
def overlaps_with(self, other: Label) -> bool:
    """Check if this label overlaps with another.

    Parameters
    ----------
    other : Label
        The other label to check.

    Returns
    -------
    bool
        True if the labels overlap.
    """
    return not (self.end <= other.start or other.end <= self.start)
validate_positions() -> Self pydantic-validator

Validate that end position is at or after start position.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_positions(self) -> Self:
    """Validate that end position is at or after start position."""
    if self.end < self.start:
        msg = f"End position ({self.end}) must be at or after start position ({self.start})"
        raise ValueError(msg)
    return self

Lexeme pydantic-model

Bases: GlazingBaseModel

A lexical form in a lexical unit.

ATTRIBUTE DESCRIPTION
name

The word form (validated pattern).

TYPE: str

pos

Part of speech tag.

TYPE: FrameNetPOS

headword

True if this is the head word of the LU.

TYPE: bool, default=False

break_before

True if there should be a break before this lexeme.

TYPE: bool, default=False

order

Order position in multi-word LUs.

TYPE: int, default=1

METHOD DESCRIPTION
is_headword

Check if this is the headword.

Examples:

>>> lexeme = Lexeme(name="abandon", pos="V", headword=True)
>>> print(lexeme.is_headword())
True

Fields:

Validators:

Attributes
break_before: bool = False pydantic-field

Break before this lexeme

headword: bool = False pydantic-field

True if this is the head word

name: str pydantic-field

The word form

order: int = 1 pydantic-field

Order position in multi-word LUs

pos: FrameNetPOS pydantic-field

Part of speech

Functions
is_headword() -> bool

Check if this is the headword.

RETURNS DESCRIPTION
bool

True if this lexeme is marked as headword.

Source code in src/glazing/framenet/models.py
def is_headword(self) -> bool:
    """Check if this is the headword.

    Returns
    -------
    bool
        True if this lexeme is marked as headword.
    """
    return self.headword
validate_lexeme_name(v: str) -> str pydantic-validator

Validate lexeme name (individual word form).

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_lexeme_name(cls, v: str) -> str:
    """Validate lexeme name (individual word form)."""
    return validate_pattern(v, LEXEME_NAME_PATTERN, "lexeme name")

LexicalUnit pydantic-model

Bases: GlazingBaseModel

A word or phrase that evokes a frame.

ATTRIBUTE DESCRIPTION
id

Unique lexical unit identifier.

TYPE: LexicalUnitID

lemma_id

Lemma identifier.

TYPE: int | None, default=None

name

LU name in lemma.pos format (validated).

TYPE: LexicalUnitName

pos

Part of speech tag.

TYPE: FrameNetPOS

definition

LU definition (may have COD: or FN: prefix).

TYPE: str

annotation_status

Annotation completion status.

TYPE: AnnotationStatus | None, default=None

total_annotated

Total number of annotated instances.

TYPE: int | None, default=None

has_annotated_examples

Whether this LU has annotated examples.

TYPE: bool, default=False

frame_id

ID of the frame this LU evokes.

TYPE: FrameID

frame_name

Name of the frame this LU evokes.

TYPE: FrameName

sentence_count

Sentence frequency information.

TYPE: SentenceCount

lexemes

Individual word forms in this LU.

TYPE: list[Lexeme]

semtypes

Semantic type references.

TYPE: list[SemTypeRef], default=[]

valence_patterns

Syntactic valence patterns.

TYPE: list[ValencePattern], default=[]

annotation_sets

Annotation sets for this LU.

TYPE: list[AnnotationSet], default=[]

created_by

Creator username.

TYPE: Username | None, default=None

created_date

Creation timestamp.

TYPE: datetime | None, default=None

METHOD DESCRIPTION
get_headword_lexeme

Get the headword lexeme.

has_valence_patterns

Check if LU has valence patterns.

get_annotation_rate

Get sentence annotation completion rate.

is_multi_word

Check if this is a multi-word LU.

get_most_frequent_valence

Get most frequent valence pattern.

Examples:

>>> lu = LexicalUnit(
...     id=1234,
...     name="abandon.v",
...     pos="V",
...     definition="To leave behind permanently",
...     frame_id=2031,
...     frame_name="Abandonment",
...     sentence_count=SentenceCount(annotated=50, total=100),
...     lexemes=[Lexeme(name="abandon", pos="V", headword=True)]
... )
>>> print(lu.get_annotation_rate())
0.5

Fields:

Validators:

Attributes
annotation_sets: list[AnnotationSet] pydantic-field

Annotation sets

annotation_status: AnnotationStatus | None = None pydantic-field

Annotation completion status

created_by: Username | None = None pydantic-field

Creator username

created_date: datetime | None = None pydantic-field

Creation timestamp

definition: str pydantic-field

LU definition

frame_id: FrameID pydantic-field

Frame ID this LU evokes

frame_name: FrameName pydantic-field

Frame name this LU evokes

has_annotated_examples: bool = False pydantic-field

Whether this LU has annotated examples

id: LexicalUnitID pydantic-field

Unique lexical unit identifier

lemma_id: int | None = None pydantic-field

Lemma identifier

lexemes: list[Lexeme] pydantic-field

Individual word forms

name: LexicalUnitName pydantic-field

LU name (lemma.pos format)

pos: FrameNetPOS pydantic-field

Part of speech tag

semtypes: list[SemTypeRef] pydantic-field

Semantic type references

sentence_count: SentenceCount pydantic-field

Sentence frequency information

total_annotated: int | None = None pydantic-field

Total annotated instances

valence_patterns: list[ValencePattern] pydantic-field

Syntactic valence patterns

Functions
get_annotation_rate() -> float

Get sentence annotation completion rate.

RETURNS DESCRIPTION
float

Annotation rate from sentence count (0.0-1.0).

Source code in src/glazing/framenet/models.py
def get_annotation_rate(self) -> float:
    """Get sentence annotation completion rate.

    Returns
    -------
    float
        Annotation rate from sentence count (0.0-1.0).
    """
    return self.sentence_count.get_annotation_rate()
get_annotation_set_by_id(anno_id: AnnotationSetID) -> AnnotationSet | None

Get annotation set by ID.

PARAMETER DESCRIPTION
anno_id

Annotation set ID to find.

TYPE: AnnotationSetID

RETURNS DESCRIPTION
AnnotationSet | None

The annotation set, or None if not found.

Source code in src/glazing/framenet/models.py
def get_annotation_set_by_id(self, anno_id: AnnotationSetID) -> AnnotationSet | None:
    """Get annotation set by ID.

    Parameters
    ----------
    anno_id : AnnotationSetID
        Annotation set ID to find.

    Returns
    -------
    AnnotationSet | None
        The annotation set, or None if not found.
    """
    for anno_set in self.annotation_sets:
        if anno_set.id == anno_id:
            return anno_set
    return None
get_headword_lexeme() -> Lexeme | None

Get the headword lexeme.

RETURNS DESCRIPTION
Lexeme | None

The headword lexeme, or None if none found.

Source code in src/glazing/framenet/models.py
def get_headword_lexeme(self) -> Lexeme | None:
    """Get the headword lexeme.

    Returns
    -------
    Lexeme | None
        The headword lexeme, or None if none found.
    """
    for lexeme in self.lexemes:
        if lexeme.headword:
            return lexeme
    return None
get_most_frequent_valence() -> ValencePattern | None

Get most frequent valence pattern.

RETURNS DESCRIPTION
ValencePattern | None

Most frequent pattern, or None if no patterns.

Source code in src/glazing/framenet/models.py
def get_most_frequent_valence(self) -> ValencePattern | None:
    """Get most frequent valence pattern.

    Returns
    -------
    ValencePattern | None
        Most frequent pattern, or None if no patterns.
    """
    if not self.valence_patterns:
        return None
    return max(self.valence_patterns, key=lambda p: p.total_annotated)
has_valence_patterns() -> bool

Check if LU has valence patterns.

RETURNS DESCRIPTION
bool

True if valence patterns exist.

Source code in src/glazing/framenet/models.py
def has_valence_patterns(self) -> bool:
    """Check if LU has valence patterns.

    Returns
    -------
    bool
        True if valence patterns exist.
    """
    return len(self.valence_patterns) > 0
is_multi_word() -> bool

Check if this is a multi-word LU.

RETURNS DESCRIPTION
bool

True if LU contains multiple lexemes.

Source code in src/glazing/framenet/models.py
def is_multi_word(self) -> bool:
    """Check if this is a multi-word LU.

    Returns
    -------
    bool
        True if LU contains multiple lexemes.
    """
    return len(self.lexemes) > 1
validate_created_by(v: str | None) -> str | None pydantic-validator

Validate creator username format.

Source code in src/glazing/framenet/models.py
@field_validator("created_by")
@classmethod
def validate_created_by(cls, v: str | None) -> str | None:
    """Validate creator username format."""
    if v is not None:
        return validate_pattern(v, USERNAME_PATTERN, "username")
    return v
validate_definition(v: str) -> str pydantic-validator

Parse and validate definition with optional prefix.

Source code in src/glazing/framenet/models.py
@field_validator("definition")
@classmethod
def validate_definition(cls, v: str) -> str:
    """Parse and validate definition with optional prefix."""
    # Definitions often start with COD: or FN: but can be freeform
    # Allow any non-empty definition
    return v
validate_frame_name(v: str) -> str pydantic-validator

Validate frame name format.

Source code in src/glazing/framenet/models.py
@field_validator("frame_name")
@classmethod
def validate_frame_name(cls, v: str) -> str:
    """Validate frame name format."""
    return validate_pattern(v, FRAME_NAME_PATTERN, "frame name")
validate_lu_consistency() -> Self pydantic-validator

Validate lexical unit consistency.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_lu_consistency(self) -> Self:
    """Validate lexical unit consistency."""
    # Check that at least one lexeme exists
    if not self.lexemes:
        raise ValueError("Lexical unit must have at least one lexeme")

    # Check that exactly one lexeme is marked as headword
    headwords = [lex for lex in self.lexemes if lex.headword]
    if len(headwords) != 1:
        raise ValueError("Lexical unit must have exactly one headword lexeme")

    # Validate total_annotated consistency
    if (
        self.total_annotated is not None
        and self.total_annotated > 0
        and self.sentence_count.total > 0
        and self.total_annotated > self.sentence_count.total
    ):
        raise ValueError("total_annotated cannot exceed sentence count total")

    return self
validate_lu_name(v: str) -> str pydantic-validator

Validate LU name format (e.g., 'abandon.v', 'give_up.v').

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_lu_name(cls, v: str) -> str:
    """Validate LU name format (e.g., 'abandon.v', 'give_up.v')."""
    return validate_pattern(v, LU_NAME_PATTERN, "lexical unit name")

SemTypeRef pydantic-model

Bases: GlazingBaseModel

Reference to a semantic type with name and ID.

ATTRIBUTE DESCRIPTION
name

Semantic type name.

TYPE: str

id

Semantic type ID.

TYPE: SemTypeID

METHOD DESCRIPTION
is_valid_name

Check if the name follows semantic type naming conventions.

Examples:

>>> ref = SemTypeRef(name="Sentient", id=123)
>>> print(ref.name)
'Sentient'

Fields:

Validators:

Attributes
id: SemTypeID pydantic-field

Semantic type ID

name: str pydantic-field

Semantic type name

Functions
is_valid_name() -> bool

Check if the name follows standard semantic type naming conventions.

RETURNS DESCRIPTION
bool

True if name follows standard pattern.

Source code in src/glazing/framenet/models.py
def is_valid_name(self) -> bool:
    """Check if the name follows standard semantic type naming conventions.

    Returns
    -------
    bool
        True if name follows standard pattern.
    """
    return bool(re.match(r"^[A-Z][A-Za-z0-9_]*$", self.name))
validate_name(v: str) -> str pydantic-validator

Validate semantic type name format.

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_name(cls, v: str) -> str:
    """Validate semantic type name format."""
    # Allow flexible semantic type names - some may have spaces, hyphens, etc.
    if not re.match(r"^[A-Z][A-Za-z0-9_\s-]*$", v):
        # Log unusual formats but don't fail validation
        pass
    return v

SemanticType pydantic-model

Bases: GlazingBaseModel

Semantic type in the FrameNet type system.

ATTRIBUTE DESCRIPTION
id

Semantic type identifier.

TYPE: SemTypeID

name

Type name.

TYPE: str

abbrev

Type abbreviation.

TYPE: str

definition

Type definition.

TYPE: str

super_type_id

Parent type ID.

TYPE: SemTypeID | None, default=None

super_type_name

Parent type name.

TYPE: str | None, default=None

root_type_id

Root type ID.

TYPE: SemTypeID | None, default=None

root_type_name

Root type name.

TYPE: str | None, default=None

METHOD DESCRIPTION
is_root_type

Check if this is a root semantic type.

get_depth

Get depth in the type hierarchy.

Examples:

>>> sem_type = SemanticType(
...     id=123,
...     name="Sentient",
...     abbrev="sent",
...     definition="Capable of perception and feeling"
... )
>>> print(sem_type.is_root_type())
True

Fields:

Validators:

Attributes
abbrev: str pydantic-field

Type abbreviation

definition: str pydantic-field

Type definition

id: SemTypeID pydantic-field

Semantic type identifier

name: str pydantic-field

Type name

root_type_id: SemTypeID | None = None pydantic-field

Root type ID

root_type_name: str | None = None pydantic-field

Root type name

super_type_id: SemTypeID | None = None pydantic-field

Parent type ID

super_type_name: str | None = None pydantic-field

Parent type name

Functions
get_depth() -> int

Get depth in the type hierarchy.

RETURNS DESCRIPTION
int

Depth (0 for root types, 1 for direct children, etc.).

Source code in src/glazing/framenet/models.py
def get_depth(self) -> int:
    """Get depth in the type hierarchy.

    Returns
    -------
    int
        Depth (0 for root types, 1 for direct children, etc.).
    """
    if self.is_root_type():
        return 0
    # Note: This would need access to the full type hierarchy to compute accurately
    # For now, return estimated depth based on available information
    return 1 if self.super_type_id else 0
is_root_type() -> bool

Check if this is a root semantic type.

RETURNS DESCRIPTION
bool

True if this type has no super type.

Source code in src/glazing/framenet/models.py
def is_root_type(self) -> bool:
    """Check if this is a root semantic type.

    Returns
    -------
    bool
        True if this type has no super type.
    """
    return self.super_type_id is None
validate_type_hierarchy() -> Self pydantic-validator

Validate semantic type hierarchy consistency.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_type_hierarchy(self) -> Self:
    """Validate semantic type hierarchy consistency."""
    # If super_type_id is provided, super_type_name should also be provided
    if self.super_type_id is not None and self.super_type_name is None:
        raise ValueError("super_type_name required when super_type_id is provided")
    if self.super_type_name is not None and self.super_type_id is None:
        raise ValueError("super_type_id required when super_type_name is provided")

    # Same for root type
    if self.root_type_id is not None and self.root_type_name is None:
        raise ValueError("root_type_name required when root_type_id is provided")
    if self.root_type_name is not None and self.root_type_id is None:
        raise ValueError("root_type_id required when root_type_name is provided")

    return self

Sentence pydantic-model

Bases: GlazingBaseModel

A sentence with its annotations.

ATTRIBUTE DESCRIPTION
id

Sentence identifier.

TYPE: SentenceID

text

The sentence text.

TYPE: str

paragraph_no

Paragraph number in document.

TYPE: int | None, default=None

sentence_no

Sentence number in paragraph.

TYPE: int | None, default=None

doc_id

Document identifier.

TYPE: DocumentID | None, default=None

corpus_id

Corpus identifier.

TYPE: CorpusID | None, default=None

apos

Absolute position in document.

TYPE: int | None, default=None

annotation_sets

Annotation sets for this sentence.

TYPE: list[AnnotationSet], default=[]

METHOD DESCRIPTION
get_annotation_set_by_id

Get annotation set by ID.

has_annotations

Check if sentence has any annotations.

get_annotation_count

Get number of annotation sets.

Examples:

>>> sentence = Sentence(
...     id=123,
...     text="John abandoned the car.",
...     paragraph_no=1,
...     sentence_no=1
... )

Fields:

Attributes
annotation_sets: list[AnnotationSet] pydantic-field

Annotation sets

apos: int | None = None pydantic-field

Absolute position in document

corpus_id: CorpusID | None = None pydantic-field

Corpus identifier

doc_id: DocumentID | None = None pydantic-field

Document identifier

id: SentenceID pydantic-field

Sentence identifier

paragraph_no: int | None = None pydantic-field

Paragraph number

sentence_no: int | None = None pydantic-field

Sentence number

text: str pydantic-field

The sentence text

Functions
get_annotation_count() -> int

Get number of annotation sets.

RETURNS DESCRIPTION
int

Number of annotation sets.

Source code in src/glazing/framenet/models.py
def get_annotation_count(self) -> int:
    """Get number of annotation sets.

    Returns
    -------
    int
        Number of annotation sets.
    """
    return len(self.annotation_sets)
get_annotation_set_by_id(anno_id: AnnotationSetID) -> AnnotationSet | None

Get annotation set by ID.

PARAMETER DESCRIPTION
anno_id

The annotation set ID to find.

TYPE: AnnotationSetID

RETURNS DESCRIPTION
AnnotationSet | None

The annotation set, or None if not found.

Source code in src/glazing/framenet/models.py
def get_annotation_set_by_id(self, anno_id: AnnotationSetID) -> AnnotationSet | None:
    """Get annotation set by ID.

    Parameters
    ----------
    anno_id : AnnotationSetID
        The annotation set ID to find.

    Returns
    -------
    AnnotationSet | None
        The annotation set, or None if not found.
    """
    for anno_set in self.annotation_sets:
        if anno_set.id == anno_id:
            return anno_set
    return None
has_annotations() -> bool

Check if sentence has any annotations.

RETURNS DESCRIPTION
bool

True if there are annotation sets.

Source code in src/glazing/framenet/models.py
def has_annotations(self) -> bool:
    """Check if sentence has any annotations.

    Returns
    -------
    bool
        True if there are annotation sets.
    """
    return len(self.annotation_sets) > 0

SentenceCount pydantic-model

Bases: GlazingBaseModel

Frequency counts for annotated sentences.

ATTRIBUTE DESCRIPTION
annotated

Number of annotated sentences.

TYPE: int, default=0

total

Total number of sentences.

TYPE: int, default=0

METHOD DESCRIPTION
get_annotation_rate

Calculate the annotation completion rate.

has_annotations

Check if any sentences are annotated.

Examples:

>>> count = SentenceCount(annotated=50, total=100)
>>> print(count.get_annotation_rate())
0.5

Fields:

Validators:

Attributes
annotated: int = 0 pydantic-field

Number of annotated sentences

total: int = 0 pydantic-field

Total number of sentences

Functions
get_annotation_rate() -> float

Calculate the annotation completion rate.

RETURNS DESCRIPTION
float

Completion rate (0.0-1.0), or 0.0 if no total sentences.

Source code in src/glazing/framenet/models.py
def get_annotation_rate(self) -> float:
    """Calculate the annotation completion rate.

    Returns
    -------
    float
        Completion rate (0.0-1.0), or 0.0 if no total sentences.
    """
    return self.annotated / self.total if self.total > 0 else 0.0
has_annotations() -> bool

Check if any sentences are annotated.

RETURNS DESCRIPTION
bool

True if annotated count > 0.

Source code in src/glazing/framenet/models.py
def has_annotations(self) -> bool:
    """Check if any sentences are annotated.

    Returns
    -------
    bool
        True if annotated count > 0.
    """
    return self.annotated > 0
validate_counts() -> Self pydantic-validator

Validate that annotated count doesn't exceed total.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_counts(self) -> Self:
    """Validate that annotated count doesn't exceed total."""
    if self.annotated > self.total:
        msg = f"Annotated count ({self.annotated}) cannot exceed total ({self.total})"
        raise ValueError(msg)
    return self

TextAnnotation pydantic-model

Bases: GlazingBaseModel

An annotation within text (FE reference, target, example, etc.).

ATTRIBUTE DESCRIPTION
start

Start position in plain text (0-based).

TYPE: int

end

End position in plain text (exclusive).

TYPE: int

type

Type of annotation markup.

TYPE: MarkupType

name

For FE references - validated as alphanumeric + underscore.

TYPE: str | None, default=None

ref_id

ID of referenced element.

TYPE: int | None, default=None

text

The annotated text span.

TYPE: str

METHOD DESCRIPTION
get_length

Get the length of the annotation span.

overlaps_with

Check if this annotation overlaps with another.

Examples:

>>> annotation = TextAnnotation(
...     start=3, end=8, type="fex", name="Agent", text="Agent"
... )
>>> print(annotation.get_length())
5

Fields:

Validators:

Attributes
end: int pydantic-field

End position in plain text

name: str | None = None pydantic-field

FE name for fex/fen annotations

ref_id: int | None = None pydantic-field

ID of referenced element

start: int pydantic-field

Start position in plain text

text: str pydantic-field

The annotated text span

Functions
get_length() -> int

Get the length of the annotation span.

RETURNS DESCRIPTION
int

Length of the text span.

Source code in src/glazing/framenet/models.py
def get_length(self) -> int:
    """Get the length of the annotation span.

    Returns
    -------
    int
        Length of the text span.
    """
    return self.end - self.start
overlaps_with(other: TextAnnotation) -> bool

Check if this annotation overlaps with another.

PARAMETER DESCRIPTION
other

The other annotation to check.

TYPE: TextAnnotation

RETURNS DESCRIPTION
bool

True if the annotations overlap.

Source code in src/glazing/framenet/models.py
def overlaps_with(self, other: TextAnnotation) -> bool:
    """Check if this annotation overlaps with another.

    Parameters
    ----------
    other : TextAnnotation
        The other annotation to check.

    Returns
    -------
    bool
        True if the annotations overlap.
    """
    return not (self.end <= other.start or other.end <= self.start)
validate_annotation_requirements() -> Self pydantic-validator

Validate annotation type-specific requirements.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_annotation_requirements(self) -> Self:
    """Validate annotation type-specific requirements."""
    if self.type in ("fex", "fen") and self.name is None:
        msg = f"Annotation type '{self.type}' requires a name"
        raise ValueError(msg)
    return self
validate_name(v: str | None) -> str | None pydantic-validator

Validate FE reference names.

Source code in src/glazing/framenet/models.py
@field_validator("name")
@classmethod
def validate_name(cls, v: str | None) -> str | None:
    """Validate FE reference names."""
    if v is not None and not re.match(FE_NAME_PATTERN, v):
        msg = f"Invalid FE name format: {v}"
        raise ValueError(msg)
    return v
validate_positions() -> Self pydantic-validator

Validate that end position is at or after start position.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_positions(self) -> Self:
    """Validate that end position is at or after start position."""
    if self.end < self.start:
        msg = f"End position ({self.end}) must be at or after start position ({self.start})"
        raise ValueError(msg)
    return self

ValenceAnnotationPattern pydantic-model

Bases: GlazingBaseModel

A specific valence pattern with annotated examples.

ATTRIBUTE DESCRIPTION
anno_sets

References to annotation sets.

TYPE: list[AnnotationSetID]

pattern

FE group realizations in this pattern.

TYPE: list[FEGroupRealization]

METHOD DESCRIPTION
get_annotation_count

Get number of annotation sets.

get_fe_groups

Get all FE groups in pattern.

Examples:

>>> pattern = ValenceAnnotationPattern(
...     anno_sets=[1, 2, 3],
...     pattern=[FEGroupRealization(...)]
... )

Fields:

Attributes
anno_sets: list[AnnotationSetID] pydantic-field

Annotation set references

pattern: list[FEGroupRealization] pydantic-field

FE group realizations

Functions
get_annotation_count() -> int

Get number of annotation sets.

RETURNS DESCRIPTION
int

Number of annotation sets.

Source code in src/glazing/framenet/models.py
def get_annotation_count(self) -> int:
    """Get number of annotation sets.

    Returns
    -------
    int
        Number of annotation sets.
    """
    return len(self.anno_sets)
get_fe_groups() -> list[FEGroupRealization]

Get all FE groups in pattern.

RETURNS DESCRIPTION
list[FEGroupRealization]

List of FE group realizations.

Source code in src/glazing/framenet/models.py
def get_fe_groups(self) -> list[FEGroupRealization]:
    """Get all FE groups in pattern.

    Returns
    -------
    list[FEGroupRealization]
        List of FE group realizations.
    """
    return self.pattern

ValencePattern pydantic-model

Bases: GlazingBaseModel

Syntactic valence pattern for a lexical unit.

ATTRIBUTE DESCRIPTION
total_annotated

Total number of annotated instances.

TYPE: int

fe_realizations

How frame elements are realized.

TYPE: list[FERealization]

patterns

Specific valence patterns with examples.

TYPE: list[ValenceAnnotationPattern]

METHOD DESCRIPTION
get_fe_realization

Get realization info for a specific FE.

get_most_frequent_fe

Get the most frequently realized FE.

has_fe_realizations

Check if FE realizations exist.

Examples:

>>> valence = ValencePattern(
...     total_annotated=100,
...     fe_realizations=[...],
...     patterns=[...]
... )

Fields:

Attributes
fe_realizations: list[FERealization] pydantic-field

FE realizations

patterns: list[ValenceAnnotationPattern] pydantic-field

Valence annotation patterns

total_annotated: int pydantic-field

Total annotated instances

Functions
get_fe_realization(fe_name: str) -> FERealization | None

Get realization info for a specific FE.

PARAMETER DESCRIPTION
fe_name

Frame element name.

TYPE: str

RETURNS DESCRIPTION
FERealization | None

FE realization, or None if not found.

Source code in src/glazing/framenet/models.py
def get_fe_realization(self, fe_name: str) -> FERealization | None:
    """Get realization info for a specific FE.

    Parameters
    ----------
    fe_name : str
        Frame element name.

    Returns
    -------
    FERealization | None
        FE realization, or None if not found.
    """
    for fe_real in self.fe_realizations:
        if fe_real.fe_name == fe_name:
            return fe_real
    return None
get_most_frequent_fe() -> FERealization | None

Get the most frequently realized FE.

RETURNS DESCRIPTION
FERealization | None

Most frequent FE, or None if no realizations.

Source code in src/glazing/framenet/models.py
def get_most_frequent_fe(self) -> FERealization | None:
    """Get the most frequently realized FE.

    Returns
    -------
    FERealization | None
        Most frequent FE, or None if no realizations.
    """
    if not self.fe_realizations:
        return None
    return max(self.fe_realizations, key=lambda fe: fe.total)
has_fe_realizations() -> bool

Check if FE realizations exist.

RETURNS DESCRIPTION
bool

True if there are FE realizations.

Source code in src/glazing/framenet/models.py
def has_fe_realizations(self) -> bool:
    """Check if FE realizations exist.

    Returns
    -------
    bool
        True if there are FE realizations.
    """
    return len(self.fe_realizations) > 0

ValenceRealizationPattern pydantic-model

Bases: GlazingBaseModel

A specific realization pattern for an FE.

ATTRIBUTE DESCRIPTION
valence_units

Valence units in this pattern.

TYPE: list[ValenceUnit]

anno_set_ids

Annotation set IDs supporting this pattern.

TYPE: list[int]

total

Frequency count for this pattern.

TYPE: int

METHOD DESCRIPTION
get_pattern_signature

Get a string signature for this pattern.

has_null_instantiation

Check if pattern includes null instantiation.

Examples:

>>> pattern = ValenceRealizationPattern(
...     valence_units=[ValenceUnit(gf="Ext", pt="NP", fe="Agent")],
...     anno_set_ids=[1, 2, 3],
...     total=3
... )

Fields:

Validators:

Attributes
anno_set_ids: list[int] pydantic-field

Supporting annotation set IDs

total: int pydantic-field

Frequency count

valence_units: list[ValenceUnit] pydantic-field

Valence units in pattern

Functions
get_pattern_signature() -> str

Get a string signature for this pattern.

RETURNS DESCRIPTION
str

Pattern signature like "Ext:NP:Agent|Obj:NP:Theme".

Source code in src/glazing/framenet/models.py
def get_pattern_signature(self) -> str:
    """Get a string signature for this pattern.

    Returns
    -------
    str
        Pattern signature like "Ext:NP:Agent|Obj:NP:Theme".
    """
    units = []
    for unit in self.valence_units:
        units.append(f"{unit.gf}:{unit.pt}:{unit.fe}")
    return "|".join(units)
has_null_instantiation() -> bool

Check if pattern includes null instantiation.

RETURNS DESCRIPTION
bool

True if any valence unit is null instantiation.

Source code in src/glazing/framenet/models.py
def has_null_instantiation(self) -> bool:
    """Check if pattern includes null instantiation.

    Returns
    -------
    bool
        True if any valence unit is null instantiation.
    """
    return any(unit.is_null_instantiation() for unit in self.valence_units)
validate_consistency() -> Self pydantic-validator

Validate pattern consistency.

Source code in src/glazing/framenet/models.py
@model_validator(mode="after")
def validate_consistency(self) -> Self:
    """Validate pattern consistency."""
    if self.total > 0 and not self.anno_set_ids:
        # Allow empty anno_set_ids if total is provided
        pass
    return self

ValenceUnit pydantic-model

Bases: GlazingBaseModel

A valence unit in a realization pattern.

ATTRIBUTE DESCRIPTION
gf

Grammatical function (can be empty string or special values).

TYPE: GrammaticalFunction | str

pt

Phrase type or special values.

TYPE: PhraseType | str

fe

Frame element name.

TYPE: str

METHOD DESCRIPTION
is_null_instantiation

Check if this represents null instantiation.

has_grammatical_function

Check if a grammatical function is specified.

Examples:

>>> unit = ValenceUnit(gf="Ext", pt="NP", fe="Agent")
>>> print(unit.has_grammatical_function())
True

Fields:

  • gf (GrammaticalFunction | str)
  • pt (PhraseType | str)
  • fe (str)

Validators:

Attributes
fe: str pydantic-field

Frame element name

gf: GrammaticalFunction | str pydantic-field

Grammatical function

pt: PhraseType | str pydantic-field

Phrase type

Functions
has_grammatical_function() -> bool

Check if a grammatical function is specified.

RETURNS DESCRIPTION
bool

True if GF is not empty.

Source code in src/glazing/framenet/models.py
def has_grammatical_function(self) -> bool:
    """Check if a grammatical function is specified.

    Returns
    -------
    bool
        True if GF is not empty.
    """
    return self.gf != ""
is_null_instantiation() -> bool

Check if this represents null instantiation.

RETURNS DESCRIPTION
bool

True if this is a null instantiation pattern.

Source code in src/glazing/framenet/models.py
def is_null_instantiation(self) -> bool:
    """Check if this represents null instantiation.

    Returns
    -------
    bool
        True if this is a null instantiation pattern.
    """
    return self.pt in ["CNI", "INI", "DNI", "NI"]
validate_gf(v: str) -> str pydantic-validator

Validate grammatical function.

Source code in src/glazing/framenet/models.py
@field_validator("gf")
@classmethod
def validate_gf(cls, v: str) -> str:
    """Validate grammatical function."""
    # GF can be empty string or special null instantiation values
    if v == "" or v in ["CNI", "INI", "DNI", "NI"]:
        return v
    # Otherwise should be a valid GrammaticalFunction or pass through
    return v
validate_pt(v: str) -> str pydantic-validator

Validate phrase type.

Source code in src/glazing/framenet/models.py
@field_validator("pt")
@classmethod
def validate_pt(cls, v: str) -> str:
    """Validate phrase type."""
    # PT can be special null instantiation values
    if v in ["CNI", "INI", "DNI", "NI", "--", "unknown"]:
        return v
    # Otherwise should be a valid PhraseType or pass through
    return v

Functions