Remove Lightning_Report_Automatic.json file, eliminating the associated n8n workflow and its components for report generation and token management. Update Lightning_Report_Manual.json to reflect changes in node positions and IDs, ensuring consistency across workflows. Enhance report generation logic by adding detailed strike list sections for cloud-to-ground and intercloud lightning events, improving clarity and user experience in report outputs.
This commit is contained in:
parent
7fd27ffed8
commit
8152e76d05
410
Import_Wind_Turbine_Farm.json
Normal file
410
Import_Wind_Turbine_Farm.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
4
examples/wind_turbines_sample.csv
Normal file
4
examples/wind_turbines_sample.csv
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
name,latitude,longitude,farm_name
|
||||||
|
WTG-01,39.854321,32.765432,Sample Wind Farm
|
||||||
|
WTG-02,39.855100,32.766200,Sample Wind Farm
|
||||||
|
WTG-03,39.855880,32.766968,Sample Wind Farm
|
||||||
|
@ -31,6 +31,7 @@ _LIGHTNING_COLUMN_ALIASES: dict[str, list[str]] = {
|
|||||||
"time",
|
"time",
|
||||||
"timestamp",
|
"timestamp",
|
||||||
],
|
],
|
||||||
|
"ic_height": ["ic_height", "inCloudHeight", "in_cloud_height", "InCloudHeight"],
|
||||||
}
|
}
|
||||||
|
|
||||||
_TURBINE_COLUMN_ALIASES: dict[str, list[str]] = {
|
_TURBINE_COLUMN_ALIASES: dict[str, list[str]] = {
|
||||||
@ -158,6 +159,9 @@ def _build_lightning_df(
|
|||||||
if "current_abs" not in df.columns:
|
if "current_abs" not in df.columns:
|
||||||
df["current_abs"] = df["current"].abs()
|
df["current_abs"] = df["current"].abs()
|
||||||
|
|
||||||
|
if "ic_height" in df.columns:
|
||||||
|
df["ic_height"] = pd.to_numeric(df["ic_height"], errors="coerce")
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import io
|
|||||||
import os
|
import os
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Iterable
|
from typing import Any, Iterable, Literal
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import matplotlib
|
import matplotlib
|
||||||
@ -163,6 +163,24 @@ def _add_paragraph(doc: Document, text: str, size_pt: int = 11, align: WD_ALIGN_
|
|||||||
r.font.size = Pt(size_pt)
|
r.font.size = Pt(size_pt)
|
||||||
|
|
||||||
|
|
||||||
|
def _add_multiline_paragraph(
|
||||||
|
doc: Document,
|
||||||
|
text: str,
|
||||||
|
size_pt: int = 11,
|
||||||
|
align: WD_ALIGN_PARAGRAPH = WD_ALIGN_PARAGRAPH.LEFT,
|
||||||
|
) -> None:
|
||||||
|
lines = [line.strip() for line in text.splitlines() if line.strip()]
|
||||||
|
if not lines:
|
||||||
|
return
|
||||||
|
p = doc.add_paragraph()
|
||||||
|
p.alignment = align
|
||||||
|
for index, line in enumerate(lines):
|
||||||
|
if index > 0:
|
||||||
|
p.add_run().add_break()
|
||||||
|
run = p.add_run(line)
|
||||||
|
run.font.size = Pt(size_pt)
|
||||||
|
|
||||||
|
|
||||||
def _add_bullets(doc: Document, items: Iterable[str], size_pt: int = 10) -> None:
|
def _add_bullets(doc: Document, items: Iterable[str], size_pt: int = 10) -> None:
|
||||||
for item in items:
|
for item in items:
|
||||||
p = doc.add_paragraph(style="List Bullet")
|
p = doc.add_paragraph(style="List Bullet")
|
||||||
@ -499,6 +517,56 @@ def _fit_one_line_table_layout(
|
|||||||
return font_pt, [w * scale for w in required]
|
return font_pt, [w * scale for w in required]
|
||||||
|
|
||||||
|
|
||||||
|
def _add_detailed_strike_list_section(
|
||||||
|
doc: Document,
|
||||||
|
title: str,
|
||||||
|
description: str,
|
||||||
|
empty_message: str,
|
||||||
|
centroid_lat: float,
|
||||||
|
centroid_lng: float,
|
||||||
|
lightning_df: pd.DataFrame,
|
||||||
|
strike_type: Literal["cg", "ic"],
|
||||||
|
content_width: float,
|
||||||
|
lang,
|
||||||
|
) -> None:
|
||||||
|
_add_title(doc, title, size_pt=14)
|
||||||
|
_add_multiline_paragraph(doc, description, size_pt=10)
|
||||||
|
table_data, row_colors = build_lightning_event_table_data(
|
||||||
|
centroid_lat,
|
||||||
|
centroid_lng,
|
||||||
|
lightning_df,
|
||||||
|
lang,
|
||||||
|
strike_type=strike_type,
|
||||||
|
)
|
||||||
|
if len(table_data) <= 1:
|
||||||
|
_add_paragraph(doc, empty_message, size_pt=10)
|
||||||
|
return
|
||||||
|
|
||||||
|
table_data[0] = [
|
||||||
|
str(h).replace(" ", "\u00A0", 1) if " " in str(h) else str(h) for h in table_data[0]
|
||||||
|
]
|
||||||
|
available_width_cm = float(content_width) * 2.54
|
||||||
|
if strike_type == "ic":
|
||||||
|
min_col_widths_cm = [1, 3.2, 1.6, 1.6, 1.9, 1.4, 1.8]
|
||||||
|
else:
|
||||||
|
min_col_widths_cm = [1, 3.2, 1.6, 1.6, 1.9, 1.8]
|
||||||
|
font_pt, col_widths_cm = _fit_one_line_table_layout(
|
||||||
|
table_data=table_data,
|
||||||
|
available_width_cm=available_width_cm,
|
||||||
|
min_col_widths_cm=min_col_widths_cm,
|
||||||
|
max_font_pt=15,
|
||||||
|
min_font_pt=8,
|
||||||
|
)
|
||||||
|
_add_table(
|
||||||
|
doc,
|
||||||
|
table_data,
|
||||||
|
row_colors=row_colors,
|
||||||
|
column_widths_cm=col_widths_cm,
|
||||||
|
font_size_pt=float(font_pt),
|
||||||
|
autofit=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _add_table(
|
def _add_table(
|
||||||
doc: Document,
|
doc: Document,
|
||||||
table_data: list[list[str]],
|
table_data: list[list[str]],
|
||||||
@ -813,7 +881,7 @@ def create_docx_report(
|
|||||||
|
|
||||||
doc.add_page_break()
|
doc.add_page_break()
|
||||||
|
|
||||||
# Farm-wide maps + charts + risk table, anchored at the n8n-supplied centroid.
|
# Risk table, then farm-wide maps and charts anchored at the n8n-supplied centroid.
|
||||||
centroid_row = pd.Series({
|
centroid_row = pd.Series({
|
||||||
"lat": centroid_lat,
|
"lat": centroid_lat,
|
||||||
"lng": centroid_lng,
|
"lng": centroid_lng,
|
||||||
@ -825,6 +893,13 @@ def create_docx_report(
|
|||||||
has_cg = bool(((type_values == "0") & mask_within).any())
|
has_cg = bool(((type_values == "0") & mask_within).any())
|
||||||
has_ic = bool(((type_values != "0") & mask_within).any())
|
has_ic = bool(((type_values != "0") & mask_within).any())
|
||||||
|
|
||||||
|
risk_table_data, risk_row_colors = build_risk_table_data(turbine_df, lang)
|
||||||
|
if risk_table_data and len(risk_table_data) > 1:
|
||||||
|
_add_title(doc, s.turbine_risk_assessment, size_pt=14)
|
||||||
|
_add_paragraph(doc, s.turbine_risk_assessment_desc, size_pt=10)
|
||||||
|
_add_table(doc, risk_table_data, row_colors=risk_row_colors)
|
||||||
|
doc.add_page_break()
|
||||||
|
|
||||||
if has_cg:
|
if has_cg:
|
||||||
_add_title(doc, s.cloud_to_ground_lightnings, size_pt=14)
|
_add_title(doc, s.cloud_to_ground_lightnings, size_pt=14)
|
||||||
if start_date and end_date:
|
if start_date and end_date:
|
||||||
@ -849,6 +924,18 @@ def create_docx_report(
|
|||||||
)
|
)
|
||||||
if cg_chart is not None:
|
if cg_chart is not None:
|
||||||
_add_image_from_bytes(doc, cg_chart.to_image(format="png", width=1200, height=900, scale=2, engine="kaleido"), content_width)
|
_add_image_from_bytes(doc, cg_chart.to_image(format="png", width=1200, height=900, scale=2, engine="kaleido"), content_width)
|
||||||
|
_add_detailed_strike_list_section(
|
||||||
|
doc,
|
||||||
|
s.detailed_cg_events,
|
||||||
|
s.detailed_cg_events_desc,
|
||||||
|
s.detailed_cg_events_empty,
|
||||||
|
centroid_lat,
|
||||||
|
centroid_lng,
|
||||||
|
lightning_df,
|
||||||
|
"cg",
|
||||||
|
content_width,
|
||||||
|
lang,
|
||||||
|
)
|
||||||
doc.add_page_break()
|
doc.add_page_break()
|
||||||
|
|
||||||
if has_ic:
|
if has_ic:
|
||||||
@ -875,13 +962,18 @@ def create_docx_report(
|
|||||||
)
|
)
|
||||||
if ic_chart is not None:
|
if ic_chart is not None:
|
||||||
_add_image_from_bytes(doc, ic_chart.to_image(format="png", width=1200, height=900, scale=2, engine="kaleido"), content_width)
|
_add_image_from_bytes(doc, ic_chart.to_image(format="png", width=1200, height=900, scale=2, engine="kaleido"), content_width)
|
||||||
doc.add_page_break()
|
_add_detailed_strike_list_section(
|
||||||
|
doc,
|
||||||
risk_table_data, risk_row_colors = build_risk_table_data(turbine_df, lang)
|
s.detailed_ic_events,
|
||||||
if risk_table_data and len(risk_table_data) > 1:
|
s.detailed_ic_events_desc,
|
||||||
_add_title(doc, s.turbine_risk_assessment, size_pt=14)
|
s.detailed_ic_events_empty,
|
||||||
_add_paragraph(doc, s.turbine_risk_assessment_desc, size_pt=10)
|
centroid_lat,
|
||||||
_add_table(doc, risk_table_data, row_colors=risk_row_colors)
|
centroid_lng,
|
||||||
|
lightning_df,
|
||||||
|
"ic",
|
||||||
|
content_width,
|
||||||
|
lang,
|
||||||
|
)
|
||||||
doc.add_page_break()
|
doc.add_page_break()
|
||||||
|
|
||||||
# Daily breakdown
|
# Daily breakdown
|
||||||
@ -1081,30 +1173,6 @@ def create_docx_report(
|
|||||||
)
|
)
|
||||||
doc.add_page_break()
|
doc.add_page_break()
|
||||||
|
|
||||||
# Farm-wide lightning event table, anchored at the n8n-supplied centroid.
|
|
||||||
_add_title(doc, s.detailed_lightning_data, size_pt=14)
|
|
||||||
table_data, row_colors = build_lightning_event_table_data(centroid_lat, centroid_lng, lightning_df, lang)
|
|
||||||
if table_data and table_data[0]:
|
|
||||||
table_data[0] = [str(h).replace(" ", "\u00A0", 1) if " " in str(h) else str(h) for h in table_data[0]]
|
|
||||||
available_width_cm = float(content_width) * 2.54
|
|
||||||
min_col_widths_cm = [1, 3.2, 1.6, 1.6, 1.9, 1.4, 2.0, 1.8]
|
|
||||||
font_pt, col_widths_cm = _fit_one_line_table_layout(
|
|
||||||
table_data=table_data,
|
|
||||||
available_width_cm=available_width_cm,
|
|
||||||
min_col_widths_cm=min_col_widths_cm,
|
|
||||||
max_font_pt=15,
|
|
||||||
min_font_pt=8,
|
|
||||||
)
|
|
||||||
_add_table(
|
|
||||||
doc,
|
|
||||||
table_data,
|
|
||||||
row_colors=row_colors,
|
|
||||||
column_widths_cm=col_widths_cm,
|
|
||||||
font_size_pt=float(font_pt),
|
|
||||||
autofit=False,
|
|
||||||
)
|
|
||||||
doc.add_page_break()
|
|
||||||
|
|
||||||
# Appendix
|
# Appendix
|
||||||
_add_title(doc, s.appendix, size_pt=16)
|
_add_title(doc, s.appendix, size_pt=16)
|
||||||
_add_title(doc, s.risk_calc_method, size_pt=14)
|
_add_title(doc, s.risk_calc_method, size_pt=14)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable, Literal
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -280,17 +280,45 @@ def build_lightning_event_table_data(
|
|||||||
centroid_lng: float,
|
centroid_lng: float,
|
||||||
lightning_df: pd.DataFrame,
|
lightning_df: pd.DataFrame,
|
||||||
lang: ReportLanguage | None = None,
|
lang: ReportLanguage | None = None,
|
||||||
|
strike_type: Literal["cg", "ic", "all"] = "all",
|
||||||
) -> tuple[list[list[str]], list[str]]:
|
) -> tuple[list[list[str]], list[str]]:
|
||||||
s = get_strings(lang or get_report_language())
|
s = get_strings(lang or get_report_language())
|
||||||
|
include_type_column = strike_type == "all"
|
||||||
|
include_height_column = strike_type != "cg"
|
||||||
|
|
||||||
|
if strike_type == "cg":
|
||||||
|
source_df = lightning_df[lightning_df["p_type"].astype(str) == "0"].copy()
|
||||||
|
elif strike_type == "ic":
|
||||||
|
source_df = lightning_df[lightning_df["p_type"].astype(str) != "0"].copy()
|
||||||
|
else:
|
||||||
|
source_df = lightning_df.copy()
|
||||||
|
|
||||||
|
header = [
|
||||||
|
s.col_no,
|
||||||
|
s.col_time_local,
|
||||||
|
s.col_lat,
|
||||||
|
s.col_lng,
|
||||||
|
s.col_current_amps,
|
||||||
|
]
|
||||||
|
if include_height_column:
|
||||||
|
header.append(s.col_height_m)
|
||||||
|
if include_type_column:
|
||||||
|
header.append(s.col_lightning_type)
|
||||||
|
header.append(s.col_proximity_km)
|
||||||
|
|
||||||
|
if source_df.empty:
|
||||||
|
return [header], ["lightgrey"]
|
||||||
|
|
||||||
pre = precompute_distances_and_rings(
|
pre = precompute_distances_and_rings(
|
||||||
centroid_lat, centroid_lng, lightning_df, config.distance_rings
|
centroid_lat, centroid_lng, source_df, config.distance_rings
|
||||||
)
|
)
|
||||||
rows: list[list[str]] = []
|
rows: list[list[str]] = []
|
||||||
row_colors: list[str] = []
|
row_colors: list[str] = []
|
||||||
outermost_km = max(config.distance_rings) / 1000.0
|
outermost_km = max(config.distance_rings) / 1000.0
|
||||||
rings_km = [r / 1000.0 for r in config.distance_rings]
|
rings_km = [r / 1000.0 for r in config.distance_rings]
|
||||||
|
proximity_index = len(header) - 1
|
||||||
|
|
||||||
for i, rec in enumerate(lightning_df.itertuples(index=False)):
|
for i, rec in enumerate(source_df.itertuples(index=False)):
|
||||||
proximity = float(pre["dists_km"][i])
|
proximity = float(pre["dists_km"][i])
|
||||||
if proximity > outermost_km:
|
if proximity > outermost_km:
|
||||||
continue
|
continue
|
||||||
@ -310,48 +338,43 @@ def build_lightning_event_table_data(
|
|||||||
except Exception:
|
except Exception:
|
||||||
local_time = str(getattr(rec, "local_time", ""))[:19]
|
local_time = str(getattr(rec, "local_time", ""))[:19]
|
||||||
|
|
||||||
lightning_type = s.lightning_type_cg if str(rec.p_type) == "0" else s.lightning_type_ic
|
row = [
|
||||||
height_val = getattr(rec, "ic_height", "")
|
|
||||||
if height_val == "":
|
|
||||||
height_val = getattr(rec, "height", "")
|
|
||||||
|
|
||||||
rows.append(
|
|
||||||
[
|
|
||||||
"",
|
"",
|
||||||
local_time,
|
local_time,
|
||||||
f"{rec.lat:.5f}",
|
f"{rec.lat:.5f}",
|
||||||
f"{rec.lng:.5f}",
|
f"{rec.lng:.5f}",
|
||||||
str(rec.current),
|
str(rec.current),
|
||||||
str(height_val),
|
|
||||||
lightning_type,
|
|
||||||
f"{proximity:.2f}",
|
|
||||||
]
|
]
|
||||||
)
|
if include_height_column:
|
||||||
|
height_val = getattr(rec, "ic_height", "")
|
||||||
|
if height_val == "" or pd.isna(height_val):
|
||||||
|
height_val = getattr(rec, "inCloudHeight", "")
|
||||||
|
row.append("" if height_val == "" or pd.isna(height_val) else str(height_val))
|
||||||
|
if include_type_column:
|
||||||
|
lightning_type = s.lightning_type_cg if str(rec.p_type) == "0" else s.lightning_type_ic
|
||||||
|
row.append(lightning_type)
|
||||||
|
row.append(f"{proximity:.2f}")
|
||||||
|
rows.append(row)
|
||||||
row_colors.append(color)
|
row_colors.append(color)
|
||||||
|
|
||||||
|
if rows:
|
||||||
|
if include_type_column:
|
||||||
|
type_index = proximity_index - 1
|
||||||
sorted_data = sorted(
|
sorted_data = sorted(
|
||||||
zip(rows, row_colors),
|
zip(rows, row_colors),
|
||||||
key=lambda x: (0 if x[0][6] == s.lightning_type_cg else 1, float(x[0][7])),
|
key=lambda x: (0 if x[0][type_index] == s.lightning_type_cg else 1, float(x[0][proximity_index])),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sorted_data = sorted(
|
||||||
|
zip(rows, row_colors),
|
||||||
|
key=lambda x: float(x[0][proximity_index]),
|
||||||
)
|
)
|
||||||
if sorted_data:
|
|
||||||
rows, row_colors = zip(*sorted_data)
|
rows, row_colors = zip(*sorted_data)
|
||||||
rows = list(rows)
|
rows = list(rows)
|
||||||
row_colors = list(row_colors)
|
row_colors = list(row_colors)
|
||||||
for idx, row in enumerate(rows):
|
for idx, row in enumerate(rows):
|
||||||
row[0] = str(idx + 1)
|
row[0] = str(idx + 1)
|
||||||
else:
|
|
||||||
rows, row_colors = [], []
|
|
||||||
|
|
||||||
header = [
|
|
||||||
s.col_no,
|
|
||||||
s.col_time_local,
|
|
||||||
s.col_lat,
|
|
||||||
s.col_lng,
|
|
||||||
s.col_current_amps,
|
|
||||||
s.col_height_m,
|
|
||||||
s.col_lightning_type,
|
|
||||||
s.col_proximity_km,
|
|
||||||
]
|
|
||||||
return [header] + rows, ["lightgrey"] + row_colors
|
return [header] + rows, ["lightgrey"] + row_colors
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -98,6 +98,12 @@ class ReportStrings:
|
|||||||
storm_cells: str
|
storm_cells: str
|
||||||
storm_cells_daily_viz: str
|
storm_cells_daily_viz: str
|
||||||
detailed_lightning_data: str
|
detailed_lightning_data: str
|
||||||
|
detailed_cg_events: str
|
||||||
|
detailed_ic_events: str
|
||||||
|
detailed_cg_events_desc: str
|
||||||
|
detailed_ic_events_desc: str
|
||||||
|
detailed_cg_events_empty: str
|
||||||
|
detailed_ic_events_empty: str
|
||||||
appendix: str
|
appendix: str
|
||||||
risk_calc_method: str
|
risk_calc_method: str
|
||||||
how_risk_determined: str
|
how_risk_determined: str
|
||||||
@ -308,6 +314,19 @@ _STRINGS_EN = ReportStrings(
|
|||||||
storm_cells="Storm Cells",
|
storm_cells="Storm Cells",
|
||||||
storm_cells_daily_viz="Daily storm cells visualization.",
|
storm_cells_daily_viz="Daily storm cells visualization.",
|
||||||
detailed_lightning_data="Detailed Lightning Event Data",
|
detailed_lightning_data="Detailed Lightning Event Data",
|
||||||
|
detailed_cg_events="Detailed Cloud-to-Ground Lightning List",
|
||||||
|
detailed_ic_events="Detailed Intercloud Lightning List",
|
||||||
|
detailed_cg_events_desc=(
|
||||||
|
"Current (amps): peak current of the cloud-to-ground strike.\n"
|
||||||
|
"Proximity (km): air distance from the strike to the wind farm centroid."
|
||||||
|
),
|
||||||
|
detailed_ic_events_desc=(
|
||||||
|
"Current (amps): peak current of the in-cloud strike.\n"
|
||||||
|
"Height (m): in-cloud flash height.\n"
|
||||||
|
"Proximity (km): air distance from the strike to the wind farm centroid."
|
||||||
|
),
|
||||||
|
detailed_cg_events_empty="No cloud-to-ground lightning events were recorded within the analysis area during this period.",
|
||||||
|
detailed_ic_events_empty="No intercloud lightning events were recorded within the analysis area during this period.",
|
||||||
appendix="Appendix",
|
appendix="Appendix",
|
||||||
risk_calc_method="1. Risk Calculation Method",
|
risk_calc_method="1. Risk Calculation Method",
|
||||||
how_risk_determined="How Risk Scores Are Determined:",
|
how_risk_determined="How Risk Scores Are Determined:",
|
||||||
@ -328,14 +347,14 @@ _STRINGS_EN = ReportStrings(
|
|||||||
max_risk_score="Maximum Risk Score: ~2.500 (close distance, high current)",
|
max_risk_score="Maximum Risk Score: ~2.500 (close distance, high current)",
|
||||||
typical_range="Typical Range: 0.010 - 1.000 for most lightning events",
|
typical_range="Typical Range: 0.010 - 1.000 for most lightning events",
|
||||||
risk_categories="Risk Score Categories (Fixed Color Intervals):",
|
risk_categories="Risk Score Categories (Fixed Color Intervals):",
|
||||||
risk_cat_very_low="Very Low Risk (<0.1): Blue - Distant lightning with low current",
|
risk_cat_very_low="Very Low Risk (<0.1): Blue",
|
||||||
risk_cat_low="Low Risk (0.1-0.2): Teal - Moderate distance lightning",
|
risk_cat_low="Low Risk (0.1-0.2): Teal",
|
||||||
risk_cat_med_low="Med-Low Risk (0.2-0.4): Green - Closer lightning",
|
risk_cat_med_low="Med-Low Risk (0.2-0.4): Green",
|
||||||
risk_cat_medium="Medium Risk (0.4-0.6): Yellow - Moderate risk lightning",
|
risk_cat_medium="Medium Risk (0.4-0.6): Yellow",
|
||||||
risk_cat_med_high="Med-High Risk (0.6-0.8): Orange - High risk lightning",
|
risk_cat_med_high="Med-High Risk (0.6-0.8): Orange",
|
||||||
risk_cat_high="High Risk (0.8-1.0): Dark Orange - Very high risk lightning",
|
risk_cat_high="High Risk (0.8-1.0): Dark Orange",
|
||||||
risk_cat_very_high="Very High Risk (1.0-1.2): Red - Extreme risk lightning",
|
risk_cat_very_high="Very High Risk (1.0-1.2): Red",
|
||||||
risk_cat_critical="Critical Risk (>1.2): Dark Red - Critical risk lightning",
|
risk_cat_critical="Critical Risk (>1.2): Dark Red",
|
||||||
risk_chart="3. Risk Score Calculation Chart",
|
risk_chart="3. Risk Score Calculation Chart",
|
||||||
chart_reference="Chart Reference Guide:",
|
chart_reference="Chart Reference Guide:",
|
||||||
risk_chart_desc_1="The following chart shows how distance and current magnitude affect risk scores.",
|
risk_chart_desc_1="The following chart shows how distance and current magnitude affect risk scores.",
|
||||||
@ -527,6 +546,19 @@ _STRINGS_TR = ReportStrings(
|
|||||||
storm_cells="Fırtına Hücreleri",
|
storm_cells="Fırtına Hücreleri",
|
||||||
storm_cells_daily_viz="Fırtına hücrelerinin dağılımı",
|
storm_cells_daily_viz="Fırtına hücrelerinin dağılımı",
|
||||||
detailed_lightning_data="Ayrıntılı Yıldırım Olay Verileri",
|
detailed_lightning_data="Ayrıntılı Yıldırım Olay Verileri",
|
||||||
|
detailed_cg_events="Ayrıntılı Yıldırım Listesi",
|
||||||
|
detailed_ic_events="Ayrıntılı Şimşek Listesi",
|
||||||
|
detailed_cg_events_desc=(
|
||||||
|
"Akım (amper): yıldırımın akım büyüklüğü.\n"
|
||||||
|
"Yakınlık (km): yıldırımın rüzgar çiftliğinin merkez noktasına (centroid) olan kuş uçuşu mesafesi."
|
||||||
|
),
|
||||||
|
detailed_ic_events_desc=(
|
||||||
|
"Akım (amper): şimşeğin akım büyüklüğü.\n"
|
||||||
|
"Yükseklik (m): şimşeğin oluştuğu yükseklik.\n"
|
||||||
|
"Yakınlık (km): şimşeğin rüzgar çiftliğinin merkez noktasına olan kuş uçuşu mesafesi."
|
||||||
|
),
|
||||||
|
detailed_cg_events_empty="Bu dönemde analiz alanında yıldırım olayı kaydedilmemiştir.",
|
||||||
|
detailed_ic_events_empty="Bu dönemde analiz alanında şimşek olayı kaydedilmemiştir.",
|
||||||
appendix="Ek",
|
appendix="Ek",
|
||||||
risk_calc_method="1. Risk Hesaplama Yöntemi",
|
risk_calc_method="1. Risk Hesaplama Yöntemi",
|
||||||
how_risk_determined="Risk Skorları Nasıl Belirlenir:",
|
how_risk_determined="Risk Skorları Nasıl Belirlenir:",
|
||||||
@ -547,14 +579,14 @@ _STRINGS_TR = ReportStrings(
|
|||||||
max_risk_score="Maksimum Risk Skoru: ~2.500 (yakın mesafe, yüksek akım)",
|
max_risk_score="Maksimum Risk Skoru: ~2.500 (yakın mesafe, yüksek akım)",
|
||||||
typical_range="Tipik Aralık: çoğu yıldırım olayı için 0.010 - 1.000",
|
typical_range="Tipik Aralık: çoğu yıldırım olayı için 0.010 - 1.000",
|
||||||
risk_categories="Risk Skoru Kategorileri (Sabit Renk Aralıkları):",
|
risk_categories="Risk Skoru Kategorileri (Sabit Renk Aralıkları):",
|
||||||
risk_cat_very_low="Çok Düşük Risk (<0.1): Mavi - Uzak, düşük akımlı yıldırım",
|
risk_cat_very_low="Çok düşük risk (<0.1): Mavi",
|
||||||
risk_cat_low="Düşük Risk (0.1-0.2): Turkuaz - Orta mesafeli yıldırım",
|
risk_cat_low="Düşük Risk (0.1-0.2): Turkuaz",
|
||||||
risk_cat_med_low="Orta-Düşük Risk (0.2-0.4): Yeşil - Daha yakın yıldırım",
|
risk_cat_med_low="Orta-Düşük Risk (0.2-0.4): Yeşil",
|
||||||
risk_cat_medium="Orta Risk (0.4-0.6): Sarı - Orta riskli yıldırım",
|
risk_cat_medium="Orta Risk (0.4-0.6): Sarı",
|
||||||
risk_cat_med_high="Orta-Yüksek Risk (0.6-0.8): Turuncu - Yüksek riskli yıldırım",
|
risk_cat_med_high="Orta-Yüksek Risk (0.6-0.8): Turuncu",
|
||||||
risk_cat_high="Yüksek Risk (0.8-1.0): Koyu Turuncu - Çok yüksek riskli yıldırım",
|
risk_cat_high="Yüksek Risk (0.8-1.0): Koyu Turuncu",
|
||||||
risk_cat_very_high="Çok Yüksek Risk (1.0-1.2): Kırmızı - Aşırı riskli yıldırım",
|
risk_cat_very_high="Çok Yüksek Risk (1.0-1.2): Kırmızı",
|
||||||
risk_cat_critical="Kritik Risk (>1.2): Koyu Kırmızı - Kritik riskli yıldırım",
|
risk_cat_critical="Kritik Risk (>1.2): Koyu Kırmızı",
|
||||||
risk_chart="3. Risk Skoru Hesaplama Grafiği",
|
risk_chart="3. Risk Skoru Hesaplama Grafiği",
|
||||||
chart_reference="Grafik Referans Kılavuzu:",
|
chart_reference="Grafik Referans Kılavuzu:",
|
||||||
risk_chart_desc_1="Aşağıdaki grafik, mesafe ve akım büyüklüğünün risk skorlarını nasıl etkilediğini gösterir.",
|
risk_chart_desc_1="Aşağıdaki grafik, mesafe ve akım büyüklüğünün risk skorlarını nasıl etkilediğini gösterir.",
|
||||||
|
|||||||
@ -11,6 +11,8 @@ COORDINATE_PLANE_RING_LINE_WIDTH = 4
|
|||||||
COORDINATE_PLANE_LIGHTNING_SIZE_MIN = 10
|
COORDINATE_PLANE_LIGHTNING_SIZE_MIN = 10
|
||||||
COORDINATE_PLANE_LIGHTNING_SIZE_MAX = 24
|
COORDINATE_PLANE_LIGHTNING_SIZE_MAX = 24
|
||||||
COORDINATE_PLANE_LIGHTNING_CURRENT_SCALE = 800
|
COORDINATE_PLANE_LIGHTNING_CURRENT_SCALE = 800
|
||||||
|
COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE = 9
|
||||||
|
COORDINATE_PLANE_TURBINE_TEXT_POSITION = 'middle center'
|
||||||
|
|
||||||
def plot_turbine_map(turbine_row: pd.Series, lightning_df: pd.DataFrame, turbine_df: pd.DataFrame) -> go.Figure:
|
def plot_turbine_map(turbine_row: pd.Series, lightning_df: pd.DataFrame, turbine_df: pd.DataFrame) -> go.Figure:
|
||||||
turbine_lat = turbine_row['lat']
|
turbine_lat = turbine_row['lat']
|
||||||
@ -371,8 +373,8 @@ def plot_coordinate_plane(turbine_row: pd.Series, lightning_df: pd.DataFrame, tu
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=turbine_df['name'].tolist(),
|
text=turbine_df['name'].tolist(),
|
||||||
textfont=dict(size=18, color='black'), # turbine name label font size
|
textfont=dict(size=COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE, color='black'),
|
||||||
textposition='middle center',
|
textposition=COORDINATE_PLANE_TURBINE_TEXT_POSITION,
|
||||||
name='Wind Turbines',
|
name='Wind Turbines',
|
||||||
showlegend=True
|
showlegend=True
|
||||||
))
|
))
|
||||||
@ -394,7 +396,7 @@ def plot_coordinate_plane(turbine_row: pd.Series, lightning_df: pd.DataFrame, tu
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=['S'] * len(storm_df),
|
text=['S'] * len(storm_df),
|
||||||
textfont=dict(size=18, color='white'), # storm "S" label font size
|
textfont=dict(size=18, color='white'),
|
||||||
textposition='middle center',
|
textposition='middle center',
|
||||||
name='Storm Cells',
|
name='Storm Cells',
|
||||||
showlegend=True
|
showlegend=True
|
||||||
@ -521,8 +523,8 @@ def plot_intercloud_coordinate_plane(turbine_row: pd.Series, lightning_df: pd.Da
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=turbine_df['name'].tolist(),
|
text=turbine_df['name'].tolist(),
|
||||||
textfont=dict(size=24, color='black'),
|
textfont=dict(size=COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE, color='black'),
|
||||||
textposition='middle center',
|
textposition=COORDINATE_PLANE_TURBINE_TEXT_POSITION,
|
||||||
name=s.map_wind_turbines,
|
name=s.map_wind_turbines,
|
||||||
showlegend=True
|
showlegend=True
|
||||||
))
|
))
|
||||||
@ -694,8 +696,8 @@ def plot_cloud_to_ground_coordinate_plane(turbine_row: pd.Series, lightning_df:
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=turbine_df['name'].tolist(),
|
text=turbine_df['name'].tolist(),
|
||||||
textfont=dict(size=18, color='black'), # turbine name label font size
|
textfont=dict(size=COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE, color='black'),
|
||||||
textposition='middle center',
|
textposition=COORDINATE_PLANE_TURBINE_TEXT_POSITION,
|
||||||
name=s.map_wind_turbines,
|
name=s.map_wind_turbines,
|
||||||
showlegend=True
|
showlegend=True
|
||||||
))
|
))
|
||||||
@ -717,7 +719,7 @@ def plot_cloud_to_ground_coordinate_plane(turbine_row: pd.Series, lightning_df:
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=['S'] * len(storm_df),
|
text=['S'] * len(storm_df),
|
||||||
textfont=dict(size=18, color='white'), # storm "S" label font size
|
textfont=dict(size=18, color='white'),
|
||||||
textposition='middle center',
|
textposition='middle center',
|
||||||
name=s.map_storm_cells,
|
name=s.map_storm_cells,
|
||||||
showlegend=True
|
showlegend=True
|
||||||
|
|||||||
@ -13,6 +13,10 @@ from src.config import config
|
|||||||
from src.reporting.strings import ReportLanguage, get_report_language, get_strings
|
from src.reporting.strings import ReportLanguage, get_report_language, get_strings
|
||||||
from src.utils import parse_period_string_to_datetime
|
from src.utils import parse_period_string_to_datetime
|
||||||
from src.visualization.basemap import add_satellite_basemap
|
from src.visualization.basemap import add_satellite_basemap
|
||||||
|
from src.visualization.maps import (
|
||||||
|
COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE,
|
||||||
|
COORDINATE_PLANE_TURBINE_TEXT_POSITION,
|
||||||
|
)
|
||||||
|
|
||||||
def format_datetime_for_display(datetime_str: str) -> str:
|
def format_datetime_for_display(datetime_str: str) -> str:
|
||||||
"""
|
"""
|
||||||
@ -177,8 +181,8 @@ def create_storm_cells_coordinate_plane(storm_data: List[Dict], turbine_df: pd.D
|
|||||||
line=dict(color='black', width=1)
|
line=dict(color='black', width=1)
|
||||||
),
|
),
|
||||||
text=turbine_df['name'].tolist(),
|
text=turbine_df['name'].tolist(),
|
||||||
textfont=dict(size=12, color='black'),
|
textfont=dict(size=COORDINATE_PLANE_TURBINE_NAME_FONT_SIZE, color='black'),
|
||||||
textposition='middle center',
|
textposition=COORDINATE_PLANE_TURBINE_TEXT_POSITION,
|
||||||
name=s.map_wind_turbines,
|
name=s.map_wind_turbines,
|
||||||
showlegend=True,
|
showlegend=True,
|
||||||
hovertemplate=(
|
hovertemplate=(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user