Skip to content

[FL-728][FLPY-62] Add Default Report Config for Report Summary Table #1074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
May 23, 2025
Merged
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
8 changes: 8 additions & 0 deletions flow360/component/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from flow360.component.volume_mesh import VolumeMeshV2
from flow360.exceptions import Flow360FileError, Flow360ValueError, Flow360WebError
from flow360.log import log
from flow360.plugins.report.report import get_default_report_summary_template
from flow360.version import __solver_version__

AssetOrResource = Union[type[AssetBase], type[Flow360Resource]]
Expand Down Expand Up @@ -1275,6 +1276,7 @@ def _run(
root asset (Geometry or VolumeMesh) is not initialized.
"""

# pylint: disable=too-many-branches
if use_beta_mesher is None:
if use_geometry_AI is True:
log.info("Beta mesher is enabled to use Geometry AI.")
Expand Down Expand Up @@ -1550,4 +1552,10 @@ def run_case(
tags=tags,
**kwargs,
)
report_template = get_default_report_summary_template()
report_template.create_in_cloud(
name="ResultSummary",
cases=[case],
solver_version=solver_version if solver_version else self.solver_version,
)
return case
2 changes: 1 addition & 1 deletion flow360/component/simulation/framework/updater_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def compare_lists(list1, list2, atol=1e-15, rtol=1e-10, ignore_keys=None):
if len(list1) != len(list2):
return False

if list1 and not isinstance(list1[0], dict):
if list1 and not any(isinstance(item, dict) for item in list1):
list1, list2 = sorted(list1), sorted(list2)

for item1, item2 in zip(list1, list2):
Expand Down
14 changes: 14 additions & 0 deletions flow360/component/simulation/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
ValidationContext,
)
from flow360.exceptions import Flow360RuntimeError, Flow360TranslationError
from flow360.plugins.report.report import get_default_report_summary_template
from flow360.version import __version__

unit_system_map = {
Expand Down Expand Up @@ -764,3 +765,16 @@ def update_simulation_json(*, params_as_dict: dict, target_python_api_version: s
# Expected exceptions
errors.append(str(e))
return updated_params_as_dict, errors


def get_default_report_config() -> dict:
"""
Get the default report config
Returns
-------
dict
default report config
"""
return get_default_report_summary_template().model_dump(
exclude_none=True,
)
40 changes: 39 additions & 1 deletion flow360/plugins/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
# pylint: disable=import-error
from pylatex import Section, Subsection

from flow360 import Case
from flow360.cloud.flow360_requests import NewReportRequest
from flow360.cloud.rest_api import RestApi
from flow360.component.case import Case
from flow360.component.interfaces import ReportInterface
from flow360.component.resource_base import AssetMetaBaseModel, Flow360Resource
from flow360.component.simulation.framework.base_model import Flow360BaseModel
Expand All @@ -32,6 +32,8 @@
Table,
)
from flow360.plugins.report.utils import (
Average,
DataItem,
RequirementItem,
get_requirements_from_data_path,
)
Expand Down Expand Up @@ -319,3 +321,39 @@ def create_pdf(
item.get_doc_item(case_context, self.settings)

report_doc.generate_pdf(os.path.join(data_storage, filename))


def get_default_report_summary_template() -> ReportTemplate:
"""
Returns default report template for result summary.
"""
avg = Average(fraction=0.1)

data = [
"volume_mesh/bounding_box/length",
"volume_mesh/bounding_box/height",
"volume_mesh/bounding_box/width",
"params/reference_geometry/moment_length",
"params/reference_geometry/area",
DataItem(data="surface_forces/totalCL", title="CL", operations=avg),
DataItem(data="surface_forces/totalCD", title="CD", operations=avg),
DataItem(data="surface_forces/totalCFy", title="CFy", operations=avg),
DataItem(data="surface_forces/totalCMx", title="CMx", operations=avg),
DataItem(data="surface_forces/totalCMy", title="CMy", operations=avg),
DataItem(data="surface_forces/totalCMz", title="CMz", operations=avg),
]
headers = [
"OAL",
"OAH",
"OAW",
"Reference Length",
"Reference Area",
"CL",
"CD",
"CFy",
"CMx",
"CMy",
"CMz",
]
table = Table(data=data, section_title="result_summary", headers=headers)
return ReportTemplate(items=[table], settings=Settings(dump_table_csv=True))
2 changes: 1 addition & 1 deletion flow360/plugins/report/report_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# pylint: disable=import-error
from pylatex import Document, Section, Subsection

from flow360 import Case
from flow360.component.case import Case


class ReportContext(pd.BaseModel):
Expand Down
10 changes: 9 additions & 1 deletion flow360/plugins/report/report_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@
# pylint: disable=import-error
from pylatex.utils import bold, escape_latex

from flow360 import Case, SimulationParams
from flow360.component.case import Case
from flow360.component.simulation.framework.base_model import Flow360BaseModel
from flow360.component.simulation.outputs.output_fields import (
IsoSurfaceFieldNames,
SurfaceFieldNames,
get_unit_for_field,
)
from flow360.component.simulation.simulation_params import SimulationParams
from flow360.component.simulation.time_stepping.time_stepping import Unsteady
from flow360.component.simulation.unit_system import (
DimensionedTypes,
Expand Down Expand Up @@ -108,7 +109,10 @@ class Settings(Flow360BaseModel):
If not specified, defaults to 300.
"""

# pylint: disable=fixme
# TODO: Create a setting class for each type of report items.
dpi: Optional[pd.PositiveInt] = 300
dump_table_csv: Optional[pd.StrictBool] = False


class ReportItem(Flow360BaseModel):
Expand Down Expand Up @@ -408,6 +412,10 @@ def get_doc_item(self, context: ReportContext, settings: Settings = None) -> Non
table.add_row(formatted)
table.add_hline()

if settings is not None and settings.dump_table_csv:
df = self.to_dataframe(context=context)
df.to_csv(f"{self.section_title}.csv", index=False)


class PatternCaption(Flow360BaseModel):
"""
Expand Down
2 changes: 1 addition & 1 deletion flow360/plugins/report/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# pylint: disable=import-error
from pylatex import NoEscape, Package, Tabular

from flow360 import Case
from flow360.component.case import Case
from flow360.component.results import base_results, case_results
from flow360.component.simulation.framework.base_model import (
Conflicts,
Expand Down
2 changes: 1 addition & 1 deletion flow360/plugins/report/uvf_shutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

import pydantic as pd

from flow360 import Env
from flow360.component.simulation.framework.base_model import Flow360BaseModel
from flow360.environment import Env
from flow360.exceptions import (
Flow360RuntimeError,
Flow360WebError,
Expand Down
17 changes: 17 additions & 0 deletions tests/data/mock_webapi/report_meta_resp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"data": {
"userId": "AIDAU77I6BZ2QYZLLVSRW",
"id": "rep-00508a80-2566-45bf-9572-56228a3161fd",
"status": "submitted",
"name": "ResultSummary",
"resources": [
{
"type": "Case",
"id": "case-f813742a-61d3-497c-8447-3ac8b0c997f1",
"rawData": null
}
],
"createdAt": "2025-05-19T18:30:51.476347Z",
"updatedAt": "2025-05-19T18:30:51.476347Z"
}
}
11 changes: 11 additions & 0 deletions tests/mock_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,16 @@ def json(self):
return res


class MockResponseReportSubmit(MockResponse):
"""response for report_template.create_in_cloud's meta json"""

@staticmethod
def json():
with open(os.path.join(here, "data/mock_webapi/report_meta_resp.json")) as fh:
res = json.load(fh)
return res


GET_RESPONSE_MAP = {
"/volumemeshes/00112233-4455-6677-8899-aabbccddeeff": MockResponseVolumeMesh,
"/volumemeshes/00000000-0000-0000-0000-000000000000": MockResponseVolumeMesh,
Expand Down Expand Up @@ -574,6 +584,7 @@ def json(self):
"/v2/drafts/vm-7c3681cd-8c6c-4db7-a62c-1742d825e9d3/run": MockResponseProjectVolumeMesh,
"/v2/drafts/case-84d4604e-f3cd-4c6b-8517-92a80a3346d3/simulation/file": MockResponseProjectCaseForkSimConfig,
"/v2/drafts/case-84d4604e-f3cd-4c6b-8517-92a80a3346d3/run": MockResponseProjectCaseFork,
"/v2/report": MockResponseReportSubmit,
}


Expand Down
112 changes: 112 additions & 0 deletions tests/simulation/service/ref/default_report_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"items": [
{
"data": [
"volume_mesh/bounding_box/length",
"volume_mesh/bounding_box/height",
"volume_mesh/bounding_box/width",
"params/reference_geometry/moment_length",
"params/reference_geometry/area",
{
"data": "surface_forces/totalCL",
"title": "CL",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
},
{
"data": "surface_forces/totalCD",
"title": "CD",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
},
{
"data": "surface_forces/totalCFy",
"title": "CFy",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
},
{
"data": "surface_forces/totalCMx",
"title": "CMx",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
},
{
"data": "surface_forces/totalCMy",
"title": "CMy",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
},
{
"data": "surface_forces/totalCMz",
"title": "CMz",
"operations": [
{
"fraction": 0.1,
"type_name": "Average"
}
],
"type_name": "DataItem"
}
],
"section_title": "result_summary",
"headers": [
"OAL",
"OAH",
"OAW",
"Reference Length",
"Reference Area",
"CL",
"CD",
"CFy",
"CMx",
"CMy",
"CMz"
],
"type_name": "Table",
"formatter": [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
}
],
"include_case_by_case": false,
"settings": {
"dpi": 300,
"dump_table_csv": true
}
}
7 changes: 7 additions & 0 deletions tests/simulation/service/test_services_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1258,3 +1258,10 @@ def _get_all_units(value):
f"Unit {unit_system_dimension_string} (A.K.A {field_name}) is not supported by the front-end.",
"Please ensure front end team is aware of this new unit and add its support.",
)


def test_get_default_report_config_json():
report_config_dict = services.get_default_report_config()
with open("ref/default_report_config.json", "r") as fp:
ref_dict = json.load(fp)
assert compare_values(report_config_dict, ref_dict, ignore_keys=["formatter"])