import enerhabitat as eh
import pandas as pd
import matplotlib.pyplot as plt # Comment or delete if not creating visualization
import matplotlib.dates as mdates # Comment or delete if not creating visualization
eh.config.file = "data/materials.ini"
epw_file = "data/MEX_MOR_Cuernavaca-Matamoros.Intl.AP.767260_TMYx.2004-2018.epw"Usage: 1D
The Quickstart steps applied to a homogeneous layer stack, in both modes, free-running and air-conditioned. The examples show real results for the average day of May in Cuernavaca, Mexico (the EPW and materials.ini used here live in docs/data/ in the repository), and are executed when this documentation is rendered.
Setup shared by all the examples:
Plot helper used by the examples (click to show)
EH_COLORS = {"Ti": "#2a78d6", "Tsa": "#eb6834", "Ta": "#008300", "Tn": "#6b7280"}
def plot_day(df, title=""):
"""Temperatures of the average day (with the comfort zone Tn ± DeltaTn)
and the solar irradiance components carried by the same dataframe."""
fig, (ax, axr) = plt.subplots(2, 1, figsize=(7.2, 5.8), sharex=True,
height_ratios=[3, 2])
# --- temperatures ---
# comfort zone: Tn and DeltaTn are columns (constant along the day)
ax.fill_between(df.index, df["Tn"] - df["DeltaTn"], df["Tn"] + df["DeltaTn"],
color=EH_COLORS["Tn"], alpha=0.12, lw=0)
ax.plot(df["Tn"], color=EH_COLORS["Tn"], ls="--", lw=1, label="Tn ± ΔTn")
ax.plot(df["Ta"], color=EH_COLORS["Ta"], lw=2, label="Ta")
ax.plot(df["Tsa"], color=EH_COLORS["Tsa"], lw=2, label="Tsa")
ax.plot(df["Ti"], color=EH_COLORS["Ti"], lw=2, label="Ti")
ax.set_ylabel("temperature (°C)")
ax.set_title(title, fontsize=10)
ax.legend(frameon=False, fontsize=9, loc="upper left")
# --- solar irradiance (same dataframe: Ig, Ib, Id from the EPW; Is on the
# tilted/oriented surface, computed by Tsa()) ---
axr.plot(df["Ig"], color="#f59e0b", lw=1.5, label="Ig (global horizontal)")
axr.plot(df["Ib"], color="#a16207", lw=1.5, label="Ib (direct normal)")
axr.plot(df["Id"], color="#60a5fa", lw=1.5, label="Id (diffuse horizontal)")
axr.plot(df["Is"], color="#dc2626", lw=2, label="Is (on the surface)")
axr.set_ylabel("irradiance (W/m²)")
axr.set_xlabel("hour of the average day (civil time)")
axr.legend(frameon=False, fontsize=8, loc="upper left")
# tz=... keeps the labels in local time (matplotlib defaults to UTC)
axr.xaxis.set_major_locator(mdates.HourLocator(byhour=[0, 6, 12, 18], tz=df.index.tz))
axr.xaxis.set_major_formatter(mdates.DateFormatter("%H", tz=df.index.tz))
for a in (ax, axr):
a.grid(alpha=0.25, lw=0.5)
a.spines["top"].set_visible(False)
a.spines["right"].set_visible(False)
fig.tight_layout()
plt.show()1D wall, free-running
wall = eh.System(eh.Location(epw_file))
wall.azimuth = 90 # east-facing
wall.absortance = 0.3
wall.layers = [("Mortero", 0.025), ("Ladrillo", 0.10)]
wall.location.meanDay(month=5, year=2025)
wall.Tsa()
data = wall.solve() # free-running Ti
data = pd.concat([data, wall.Tso, wall.Tsi, wall.Tsa()], axis=1)
print(f"energy_transfer = {wall.energy_transfer:,.0f} J/(m²·day)"
f" = {wall.energy_transfer/3600:,.1f} Wh/(m²·day)")energy_transfer = 31,973 J/(m²·day) = 8.9 Wh/(m²·day)
Both solvers return a pandas.Series named "Ti", indexed by time of day on the same time grid as Tsa(); that is why the pd.concat above aligns without NaN and promotes the Series to a column. The surface temperatures of the last solve are available the same way, as the read-only Series wall.Tso (outdoor surface) and wall.Tsi (indoor surface). When a DataFrame is required, convert with wall.solve().to_frame("Ti").
The time axis is civil (clock) time, inherited from the EPW, not solar time. That is why this east-facing wall keeps direct sun past 12:00: solar noon in Cuernavaca falls at about 12:33 (the site lies 9.2° west of the UTC−6 reference meridian, which adds 37 min, minus some 4 min of equation of time in May). The sharp drop in Is (mirrored by Tsa) marks that moment: the sun crosses due south and the east wall is left with diffuse irradiance only.
1D wall, air-conditioned
Same wall; solveAC() holds Ti at the neutrality temperature Tn and reports the energy needed to do so:
dataAC = wall.solveAC()
dataAC = pd.concat([dataAC, wall.Tsa()], axis=1)
print(f"cooling_energy = {wall.cooling_energy:,.0f} J/(m²·day)"
f" = {wall.cooling_energy/3600:,.1f} Wh/(m²·day)")
print(f"heating_energy = {wall.heating_energy:,.0f} J/(m²·day)"
f" = {wall.heating_energy/3600:,.1f} Wh/(m²·day)")cooling_energy = 943,968 J/(m²·day) = 262.2 Wh/(m²·day)
heating_energy = 386,936 J/(m²·day) = 107.5 Wh/(m²·day)
Where to go next
For systems whose section is not a simple layer stack (hollow blocks, joist-and-block slabs), continue with Usage — 2D. The global parameters (La, ho, hi, Nx) are documented in the configuration.

