API#

Example module of the python package ctao_datamodel.

AstroField(description: str | None = None, *, fits_keyword: str | None = None, ivoa_keyword: str | None = None, unit: str | None = None, ucd: str | None = None, examples: list[str] | None = None, **kwargs) Field[source]#

Return a Field with extra astronomy-related metadata.

The extra info is not for validation, but used for documentation or serialization. This is just a helper to avoid having to add a json_schema_extra dict manually.

pydantic model ModelBase[source]#

Base class for all CTAO models.

Should just set the common model_config here.

Show JSON schema
{
   "title": "ModelBase",
   "description": "Base class for all CTAO models.\n\nShould just set the common model_config here.",
   "type": "object",
   "properties": {},
   "additionalProperties": false
}

Config:
  • extra: str = forbid

class ParentInfo(item_name: str, item_type: type, is_optional: bool, parent_relation: Relation, field: FieldInfo)[source]#

Info about parent of the current element.

class PlantUMLDiagram(model_or_text: str | type[BaseModel | Enum], relations: bool = True, inheritance: bool = False, details: bool = False, max_depth: int = 1000, cwd: Path | str | None = None)[source]#

Render a PlantUML diagram in a jupyter notebook.

Diagrams can be composed using the + operator.

classmethod from_path(path) Self[source]#

Return diagram from an existing file at path.

class Relation(*values)[source]#

Parent relationship.

class StrFlag(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Like enum.Flag, but allowing string input, like A|B.

to_string() str[source]#

Turn the flag into a string representation.

all_classes_in_model(model: type[BaseModel], allowed_types=pydantic.main.BaseModel | enum.Enum)[source]#

Return all classes and related classes in the model.

classes_in_model(model: type[BaseModel], allowed_types=pydantic.main.BaseModel | enum.Enum, max_depth: int = 1000)[source]#

Return list of unique classes used in the given model.

Parameters:
modelBaseModel

model to search

allowed_typestype

Types to find. Default is BaseModel, but you can also specify e.g. BaseModel|Enum

doc(obj)[source]#

Return cleaned up docstring for the object, suitable for a description field.

enum_doc(enum: type[StrEnum]) str[source]#

Return nicer documentation for an Enum.

fits_header_to_flat_dict(header: Header, model: type[BaseModel], ignore_extra_keys: bool = True) dict[str, str][source]#

Turn a FITS header back into a flat dict of CTAO keywords.

Parameters:
header: Header

FITS header with keys and values to extract

model: type[BaseModel]

Model to use for schema and key mapping

ignore_extra_keys: bool

If False, issue warnings for keys in header that do not map to model.

Returns:
dict[str,str]:

mapping of CTAO keyword to string value.

fits_header_to_instance(header: Header, model: type[BaseModel], ignore_extra_keys: bool = True) BaseModel[source]#

Turn a FITS header back into an instance of a model.

Parameters:
header: Header

FITS header with keys and values to extract

model: type[BaseModel]

Model to use for schema and key mapping

ignore_extra_keys: bool

If False, issue warnings for keys in header that do not map to model.

Returns:
BaseModel:

instance of model provided

flatten_model_instance(model_instance: BaseModel, parent_key: str = '', separator: str = '.', to_string: bool = True, expand_lists: bool = True)[source]#

Return the flattened model instance.

Parameters:
model_instance: BaseModel

model instance to flatten (not the class!)

parent_key: str

starting key

separator: str

separator between keys

to_string: bool

if True, turn the leaf values into strings

expand_lists: bool

if True, split lists into key.N, where N is the index If this is not True, and to_string is True, the string rep of the list will be used, which might cause issues for round-tripping back to a Pydantic model.

generate_latex_table_includes(models: list[type[BaseModel]], output_dir: Path | str) None[source]#

Write descriptive LaTeX tables for given models to the output_dir.

These can then be included in latex documents.

Parameters:
models: list[BaseModel]

models to write

output_dir: Path|str

output directory

generate_plantuml_diagrams(models: list[type[BaseModel]], output_dir: Path | str, show_inheritance: bool = True, imports: bool = True, max_depth: int = 1000) None[source]#

Generate plantuml diagrams for the given models.

Parameters:
models: list[type[BaseModel]]

list of Models to generte diagrams for

output_dir: Path | str

where to write the plantuml code

show_inheritance: bool

If True, also include parent/child relations and classes

max_depth: int

maximum depth to include in the diagrams.

instance_to_fits_header(model_instance: BaseModel, use_short: bool = True, hieararch_namespace: str = 'CTAO') Header[source]#

Convert a model instance to a FITS header.

The resulting header will have a Card for each keyword. Long keywords will use the FITS HIERARCH standard in the given namespace

Parameters:
model_instance: BaseModel

model instance to serialize

use_short: bool

if True, replace any log keywords that have fits_keyword mapping with their short form.

hierarch_namespace: str

starting string for the HIERARCH keyword

Returns:
Header:

FITS header suitable for writing to a file.

keyword_mapping_latex_table(model: type[BaseModel], separator: str = '.', return_table: bool = False)[source]#

Return LaTeX table with mappings to FITS and IVOA.

Parameters:
modeltype[BaseModel]

Model class to use.

sepstr

Separator to use when generating the CTAO key

return_tablebool

if True, return the Astropy table instead of the LaTeX representation.

model_to_latex_table(model: type[BaseModel]) str[source]#

Return LaTeX table in format used by Data Model documents.

model_to_plantuml_class(model: type[BaseModel | Enum]) str[source]#

Return PlantUML class string.

model_to_plantuml_relations(model: type[BaseModel], *, max_depth=1000, import_definitions: bool = False, show_inheritance: bool = False) str[source]#

Output PlantUML relationships for a model.

By default containment relations are generated, and optionally inheritance relations.

Parameters:
model: type[BaseModel]

the model

max_depth: int

how deep to go

import_defintions: bool

include plantuml imports of the class definitions

show_inheritance: bool

include parent/child relations

Returns:
str:

PlantUML code

model_to_table(model: type[BaseModel], optional_symbol='${^\\oslash}$', type_sep: str = ' | ') Table[source]#

Turn a model into an Astropy table.

print_model(model, max_depth: int = 1000) None[source]#

Print out the model, for debugging.

related_classes_in_model(model: type[BaseModel], allowed_types=pydantic.main.BaseModel | enum.Enum) tuple[list, list][source]#

Return all parent and child classes of those in the given model.

Parameters:
modeltype[BaseModel]

Root model or module containing Pydantic/BaseModel classes.

allowed_typestype | tuple[type], optional

Only include classes that are subclasses of these types.

unflatten_model_instance(flat_dict: dict, model: type[BaseModel], parent_key: str = '', separator: str = '.') BaseModel[source]#

Return the flattened model instance.

Parameters:
flat_dict: dict

flattened dictionary of keywords, e.g. as loaded from json

model_instance: BaseModel

model instance to flatten (not the class!)

parent_key: str

starting key

separator: str

separator between keys

walk_model(model: type[BaseModel], parent_key: str = '') Generator[tuple[type, list[ParentInfo]]][source]#

Recursively walk the pydantic model.

Parameters:
model: Type[BaseModel]

Model class (not instance) to visit

parent_key: str

Key to use for first element in the model If not specified, the model name is used.

Returns:
Generator[tuple[BaseModel, list[Element]]]:

Element class and path at each step. The path is a list of ParentInfo describing the parents of the current element in order of ancestry, e.g. the current model element’s parent is path[-1], the grandparent is path[-2], …

Examples

To generate a hierarchical list of the elements and sub-elements:

>>> for model_element, path in walk_model(some_model):
>>>     name = '.'.join(p.item_name for p in path)
>>>     print(f"{'*' * (len(path)+1)} {name} : {model_element.__name__}")
*  Rererence : Reference
** process : Process
*** process.type : ObservatoryProcess
** data : Product
*** data.category : DataCategory
*** data.level : DataLevel
*** data.division : DataDivision
*** data.association : DataAssociation
*** data.type : DataType
...
walk_model_to_depth(model: type[BaseModel], max_depth: int = 1000, parent_key: str = '')[source]#

Walk the model as in walk_model, but stop at depth.