Building Profiles with CIMTool¶
What is CIMTool?¶
CIMTool is an open source tool maintained by the UCAIug CIM User Group community for working with the CIM canonical model to produce design artifacts such as database schemas, message exchange syntax, source code classes, and reference documentation.
CIMTool operates on Contextual Profiles - UML-based subsets of the full CIM that define which classes, attributes, and associations are needed for a specific application. These Contextual Profiles are then used by "builders" (XSLT transforms) to generate various output formats.
CIMTool Capabilities¶
CIMTool provides comprehensive functionality for profile management:
Profile Creation and Management¶
- Create Contextual Profiles from the CIM Unified Model Language (UML)
- Import Contextual Profiles from spreadsheets
- Constrain cardinality of attributes
- Remove unwanted classes and attributes
- Document profile-specific usage notes
Schema Generation¶
- Generate Resource Description Framework Schema (RDF Schema) from Contextual Profiles
- Create XML Schema Definition (XSD) files
- Produce JSON schemas
- Generate custom formats using XSLT builders
Validation¶
- Validate Contextual Profile schemas against CIM UML
- Validate data instances against a Contextual Profile schema
- Validate incremental data instances against an existing instance
Extensibility¶
- Create custom builders using XSLT transforms
- Import custom builders to generate specialized outputs:
- Word documentation
- SQL database scripts
- Python dataclass schemas (CIMantic Graphs)
- Custom application code
The CIMantic Graphs Custom Builder¶
While CIMTool provides several built-in builders (RDF Schema, XSD, etc.), CIMantic Graphs uses a custom XSLT builder to generate Python-specific output.
The CIMantic Graphs builder actually consists of two companion builders:
- cimantic-graphs.xsl - Generates the main Python dataclass schema file
- cimantic-graphs-init.xsl - Generates the
__init__.pyfile for proper Python imports
These builders transform a CIMTool Contextual Profile into a hierarchical tree of Python dataclasses that serve as the "single-source-of-truth" for:
- Database query generation
- Graph traversal algorithms
- Type checking and validation
- IDE autocomplete and introspection
Generated Python Dataclass Structure¶
The CIMantic Graphs builder produces Python dataclasses with rich metadata that preserves all the semantic information from the CIM UML model.
Key Features of Generated Dataclasses:¶
- Inheritance Hierarchy - Preserves CIM class inheritance (e.g.,
Terminal→ACDCTerminal→IdentifiedObject) - Type Annotations - Full Python type hints for all attributes
- Field Metadata - Embedded UML metadata including:
- Field type (Attribute, Association, enumeration)
- Cardinality (minOccurs, maxOccurs)
- Inverse relationships for bidirectional associations
- Docstrings - CIM documentation embedded in Python docstrings
Example Generated Code:¶
Below is an example of the hierarchical dataclass structure generated by the builder:
Summary¶
Building custom CIM profiles with CIMTool enables you to:
- Reduce Complexity - Work with only the CIM classes needed for your application
- Improve Performance - Smaller profiles mean faster parsing and validation
- Enhance Maintainability - Focused profiles are easier to understand and maintain
- Enable Type Safety - Python dataclasses provide IDE support and type checking
- Facilitate Integration - Custom profiles can bridge between different CIM versions or add extensions
Key Takeaways:¶
- CIMTool Contextual Profiles define the UML subset
- XSLT builders transform profiles into usable formats
- CIMantic Graphs builders create Python dataclass schemas
- Start small and expand profiles iteratively
- Test early and often with real data
- Maintain profile documentation and version control
Next Steps:¶
The following notebooks will show you how to:
- Work with CIM objects and their attributes
- Manage model changes using incrementals
- Handle physical quantities with proper units
Now that you can build profiles, let's learn how to use them effectively!
Common Issues and Troubleshooting¶
Import Errors After Profile Generation¶
Problem: ModuleNotFoundError: No module named 'cimgraph.data_profile.my_profile'
Solutions:
- Verify the profile directory exists in
cimgraph/data_profile/ - Check that both
.pyand__init__.pyfiles are present - Ensure the module name in
__init__.pymatches the directory name - Restart Python interpreter to clear import cache
Invalid Dataclass Definitions¶
Problem: Generated dataclasses have syntax errors or missing attributes
Solutions:
- Verify CIMTool builder is XSLT 1.0 compliant
- Check that the CIM UML model is properly loaded in CIMTool
- Ensure all required classes have proper inheritance chains
- Re-generate the profile with updated builder versions
Missing Associations¶
Problem: Association attributes are missing or incomplete
Solutions:
- Check that both ends of the association are included in the profile
- Verify inverse relationship is properly defined in CIMTool
- Ensure association cardinality is correctly specified
- Review profile constraints on associations
Circular Import Issues¶
Problem: Circular import errors when using the profile
Solutions:
- Use string type hints for forward references (already handled by builder)
- Verify
from __future__ import annotationsis at top of generated file - Check for custom modifications that may have broken imports
Profile Doesn't Match XML Data¶
Problem: Cannot parse existing CIM XML with your profile
Solutions:
- Ensure profile includes all classes present in the XML
- Check namespace URIs match between profile and XML
- Verify CIM version compatibility (CIM16 vs CIM17 vs CIM100)
- Use incremental validation to identify specific mismatches
Best Practices for Profile Development¶
Start Small and Iterate¶
- Begin with the absolute minimum classes needed
- Test with sample data early and often
- Expand the profile gradually as requirements become clear
- Avoid "gold-plating" with unnecessary classes
Maintain Profile Documentation¶
- Document the intended use case clearly
- Keep notes on why classes were included or excluded
- Track deviations from standard CIM patterns
- Maintain a changelog as the profile evolves
Version Control Your Profiles¶
- Keep CIMTool
.owlprofile files in version control - Tag stable versions (v1.0, v2.0, etc.)
- Document breaking changes between versions
- Consider semantic versioning
Test Profile Compatibility¶
- Validate generated code imports correctly
- Test round-trip serialization (object → XML → object)
- Verify compatibility with target applications
- Check that all associations have proper inverses
Coordinate Across Teams¶
- Share profiles with other teams using the same data
- Establish naming conventions for custom profiles
- Maintain a registry of available profiles
- Reuse existing profiles when possible instead of creating new ones
# Import your custom profile
import cimgraph.data_profile.my_custom_profile as cim
# Or set it as the default profile
import os
os.environ['CIMG_CIM_PROFILE'] = 'my_custom_profile'
# Create objects using your profile
line = cim.ACLineSegment(
mRID='line-001',
name='Feeder_Line_1'
)
terminal = cim.Terminal(
mRID='term-001',
name='Line_Terminal_1'
)
print(f"Created {line.name} with mRID: {line.mRID}")
print(f"Created {terminal.name} with mRID: {terminal.mRID}")
Step 8: Use Your Custom Profile¶
Once installed, import and use your custom profile just like the built-in profiles:
Step 5: Configure the CIMantic Graphs Builders¶
Import the Builders¶
- In CIMTool, go to "Maintain XSLT Transform Builders"
- Import cimantic-graphs.xsl:
- Set type:
TEXT - Set extension:
py
- Set type:
- Import cimantic-graphs-init.xsl:
- Set type:
TEXT - Set extension:
__init__.py
- Set type:
Important Note: CIMTool requires unique file extensions for each builder. The extension determines the output filename, so __init__.py ensures the initialization file is named correctly.
Configure Builder Settings¶
In the Profile Summary tab:
- Select both CIMantic Graphs builders
- Ensure XSLT version is set to 1.0 (compatible with both builders)
- Review output directory settings
Step 6: Generate the Data Profile¶
- Click "Save" or "Generate" in CIMTool
- CIMTool will create two files:
<profile_name>.py- Main dataclass schema<profile_name>.__init__.py- Python package initialization
Step 7: Install the Data Profile¶
- Create a new directory:
cimgraph/data_profile/<profile_name>/ - Copy both generated files to this directory
- Rename if needed:
- The main
.pyfile should match your profile/namespace name - Ensure the
__init__.pyfile imports from the correct module name
- The main
Example structure:
cimgraph/
data_profile/
my_custom_profile/
__init__.py
my_custom_profile.py
Step-by-Step: Building a Profile with CIMTool¶
Prerequisites¶
- Install CIMTool - Download from UCAIug CIM User Group
- Obtain CIM UML Model - Download the base CIM UML (e.g., IEC 61970 CIM17v40)
- Install CIMantic Graphs Builders - Import the two XSLT builders into CIMTool
Step 1: Create or Open a Contextual Profile¶
In CIMTool:
- Create a new profile or open an existing
.owlprofile file - Base it on the appropriate CIM UML version (e.g., CIM17, CIM100)
- Name your profile descriptively (e.g., "DistributionTopology", "TransmissionPlanning")
Step 2: Select Classes and Attributes¶
Browse the CIM UML model and select:
- Required classes - Only classes needed for your use case
- Required attributes - Remove unnecessary attributes from selected classes
- Associations - Keep only relevant relationships between classes
Best Practice: Start with the minimum classes needed. You can always expand later.
Step 3: Configure Cardinality¶
For each attribute and association:
- Review default cardinality from base CIM
- Constrain if needed (e.g., make optional attributes required)
- Document any constraints in profile notes
Step 4: Add Profile Documentation¶
Document your profile with:
- Purpose and use case description
- Intended audience and applications
- Any deviations or constraints from base CIM
- Usage examples and patterns
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class IdentifiedObject:
'''
Root class providing common identification for all classes needing
identification and naming attributes.
'''
mRID: Optional[str] = field(
default=None,
metadata={
'type': 'Attribute',
'minOccurs': '0',
'maxOccurs': '1'
})
'''
Master resource identifier issued by a model authority. The mRID is unique
within an exchange context. Global uniqueness is easily achieved by using
a UUID, as specified in RFC 4122, for the mRID.
'''
name: Optional[str] = field(
default=None,
metadata={
'type': 'Attribute',
'minOccurs': '0',
'maxOccurs': '1'
})
@dataclass
class ACDCTerminal(IdentifiedObject):
'''
An electrical connection point (AC or DC) to a piece of conducting equipment.
Terminals are connected at physical connection points called connectivity nodes.
'''
BusNameMarker: Optional[str] = field(
default=None,
metadata={
'type': 'Association',
'minOccurs': '0',
'maxOccurs': '1',
'inverse': 'BusNameMarker.Terminal'
})
'''The bus name marker used to name the bus (topological node).'''
@dataclass
class Terminal(ACDCTerminal):
'''
An AC electrical connection point to a piece of conducting equipment.
Terminals are connected at physical connection points called connectivity nodes.
'''
phases: Optional[str] = field(
default=None,
metadata={
'type': 'enumeration',
'minOccurs': '0',
'maxOccurs': '1'
})
ConnectivityNode: Optional[str] = field(
default=None,
metadata={
'type': 'Association',
'minOccurs': '0',
'maxOccurs': '1',
'inverse': 'ConnectivityNode.Terminals'
})
'''The connectivity node to which this terminal connects.'''