| name | co2-estimation |
| description | Calculate carbon footprint of construction projects. Estimate CO2 emissions from materials, transportation, and construction processes using emission factors databases. |
| homepage | https://datadrivenconstruction.io |
| metadata | {"openclaw":{"emoji":"🎬","os":["darwin","linux","win32"],"homepage":"https://datadrivenconstruction.io","requires":{"bins":["python3"]}}} |
CO2 Estimation for Construction
Overview
Based on DDC methodology (Chapter 3.3), this skill provides comprehensive CO2 and carbon footprint calculations for construction projects. Sustainability is no longer optional - clients and regulations demand accurate environmental impact assessments.
Book Reference: "4D, 6D-8D и расчет CO2" / "4D-8D BIM and CO2 Calculation"
"Расчет углеродного следа становится обязательным требованием для многих проектов. BIM-модель содержит все необходимые данные для автоматизации этого процесса."
— DDC Book, Chapter 3.3
Quick Start
import pandas as pd
df = pd.read_excel("bim_elements.xlsx")
emission_factors = {
'Concrete': 0.13,
'Steel': 1.85,
'Brick': 0.24,
'Timber': -1.6,
'Glass': 0.85,
'Aluminum': 8.14
}
df['CO2_kg'] = df.apply(
lambda row: row['Weight_kg'] * emission_factors.get(row['Material'], 0),
axis=1
)
total_co2 = df['CO2_kg'].sum()
print(f"Total Carbon Footprint: {total_co2:,.0f} kg CO2")
print(f"Equivalent: {total_co2/1000:,.1f} tonnes CO2")
Emission Factors Database
Material Emission Factors (Embodied Carbon)
EMISSION_FACTORS_KG = {
'Concrete_C20': 0.10,
'Concrete_C30': 0.13,
'Concrete_C40': 0.16,
'Concrete_C50': 0.19,
'Cement_Portland': 0.83,
'Mortar': 0.20,
'Steel_Reinforcing': 1.85,
'Steel_Structural': 1.55,
'Steel_Recycled': 0.47,
'Aluminum_Primary': 8.14,
'Aluminum_Recycled': 0.52,
'Copper': 2.71,
'Brick_Clay': 0.24,
'Brick_Concrete': 0.12,
'Stone_Natural': 0.06,
'Block_Concrete': 0.10,
'Timber_Softwood': -1.60,
'Timber_Hardwood': -1.40,
'Plywood': 0.45,
'CLT': -1.20,
'Glulam': -1.10,
'Insulation_Mineral': ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
:
}
EMISSION_FACTORS_M3 = {
: ,
: ,
: -,
: ,
:
}
Carbon Footprint Calculator
Basic Calculator
class CarbonCalculator:
"""Calculate carbon footprint for construction projects"""
def __init__(self, emission_factors=None):
self.factors = emission_factors or EMISSION_FACTORS_KG
self.results = {}
def calculate_embodied_carbon(self, df, material_col='Material',
weight_col='Weight_kg'):
"""Calculate embodied carbon from materials"""
df = df.copy()
df['Emission_Factor'] = df[material_col].map(self.factors).fillna(0)
df['CO2_kg'] = df[weight_col] * df['Emission_Factor']
summary = df.groupby(material_col).agg({
weight_col: 'sum',
'CO2_kg': 'sum'
}).round(2)
self.results['embodied'] = {
'total_kg': df['CO2_kg'].sum(),
'by_material': summary,
'details': df
}
return df
def calculate_transport_carbon(self, df, distance_col='Distance_km',
weight_col='Weight_kg',
transport_type=):
transport_factors = {
: ,
: ,
: ,
:
}
factor = transport_factors.get(transport_type, )
df = df.copy()
df[] = (df[weight_col] / ) * df[distance_col] * factor
.results[] = {
: df[].(),
: factor,
: transport_type
}
df
():
equipment_factors = {
: ,
: ,
: ,
: ,
: ,
:
}
equipment_hours:
construction_co2 = (
hours * equipment_factors.get(equip, )
equip, hours equipment_hours.items()
)
fuel_consumption:
construction_co2 = fuel_consumption *
:
construction_co2 =
.results[] = {
: construction_co2
}
construction_co2
():
total = (
r.get(, )
r .results.values()
)
{
: total,
: total / ,
: {k: v.get(, ) k, v .results.items()}
}
():
footprint = .get_total_footprint()
report = []
report.append( * )
report.append()
report.append( * )
report.append()
report.append()
report.append()
report.append()
category, value footprint[].items():
pct = (value / footprint[] * ) footprint[] >
report.append()
report.append()
report.append( * )
.join(report)
Usage Example
elements = pd.read_excel("bim_export.xlsx")
calc = CarbonCalculator()
elements = calc.calculate_embodied_carbon(
elements,
material_col='Material',
weight_col='Weight_kg'
)
elements['Distance_km'] = 50
elements = calc.calculate_transport_carbon(
elements,
distance_col='Distance_km',
weight_col='Weight_kg',
transport_type='truck'
)
equipment_usage = {
'excavator': 120,
'crane': 500,
'concrete_pump': 80,
'loader': 200
}
calc.calculate_construction_carbon(equipment_hours=equipment_usage)
print(calc.generate_report())
footprint = calc.get_total_footprint()
Life Cycle Assessment (LCA)
Full LCA Calculation
class ConstructionLCA:
"""Life Cycle Assessment for construction projects"""
def __init__(self, building_lifespan=50):
self.lifespan = building_lifespan
self.phases = {}
def calculate_a1_a3(self, materials_df):
"""Product stage: Raw material supply, transport, manufacturing"""
materials_df['A1_A3'] = materials_df.apply(
lambda row: row['Weight_kg'] * EMISSION_FACTORS_KG.get(row['Material'], 0),
axis=1
)
self.phases['A1-A3'] = materials_df['A1_A3'].sum()
return self.phases['A1-A3']
def calculate_a4(self, materials_df, avg_distance_km=100):
"""Transport to site"""
self.phases['A4'] = (materials_df['Weight_kg'].sum() / 1000) * avg_distance_km * 0.062
return self.phases['A4']
def calculate_a5(self, construction_energy_kwh, waste_factor=0.05):
energy_emissions = construction_energy_kwh *
.phases[] = energy_emissions
.phases[]
():
annual_operation = annual_energy_kwh *
total_operational = (annual_operation + maintenance_co2_annual) * .lifespan
.phases[] = total_operational
.phases[]
():
demolition = demolition_energy_kwh *
transport = (materials_df[].() / ) * *
disposal = materials_df[].() *
.phases[] = demolition + transport + disposal
.phases[]
():
credits = recycled_materials_df.apply(
row: -row[] * EMISSION_FACTORS_KG.get(row[], ) * ,
axis=
).() (recycled_materials_df) >
.phases[] = credits
.phases[]
():
embodied = .phases.get(, ) + .phases.get(, ) + .phases.get(, )
operational = .phases.get(, )
end_of_life = .phases.get(, )
credits = .phases.get(, )
{
: embodied,
: operational,
: end_of_life,
: credits,
: embodied + operational + end_of_life + credits,
: .phases
}
():
lca = .get_total_lca()
{
: lca[] / floor_area_m2,
: lca[] / (floor_area_m2 * .lifespan),
: lca[] / floor_area_m2
}
Reporting and Visualization
Carbon Report Generation
def generate_carbon_report(df, project_name, floor_area_m2):
"""Generate comprehensive carbon footprint report"""
total_co2 = df['CO2_kg'].sum()
co2_per_m2 = total_co2 / floor_area_m2
by_category = df.groupby('Category')['CO2_kg'].sum().sort_values(ascending=False)
by_material = df.groupby('Material')['CO2_kg'].sum().sort_values(ascending=False)
report = {
'project': project_name,
'floor_area_m2': floor_area_m2,
'total_co2_kg': total_co2,
'total_co2_tonnes': total_co2 / 1000,
'co2_per_m2': co2_per_m2,
'by_category': by_category.to_dict(),
'by_material': by_material.to_dict(),
'benchmark_comparison': classify_carbon_intensity(co2_per_m2)
}
return report
def classify_carbon_intensity(co2_per_m2):
"""Classify building carbon intensity against benchmarks"""
if co2_per_m2 < 300:
return {'rating': 'A+', 'description': 'Ultra-low carbon'}
elif co2_per_m2 < 500:
return {'rating': , : }
co2_per_m2 < :
{: , : }
co2_per_m2 < :
{: , : }
co2_per_m2 < :
{: , : }
:
{: , : }
():
pd.ExcelWriter(filepath, engine=) writer:
summary_df = pd.DataFrame({
: [, , , ],
: [
,
,
report[][],
]
})
summary_df.to_excel(writer, sheet_name=, index=)
cat_df = pd.DataFrame.from_dict(report[], orient=, columns=[])
cat_df.to_excel(writer, sheet_name=)
mat_df = pd.DataFrame.from_dict(report[], orient=, columns=[])
mat_df.to_excel(writer, sheet_name=)
Carbon Reduction Strategies
Material Optimization
def suggest_carbon_reduction(df, material_col='Material'):
"""Suggest material substitutions to reduce carbon"""
alternatives = {
'Concrete_C40': ('Concrete_C30', 0.19, 0.13),
'Steel_Structural': ('Steel_Recycled', 1.55, 0.47),
'Aluminum_Primary': ('Aluminum_Recycled', 8.14, 0.52),
'Insulation_EPS': ('Insulation_Cellulose', 3.29, 0.10),
'Brick_Clay': ('Timber_CLT', 0.24, -1.20)
}
suggestions = []
for material, (alt, current, alt_factor) in alternatives.items():
subset = df[df[material_col] == material]
if len(subset) > 0:
current_co2 = subset['Weight_kg'].sum() * current
alt_co2 = subset['Weight_kg'].sum() * alt_factor
saving = current_co2 - alt_co2
suggestions.append({
'current_material': material,
'alternative': alt,
'current_co2_kg': current_co2,
'alternative_co2_kg': alt_co2,
'potential_saving_kg': saving,
'saving_percent': (saving / current_co2 * 100) current_co2 >
})
pd.DataFrame(suggestions).sort_values(, ascending=)
Quick Reference
| Metric | Formula |
|---|
| Embodied Carbon | Weight_kg × Emission_Factor |
| Transport Carbon | (Weight_tonnes) × Distance_km × 0.062 |
| Carbon Intensity | Total_CO2 / Floor_Area_m2 |
| LCA Total | A1-A3 + A4 + A5 + B1-B7 + C1-C4 + D |
Common Emission Factors
| Material | kg CO2e/kg | kg CO2e/m³ |
|---|
| Concrete C30 | 0.13 | 312 |
| Steel (new) | 1.85 | 14,430 |
| Steel (recycled) | 0.47 | 3,666 |
| Timber | -1.60 | -800 |
| Brick | 0.24 | 432 |
| Aluminum | 8.14 | 21,978 |
Resources
- Book: "Data-Driven Construction" by Artem Boiko, Chapter 3.3
- Website: https://datadrivenconstruction.io
- ICE Database: Inventory of Carbon and Energy
- EN 15978: Sustainability of construction works standard
Next Steps
- See
cost-prediction for cost-carbon optimization
- See
qto-report for extracting quantities for CO2 calculation
- See
data-visualization for carbon dashboards