CoolFace
Apppublic

mabuseif/HVAC

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
visualization.py513 linesDownload Raw Back to root
1"""2Visualization utilities for HVAC Load Calculator3 4This module provides enhanced visualization functions for creating interactive5and informative charts for the HVAC Load Calculator application.6"""7 8import plotly.express as px9import plotly.graph_objects as go10import pandas as pd11import numpy as np12 13 14def create_load_breakdown_chart(load_components, title="Load Breakdown"):15    """16    Create an enhanced pie chart for load components breakdown.17    18    Args:19        load_components (dict): Dictionary of load components and their values20        title (str): Chart title21        22    Returns:23        plotly.graph_objects.Figure: Interactive pie chart24    """25    # Remove zero values26    load_components = {k: v for k, v in load_components.items() if v > 0}27    28    # Create figure29    fig = go.Figure()30    31    # Add pie chart32    fig.add_trace(go.Pie(33        labels=list(load_components.keys()),34        values=list(load_components.values()),35        textinfo='label+percent',36        insidetextorientation='radial',37        marker=dict(38            colors=px.colors.qualitative.Bold,39            line=dict(color='white', width=2)40        ),41        pull=[0.05 if x == max(load_components.values()) else 0 for x in load_components.values()],42        hovertemplate='<b>%{label}</b><br>%{value:.1f} W<br>%{percent}<extra></extra>'43    ))44    45    # Update layout46    fig.update_layout(47        title={48            'text': title,49            'y': 0.95,50            'x': 0.5,51            'xanchor': 'center',52            'yanchor': 'top',53            'font': dict(size=20)54        },55        legend=dict(56            orientation="h",57            yanchor="bottom",58            y=-0.2,59            xanchor="center",60            x=0.5,61            font=dict(size=12)62        ),63        height=500,64        margin=dict(t=80, b=80, l=40, r=40),65        paper_bgcolor='rgba(0,0,0,0)',66        plot_bgcolor='rgba(0,0,0,0)'67    )68    69    return fig70 71 72def create_component_bar_chart(df, x_col, y_col, color_col=None, title="Component Breakdown"):73    """74    Create an enhanced bar chart for component breakdown.75    76    Args:77        df (pd.DataFrame): DataFrame containing the data78        x_col (str): Column name for x-axis79        y_col (str): Column name for y-axis80        color_col (str, optional): Column name for color grouping81        title (str): Chart title82        83    Returns:84        plotly.graph_objects.Figure: Interactive bar chart85    """86    # Create figure87    if color_col:88        fig = px.bar(89            df,90            x=x_col,91            y=y_col,92            color=color_col,93            title=title,94            color_discrete_sequence=px.colors.qualitative.Bold,95            height=500,96            text=y_col97        )98    else:99        fig = px.bar(100            df,101            x=x_col,102            y=y_col,103            title=title,104            color_discrete_sequence=px.colors.qualitative.Bold,105            height=500,106            text=y_col107        )108    109    # Update layout110    fig.update_layout(111        xaxis_title=x_col,112        yaxis_title=y_col,113        legend_title=color_col if color_col else "",114        font=dict(size=12),115        xaxis={'categoryorder': 'total descending'},116        paper_bgcolor='rgba(0,0,0,0)',117        plot_bgcolor='rgba(0,0,0,0)',118        hovermode="x unified"119    )120    121    # Add data labels122    fig.update_traces(123        texttemplate='%{y:.1f}',124        textposition='outside',125        hovertemplate='<b>%{x}</b><br>%{y:.1f}<extra></extra>'126    )127    128    # Add grid lines129    fig.update_yaxes(130        showgrid=True,131        gridwidth=1,132        gridcolor='rgba(211,211,211,0.3)'133    )134    135    return fig136 137 138def create_stacked_bar_chart(df, x_col, y_cols, names, title="Stacked Bar Chart"):139    """140    Create an enhanced stacked bar chart.141    142    Args:143        df (pd.DataFrame): DataFrame containing the data144        x_col (str): Column name for x-axis145        y_cols (list): List of column names for y-axis values146        names (list): List of names for each y-column147        title (str): Chart title148        149    Returns:150        plotly.graph_objects.Figure: Interactive stacked bar chart151    """152    # Create figure153    fig = go.Figure()154    155    # Add bars for each y column156    for i, y_col in enumerate(y_cols):157        fig.add_trace(go.Bar(158            x=df[x_col],159            y=df[y_col],160            name=names[i],161            hovertemplate=f'<b>{names[i]}</b>: %{{y:.1f}}<extra></extra>'162        ))163    164    # Update layout165    fig.update_layout(166        title=title,167        xaxis_title=x_col,168        yaxis_title="Value",169        barmode='stack',170        height=500,171        legend=dict(172            orientation="h",173            yanchor="bottom",174            y=1.02,175            xanchor="center",176            x=0.5177        ),178        paper_bgcolor='rgba(0,0,0,0)',179        plot_bgcolor='rgba(0,0,0,0)',180        hovermode="x unified"181    )182    183    # Add grid lines184    fig.update_yaxes(185        showgrid=True,186        gridwidth=1,187        gridcolor='rgba(211,211,211,0.3)'188    )189    190    return fig191 192 193def create_grouped_bar_chart(df, x_col, y_cols, names, title="Grouped Bar Chart"):194    """195    Create an enhanced grouped bar chart.196    197    Args:198        df (pd.DataFrame): DataFrame containing the data199        x_col (str): Column name for x-axis200        y_cols (list): List of column names for y-axis values201        names (list): List of names for each y-column202        title (str): Chart title203        204    Returns:205        plotly.graph_objects.Figure: Interactive grouped bar chart206    """207    # Create figure208    fig = go.Figure()209    210    # Add bars for each y column211    for i, y_col in enumerate(y_cols):212        fig.add_trace(go.Bar(213            x=df[x_col],214            y=df[y_col],215            name=names[i],216            hovertemplate=f'<b>{names[i]}</b>: %{{y:.1f}}<extra></extra>'217        ))218    219    # Update layout220    fig.update_layout(221        title=title,222        xaxis_title=x_col,223        yaxis_title="Value",224        barmode='group',225        height=500,226        legend=dict(227            orientation="h",228            yanchor="bottom",229            y=1.02,230            xanchor="center",231            x=0.5232        ),233        paper_bgcolor='rgba(0,0,0,0)',234        plot_bgcolor='rgba(0,0,0,0)',235        hovermode="x unified"236    )237    238    # Add grid lines239    fig.update_yaxes(240        showgrid=True,241        gridwidth=1,242        gridcolor='rgba(211,211,211,0.3)'243    )244    245    return fig246 247 248def create_heat_map_chart(df, x_col, y_col, z_col, title="Heat Map"):249    """250    Create an enhanced heat map chart.251    252    Args:253        df (pd.DataFrame): DataFrame containing the data254        x_col (str): Column name for x-axis255        y_col (str): Column name for y-axis256        z_col (str): Column name for z-axis (color)257        title (str): Chart title258        259    Returns:260        plotly.graph_objects.Figure: Interactive heat map chart261    """262    # Create figure263    fig = px.density_heatmap(264        df,265        x=x_col,266        y=y_col,267        z=z_col,268        title=title,269        color_continuous_scale="Viridis",270        height=500271    )272    273    # Update layout274    fig.update_layout(275        xaxis_title=x_col,276        yaxis_title=y_col,277        font=dict(size=12),278        paper_bgcolor='rgba(0,0,0,0)',279        plot_bgcolor='rgba(0,0,0,0)'280    )281    282    return fig283 284 285def create_line_chart(df, x_col, y_cols, names, title="Line Chart"):286    """287    Create an enhanced line chart.288    289    Args:290        df (pd.DataFrame): DataFrame containing the data291        x_col (str): Column name for x-axis292        y_cols (list): List of column names for y-axis values293        names (list): List of names for each y-column294        title (str): Chart title295        296    Returns:297        plotly.graph_objects.Figure: Interactive line chart298    """299    # Create figure300    fig = go.Figure()301    302    # Add lines for each y column303    for i, y_col in enumerate(y_cols):304        fig.add_trace(go.Scatter(305            x=df[x_col],306            y=df[y_col],307            mode='lines+markers',308            name=names[i],309            hovertemplate=f'<b>{names[i]}</b>: %{{y:.1f}}<extra></extra>'310        ))311    312    # Update layout313    fig.update_layout(314        title=title,315        xaxis_title=x_col,316        yaxis_title="Value",317        height=500,318        legend=dict(319            orientation="h",320            yanchor="bottom",321            y=1.02,322            xanchor="center",323            x=0.5324        ),325        paper_bgcolor='rgba(0,0,0,0)',326        plot_bgcolor='rgba(0,0,0,0)',327        hovermode="x unified"328    )329    330    # Add grid lines331    fig.update_yaxes(332        showgrid=True,333        gridwidth=1,334        gridcolor='rgba(211,211,211,0.3)'335    )336    337    fig.update_xaxes(338        showgrid=True,339        gridwidth=1,340        gridcolor='rgba(211,211,211,0.3)'341    )342    343    return fig344 345 346def create_sankey_diagram(nodes, links, title="Energy Flow"):347    """348    Create a Sankey diagram for energy flow visualization.349    350    Args:351        nodes (list): List of node labels352        links (dict): Dictionary with source, target, and value lists353        title (str): Chart title354        355    Returns:356        plotly.graph_objects.Figure: Interactive Sankey diagram357    """358    # Create figure359    fig = go.Figure(data=[go.Sankey(360        node=dict(361            pad=15,362            thickness=20,363            line=dict(color="black", width=0.5),364            label=nodes,365            color="blue"366        ),367        link=dict(368            source=links['source'],369            target=links['target'],370            value=links['value'],371            hovertemplate='%{source.label} → %{target.label}: %{value:.1f} W<extra></extra>'372        )373    )])374    375    # Update layout376    fig.update_layout(377        title=title,378        font=dict(size=12),379        height=600,380        paper_bgcolor='rgba(0,0,0,0)',381        plot_bgcolor='rgba(0,0,0,0)'382    )383    384    return fig385 386 387def create_gauge_chart(value, min_val, max_val, title="Gauge", threshold_values=None, threshold_colors=None):388    """389    Create a gauge chart for displaying a value within a range.390    391    Args:392        value (float): Value to display393        min_val (float): Minimum value of the range394        max_val (float): Maximum value of the range395        title (str): Chart title396        threshold_values (list, optional): List of threshold values397        threshold_colors (list, optional): List of colors for each threshold398        399    Returns:400        plotly.graph_objects.Figure: Interactive gauge chart401    """402    # Set default thresholds if not provided403    if threshold_values is None:404        threshold_values = [min_val, (min_val + max_val) / 2, max_val]405    406    if threshold_colors is None:407        threshold_colors = ["green", "yellow", "red"]408    409    # Create figure410    fig = go.Figure(go.Indicator(411        mode="gauge+number",412        value=value,413        domain={'x': [0, 1], 'y': [0, 1]},414        title={'text': title},415        gauge={416            'axis': {'range': [min_val, max_val]},417            'bar': {'color': "darkblue"},418            'steps': [419                {'range': [threshold_values[i], threshold_values[i+1]], 'color': threshold_colors[i]} 420                for i in range(len(threshold_values)-1)421            ],422            'threshold': {423                'line': {'color': "red", 'width': 4},424                'thickness': 0.75,425                'value': value426            }427        }428    ))429    430    # Update layout431    fig.update_layout(432        height=300,433        paper_bgcolor='rgba(0,0,0,0)',434        plot_bgcolor='rgba(0,0,0,0)'435    )436    437    return fig438 439 440def create_enhanced_results_visualization(results):441    """442    Create enhanced visualizations for HVAC load calculation results.443    444    Args:445        results (dict): Dictionary containing calculation results446        447    Returns:448        dict: Dictionary of plotly figures449    """450    figures = {}451    452    # Prepare data for load breakdown pie chart453    load_components = {454        'Walls': results.get('wall_loss', 0),455        'Roof': results.get('roof_loss', 0),456        'Floor': results.get('floor_loss', 0),457        'Windows & Doors': results.get('window_loss', 0),458        'Infiltration': results.get('infiltration_loss', 0),459        'Ventilation': results.get('ventilation_loss', 0) - results.get('infiltration_loss', 0)460    }461    462    # Create load breakdown pie chart463    figures['load_breakdown'] = create_load_breakdown_chart(464        load_components, 465        title="Heating Load Components"466    )467    468    # Create energy flow Sankey diagram469    if 'internal_gain' in results and results['internal_gain'] > 0:470        # Create nodes and links for Sankey diagram471        nodes = [472            "Walls", "Roof", "Floor", "Windows & Doors", 473            "Infiltration", "Ventilation", "Internal Gains", 474            "Total Heat Loss", "Net Heating Load"475        ]476        477        links = {478            'source': [0, 1, 2, 3, 4, 5, 7, 6],479            'target': [7, 7, 7, 7, 7, 7, 8, 8],480            'value': [481                load_components['Walls'],482                load_components['Roof'],483                load_components['Floor'],484                load_components['Windows & Doors'],485                load_components['Infiltration'],486                load_components['Ventilation'],487                results['internal_gain'],488                results['total_heat_loss']489            ]490        }491        492        figures['energy_flow'] = create_sankey_diagram(493            nodes, 494            links, 495            title="Heating Energy Flow"496        )497    498    # Create gauge chart for heating load per area499    if 'net_heating_load' in results and 'building_info' in results:500        floor_area = results['building_info'].get('floor_area', 80.0)501        heating_load_per_area = results['net_heating_load'] / floor_area502        503        figures['load_per_area_gauge'] = create_gauge_chart(504            heating_load_per_area,505            0,506            200,507            title="Heating Load per Area (W/m²)",508            threshold_values=[0, 50, 100, 150, 200],509            threshold_colors=["green", "lightgreen", "yellow", "orange", "red"]510        )511    512    return figures513