Source code for npap.aggregation.modes

"""
Pre-defined aggregation modes for common use cases

Each mode provides a validated combination of:
- Topology strategy
- Physical aggregation strategy (if applicable)
- Statistical property aggregation defaults
"""

from npap.interfaces import AggregationMode, AggregationProfile


[docs] def get_mode_profile(mode: AggregationMode, **overrides) -> AggregationProfile: """ Get pre-configured aggregation profile for a given mode. Parameters ---------- mode : AggregationMode Aggregation mode enum. **overrides Override any profile parameters. Returns ------- AggregationProfile AggregationProfile configured for the mode. Examples -------- >>> profile = get_mode_profile(AggregationMode.GEOGRAPHICAL) """ if mode == AggregationMode.SIMPLE: profile = _simple_mode() elif mode == AggregationMode.GEOGRAPHICAL: profile = _geographical_mode() elif mode == AggregationMode.CUSTOM: profile = AggregationProfile(mode=AggregationMode.CUSTOM) elif mode in [AggregationMode.DC_KRON]: raise NotImplementedError( f"Mode {mode} is not yet implemented. " f"Use AggregationMode.SIMPLE or AggregationMode.GEOGRAPHICAL for now." ) else: raise ValueError(f"Unknown aggregation mode: {mode}") # Apply overrides for key, value in overrides.items(): if hasattr(profile, key): current_value = getattr(profile, key) if isinstance(current_value, dict) and isinstance(value, dict): # Add new keys or overwrites existing ones current_value.update(value) elif isinstance(current_value, list) and isinstance(value, list): # Add the user's list to the end of the existing list current_value.extend(value) else: # Replace the existing value setattr(profile, key, value) return profile
def _simple_mode() -> AggregationProfile: """ Simple aggregation mode - basic statistical aggregation Use case: Generic graph aggregation without physical constraints - Topology: Simple (no new edges) - Physical: None - Node properties: Sum numerical, first for others - Edge properties: Sum numerical, first for others """ return AggregationProfile( mode=AggregationMode.SIMPLE, topology_strategy="simple", physical_strategy=None, physical_properties=[], node_properties={}, # Will use defaults edge_properties={}, # Will use defaults default_node_strategy="sum", default_edge_strategy="sum", warn_on_defaults=False, # Simple mode uses defaults by design ) def _geographical_mode() -> AggregationProfile: """ Geographical aggregation mode Use case: Spatial network aggregation based on geographical clustering - Topology: Simple - Physical: None - Node properties: Average coordinates, sum base voltage - Edge properties: Sum p_max, average reactance (x) """ return AggregationProfile( mode=AggregationMode.GEOGRAPHICAL, topology_strategy="simple", physical_strategy=None, physical_properties=[], node_properties={ "lat": "average", # similar to middle point "lon": "average", # similar to middle point "base_voltage": "average", }, edge_properties={"p_max": "sum", "x": "average"}, default_node_strategy="average", default_edge_strategy="average", warn_on_defaults=True, )