Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions app/dashboard/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import numpy as np
import pandas as pd
from django.core.exceptions import PermissionDenied
from django.template.loader import get_template
from django.db.models import Count, Value, F, Q, Case, When
from django.db.models.functions import Concat, Replace
from django.http.response import Http404, HttpResponse

from dashboard.helpers import *
from dashboard.models import (
AssetsResults,
Expand Down Expand Up @@ -66,6 +68,8 @@
import traceback
from projects.helpers import parameters_helper

import oemof.eesyplan.postprocessing.graphs as eesyplan_graphs

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -1223,22 +1227,35 @@ def scenario_visualize_sankey(request, scen_id, ts=None):
is False
):
raise PermissionDenied
if ts is not None:
ts = int(ts)
results_json = report_item_render_to_json(
report_item_id="sankey",
data=REPORT_GRAPHS[GRAPH_SANKEY](
simulation=scenario.simulation,
energy_vector=scenario.energy_vectors,
timestep=ts,
),
title="Sankey",
report_item_type=GRAPH_SANKEY,
)

return JsonResponse(
results_json, status=200, content_type="application/json", safe=False
)
if scenario.datapackage is None:
if ts is not None:
ts = int(ts)

results_json = report_item_render_to_json(
report_item_id="sankey",
data=REPORT_GRAPHS[GRAPH_SANKEY](
simulation=scenario.simulation,
energy_vector=scenario.energy_vectors,
timestep=ts,
),
title="Sankey",
report_item_type=GRAPH_SANKEY,
)
return JsonResponse(
results_json, status=200, content_type="application/json", safe=False
)
else:
# TODO this sankey implementation does not allow for single timesteps
# if ts is not None:
# ts = int(ts)
results = scenario.simulation.eesyplan_results()

fig, links_df = eesyplan_graphs.sankey(results["flow"], title="Test Sankey")

return JsonResponse(
fig.to_dict(), status=200, content_type="application/json", safe=False
)


@login_required
Expand Down
4 changes: 2 additions & 2 deletions app/projects/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ class ScenarioCreateForm(OpenPlanModelForm):

class Meta:
model = Scenario
exclude = ["id", "capex_var", "opex_fix", "opex_var"]
exclude = ["id", "capex_var", "opex_fix", "opex_var", "datapackage"]
widgets = scenario_widgets
labels = scenario_labels

Expand Down Expand Up @@ -529,7 +529,7 @@ class ScenarioUpdateForm(OpenPlanModelForm):

class Meta:
model = Scenario
exclude = ["id", "capex_var", "opex_fix", "opex_var"]
exclude = ["id", "capex_var", "opex_fix", "opex_var", "datapackage"]
widgets = scenario_widgets
labels = scenario_labels

Expand Down
136 changes: 136 additions & 0 deletions app/projects/helpers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import copy
import json
import logging
import os
import io
import csv

import pandas as pd
from openpyxl import load_workbook
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.utils.html import html_safe
from django.core.exceptions import ValidationError

from jsonschema import validate
from jsonschema.exceptions import ValidationError as JSONSchemaValidationError

from epa.settings import RESOURCES_DIR
from projects.dtos import convert_to_dto
Expand Down Expand Up @@ -683,3 +690,132 @@ def parse_input_timeseries(timeseries_file):
params={"fname": timeseries_file.name},
)
return timeseries_values


DP_RESULTS_SCHEMA = {
"type": "object",
"required": ["metadata", "data"],
"additionalProperties": False,
"properties": {
"metadata": {
"type": "object",
"required": ["name", "profile", "resources"],
"additionalProperties": False,
"properties": {
"name": {
"type": "string",
"minLength": 1,
},
"profile": {
"type": "string",
"minLength": 1,
},
"resources": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"path",
"kind",
"format",
"dialect",
"encoding",
],
"additionalProperties": False,
"properties": {
"name": {
"type": "string",
"minLength": 1,
},
"path": {
"type": "string",
"minLength": 1,
},
"kind": {
"type": "string",
"enum": ["element", "sequence"],
},
"format": {
"type": "string",
"enum": ["csv"],
},
"dialect": {
"type": "object",
"required": ["header"],
"additionalProperties": False,
"properties": {
"header": {
"type": "boolean",
},
"headerRows": {
"type": "array",
"items": {
"type": "integer",
"minimum": 0,
},
},
},
},
"encoding": {
"type": "string",
"minLength": 1,
},
},
},
},
},
},
"data": {
"type": "object",
"minProperties": 1,
"additionalProperties": {
"$ref": "#/$defs/result_table",
},
},
},
"$defs": {
"result_table": {
"type": "object",
"required": ["index", "columns_names", "values"],
"additionalProperties": False,
"properties": {
"index": {
"type": "array",
"items": {
"type": "string",
},
},
"columns_names": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
},
{
"type": "array",
"items": {
"type": "string",
},
},
],
},
},
"values": {
"type": "array",
"items": {
"type": "number",
},
},
},
},
},
}


def validate_dp_results(value):
try:
validate(instance=value, schema=DP_RESULTS_SCHEMA)
except JSONSchemaValidationError as exc:
raise ValidationError(f"Invalid dp_results format: {exc.message}")
18 changes: 18 additions & 0 deletions app/projects/migrations/0029_scenario_datapackage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2.13 on 2026-05-28 09:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("projects", "0028_sensitivityanalysis_server_simulation_server"),
]

operations = [
migrations.AddField(
model_name="scenario",
name="datapackage",
field=models.JSONField(null=True),
),
]
23 changes: 23 additions & 0 deletions app/projects/migrations/0030_simulation_dp_results.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.2.13 on 2026-06-09 14:27

import projects.models.simulation_models
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("projects", "0029_scenario_datapackage"),
]

operations = [
migrations.AddField(
model_name="simulation",
name="dp_results",
field=models.JSONField(
blank=True,
null=True,
validators=[projects.models.simulation_models.validate_dp_results],
),
),
]
Loading
Loading