Skip to content

aeromaps.models.impacts.life_cycle_assessment.plots

Plots for life cycle assessments interpretation

process_tree

process_tree(model, foreground_only=True, outfile=default_process_tree_filename, colormap='Pastel2')

Plots an interactive tree to visualize the activities and exchanges declared in the LCA module. :param model: The model containing activities and exchanges. :param foreground_only: Boolean flag to include only foreground activities. :param outfile: Output filename for the generated tree. :param colormap: Colormap to use for node coloring.

Source code in aeromaps/models/impacts/life_cycle_assessment/plots.py
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def process_tree(
    model: Activity,
    foreground_only: bool = True,
    outfile: str = default_process_tree_filename,
    colormap: str = "Pastel2",
):
    """
    Plots an interactive tree to visualize the activities and exchanges declared in the LCA module.
    :param model: The model containing activities and exchanges.
    :param foreground_only: Boolean flag to include only foreground activities.
    :param outfile: Output filename for the generated tree.
    :param colormap: Colormap to use for node coloring.
    """
    # Init network
    net = Network(
        notebook=True, directed=True, layout=True, cdn_resources="remote", filter_menu=False
    )

    # Get processes hierarchy
    df = list_processes(model, foreground_only)
    df["description"] = df["activity"] + "\n" + df["unit"].fillna("")

    # Colors
    unique_values = df["database"].unique()
    value_indices = {value: i for i, value in enumerate(unique_values)}
    norm = matplotlib.colors.Normalize(vmin=0, vmax=len(unique_values), clip=True)
    mapper = plt.cm.ScalarMappable(norm=norm, cmap=plt.get_cmap(colormap))
    colors = df["database"].apply(
        lambda x: matplotlib.colors.to_hex(mapper.to_rgba(value_indices[x]))
    )

    # Populate network
    edge_data = zip(
        df["activity"],
        df["description"],
        df["parents"],
        df["amounts"],
        df["level"],
        df["database"],
        colors,
    )

    edges = {}
    for activity, description, parents, amounts, level, database, color in edge_data:
        src = activity if database == USER_DB else f"{activity}\n[{database}]"
        # desc_array = description.split(',')
        # desc_db = description.split('(')
        # desc = ',\n'.join(desc_array[:2]) if len(desc_array) > 1 else desc_array[0]
        # desc += f"\n({desc_db[-1]}" if len(desc_db) > 1 else ''
        desc = description

        net.add_node(src, desc, title=src, level=level + 1, shape="box", color=color)

        for parent, amount in zip(parents, amounts):
            if parent:
                edge_key = (src, parent)
                if edge_key in edges:  # Multiple edges between the same nodes
                    edges[edge_key].append(str(amount))
                else:  # first time edge links act and its parent: create new node for parent
                    edges[edge_key] = [str(amount)]

    # Add edges to the network with unique labels
    for (src, dst), labels in edges.items():
        if len(labels) == 1:
            net.add_edge(src, dst, label=labels[0], title=f"Exch. 1: {labels[0]}")
        else:
            num_edges = len(labels)
            roundness_step = 0.1 / num_edges  # Adjust the denominator to control spacing
            for i, label in enumerate(labels):
                curve_type = "curvedCW" if i % 2 == 0 else "curvedCCW"
                roundness = roundness_step * (
                    i + 1
                )  # Adjust roundness to avoid excessive curvature
                net.add_edge(
                    src,
                    dst,
                    label=label,
                    title=f"Exch. {i + 1}: {label}",
                    smooth={"enabled": True, "type": curve_type, "roundness": roundness},
                )

    # Set options
    net.set_edge_smooth("vertical")
    net.toggle_physics(False)
    net.show_buttons(filter_=True)
    net.options.layout.hierarchical.nodeSpacing = 200

    # Save
    net.save_graph(outfile)

    # Display in Jupyter Notebook
    display(IFrame(src=os.path.relpath(outfile), width="100%", height=700))