Sensor Mapping¶
Customize how CSV sensor columns map to Brick ontology classes.
Overview¶
The sensor mapping file (sensor_to_brick_mapping.yaml) defines how CSV column names translate to Brick point classes. This allows you to:
- Customize mappings for your specific data
- Add new sensor types not in the default mapping
- Modify Brick classes for existing sensors
- Document sensor meanings with descriptions
Default Mapping File¶
The package includes a default mapping at:
This is used automatically unless you provide a custom file.
Mapping File Format¶
YAML Structure¶
Each sensor mapping has four fields:
sensor_name:
brick_class: "brick:ClassName"
description: "Human-readable description"
unit: "UNIT_TYPE"
equipment: "equipment_type"
Example Entry¶
hw_supply_temp:
brick_class: "brick:Hot_Water_Supply_Temperature_Sensor"
description: "Hot water supply temperature"
unit: "DEG_C"
equipment: "primary_loop"
Fields Explained¶
| Field | Required | Description | Example |
|---|---|---|---|
brick_class |
Yes | Full Brick class name | brick:Hot_Water_Supply_Temperature_Sensor |
description |
Yes | Sensor description | "Primary loop supply temperature" |
unit |
No | Unit of measurement | DEG_C, L_PER_MIN, KW |
equipment |
No | Associated equipment | boiler, heat_exchanger, pump |
Default Mappings¶
Temperature Sensors¶
# Primary Loop
hw_supply_temp:
brick_class: "brick:Hot_Water_Supply_Temperature_Sensor"
description: "Primary hot water supply temperature"
unit: "DEG_C"
equipment: "primary_loop"
hw_return_temp:
brick_class: "brick:Hot_Water_Return_Temperature_Sensor"
description: "Primary hot water return temperature"
unit: "DEG_C"
equipment: "primary_loop"
# Secondary Loop
secondary_supply_temp:
brick_class: "brick:Hot_Water_Supply_Temperature_Sensor"
description: "Secondary loop supply temperature"
unit: "DEG_C"
equipment: "secondary_loop"
secondary_return_temp:
brick_class: "brick:Hot_Water_Return_Temperature_Sensor"
description: "Secondary loop return temperature"
unit: "DEG_C"
equipment: "secondary_loop"
# Outdoor
outdoor_temp:
brick_class: "brick:Outside_Air_Temperature_Sensor"
description: "Outdoor air temperature"
unit: "DEG_C"
equipment: "building"
Flow Sensors¶
hw_flow:
brick_class: "brick:Water_Flow_Sensor"
description: "Primary hot water flow rate"
unit: "L_PER_MIN"
equipment: "primary_loop"
secondary_flow:
brick_class: "brick:Water_Flow_Sensor"
description: "Secondary loop flow rate"
unit: "L_PER_MIN"
equipment: "secondary_loop"
Numbered Sensors (Boilers)¶
sup1:
brick_class: "brick:Leaving_Hot_Water_Temperature_Sensor"
description: "Supply water temperature leaving boiler 1"
unit: "DEG_C"
equipment: "boiler"
ret1:
brick_class: "brick:Entering_Hot_Water_Temperature_Sensor"
description: "Return water temperature entering boiler 1"
unit: "DEG_C"
equipment: "boiler"
fire1:
brick_class: "brick:Firing_Rate_Sensor"
description: "Boiler 1 firing rate"
unit: "PERCENT"
equipment: "boiler"
Pump Sensors¶
pmp1_pwr:
brick_class: "brick:Power_Sensor"
description: "Pump 1 power consumption"
unit: "KW"
equipment: "pump"
pmp1_spd:
brick_class: "brick:Speed_Sensor"
description: "Pump 1 speed"
unit: "PERCENT"
equipment: "pump"
pmp1_vfd:
brick_class: "brick:VFD_Enable_Command"
description: "Pump 1 VFD enable status"
unit: "BINARY"
equipment: "pump"
Valves¶
hw_valve:
brick_class: "brick:Heating_Valve"
description: "Hot water control valve position"
unit: "PERCENT"
equipment: "valve"
Creating Custom Mappings¶
Step 1: Copy Default File¶
Start with the default as a template:
Step 2: Edit Mappings¶
Open custom_mapping.yaml and modify:
# Add your custom sensors
chilled_water_supply:
brick_class: "brick:Chilled_Water_Supply_Temperature_Sensor"
description: "Chilled water supply temperature"
unit: "DEG_C"
equipment: "chiller"
chilled_water_return:
brick_class: "brick:Chilled_Water_Return_Temperature_Sensor"
description: "Chilled water return temperature"
unit: "DEG_C"
equipment: "chiller"
# Modify existing mappings
outdoor_temp:
brick_class: "brick:Outside_Air_Temperature_Sensor"
description: "Custom outdoor sensor at roof level" # Changed
unit: "DEG_F" # Changed to Fahrenheit
equipment: "building"
Step 3: Use Custom Mapping¶
from hhw_brick import CSVToBrickConverter
converter = CSVToBrickConverter()
result = converter.convert_to_brick(
metadata_csv="metadata.csv",
vars_csv="vars.csv",
sensor_mapping="custom_mapping.yaml", # Your custom file
output_path="output.ttl"
)
Common Customizations¶
Add Building-Specific Sensors¶
Your building has unique sensors:
# custom_mapping.yaml
# Add solar collector sensors
solar_panel_temp:
brick_class: "brick:Solar_Panel_Temperature_Sensor"
description: "Solar thermal panel temperature"
unit: "DEG_C"
equipment: "solar_collector"
solar_flow:
brick_class: "brick:Water_Flow_Sensor"
description: "Solar collector flow rate"
unit: "L_PER_MIN"
equipment: "solar_collector"
# Add thermal storage sensors
storage_tank_top:
brick_class: "brick:Temperature_Sensor"
description: "Thermal storage tank top temperature"
unit: "DEG_C"
equipment: "thermal_storage"
storage_tank_bottom:
brick_class: "brick:Temperature_Sensor"
description: "Thermal storage tank bottom temperature"
unit: "DEG_C"
equipment: "thermal_storage"
Change Units¶
Convert between measurement systems:
# Use Fahrenheit instead of Celsius
hw_supply_temp:
brick_class: "brick:Hot_Water_Supply_Temperature_Sensor"
description: "Hot water supply temperature"
unit: "DEG_F" # Changed from DEG_C
equipment: "primary_loop"
# Use gallons per minute instead of liters
hw_flow:
brick_class: "brick:Water_Flow_Sensor"
description: "Primary hot water flow rate"
unit: "GAL_PER_MIN" # Changed from L_PER_MIN
equipment: "primary_loop"
Use More Specific Classes¶
Brick has many specialized classes:
# Instead of generic Temperature_Sensor
# Use specific class:
supply_temp:
brick_class: "brick:Leaving_Hot_Water_Temperature_Sensor" # Specific
# vs brick:Temperature_Sensor (generic)
description: "Hot water leaving temperature"
unit: "DEG_C"
equipment: "boiler"
# Instead of generic Sensor
# Use specific measurement type:
energy_meter:
brick_class: "brick:Thermal_Energy_Sensor" # Specific
# vs brick:Sensor (generic)
description: "Thermal energy meter"
unit: "KWH"
equipment: "primary_loop"
Brick Class Reference¶
Common Brick Classes¶
Temperature¶
brick:Temperature_Sensor- Genericbrick:Hot_Water_Supply_Temperature_Sensor- HW supplybrick:Hot_Water_Return_Temperature_Sensor- HW returnbrick:Leaving_Hot_Water_Temperature_Sensor- Equipment leavingbrick:Entering_Hot_Water_Temperature_Sensor- Equipment enteringbrick:Outside_Air_Temperature_Sensor- Outdoorbrick:Chilled_Water_Supply_Temperature_Sensor- CHW supplybrick:Chilled_Water_Return_Temperature_Sensor- CHW return
Flow¶
brick:Water_Flow_Sensor- Water flow ratebrick:Air_Flow_Sensor- Air flow ratebrick:Steam_Flow_Sensor- Steam flow
Pressure¶
brick:Water_Pressure_Sensor- Water pressurebrick:Steam_Pressure_Sensor- Steam pressurebrick:Differential_Pressure_Sensor- Pressure difference
Power/Energy¶
brick:Power_Sensor- Electrical powerbrick:Energy_Sensor- Energy consumptionbrick:Thermal_Power_Sensor- Thermal powerbrick:Thermal_Energy_Sensor- Thermal energy
Control¶
brick:Valve_Command- Valve positionbrick:Heating_Valve- Heating valvebrick:VFD_Enable_Command- VFD statusbrick:Speed_Setpoint- Speed setpoint
Status¶
brick:Run_Status- Equipment runningbrick:Enable_Status- Equipment enabledbrick:Alarm_Status- Alarm condition
Finding Brick Classes¶
Browse online: Brick Schema Explorer
Search in Python:
from brickschema import Graph
g = Graph(load_brick=True)
# Find all sensor types
query = """
PREFIX brick: <https://brickschema.org/schema/Brick#>
SELECT ?sensor WHERE {
?sensor rdfs:subClassOf* brick:Sensor .
}
"""
for row in g.query(query):
print(row.sensor)
Validation¶
Check Your Mapping¶
Validate mapping file structure:
import yaml
# Load mapping
with open('custom_mapping.yaml', 'r') as f:
mapping = yaml.safe_load(f)
# Check required fields
for sensor, config in mapping.items():
if 'brick_class' not in config:
print(f"❌ {sensor}: missing brick_class")
if 'description' not in config:
print(f"⚠️ {sensor}: missing description (optional)")
# Check brick_class format
if not config['brick_class'].startswith('brick:'):
print(f"⚠️ {sensor}: brick_class should start with 'brick:'")
Test Custom Mapping¶
Test with a small dataset:
from hhw_brick import CSVToBrickConverter
converter = CSVToBrickConverter()
try:
result = converter.convert_to_brick(
metadata_csv="test_metadata.csv",
vars_csv="test_vars.csv",
building_tag="105",
sensor_mapping="custom_mapping.yaml",
output_path="test_output.ttl"
)
print(f"✓ Custom mapping works! Created {len(result)} triples")
except Exception as e:
print(f"❌ Error with custom mapping: {e}")
Complete Custom Mapping Example¶
Building with Geothermal System¶
# geothermal_mapping.yaml
# Geothermal loop sensors
geo_source_supply:
brick_class: "brick:Leaving_Water_Temperature_Sensor"
description: "Geothermal source loop supply temperature"
unit: "DEG_C"
equipment: "geothermal_loop"
geo_source_return:
brick_class: "brick:Entering_Water_Temperature_Sensor"
description: "Geothermal source loop return temperature"
unit: "DEG_C"
equipment: "geothermal_loop"
geo_flow:
brick_class: "brick:Water_Flow_Sensor"
description: "Geothermal loop flow rate"
unit: "L_PER_MIN"
equipment: "geothermal_loop"
# Heat pump sensors
hp_leaving_temp:
brick_class: "brick:Leaving_Hot_Water_Temperature_Sensor"
description: "Heat pump leaving water temperature"
unit: "DEG_C"
equipment: "heat_pump"
hp_entering_temp:
brick_class: "brick:Entering_Hot_Water_Temperature_Sensor"
description: "Heat pump entering water temperature"
unit: "DEG_C"
equipment: "heat_pump"
hp_power:
brick_class: "brick:Power_Sensor"
description: "Heat pump electrical power"
unit: "KW"
equipment: "heat_pump"
hp_cop:
brick_class: "brick:Sensor"
description: "Heat pump coefficient of performance"
unit: "DIMENSIONLESS"
equipment: "heat_pump"
# Building loop (same as standard)
hw_supply_temp:
brick_class: "brick:Hot_Water_Supply_Temperature_Sensor"
description: "Building hot water supply"
unit: "DEG_C"
equipment: "building_loop"
hw_return_temp:
brick_class: "brick:Hot_Water_Return_Temperature_Sensor"
description: "Building hot water return"
unit: "DEG_C"
equipment: "building_loop"
Usage¶
from hhw_brick import CSVToBrickConverter
converter = CSVToBrickConverter()
result = converter.convert_to_brick(
metadata_csv="geothermal_buildings.csv",
vars_csv="geothermal_sensors.csv",
building_tag="205",
sensor_mapping="geothermal_mapping.yaml",
output_path="geothermal_building_205.ttl"
)
Troubleshooting¶
Issue: "Unknown sensor type"¶
Cause: Sensor in CSV not in mapping file
Solution: Add it to your custom mapping:
new_sensor:
brick_class: "brick:Sensor"
description: "New sensor type"
unit: "UNIT"
equipment: "equipment_type"
Issue: "Invalid Brick class"¶
Cause: Brick class doesn't exist
Solution: Check class name at Brick Explorer
# Wrong:
temp_sensor:
brick_class: "brick:TemperatureSensor" # No such class
# Right:
temp_sensor:
brick_class: "brick:Temperature_Sensor" # Underscores
Issue: Mapping not being used¶
Cause: File path incorrect
Solution:
import os
# Check file exists
mapping_file = "custom_mapping.yaml"
if not os.path.exists(mapping_file):
print(f"❌ File not found: {mapping_file}")
else:
print(f"✓ File exists: {os.path.abspath(mapping_file)}")
# Use absolute path
result = converter.convert_to_brick(
metadata_csv="metadata.csv",
vars_csv="vars.csv",
sensor_mapping=os.path.abspath("custom_mapping.yaml"),
output_path="output.ttl"
)
Best Practices¶
1. Start with Default¶
Don't create from scratch:
# Copy default as starting point
cp hhw_brick/conversion/sensor_to_brick_mapping.yaml my_mapping.yaml
# Edit only what you need to change
2. Use Specific Classes¶
Prefer specific Brick classes over generic:
# ✓ Good - Specific
supply_temp:
brick_class: "brick:Leaving_Hot_Water_Temperature_Sensor"
# ✗ Avoid - Too generic
supply_temp:
brick_class: "brick:Sensor"
3. Document Well¶
Write clear descriptions:
# ✓ Good - Clear description
pmp1_vfd:
brick_class: "brick:VFD_Enable_Command"
description: "Primary pump 1 variable frequency drive enable status"
unit: "BINARY"
equipment: "pump"
# ✗ Avoid - Vague
pmp1_vfd:
brick_class: "brick:VFD_Enable_Command"
description: "VFD" # Too brief
unit: "BINARY"
equipment: "pump"
4. Version Control¶
Keep mapping files in version control:
5. Test Thoroughly¶
Test with sample data before production use.
Next Steps¶
- Validation - Validate converted models
- Applications - Run analytics
- Examples - More examples
Conversion documentation complete! 🎉
Continue to Validation Guide →