Type Reader
Types loads a type library (LV/MV cable and fuse types plus name aliases) from an Excel workbook, and resolves them by Name or alias.
from pyptp.type_reader import Types
types = Types() # bundled workbook
cable = types.get_lv_cable("4* 50 VMvK/Alk")
fuse = types.get_lv_fuse("Voorbeeld 35 A")Workbook resolution
The workbook path is resolved in this order:
- The
pathargument:Types("C:/data/my_types.xlsx") - The
PYPTP_TYPES_EXCELenvironment variable - The bundled
types.xlsxshipped with the package
Expected sheet layout
Types reads the sheets Cable, Fuse, Cable alias and Fuse alias.
| Row | Content |
|---|---|
| 0 | Column headers (Name, ShortName, Unom, ...) |
| 1 (optional) | Unit row (kV, MVA, ...) |
| 2+ | Data rows |
The unit row is detected by content, not position: a first row whose Name (or ShortName) cell is empty is treated as a unit row and skipped. Workbooks without a unit row work as-is, with the first data row preserved.
Custom column names
If your workbook uses different column headers, map them with column_renames. Keys select the loader ("lv_cable", "mv_cable", "lv_fuse", "mv_fuse") and values map source Excel header → expected header:
types = Types(
"C:/data/my_types.xlsx",
column_renames={
"lv_cable": {"R_ohm": "R_c", "Naam": "Name"},
"mv_fuse": {"Naam": "Name"},
},
)LV and MV cable types are read from the same Cable sheet, which is why renames are keyed per loader rather than per sheet.
Entries extend the built-in defaults (such as Shortname → ShortName), so those keep working unless you explicitly override them. Unknown keys are ignored with a warning.
Extending Types
For type categories Types does not load natively yet (transformers, coils, ...), subclass it and use the public helpers read_type_sheet and clean_row_dict:
from pyptp.elements.mv.transformer import TransformerMV
from pyptp.type_reader import Types, clean_row_dict, read_type_sheet
class CustomTypes(Types):
def __init__(self, path: str | None = None) -> None:
super().__init__(path)
self._trafo_by_name: dict[str, TransformerMV.TransformerType] = {}
for row in read_type_sheet(self._path, sheet_name="Trafo"):
row_dict = clean_row_dict(row)
name = str(row_dict.get("Name", "")).strip()
if not name:
continue
self._trafo_by_name[name] = TransformerMV.TransformerType.deserialize(row_dict)
def get_trafo(self, name: str) -> TransformerMV.TransformerType | None:
return self._trafo_by_name.get(str(name).strip())read_type_sheet applies the same unit-row detection as the built-in loaders and accepts a rename mapping; clean_row_dict drops empty cells so dataclass defaults apply.