plots#
Visualizations for energy time-series data and psychrometric charts.
See the Examples section for interactive usage examples.
Tip
Reading the comfort plots: The h,x diagram in five minutes (reading the diagram, comfort, saving energy) for plot_mollier_hx / plot_mollier_hx_fast, and Reading the comfort compass (reading the compass, comfort, saving energy) for plot_comfort_compass. The comfort-zone and warning-band ideas apply to the other comfort plots too.
Daily Profiles#
Daily profile analysis plots.
- pyedautils.plots.profiles.plot_daily_profiles_overview(data: DataFrame, title: str = 'Daily Profiles Overview by Weekday and Season', ylab: str = 'Value', confidence: float = 95.0, colors: Dict[str, str] | None = None, seasons: List[str] | None = None, weekdays: List[str] | None = None) Figure[source]#
Create a 4x7 subplot grid showing daily profiles by season and weekday.
Each subplot shows the median line with a confidence band based on quantiles. Rows represent seasons (Spring, Summer, Fall, Winter) and columns represent weekdays (Monday through Sunday).
- Parameters:
data – DataFrame with two columns: timestamp and value.
title – Plot title.
ylab – Y-axis label (shown on first column).
confidence – Confidence level for quantile bands (0-100). Default 95.
colors – Optional color overrides. Keys: “median”, “bounds”, “fill”.
seasons – Custom season names in row order. Default: Spring, Summer, Fall, Winter.
weekdays – Custom weekday names in column order. Default: Monday through Sunday.
- Returns:
Plotly figure with the subplot grid.
- Return type:
go.Figure
- pyedautils.plots.profiles.plot_daily_profiles(data: DataFrame, method: str = 'mean', loc_time_zone: str = 'UTC', title: str | None = None, ylab: str | None = None, k: int = 672, digits: int = 1)[source]#
Create a daily profile plot with one line per weekday.
Supports three methods:
"mean": Simple mean per weekday and time-of-day."decomposed": Detrend with a rolling mean, extract the seasonal component, and normalise each weekday to start at 0 at midnight."overlayed": All individual daily profiles overlaid in blue. Hovering highlights the entire day-line in orange (requires JS).
- Parameters:
data – DataFrame with two columns: timestamp and value.
method – Aggregation method —
"mean","decomposed", or"overlayed".loc_time_zone – Timezone for localization (e.g. “Europe/Zurich”). Default “UTC”.
title – Plot title. Auto-set per method if None.
ylab – Y-axis label. Auto-set per method if None.
k – Rolling window size for trend (only used with
"decomposed"). Default 672 (7 days at 15-min resolution).digits – Number of decimal places for rounding. Default 1.
- Returns:
go.Figure for
"mean"/"decomposed", or str (self-contained HTML) for"overlayed".
Heatmaps#
Heatmap visualization plots.
- pyedautils.plots.heatmaps.plot_heatmap_median_weeks(data: DataFrame, title: str = 'Heatmap Median per Hour by Weekday and Season', ylab: str = 'Energy Consumption (kWh/h)', seasons: List[str] | None = None, colorscale: str = 'Magma') Figure[source]#
Create a heatmap of median values per hour, grouped by weekday and season.
Each season is shown as a separate subplot column. The y-axis shows weekdays (Monday at top, Sunday at bottom), the x-axis shows the hour of day (0-23), and the color intensity represents the median value.
- Parameters:
data – DataFrame with two columns: timestamp and value.
title – Plot title.
ylab – Colorbar title / value label.
seasons – Custom season names in column order. Default: Spring, Summer, Fall, Winter.
colorscale – Plotly colorscale name. Default “Magma” (≈ viridis option B).
- Returns:
Plotly figure with one heatmap subplot per season.
- Return type:
go.Figure
- pyedautils.plots.heatmaps.plot_heatmap_calendar(data: DataFrame, title: str = 'Calendar Heatmap', ylab: str = 'Energy Consumption (kWh/d)', colorscale: str = 'Magma') Figure[source]#
Create a calendar heatmap of daily aggregated values.
Each cell represents one day, coloured by the aggregated daily value. Rows are weekdays (Mon–Sun), columns are calendar weeks, and each year is shown as a separate subplot row.
- Parameters:
data – DataFrame with two columns: timestamp and value.
title – Plot title.
ylab – Colorbar title / value label.
colorscale – Plotly colorscale name. Default “Magma” (≈ viridis option B).
- Returns:
Plotly figure with one subplot row per year.
- Return type:
go.Figure
Energy Signature#
Energy signature plots.
- pyedautils.plots.energy.plot_energy_signature(data: DataFrame, title: str = 'Building Energy Signature', xlab: str = 'Outside Temperature [°C]', ylab: str = 'Energy Consumption [kWh/d]', colors: Dict[str, str] | None = None) Figure[source]#
Create a scatter plot of daily energy consumption vs outside temperature.
Each point represents one day, colored by season. The input DataFrame is aggregated to daily resolution (mean temperature, sum of value).
- Parameters:
data – DataFrame with columns
[timestamp, temperature, value].title – Plot title.
xlab – X-axis label.
ylab – Y-axis label.
colors – Season color overrides keyed by season name. Default uses
DEFAULT_SEASON_COLORS.
- Returns:
Plotly figure with the scatter plot.
- Return type:
go.Figure
- pyedautils.plots.energy.plot_energy_signature_pes(data: DataFrame, p_ihg: float = 0.0, title: str = 'Proposed Energy Signature', xlab: str = 'Outside Temperature [°C]', ylab: str = 'Power [kW]', colors: Dict[str, str] | None = None) Figure[source]#
Create a Proposed Energy Signature plot with regression lines.
Computes the PES parameters (balance temperature, heat loss coefficient, standby and hot-water power) and overlays the characteristic lines on a daily scatter plot colored by season.
- Parameters:
data – DataFrame with columns
[timestamp, outside_temp, power, room_temp].p_ihg – Internal heat gains [kW]. Default 0.
title – Plot title.
xlab – X-axis label.
ylab – Y-axis label.
colors – Season color overrides keyed by season name.
- Returns:
Plotly figure with scatter and regression lines.
- Return type:
go.Figure
Seasonal Patterns#
Seasonal and temporal pattern plots.
- pyedautils.plots.seasonal.plot_seasonal_overlapping(data: DataFrame, title: str = 'Seasonal Plot — Overlapping', ylab: str = 'Value') Figure[source]#
Seasonal plot with one line per year overlaid on the same x-axis (month).
- Parameters:
data – DataFrame with columns
[timestamp, value]. Monthly data; value should be normalised (e.g. kWh/day).title – Plot title.
ylab – Y-axis label.
- Returns:
go.Figure
- pyedautils.plots.seasonal.plot_seasonal_miniplots(data: DataFrame, title: str = 'Seasonal Miniplots', ylab: str = 'Value') Figure[source]#
Seasonal subseries plot — one mini panel per month showing values across years.
A horizontal blue line shows the per-month mean.
- Parameters:
data – DataFrame with columns
[timestamp, value].title – Plot title.
ylab – Y-axis label.
- Returns:
go.Figure
- pyedautils.plots.seasonal.plot_seasonal_before_after(data: DataFrame, date_optimization: str, title: str = 'Seasonal — Before/After Optimization', ylab: str = 'Value', confidence: float = 95.0) Figure[source]#
Seasonal plot highlighting before/after an optimization date.
Years before the optimization are shown in grey with a confidence band; years after are shown in colour.
- Parameters:
data – DataFrame with columns
[timestamp, value].date_optimization – Date string (e.g.
"2017-09-01"). Years starting after this date are “after”.title – Plot title.
ylab – Y-axis label.
confidence – Confidence level for the “before” band (0-100).
- Returns:
go.Figure
- pyedautils.plots.seasonal.plot_seasonal_polar(data: DataFrame, title: str = 'Seasonal Plot — Polar', ylab: str = 'Value') Figure[source]#
Seasonal plot in polar coordinates — one line per year.
- Parameters:
data – DataFrame with columns
[timestamp, value].title – Plot title.
ylab – Radial axis label.
- Returns:
go.Figure
- pyedautils.plots.seasonal.plot_density_seasons(data: DataFrame, title: str = 'Density Plot by Season', xlab: str = 'Value', ylab: str = 'Density', colors: Dict[str, str] | None = None) Figure[source]#
Create a kernel density plot of a value column, one curve per season.
- Parameters:
data – DataFrame with two columns: timestamp and value.
title – Plot title.
xlab – X-axis label.
ylab – Y-axis label.
colors – Season color overrides keyed by season name. Default uses
DEFAULT_SEASON_COLORS.
- Returns:
Plotly figure with one density trace per season.
- Return type:
go.Figure
Thermal Comfort#
Comfort compass (pyedautils.plots.comfort.plot_comfort_compass()):
the dashed circle is the area of 100 % of the days; the green disc (share in
range) and the eight arms (deviation directions, mild / moderate / severe from
the inside out) always add up to exactly that area.
The green disc says what it means: share plus the in-range word (
names["ok"]). When the disc is too small only the share is printed, or nothing; without the legend a caption below the glyph gives it instead (● 8% in range).Each direction label sits at the end of its own arm, anchored outward.
scale="fixed"(default, same asfixed_scale=True): the dashed 100 % circle has the same size in every chart, so rooms can be compared by area.scale="fit": zoomed to this glyph and its labels; compare such charts by their percentages only.scaletakes precedence overfixed_scale.Every visible text can be passed:
title,names,direction_labels,stage_names,count_label/count_label_singular,stats_text. German presets:_COMPASS_NAMES_DE,_COMPASS_LABELS_DE,_COMPASS_STAGE_NAMES_DEinpyedautils.plots.comfort.
Thermal comfort and psychrometric chart plots.
- pyedautils.plots.comfort.plot_comfort_sia180(data_outdoor: DataFrame, data_room: DataFrame, title: str = 'Thermal Comfort according to SIA 180:2014', colors: Dict[str, str] | None = None) Figure[source]#
SIA 180:2014 thermal comfort plot.
Scatter of room temperature vs 48-hour rolling mean outdoor temperature, colored by season, with SIA 180 comfort boundaries.
- Parameters:
data_outdoor – DataFrame
[timestamp, value]with outdoor temp.data_room – DataFrame
[timestamp, value]with room temp.title – Plot title.
colors – Season color overrides.
- Returns:
go.Figure
See also
Why temperature and humidity belong together, and how to save energy without losing comfort: https://retomarek.github.io/pyedautils/guides/mollier_hx.html#hx-comfort
- pyedautils.plots.comfort.plot_comfort_temp_humidity(data: DataFrame, title: str = 'Temperature vs Humidity Comfort Plot', colors: Dict[str, str] | None = None) Figure[source]#
Scatter of daily mean temperature vs humidity with comfort zones.
Shows two comfort zone polygons: “comfortable” (green) and “still comfortable” (orange), based on common building standards.
- Parameters:
data – DataFrame with
timestamp,temperatureandhumiditycolumns (read by name, so the order does not matter). Humidity in %rH, temperature in °C.title – Plot title.
colors – Season color overrides.
- Returns:
go.Figure
See also
The same data as an h,x diagram (
plot_mollier_hx()), and how to read comfort zone, mould risk and energy saving from it: https://retomarek.github.io/pyedautils/guides/mollier_hx.html#hx-reading-the-diagram
- pyedautils.plots.comfort.MOLLIER_DEFAULT_CAPTIONS: Dict[str, str] = {'density': 'Density ρ [kg/m³]', 'enthalpy': 'Enthalpy [kJ/kg]', 'rel_humidity': 'rel. humidity φ [%]', 'temperature': 'Temperature ϑ [°C]', 'x_axis': 'x [g/kg]', 'x_axis_title': 'absolute water content x [g/kg]'}#
Captions of the h,x-diagram grid (English defaults) for the
captionsargument ofplot_mollier_hx()/plot_mollier_hx_fast(). Copy and translate as needed;""hides a caption.x_axis_titledefaults to thex_axis_titleargument.
- pyedautils.plots.comfort.MOLLIER_DEFAULT_TEXTS: Dict[str, str] = {'altitude': '{alt} m a.s.l.', 'comfort_zone': 'Comfort zone', 'freq_days': '{n} days/year outside', 'freq_hours': '{n} h/year outside', 'latest': 'Latest', 'now': 'Now', 'outdoor': 'Outside air', 'pressure': '{hpa} hPa', 'room': 'Room', 'season_fall': 'Fall', 'season_spring': 'Spring', 'season_summer': 'Summer', 'season_winter': 'Winter', 'state_value': '{t} °C · {rh} %', 'tip_h': 'h', 'tip_phi': 'φ', 'tip_t': 'T', 'tip_td': 'Td', 'tip_x': 'x', 'ventilation_dries': 'ventilating dries', 'ventilation_humidifies': 'ventilating adds moisture', 'ventilation_neutral': 'ventilating: no change'}#
All other visible texts of
plot_mollier_hx()/plot_mollier_hx_fast()(English defaults) for theirtextsargument. Placeholders in braces are filled in:{t}°C,{rh}%,{x}g/kg,{n}count,{alt}m,{hpa}hPa.""hides the altitude / pressure line and the ventilation note.
- pyedautils.plots.comfort.plot_mollier_hx(data: DataFrame | None = None, pressure: float | None = None, altitude: float | None = None, domain_x: Tuple[float, float] = (0.0, 0.02), domain_y: Tuple[float, float] = (-20.0, 50.0), comfort_zone: Dict[str, Tuple[float, float]] | None = None, height: int = 700, convention: str = 'classical', highlight_latest: bool = True, highlight_color: str | None = 'black', states: Sequence | None = None, labels: List[str] | None = None, comfort_label: str = 'Comfort zone', comfort_zone_orange: Dict[str, object] | None = None, comfort_zone_red: Dict[str, object] | None = None, show_temperature: bool = True, show_density: bool = True, show_rel_humidity: bool = True, show_enthalpy: bool = True, show_abs_humidity: bool = True, x_axis_title: str = 'absolute water content x [g/kg]', season_labels: Dict[str, str] | None = None, show_frequency: bool = False, frequency_unit: str = 'hours', frequency_smoothing: float = 4.0, outdoor: Tuple[float, float] | None = None, current: Tuple[float, float] | None = None, outdoor_color: str = '#2563eb', ventilation_line: bool = True, ventilation_note: bool = True, ventilation_threshold: float = 0.0003, captions: Dict[str, str] | None = None, texts: Dict[str, str] | None = None) str[source]#
Create a Mollier h,x-diagram (psychrometric chart) as self-contained HTML.
Uses D3.js (v7) for fast SVG rendering with iso-lines for temperature, enthalpy, relative humidity and density, a comfort zone, and optional measured data points colour-coded by season with interactive hover tooltips. Optionally shows the outside air with the ventilation (mixing) line from the room point and a note on whether airing dries the room.
Data points, comfort zone, warning bands and frequency lines are clipped to the axes. The room point and the outside point are drawn on top; a point outside the axes becomes an arrow on the edge pointing towards it, labelled with its value (e.g.
6.8 °C · 89 %).Every visible text can be replaced through
captions(axis captions) andtexts(everything else); the defaults are English. SeeMOLLIER_DEFAULT_CAPTIONSandMOLLIER_DEFAULT_TEXTSfor the keys.- Parameters:
data – Optional DataFrame with columns [timestamp, humidity, temperature]. humidity in %, temperature in °C.
pressure – Air pressure in Pa used for all psychrometric relations and shown in the top-right corner in hPa. When
None(default), it is derived fromaltitudevia the ISA barometric formula (pyedautils.psychrometrics.pressure_from_altitude()), or 101325 Pa (sea level) without an altitude. An explicit pressure always wins;altitudeis then only the label.altitude – Optional altitude in metres above sea level. Sets the pressure when
pressureis not given (altitude=450gives 960 hPa) and is shown together with the pressure in the top-right corner. WhenNone, the shown altitude is derived frompressurevia the inverse ISA barometric formula.domain_x – Range of absolute humidity [kg/kg] for the x-axis.
domain_y – Range of the y-coordinate (≈ temperature at x=0) for the y-axis.
comfort_zone – Dict with keys “temperature”, “rel_humidity”, “abs_humidity”, each a (min, max) tuple. Defaults: T=[20, 26], phi=[0.30, 0.65], x=[0, 0.0115].
"abs_humidity": None(or aNoneupper bound, e.g.(0, None)) means no abs-humidity limit — the zone is bounded by T and φ only, likehum_abs_band=Noneofpyedautils.comfort.comfort_compass_distribution(); a missing key keeps the default 0.0115 kg/kg cap. PassFalseto disable the comfort zone.height – Diagram height in pixels. Default 700.
convention – Mollier coordinate convention.
'classical'(default) normalises enthalpy per kg of dry air (Recknagel/Sprenger style, isotherms tilt slightly up with x).'glueck'normalises per kg of moist air (per the Glück book, isotherms tilt slightly down).highlight_latest – When
True(default), the row with the most recent timestamp is overlaid as a circle on top of the seasonal scatter points (the room point, also the start of the ventilation line). Set toFalseto disable. Ignored whencurrentis given.highlight_color – CSS colour of the room point (latest row or
current). Default'black'. PassNoneto use the latest row’s season colour (so the highlight is visible only by size/order, not by colour; black forcurrent).states – Optional sequence of
MoistAirStateobjects (frompyedautils.psychrometrics.state()). When supplied, each state is drawn as a numbered point and consecutive states are connected by arrows — a psychrometric process chain in the spirit of psychrosim.com. Works alongsidedata(historical scatter is drawn underneath).labels – Optional sequence of strings used as point labels (default is the number
"1","2", …). Length must matchstates.comfort_label – Legend caption for the comfort-zone polygon. Default
"Comfort zone". Override e.g. to"Komfortzone"for German output or to a custom designation like"DIN EN 16798 Cat II". Same astexts["comfort_zone"](which wins if both are given).comfort_zone_orange –
Optional warning band drawn as a dashed orange outline (no fill). Off by default (
None). A dict with keys"temperature","rel_humidity","abs_humidity", each eithera
(min, max)tuple — absolute bounds in °C, 0–1 and kg/kg, e.g.{"temperature": (19, 27), "rel_humidity": (0.25, 0.70)}; ora scalar — a ± offset around the
comfort_zonebounds in K, rel.-humidity fraction and kg/kg, e.g.{"temperature": 1, "rel_humidity": 0.05, "abs_humidity": 0.001}for ±1 K / ±5 %-points / ±1 g/kg.
Both forms may be mixed per key. A dict without any offset keeps the absolute defaults T=[20, 26], φ=[0.30, 0.65] for missing keys and leaves the abs. humidity unclipped (the band follows its T/φ bounds). A dict with at least one offset fills missing keys with the default offsets of the band (orange: 1 K / 0.05 / 0.001 kg/kg, red: 2.5 K / 0.10 / 0.0025 kg/kg).
Trueuses all default offsets."abs_humidity": Nonemeans no upper limit (as does an offset band around a comfort zone without abs-humidity limit). Optional"label"(legend caption) and"color"(CSS colour). The default offsets are the severity-stage limits ofpyedautils.comfort.comfort_compass_distribution(); usepyedautils.comfort.comfort_warning_bands()to derive both bands from the same stage limits as the comfort compass. Offsets need a comfort zone (ValueErrorwithcomfort_zone=False).comfort_zone_red – Like
comfort_zone_orangebut drawn as a dashed red outline — e.g. the ±2.5 K / ±10 % band. Keys given as offsets are widened where needed to enclose the orange band, so the stages never overlap.show_temperature – Draw the iso-temperature lines. Default
True. The temperature y-axis itself is always shown (it is the chart’s coordinate base) — this only toggles the blue iso-lines.show_density – Draw the iso-density curves together with their value labels and the
"Density ρ [kg/m³]"caption. DefaultTrue. SetFalseto hide everything density-related.show_rel_humidity – Draw the relative-humidity (φ) curves and their value labels. Default
True. The 100 % saturation curve (the chart boundary) is always drawn regardless of this flag.show_enthalpy – Draw the iso-enthalpy lines together with their value labels and the
"Enthalpy [kJ/kg]"caption. DefaultTrue. SetFalseto hide everything enthalpy-related.show_abs_humidity – Draw the vertical iso-lines of constant absolute humidity (at the bottom-axis tick values). Default
True.x_axis_title – Caption centred below the bottom axis. Default
"absolute water content x [g/kg]". Pass""to omit it. Same ascaptions["x_axis_title"](which wins if both are given).season_labels – Optional mapping from the English season keys
"Winter","Spring","Summer","Fall"to the labels shown in the seasonal scatter tooltips and legend. Defaults to the English keys themselves. Passpyedautils.plots._constants._SEASON_LABELS_DE(or any custom dict) for German output. Same astexts["season_winter"]etc. (which win if both are given).show_frequency – Draw cumulative-frequency contour lines (“risk hours/days”) over the scatter. Each line labelled N encloses all but N units of the year, so the outer lines mark rare conditions and the inner lines the typical core. Requires
data. DefaultFalse.frequency_unit – Unit counted by the frequency lines —
"hours"(default; line N = N hours/year outside) or"days"(line N = N distinct calendar days/year with at least one hour outside).frequency_smoothing – Line-rounding amount for the frequency lines, ~0.6 (angular) to ~9 (very round). Default
4.0. Purely geometric — it rounds the curves but never enlarges the enclosed region.outdoor – Optional outside air as
(temperature [°C], relative humidity [%])— the same units as thedatacolumns, e.g.(4.0, 85). Drawn as a hollow circle (an edge arrow when outside the axes). With a room point (currentor the latest row) a dashed ventilation line joins the two: airing moves the room air along it. A note above the axes says whether airing dries the room (outside air holds more thanventilation_thresholdless water), adds moisture (more), or makes no noticeable change — seepyedautils.comfort.ventilation_effect().current – Optional room point as
(temperature [°C], relative humidity [%]), e.g. a live reading. Replaces the latest-row highlight as the room point; works withoutdata.outdoor_color – CSS colour of the outside point, the ventilation line and the note. Default
'#2563eb'(blue).ventilation_line – Draw the ventilation line (and the note) between the room point and
outdoor. DefaultTrue.ventilation_note – Show the ventilation note above the axes. Default
True; needs the ventilation line.ventilation_threshold – Difference in absolute humidity [kg/kg] up to which airing counts as “no change”. Default
0.0003(0.3 g/kg).captions – Optional dict overriding the axis captions, merged over
MOLLIER_DEFAULT_CAPTIONS(keystemperature,rel_humidity,density,enthalpy,x_axis,x_axis_title).""hides a caption. The right-edge captions shrink (8–12 px) to fit the chart height. Unknown keys raiseValueError.texts –
Optional dict overriding any other visible text, merged over
MOLLIER_DEFAULT_TEXTS: outside air and ventilation note, edge-arrow value label, tooltips, frequency-line tooltip, altitude / pressure line, legend (comfort zone, seasons, room point).""hides the altitude / pressure line or the note. Unknown keys raiseValueError. Example (German):texts={"outdoor": "Aussenluft", "room": "Raum", "ventilation_dries": "Lüften trocknet", "ventilation_humidifies": "Lüften befeuchtet", "ventilation_neutral": "Lüften: keine Änderung", "altitude": "{alt} m ü. M.", "latest": "Letzter Wert"}
- Returns:
- Self-contained HTML string with inline D3.js rendering.
Can be saved to a file, used with
streamlit.components.v1.html(), or displayed in a Jupyter notebook viaIPython.display.HTML().
- Return type:
str
See also
How to read the h,x diagram correctly, what the comfort zone and warning bands mean, and how to save energy: https://retomarek.github.io/pyedautils/guides/mollier_hx.html
- pyedautils.plots.comfort.plot_comfort_donuts(data: DataFrame, temp_range: Tuple[float, float] = (20.0, 26.0), hum_range: Tuple[float, float] = (30.0, 65.0), title: str | None = None, temp_colors: Tuple[str, str, str] = ('#3498DB', '#2ECC71', '#E74C3C'), hum_colors: Tuple[str, str, str] = ('#F39C12', '#2ECC71', '#3498DB'), count_label: str = 'days', show_center_stats: bool = True) Figure[source]#
Two donut charts showing time spent below / within / above comfort.
The left donut splits temperature into too cold / in range / too warm, the right donut splits humidity into too dry / in range / too humid. Each slice shows its share inside the ring; the centre shows the average with the min–max range; and each donut has its own vertical bullet-point legend listing the slice counts and percentages (e.g. number of days when the input is daily data). Hover tooltips show the count and the percentage.
- Parameters:
data – DataFrame with columns
temperature[°C] andhumidity[%rH] (extra columns are ignored).temp_range –
(min, max)comfort temperature band [°C].hum_range –
(min, max)comfort humidity band [%rH].title – Overall figure title. Default None.
temp_colors – Colors for (cold, in range, warm).
hum_colors – Colors for (dry, in range, humid).
count_label – Unit word for the per-slice counts, used in the legend and tooltips (e.g.
"days"->"In range — 42 days").show_center_stats – Draw the average and min–max range in the centre of each donut. Default True.
- Returns:
Plotly figure with two donut traces and a vertical bullet-point legend under each.
- Return type:
go.Figure
See also
plot_comfort_compass()for the direction of the deviations, and what the comfort zone and warning bands mean: https://retomarek.github.io/pyedautils/guides/comfort_compass.html#compass-comfort
- pyedautils.plots.comfort.plot_comfort_compass(distribution, title: str | None = None, show_direction_labels: bool = True, show_legend: bool = True, count_label: str = 'days', direction_labels: List[str] | None = None, names: Dict[str, str] | None = None, stage_names: Dict[str, str] | None = None, fixed_scale: bool = True, stats_text: str | None = None, count_label_singular: str | None = None, height: int = 460, scale: str | None = None, width: int | None = None) Figure[source]#
Area-true “comfort compass” glyph for one room / group.
A single equal-area polar glyph summarising how a room’s days split across the nine comfort states (see
pyedautils.comfort.comfort_compass_distribution()):Centre — a green disc whose area is the share of days in range. It says what green means: the share and the in-range word (
names["ok"], default"in range"), e.g.52%/in range. When the disc is too small for both lines only the share is printed inside, and when even that does not fit, nothing. Without the legend (show_legend=False) a caption below the glyph then gives the share instead, e.g.● 8% in range; with the legend its first row does.Eight wedges — one per deviation direction; the wedge area is the share of days, and the three radial sub-segments (inner → outer) split that share by severity. Severity is encoded as lightness on three fixed planes shared by all directions — mild is always the lightest shade in the glyph, severe always the darkest — so the shade alone identifies the stage. Orientation matches an h,x diagram: warm top, cold bottom, humid right, dry left; mixed directions blend the hues of their two poles.
Direction labels — each label sits just beyond the end of its own arm (at least the dashed circle), anchored outward and moved out until its text box clears the whole glyph (disc and neighbouring arms). Label lines longer than 14 characters are wrapped at spaces; a label that would still run off the figure is drawn smaller (down to 7 px).
Every glyph has the same total area (= 100 % of days) — only the shape tells the story. With
scale="fixed"(the default, same asfixed_scale=True) the radial axis is framed to the worst-case extent, so the dashed reference circle is drawn at the same size in every chart and glyphs stay directly comparable by area. Withscale="fit"the glyph is zoomed so that it and its labels fill the panel; the circle — and thus the scale — then differs from chart to chart, so compare such charts by their percentages only.
The percentages are listed in a donut-style bullet legend on the right — each deviation row shows the count, the total share and its mild/moderate/severe split (e.g.
(19% → 5/4/10%)) — followed by a grey severity key (mild / moderate / severe swatches on the same three lightness planes). Hovering a segment shows only that segment: direction · stage, its count and share.- Parameters:
distribution – Mapping of comfort-compass categories to counts, as returned by
pyedautils.comfort.comfort_compass_distribution()(keys"ok"and"<direction>_<stage>"; missing keys count as 0). Percentages and areas are derived from the counts.title – Figure title; a muted subtitle underneath shows the total count (e.g.
265 days). Default None.show_direction_labels – Draw the eight direction labels around the rose. Default True.
show_legend – Draw the bullet legend with the per-direction counts and percentages. Default True.
count_label – Unit word for the counts in legend, hover and title subtitle (e.g.
"days","hours"). Default"days".direction_labels – Optional 8 labels for the rose (order: humid, warm+humid, warm, warm+dry, dry, cold+dry, cold, cold+humid). Use
"<br>"for line breaks. Default English; passpyedautils.plots.comfort._COMPASS_LABELS_DEfor German.names – Optional mapping overriding the direction names in legend and hover and the in-range word in the green disc / caption (keys
"ok"and"f","wf","w","wt","t","ct","c","kf"; missing keys keep the English default). Pass_COMPASS_NAMES_DEfor German.stage_names – Optional mapping overriding the severity-stage names shown in the hover and the severity key (keys
"l"mild,"d"moderate,"s"severe). Default English; pass_COMPASS_STAGE_NAMES_DEfor German.fixed_scale – Keep the radial axis fixed to the worst-case extent so the dashed 100 % reference circle is the same size in every chart, keeping glyphs from different rooms/periods directly comparable. Default
True.Falseis the same asscale="fit". Ignored whenscaleis given.stats_text – Optional extra text block (e.g. min/mean/max readings) rendered left-aligned below the legend (
<br>for line breaks, inline HTML spans allowed). Withshow_legend=Falseit is drawn on its own in the legend column. Default None (off).count_label_singular – Optional singular unit word used in the legend, hover and title subtitle when a count is exactly 1 (e.g. pass
count_label="Tage", count_label_singular="Tag"for German). Default None (always usecount_label).height – Figure height in pixels. Default 460.
scale –
"fixed"(same 100 % circle in every chart) or"fit"(zoomed to this glyph and its labels). Takes precedence overfixed_scale; default None usesfixed_scale.width – Optional figure width in pixels. Default None (Plotly’s default / container width). Whether the texts fit into the green disc is estimated for this width (700 px when None).
All visible texts can be set by the caller:
title,count_label/count_label_singular,names(incl. the in-range word),direction_labels,stage_namesandstats_text; the remaining characters are numbers,%and symbols. Example for German:from pyedautils.plots.comfort import ( _COMPASS_LABELS_DE, _COMPASS_NAMES_DE, _COMPASS_STAGE_NAMES_DE) plot_comfort_compass(dist, title="Schlafzimmer", names=_COMPASS_NAMES_DE, direction_labels=_COMPASS_LABELS_DE, stage_names=_COMPASS_STAGE_NAMES_DE, count_label="Tage", count_label_singular="Tag")
- Returns:
go.Figure
- Raises:
ValueError – If
scaleis notNone,"fixed"or"fit".
See also
How to read the compass, compare rooms (
scale), and what the arms mean for comfort and energy: https://retomarek.github.io/pyedautils/guides/comfort_compass.html
- pyedautils.plots.comfort.plot_overheating_timeseries(aligned: DataFrame, method: str = 'adaptive', summer_only: bool = True, business_hours_only: bool = False, title: str = 'Overheating — temperature curve', ylab: str = 'Temperature [°C]', height: int = 400) Figure[source]#
Room-temperature curve with the comfort threshold and overheating marks.
Mirrors the temperature plot of the Streamlit overheating page: the room temperature as a line, the (adaptive or fixed) comfort threshold as a dashed line, and the samples above the threshold highlighted as red markers.
- Parameters:
aligned – DataFrame indexed by timestamp with columns
[t_room, t_oa, t_oa_48h](seepyedautils.comfort.align_hourly()).method –
"adaptive"(SIA 180 curve) or"fixed"(26.5 °C), passed topyedautils.comfort.overheating_hours().summer_only – Restrict the threshold/markers to the SIA 180 summer half-year. Default
True.business_hours_only – Restrict to 07:00–22:00. Default
False.title – Plot title.
ylab – Y-axis label.
height – Figure height in pixels. Default 400.
- Returns:
go.Figure
- pyedautils.plots.comfort.plot_overheating_bar(monthly: DataFrame, month_col: str = 'month', hours_col: str = 'hours', title: str = 'Overheating hours per month', ylab: str = 'Hours [h]', color: str = '#f59e0b', height: int = 400) Figure[source]#
Bar chart of overheating hours per calendar month.
Mirrors the monthly bar of the Streamlit overheating page: one amber bar per month (Jan–Dec, missing months shown as zero) with the hour count labelled above each bar.
- Parameters:
monthly – DataFrame with a month column (1–12) and an hours column, e.g. the output of
pyedautils.comfort.overheating_per_month().month_col – Month column name (values 1–12). Default
"month".hours_col – Overheating-hours column name. Default
"hours".title – Plot title.
ylab – Y-axis label.
color – Bar colour.
height – Figure height in pixels. Default 400.
- Returns:
go.Figure
- pyedautils.plots.comfort.plot_temp_humidity_timeseries(data: DataFrame, temp_band: Tuple[float, float] | None = (20.0, 26.0), hum_band: Tuple[float, float] | None = (30.0, 65.0), temp_band_orange: Tuple[float, float] | None = (19.0, 27.0), hum_band_orange: Tuple[float, float] | None = (25.0, 70.0), temp_band_red: Tuple[float, float] | None = (17.5, 28.5), hum_band_red: Tuple[float, float] | None = (20.0, 75.0), show_hourly: bool = True, show_daily_mean: bool = True, temp_title: str | None = None, hum_title: str | None = None, title: str = 'Temperature & humidity over time', height: int = 600) Figure[source]#
Temperature and humidity time series with comfort and warning limits.
Two stacked subplots (temperature on top, humidity below, shared time axis). Each shows the hourly readings as faint dots and the daily-mean as a bold line, plus — when given — the green comfort target band (filled, with a solid edge line top and bottom) and the moderate and severe warning limits as dashed threshold lines (the same levels used by the Mollier comfort zone and the kg-zh comfort compass). Hover labels use
T/φand the%Y-%m-%d %H:%Mdate format of the Mollier h,x chart.The daily-mean line is reindexed onto a continuous daily grid, so gaps in the data (missing days) appear as breaks rather than straight connecting lines (
connectgaps=False).- Parameters:
data – DataFrame with
timestamp,temperature[°C] andhumidity[%rH] columns (read by name, order-independent).hum_band (temp_band /) –
(low, high)comfort target band (green fill + solid edge lines). Defaults to the Mollier h,x comfort zone (T 20–26 °C, φ 30–65 %).Noneto omit.hum_band_orange (temp_band_orange /) –
(low, high)moderate warning limits, drawn as dashed orange lines. Defaults to ± 1 K / ± 5 % around the comfort band.Noneto omit.hum_band_red (temp_band_red /) –
(low, high)severe warning limits, drawn as dashed red lines. Defaults to ± 2.5 K / ± 10 % around the comfort band.Noneto omit.show_hourly – Overlay the raw readings as faint dots. Default
True.show_daily_mean – Draw the daily-mean line. Default
True.hum_title (temp_title /) – Optional title shown above the temperature / humidity subplot (e.g.
"Temperature","abs. Humidity").Noneto omit.title – Figure title.
height – Figure height in pixels. Default 600.
- Returns:
go.Figure
- pyedautils.plots.comfort.plot_mollier_hx_fast(data: DataFrame | None = None, pressure: float | None = None, altitude: float | None = None, domain_x: Tuple[float, float] = (0.0, 0.02), domain_y: Tuple[float, float] = (-20.0, 50.0), comfort_zone: Dict[str, Tuple[float, float]] | None = None, height: int = 700, convention: str = 'classical', highlight_latest: bool = True, highlight_color: str | None = 'black', states: Sequence | None = None, labels: List[str] | None = None, comfort_label: str = 'Comfort zone', comfort_zone_orange: Dict[str, object] | None = None, comfort_zone_red: Dict[str, object] | None = None, show_temperature: bool = True, show_density: bool = True, show_rel_humidity: bool = True, show_enthalpy: bool = True, show_abs_humidity: bool = True, x_axis_title: str = 'absolute water content x [g/kg]', season_labels: Dict[str, str] | None = None, show_frequency: bool = False, frequency_unit: str = 'hours', frequency_smoothing: float = 4.0, show_points: bool = True, mean_enthalpy: bool = False, mean_temperature: bool = False, outdoor: Tuple[float, float] | None = None, current: Tuple[float, float] | None = None, outdoor_color: str = '#2563eb', ventilation_line: bool = True, ventilation_note: bool = True, ventilation_threshold: float = 0.0003, captions: Dict[str, str] | None = None, texts: Dict[str, str] | None = None) str[source]#
Stateful, fast variant of
plot_mollier_hx().Renders with the d3-mollierhx
MollierChartclass: the coordinate grid is drawn once and the overlays (measurement points, comfort zone, warning bands, frequency lines, process chain, room and outside point) update in place. The created chart is exposed onwindow["mollier_<uid>"]so an embedding app can call its update methods (setData,setComfort,setFrequency,setCurrent,setOutdoor,setTexts…) without re-rendering — the basis for fast, interactive dashboards.Same inputs as
plot_mollier_hx()(includingaltitudesetting the pressure whenpressureis not given, offset warning bands,"abs_humidity": Nonefor no abs-humidity limit,outdoor/currentwith the ventilation line and note, andcaptions/texts), plus:- Parameters:
show_points – Draw the measurement points.
Falsekeeps only the frequency contour lines. DefaultTrue.mean_enthalpy – Draw the mean-enthalpy curve (h_m, binned by temperature). Default
False.mean_temperature – Draw the mean-temperature curve (t_m, binned by enthalpy). Default
False.
Differences to
plot_mollier_hx(): the chart has no legend, socomfort_label,season_labelsand the legend keys oftexts(comfort_zone,season_*,room) are accepted but not shown; the comfort zone is drawn only whencomfort_zoneis given. Data, comfort zone, bands and frequency lines are clipped to the axes; room and outside points outside the axes become edge arrows with their value.- Returns:
Self-contained HTML (loads D3 v7 from the CDN + an inline bundle).
- Return type:
str
See also
plot_mollier_hx()for the full-featured variant. How to read the diagram, comfort and saving energy: https://retomarek.github.io/pyedautils/guides/mollier_hx.html
Statistical / Exploratory#
Statistical and exploratory plots.
- pyedautils.plots.stat.plot_sum_frequency(data: DataFrame, resolution: str = 'hourly', year: int | None = None, reverse: bool = False, title: str | None = None, xlab: str | None = None, ylab: str = 'Value') Figure[source]#
Create a sum frequency (duration curve) plot.
Values are sorted and plotted against their rank (frequency). Useful for temperature duration curves or load duration curves.
- Parameters:
data – DataFrame with two columns: timestamp and value.
resolution –
"hourly"or"daily". Controls aggregation.year – Filter to a specific year. If None, use all data.
reverse – If True, the highest value is at x=0 (classic duration curve / Jahresdauerlinie). If False (default), lowest value at x=0 (R default).
title – Plot title. Auto-generated if None.
xlab – X-axis label. Auto-generated if None.
ylab – Y-axis label.
- Returns:
go.Figure
- pyedautils.plots.stat.plot_decomposition(data: DataFrame, period: int | None = None, s_window: int | None = None, title: str = 'Time Series Decomposition', ylab: str = 'Value', digits: int = 1, max_gap: int = 6) Figure[source]#
Decompose a time series into trend, seasonal, and remainder using STL.
Works for both long-term (e.g. monthly over years, period=12) and short-term data (e.g. 15-min over days, period=96).
STL needs a regular series without missing values (the period is a number of observations), so the data is prepared first:
The timestamps are sorted and aligned to the sampling step (the inferred frequency, else the most common step between timestamps), so missing timestamps become explicit gaps instead of shifting the phase of the seasonal pattern.
Gaps of at most
max_gapconsecutive steps are linearly interpolated (in time); leading and trailing gaps are trimmed.If longer gaps remain, only the longest contiguous segment without gaps is decomposed and a
UserWarningnames the segment. Fill or shorten the data yourself (or raisemax_gap) to decompose a different stretch.
Raises a
ValueErrorwhen the series (or that segment) is shorter than two full periods.- Parameters:
data – DataFrame with two columns: timestamp and value.
period – Seasonal period in number of observations. If None, auto-detected from the data frequency (e.g. 12 for monthly, 96 for 15-min, 24 for hourly).
s_window – Seasonal smoothing window for STL. If None, defaults to
2 * period + 1(robust default).title – Plot title.
ylab – Y-axis label for the raw data panel.
digits – Decimal places for rounding. Default 1.
max_gap – Longest gap (in sampling steps) that is interpolated. Default 6.
0disables interpolation.
- Returns:
Plotly figure with 4 subplot rows (observed, trend, seasonal, remainder).
- Return type:
go.Figure
- pyedautils.plots.stat.plot_timeseries(data: DataFrame, columns: List[str] | None = None, title: str = 'Time Series', ylab: str = 'Value', range_slider: bool = True, height: int = 400) Figure[source]#
Create an interactive line plot with an optional range slider.
Supports plotting one or multiple columns from a DataFrame with a DatetimeIndex.
- Parameters:
data – DataFrame with a DatetimeIndex and one or more value columns.
columns – Columns to plot. If None, plots all columns.
title – Plot title.
ylab – Y-axis label.
range_slider – Show a range slider below the plot. Default True.
height – Figure height in pixels. Default 400.
- Returns:
Plotly figure with line traces and optional range slider.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_distribution(data: DataFrame, columns: List[str] | None = None, nbins: int = 50, opacity: float = 0.6, title: str = 'Distribution', xlab: str = 'Value') Figure[source]#
Create overlaid histograms for one or more columns.
- Parameters:
data – DataFrame with a DatetimeIndex and one or more value columns.
columns – Columns to include. If None, uses all columns.
nbins – Number of histogram bins. Default 50.
opacity – Bar opacity. Default 0.6.
title – Plot title.
xlab – X-axis label.
- Returns:
Plotly histogram figure.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_boxplot(data: DataFrame, column: str | None = None, groupby: str = 'month', title: str | None = None, ylab: str = 'Value') Figure[source]#
Create a box plot grouped by a time unit extracted from the DatetimeIndex.
- Parameters:
data – DataFrame with a DatetimeIndex and one or more value columns.
column – Column to plot. If None, uses the first column.
groupby – Time grouping —
"month","hour","weekday", or"quarter". Default"month".title – Plot title. Auto-generated if None.
ylab – Y-axis label.
- Returns:
Plotly box plot figure.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_outliers(data: DataFrame, column: str | None = None, multiplier: float = 1.5, title: str | None = None, ylab: str = 'Value', height: int = 400) Figure[source]#
Visualize IQR-based outliers on a time series plot.
Plots the time series as a line with outlier points highlighted in red and dashed horizontal lines at the IQR fences.
- Parameters:
data – DataFrame with a DatetimeIndex and one or more value columns.
column – Column to analyse. If None, uses the first column.
multiplier – IQR multiplier for the fence. Default 1.5.
title – Plot title. Auto-generated if None.
ylab – Y-axis label.
height – Figure height in pixels. Default 400.
- Returns:
Plotly figure with time series, outlier markers, and fences.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_correlation(data: DataFrame, color_scale: str = 'RdBu_r', text_format: str = '.2f', title: str = 'Correlation Matrix', height: int = 500, width: int = 600) Figure[source]#
Create a correlation matrix heatmap.
- Parameters:
data – DataFrame with numeric columns (DatetimeIndex is ignored).
color_scale – Plotly colorscale name. Default
"RdBu_r".text_format – Number format for cell annotations. Default
".2f".title – Plot title.
height – Figure height in pixels. Default 500.
width – Figure width in pixels. Default 600.
- Returns:
Plotly heatmap figure of the correlation matrix.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_scatter(data: DataFrame, x_column: str | None = None, y_column: str | None = None, opacity: float = 0.2, title: str | None = None, xlab: str | None = None, ylab: str | None = None) Figure[source]#
Create a scatter plot of two variables.
Low default opacity helps reveal density in large datasets.
- Parameters:
data – DataFrame with a DatetimeIndex and at least two value columns.
x_column – Column for the x-axis. If None, uses the first column.
y_column – Column for the y-axis. If None, uses the second column.
opacity – Marker opacity. Default 0.2.
title – Plot title. Auto-generated if None.
xlab – X-axis label. Defaults to the column name.
ylab – Y-axis label. Defaults to the column name.
- Returns:
Plotly scatter plot figure.
- Return type:
go.Figure
- pyedautils.plots.stat.plot_autocorrelation(data: DataFrame, column: str | None = None, lags: int = 168, title: str | None = None, height: int = 300, max_gap: int = 6) Figure[source]#
Create an autocorrelation plot with a confidence band using Plotly.
A lag is a fixed number of sampling steps, so the series is first put on a regular time grid before the ACF is computed:
The DatetimeIndex is sorted and aligned to its sampling step (the inferred frequency, else the most common step between timestamps), so missing timestamps become explicit gaps instead of silently shifting all later values by one or more lags.
Gaps of at most
max_gapconsecutive steps are linearly interpolated (in time). Longer gaps are left empty completely; they are not partly filled. Leading and trailing gaps are trimmed.The ACF is computed on the regular series with statsmodels’
missing="conservative": each autocovariance uses only the pairs of observations where both values are present, so the remaining long gaps neither break the lag alignment nor are replaced by invented values. As with the usual(n - k) / nfactor of the ACF, values at lags with fewer available pairs are shrunk towards zero (never inflated). Without remaining gaps this is the ordinary ACF.
- Parameters:
data – DataFrame with a DatetimeIndex and one or more value columns. A non-datetime index is taken as already regular (positional).
column – Column to analyse. If None, uses the first column.
lags – Number of lags to compute. Default 168 (one week at hourly).
title – Plot title. Auto-generated if None.
height – Figure height in pixels. Default 300.
max_gap – Longest gap (in sampling steps) that is interpolated. Default 6.
0disables interpolation.
- Returns:
Plotly bar chart of autocorrelation values with a 95% confidence band.
- Return type:
go.Figure
Gradients#
Plots for heating/cooling gradients (see pyedautils.data_prep.gradients).
- pyedautils.plots.gradients.plot_gradient_boxplots(gradients: DataFrame, groupby: str = 'season', direction_labels: Tuple[str, str] = ('heating', 'cooling'), title: str = 'Temperature Gradients', ylab: str = 'Gradient [K/h]', colors: Tuple[str, str] = ('#E74C3C', '#3498DB'), season_order: list | None = None) Figure[source]#
Grouped boxplots of gradients, split by direction.
Draws one box per group and direction (e.g. heating vs cooling per season or per quarter), so heating and cooling spreads are directly comparable.
- Parameters:
gradients – Output of
pyedautils.data_prep.gradients.compute_gradients()(columns[timestamp, gradient, direction, season]).groupby – Grouping on the x-axis.
"season"uses theseasoncolumn;"quarter","month","weekday"and"hour"are derived fromtimestamp.direction_labels –
(rising, falling)labels matchingcompute_gradients().title – Plot title.
ylab – Y-axis label.
colors –
(rising_color, falling_color).season_order – Optional ordered season labels for the x-axis when
groupby="season".
- Returns:
Plotly grouped boxplot figure.
- Return type:
go.Figure
Degree Days#
Degree-day and climate-correction plots.
- pyedautils.plots.degree_days.plot_degree_days(actual, reference=None, value_col: str | None = None, title: str = 'Heating Degree Days', xlab: str = 'Month', ylab: str = 'HGT [Kd]', colors: Dict[str, str] | None = None) Figure[source]#
Grouped bar chart of degree days per period, optionally against a reference.
- Parameters:
actual – Monthly (or yearly) degree days: output of
pyedautils.degree_days.heating_degree_days()/accumulated_temperature_difference/cooling_degree_days(freq="MS"or"YS") or a Series with a DatetimeIndex.reference – Reference degree days: a
pyedautils.degree_days.ReferenceDegreeDays, a Series indexed by calendar month 1–12 (matched by month), or a Series on the same DatetimeIndex. Default None (no reference bars).value_col – Column of
actualto plot; auto-detected (hgt/atd/cdd/dd) if None.title – Plot title.
xlab – X-axis label.
ylab – Y-axis label.
colors – Color overrides keyed
"actual"and"reference".
- Returns:
Plotly figure with one bar trace per series.
- Return type:
go.Figure
- pyedautils.plots.degree_days.plot_degree_day_regression(energy, temperature, base: float = 12.0, freq: str = 'D', title: str = 'Degree-Day Regression', xlab: str = 'Outside Temperature [°C]', ylab: str = 'Energy [kWh/d]', colors: Dict[str, str] | None = None) Figure[source]#
Scatter of energy per day vs outside temperature with a fixed-base degree-day regression line.
Fits
pyedautils.degree_days.fit_degree_day_line()and draws the heating line (intercept + slope · (base − T)belowbase) and the flat base load above it. Points are colored by season (daily) or shown as a single series (monthly).- Parameters:
energy – Consumption [kWh], see
fit_degree_day_line.temperature – Outdoor temperature [°C], daily or finer.
base – Base temperature [°C] of the heating degree days. Default 12; e.g.
compute_pes(...).tb.freq –
"D"(daily points) or"MS"(monthly means per day).title – Plot title.
xlab – X-axis label.
ylab – Y-axis label.
colors – Season color overrides keyed by season name (daily) or
"points"(monthly).
- Returns:
Plotly figure with scatter, regression line and annotation of base temperature, slope and fit metrics.
- Return type:
go.Figure
Solar Influence#
Solar-influence plot (see pyedautils.data_prep.solar_influence).
- pyedautils.plots.solar.plot_solar_influence(data: DataFrame, room_col: str = 't_room', radiation_col: str = 'solar', event_col: str | None = None, title: str = 'Solar Influence', temp_label: str = 'Room temperature (°C)', radiation_label: str = 'Global radiation (W/m²)', height: int = 360) Figure[source]#
Dual-axis time series of room temperature and global radiation.
Room temperature is drawn on the left axis, global radiation on the right axis. Optional steep-rise events are marked with triangles.
- Parameters:
data – DataFrame indexed by timestamp (or with a
timestampcolumn) containing the room-temperature and radiation columns.room_col – Room-temperature column. Default
"t_room".radiation_col – Global-radiation column. Default
"solar".event_col – Optional boolean column flagging steep-rise events; flagged rows are overlaid as triangles. Default None.
title – Plot title.
temp_label – Left y-axis label.
radiation_label – Right y-axis label.
height – Figure height in pixels. Default 360.
- Returns:
Plotly dual-axis figure.
- Return type:
go.Figure