fix mode into table
add change folder for analisys
This commit is contained in:
parent
5175132deb
commit
b9b37a9aa8
@ -4,6 +4,7 @@
|
||||
"last_out_output_dir": "C:/src/____GitProjects/radar_data_reader/flight_workspace/250515_122252_Flight",
|
||||
"last_rec_output_dir": "C:\\src\\____GitProjects\\radar_data_reader\\_rec",
|
||||
"last_flight_folder": "C:/__Voli/Volo_12_25maggio2025/rec",
|
||||
"last_flight_workspace_parent_dir": "C:\\src\\____GitProjects\\radar_data_reader\\flight_workspace",
|
||||
"active_out_export_profile_name": "gsp_data",
|
||||
"export_profiles": [
|
||||
{
|
||||
@ -451,8 +452,8 @@
|
||||
"create_separate_folders": true
|
||||
},
|
||||
"flight_analysis_options": {
|
||||
"aggregate_by_scale": false,
|
||||
"aggregate_by_waveform": false
|
||||
"aggregate_by_scale": true,
|
||||
"aggregate_by_waveform": true
|
||||
},
|
||||
"segment_export_g_reconvert_config": {
|
||||
"cpp_executable_path": "C:/src/GRIFO-E/REP/Projects/Tools/wsLuna/g_reconvert/Debug/g_reconvert.exe",
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
import re
|
||||
|
||||
# --- Version Data (Generated) ---
|
||||
__version__ = "v.0.0.0.38-0-g7251cf8-dirty"
|
||||
GIT_COMMIT_HASH = "7251cf8e301716f904aab60b759fe8d9abd6664b"
|
||||
__version__ = "v.0.0.0.39-0-g4066d4b"
|
||||
GIT_COMMIT_HASH = "4066d4b92bffb9779b5bb530ff48d938a3f3fc95"
|
||||
GIT_BRANCH = "master"
|
||||
BUILD_TIMESTAMP = "2025-07-14T13:26:54.921185+00:00"
|
||||
BUILD_TIMESTAMP = "2025-07-14T13:43:12.150911+00:00"
|
||||
IS_GIT_REPO = True
|
||||
|
||||
# --- Default Values (for comparison or fallback) ---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,6 @@ log = logger.get_logger(__name__)
|
||||
|
||||
TICK_DURATION_S = 64e-6
|
||||
|
||||
|
||||
class FlightAnalyzer:
|
||||
"""Manages the multi-step process of analyzing a flight folder."""
|
||||
|
||||
@ -40,30 +39,30 @@ class FlightAnalyzer:
|
||||
self.analysis_options: dict = {}
|
||||
|
||||
def start_analysis(
|
||||
self, rec_folder_str: str, flight_name: str, analysis_options: dict
|
||||
self, rec_folder_str: str, flight_name: str, workspace_path: Path, analysis_options: dict
|
||||
) -> threading.Thread:
|
||||
self.current_flight_name = flight_name
|
||||
self.analysis_options = analysis_options
|
||||
analysis_thread = threading.Thread(
|
||||
target=self._flight_analysis_orchestrator,
|
||||
args=(rec_folder_str, flight_name),
|
||||
args=(rec_folder_str, flight_name, workspace_path),
|
||||
daemon=True,
|
||||
)
|
||||
analysis_thread.start()
|
||||
return analysis_thread
|
||||
|
||||
def _flight_analysis_orchestrator(self, rec_folder_str: str, flight_name: str):
|
||||
def _flight_analysis_orchestrator(self, rec_folder_str: str, flight_name: str, flight_dir: Path):
|
||||
self.current_flight_folder_path = None
|
||||
try:
|
||||
workspace_dir = Path.cwd() / "flight_workspace"
|
||||
flight_dir = workspace_dir / flight_name
|
||||
flight_dir.mkdir(parents=True, exist_ok=True)
|
||||
self.current_flight_folder_path = flight_dir
|
||||
|
||||
cpp_config = self.config_manager.get_cpp_converter_config()
|
||||
exe_path = cpp_config.get("cpp_executable_path")
|
||||
if not exe_path or not Path(exe_path).is_file():
|
||||
raise ValueError(f"C++ executable not found at path: {exe_path}")
|
||||
raise ValueError(
|
||||
f"C++ executable not found at path: {exe_path}"
|
||||
)
|
||||
|
||||
rec_files = sorted(Path(rec_folder_str).glob("*.rec"))
|
||||
if not rec_files:
|
||||
@ -80,9 +79,7 @@ class FlightAnalyzer:
|
||||
"/a",
|
||||
]
|
||||
|
||||
log.info(
|
||||
f"Running g_reconverter for full analysis: {' '.join(command_list)}"
|
||||
)
|
||||
log.info(f"Running g_reconverter for full analysis: {' '.join(command_list)}")
|
||||
|
||||
self.worker_process = mp.Process(
|
||||
target=run_cpp_converter,
|
||||
@ -102,12 +99,7 @@ class FlightAnalyzer:
|
||||
def handle_final_analysis_steps(self):
|
||||
if not self.current_flight_folder_path:
|
||||
log.error("Cannot run final analysis steps: flight folder path is not set.")
|
||||
self.result_queue.put(
|
||||
{
|
||||
"type": "error",
|
||||
"message": "Internal state error: flight folder path missing.",
|
||||
}
|
||||
)
|
||||
self.result_queue.put({"type": "error", "message": "Internal state error: flight folder path missing."})
|
||||
return
|
||||
|
||||
try:
|
||||
@ -129,21 +121,17 @@ class FlightAnalyzer:
|
||||
summary_df = self._create_and_save_summary(
|
||||
storyboard_df, self.current_flight_folder_path, self.analysis_options
|
||||
)
|
||||
|
||||
|
||||
self._create_flight_report_txt(summary_df, self.current_flight_folder_path)
|
||||
|
||||
self.result_queue.put(
|
||||
{
|
||||
"type": "analysis_summary_data",
|
||||
"data": summary_df,
|
||||
"flight_folder_path": self.current_flight_folder_path,
|
||||
}
|
||||
)
|
||||
self.result_queue.put({
|
||||
"type": "analysis_summary_data",
|
||||
"data": summary_df,
|
||||
"flight_folder_path": self.current_flight_folder_path
|
||||
})
|
||||
|
||||
log.info("Flight analysis complete. All artifacts saved.")
|
||||
self.result_queue.put(
|
||||
{"type": "complete", "message": "Analysis successful."}
|
||||
)
|
||||
self.result_queue.put({"type": "complete", "message": "Analysis successful."})
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"Final analysis steps failed: {e}", exc_info=True)
|
||||
@ -171,27 +159,25 @@ class FlightAnalyzer:
|
||||
header_line = f.readline().strip()
|
||||
raw_columns = [h.strip() for h in header_line.split(";") if h.strip()]
|
||||
unique_column_names = self._make_columns_unique(raw_columns)
|
||||
|
||||
|
||||
storyboard_df = pd.read_csv(
|
||||
txt_path,
|
||||
sep=";",
|
||||
header=0,
|
||||
names=unique_column_names,
|
||||
on_bad_lines="skip",
|
||||
encoding="utf-8",
|
||||
encoding_errors="ignore",
|
||||
txt_path,
|
||||
sep=';',
|
||||
header=0,
|
||||
names=unique_column_names,
|
||||
on_bad_lines='skip',
|
||||
encoding='utf-8',
|
||||
encoding_errors='ignore'
|
||||
)
|
||||
|
||||
for col in storyboard_df.select_dtypes(include=["object"]).columns:
|
||||
for col in storyboard_df.select_dtypes(include=['object']).columns:
|
||||
storyboard_df[col] = storyboard_df[col].str.strip()
|
||||
|
||||
|
||||
numeric_cols = ["Batch", "TTAG"]
|
||||
for col in numeric_cols:
|
||||
if col in storyboard_df.columns:
|
||||
storyboard_df[col] = pd.to_numeric(
|
||||
storyboard_df[col], errors="coerce"
|
||||
)
|
||||
|
||||
storyboard_df[col] = pd.to_numeric(storyboard_df[col], errors="coerce")
|
||||
|
||||
storyboard_df.dropna(subset=["Batch", "TTAG"], inplace=True)
|
||||
storyboard_df["Batch"] = storyboard_df["Batch"].astype(int)
|
||||
storyboard_df["TTAG"] = storyboard_df["TTAG"].astype(int)
|
||||
@ -199,112 +185,97 @@ class FlightAnalyzer:
|
||||
except Exception as e:
|
||||
log.error(f"Failed to read or process summary file {txt_path.name}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
if storyboard_df.empty:
|
||||
log.warning(f"DataFrame is empty after cleaning {txt_path.name}")
|
||||
return None
|
||||
|
||||
csv_path = output_dir / "flight_storyboard.csv"
|
||||
json_path = output_dir / "flight_storyboard.json"
|
||||
|
||||
log.info(f"Saving full storyboard to {csv_path}")
|
||||
storyboard_df.to_csv(csv_path, index=False)
|
||||
|
||||
|
||||
log.info(f"Saving full storyboard to {json_path}")
|
||||
storyboard_df.to_json(json_path, orient="records", indent=4)
|
||||
|
||||
return storyboard_df
|
||||
|
||||
def _create_and_save_summary(
|
||||
self, storyboard_df: "pd.DataFrame", output_dir: Path, options: dict
|
||||
) -> "pd.DataFrame":
|
||||
df = storyboard_df.copy()
|
||||
|
||||
|
||||
agg_by_scale = options.get("aggregate_by_scale", True)
|
||||
agg_by_waveform = options.get("aggregate_by_waveform", True)
|
||||
|
||||
# Costruzione dinamica della chiave di stato
|
||||
status_components = []
|
||||
|
||||
mode_part = (
|
||||
df.get("Mode", pd.Series(index=df.index, dtype=str))
|
||||
.astype(str)
|
||||
.str.strip()
|
||||
.replace("", "N/A")
|
||||
)
|
||||
status_components.append(mode_part)
|
||||
|
||||
|
||||
mode_part = df.get('Mode', pd.Series(index=df.index, dtype=str)).astype(str).str.strip().replace('', 'N/A')
|
||||
submode_part = df.get('Mode.3', pd.Series(index=df.index, dtype=str)).astype(str).str.strip().replace('', 'N/A')
|
||||
|
||||
# Unisci sempre Mode e Submode
|
||||
full_mode_part = mode_part + "-" + submode_part
|
||||
status_components.append(full_mode_part)
|
||||
|
||||
if agg_by_scale:
|
||||
scale_part = (
|
||||
df.get("Scal.2", pd.Series(index=df.index, dtype=str))
|
||||
.astype(str)
|
||||
.str.strip()
|
||||
.replace("", "N/A")
|
||||
)
|
||||
scale_part = df.get('Scal.2', pd.Series(index=df.index, dtype=str)).astype(str).str.strip().replace('', 'N/A')
|
||||
status_components.append(scale_part)
|
||||
|
||||
|
||||
if agg_by_waveform:
|
||||
wf_part1 = (
|
||||
df.get("WF", pd.Series(index=df.index, dtype=str))
|
||||
.astype(str)
|
||||
.str.strip()
|
||||
.replace("", "N/A")
|
||||
)
|
||||
wf_part2 = (
|
||||
df.get("WF.2", pd.Series(index=df.index, dtype=str))
|
||||
.astype(str)
|
||||
.str.strip()
|
||||
.replace("", "N/A")
|
||||
)
|
||||
wf_part1 = df.get('WF', pd.Series(index=df.index, dtype=str)).astype(str).str.strip().replace('', 'N/A')
|
||||
wf_part2 = df.get('WF.2', pd.Series(index=df.index, dtype=str)).astype(str).str.strip().replace('', 'N/A')
|
||||
status_components.append("wf-" + wf_part1 + "-" + wf_part2)
|
||||
|
||||
df["status"] = status_components[0]
|
||||
df['status'] = status_components[0]
|
||||
for component in status_components[1:]:
|
||||
df["status"] = df["status"] + "_" + component
|
||||
df['status'] = df['status'] + "_" + component
|
||||
|
||||
df["status_changed"] = df["status"].ne(df["status"].shift())
|
||||
df['status_changed'] = df['status'].ne(df['status'].shift())
|
||||
|
||||
min_ttag = df['TTAG'].min()
|
||||
df['flight_time_s'] = (df['TTAG'] - min_ttag) * TICK_DURATION_S
|
||||
|
||||
min_ttag = df["TTAG"].min()
|
||||
df["flight_time_s"] = (df["TTAG"] - min_ttag) * TICK_DURATION_S
|
||||
|
||||
change_indices = df[df["status_changed"]].index.tolist()
|
||||
change_indices = df[df['status_changed']].index.tolist()
|
||||
if not change_indices or change_indices[0] != 0:
|
||||
change_indices.insert(0, 0)
|
||||
if df.index[-1] + 1 not in change_indices:
|
||||
change_indices.append(df.index[-1] + 1)
|
||||
|
||||
|
||||
summary_records = []
|
||||
for i in range(len(change_indices) - 1):
|
||||
start_loc, end_loc = change_indices[i], change_indices[i + 1] - 1
|
||||
start_loc, end_loc = change_indices[i], change_indices[i+1] - 1
|
||||
segment = df.loc[start_loc:end_loc]
|
||||
|
||||
if segment.empty:
|
||||
continue
|
||||
|
||||
start_time_s = segment["flight_time_s"].iloc[0]
|
||||
end_time_s = segment["flight_time_s"].iloc[-1]
|
||||
|
||||
summary_records.append(
|
||||
{
|
||||
"Segment (Mode | Scale | WF)": segment["status"].iloc[0],
|
||||
"Start Batch": segment["Batch"].iloc[0],
|
||||
"End Batch": segment["Batch"].iloc[-1],
|
||||
"Batch Count": segment["Batch"].iloc[-1]
|
||||
- segment["Batch"].iloc[0]
|
||||
+ 1,
|
||||
"Duration (s)": end_time_s - start_time_s,
|
||||
"start_time_str": str(timedelta(seconds=int(start_time_s))),
|
||||
"end_time_str": str(timedelta(seconds=int(end_time_s))),
|
||||
"Start File": segment["file"].iloc[0],
|
||||
"End File": segment["file"].iloc[-1],
|
||||
"# Files": segment["file"].nunique(),
|
||||
}
|
||||
)
|
||||
if segment.empty: continue
|
||||
|
||||
start_time_s = segment['flight_time_s'].iloc[0]
|
||||
end_time_s = segment['flight_time_s'].iloc[-1]
|
||||
|
||||
summary_records.append({
|
||||
'Segment (Mode | Scale | WF)': segment['status'].iloc[0],
|
||||
'Start Batch': segment['Batch'].iloc[0],
|
||||
'End Batch': segment['Batch'].iloc[-1],
|
||||
'Batch Count': segment['Batch'].iloc[-1] - segment['Batch'].iloc[0] + 1,
|
||||
'Duration (s)': end_time_s - start_time_s,
|
||||
'start_time_str': str(timedelta(seconds=int(start_time_s))),
|
||||
'end_time_str': str(timedelta(seconds=int(end_time_s))),
|
||||
'Start File': segment['file'].iloc[0],
|
||||
'End File': segment['file'].iloc[-1],
|
||||
'# Files': segment['file'].nunique()
|
||||
})
|
||||
|
||||
summary_df = pd.DataFrame(summary_records)
|
||||
|
||||
|
||||
csv_path = output_dir / "flight_summary.csv"
|
||||
json_path = output_dir / "flight_summary.json"
|
||||
|
||||
|
||||
log.info(f"Saving aggregated summary to {csv_path}")
|
||||
summary_df.to_csv(csv_path, index=False)
|
||||
log.info(f"Saving aggregated summary to {json_path}")
|
||||
summary_df.to_json(json_path, orient="records", indent=4)
|
||||
|
||||
|
||||
return summary_df
|
||||
|
||||
def _create_flight_report_txt(self, summary_df: "pd.DataFrame", output_dir: Path):
|
||||
@ -312,8 +283,8 @@ class FlightAnalyzer:
|
||||
log.info(f"Generating human-readable flight report to {report_path}")
|
||||
|
||||
try:
|
||||
total_duration = summary_df["Duration (s)"].sum()
|
||||
total_batches = summary_df["Batch Count"].sum()
|
||||
total_duration = summary_df['Duration (s)'].sum()
|
||||
total_batches = summary_df['Batch Count'].sum()
|
||||
num_segments = len(summary_df)
|
||||
|
||||
with open(report_path, "w", encoding="utf-8") as f:
|
||||
@ -327,39 +298,26 @@ class FlightAnalyzer:
|
||||
f.write(f"Total Segments: {num_segments}\n\n")
|
||||
|
||||
f.write("--- SEGMENT SUMMARY ---\n")
|
||||
|
||||
|
||||
report_df = summary_df.copy()
|
||||
report_df["Duration (s)"] = report_df["Duration (s)"].map(
|
||||
"{:.2f}".format
|
||||
)
|
||||
|
||||
report_df = report_df[
|
||||
[
|
||||
"Segment (Mode | Scale | WF)",
|
||||
"Start Batch",
|
||||
"End Batch",
|
||||
"Batch Count",
|
||||
"start_time_str",
|
||||
"end_time_str",
|
||||
"Duration (s)",
|
||||
"Start File",
|
||||
"End File",
|
||||
"# Files",
|
||||
]
|
||||
]
|
||||
report_df.rename(
|
||||
columns={
|
||||
"start_time_str": "Start Time",
|
||||
"end_time_str": "End Time",
|
||||
},
|
||||
inplace=True,
|
||||
)
|
||||
report_df['Duration (s)'] = report_df['Duration (s)'].map('{:.2f}'.format)
|
||||
|
||||
report_df = report_df[[
|
||||
'Segment (Mode | Scale | WF)',
|
||||
'Start Batch', 'End Batch', 'Batch Count',
|
||||
'start_time_str', 'end_time_str', 'Duration (s)',
|
||||
'Start File', 'End File', '# Files'
|
||||
]]
|
||||
report_df.rename(columns={
|
||||
'start_time_str': 'Start Time',
|
||||
'end_time_str': 'End Time'
|
||||
}, inplace=True)
|
||||
|
||||
df_string = report_df.to_string(index=True)
|
||||
|
||||
f.write(df_string)
|
||||
f.write("\n\n" + "=" * 80 + "\n")
|
||||
f.write(" End of Report\n")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"Failed to generate flight text report: {e}")
|
||||
log.error(f"Failed to generate flight text report: {e}")
|
||||
@ -81,6 +81,7 @@ class MainWindow(tk.Frame):
|
||||
|
||||
self.analyzer_rec_folder_var = tk.StringVar()
|
||||
self.analyzer_flight_name_var = tk.StringVar()
|
||||
self.analyzer_workspace_dir_var = tk.StringVar()
|
||||
self.analyzer_info_var = tk.StringVar(
|
||||
value="Please select a folder and a flight name."
|
||||
)
|
||||
@ -137,98 +138,87 @@ class MainWindow(tk.Frame):
|
||||
|
||||
def _create_flight_analyzer_tab(self, parent):
|
||||
parent.columnconfigure(0, weight=1)
|
||||
parent.rowconfigure(4, weight=1)
|
||||
parent.rowconfigure(5, weight=1) # Aumenta per fare spazio ai nuovi frame
|
||||
|
||||
setup_frame = ttk.LabelFrame(parent, text="Flight Setup")
|
||||
# --- Frame 1: Flight Source ---
|
||||
setup_frame = ttk.LabelFrame(parent, text="Flight Source")
|
||||
setup_frame.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
|
||||
setup_frame.columnconfigure(1, weight=1)
|
||||
ttk.Label(setup_frame, text="Recordings Folder:").grid(
|
||||
row=0, column=0, padx=5, pady=5, sticky="w"
|
||||
)
|
||||
rec_folder_entry = ttk.Entry(
|
||||
setup_frame, textvariable=self.analyzer_rec_folder_var, state="readonly"
|
||||
)
|
||||
ttk.Label(setup_frame, text="Recordings Folder:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
|
||||
rec_folder_entry = ttk.Entry(setup_frame, textvariable=self.analyzer_rec_folder_var, state="readonly")
|
||||
rec_folder_entry.grid(row=0, column=1, sticky="ew", padx=5)
|
||||
ttk.Button(setup_frame, text="Browse...", command=self.controller.select_and_analyze_flight_folder).grid(row=0, column=2, padx=5)
|
||||
|
||||
# --- Frame 2: Workspace ---
|
||||
workspace_frame = ttk.LabelFrame(parent, text="Flight Workspace (Analysis Output)")
|
||||
workspace_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
|
||||
workspace_frame.columnconfigure(1, weight=1)
|
||||
|
||||
ttk.Label(workspace_frame, text="Workspace Path:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
|
||||
workspace_entry = ttk.Entry(workspace_frame, textvariable=self.analyzer_workspace_dir_var)
|
||||
workspace_entry.grid(row=0, column=1, sticky="ew", padx=5)
|
||||
|
||||
dir_buttons_frame = ttk.Frame(workspace_frame)
|
||||
dir_buttons_frame.grid(row=0, column=2, padx=5)
|
||||
ttk.Button(
|
||||
setup_frame,
|
||||
text="Browse...",
|
||||
command=self.controller.select_and_analyze_flight_folder,
|
||||
).grid(row=0, column=2, padx=5)
|
||||
ttk.Label(setup_frame, text="Flight Name:").grid(
|
||||
row=1, column=0, padx=5, pady=5, sticky="w"
|
||||
)
|
||||
flight_name_entry = ttk.Entry(
|
||||
setup_frame, textvariable=self.analyzer_flight_name_var
|
||||
)
|
||||
dir_buttons_frame, text="Browse...",
|
||||
command=lambda: self.controller.select_output_dir(self.analyzer_workspace_dir_var)
|
||||
).pack(side=tk.LEFT)
|
||||
ttk.Button(
|
||||
dir_buttons_frame, text="Open...",
|
||||
command=lambda: self.controller.open_folder_from_path(self.analyzer_workspace_dir_var.get())
|
||||
).pack(side=tk.LEFT, padx=(5, 0))
|
||||
|
||||
ttk.Label(workspace_frame, text="Flight Name:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
|
||||
flight_name_entry = ttk.Entry(workspace_frame, textvariable=self.analyzer_flight_name_var)
|
||||
flight_name_entry.grid(row=1, column=1, columnspan=2, sticky="ew", padx=5)
|
||||
|
||||
aggregation_frame = ttk.LabelFrame(parent, text="Segment Definition")
|
||||
aggregation_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
|
||||
|
||||
# --- Frame 3: Segment Definition ---
|
||||
aggregation_frame = ttk.LabelFrame(parent, text="Segment Definition Options")
|
||||
aggregation_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
|
||||
|
||||
ttk.Checkbutton(
|
||||
aggregation_frame,
|
||||
aggregation_frame,
|
||||
text="Create new segment on Scale change",
|
||||
variable=self.aggregate_by_scale_var,
|
||||
variable=self.aggregate_by_scale_var
|
||||
).pack(side=tk.LEFT, padx=10, pady=5)
|
||||
|
||||
|
||||
ttk.Checkbutton(
|
||||
aggregation_frame,
|
||||
aggregation_frame,
|
||||
text="Create new segment on Waveform (WF) change",
|
||||
variable=self.aggregate_by_waveform_var,
|
||||
variable=self.aggregate_by_waveform_var
|
||||
).pack(side=tk.LEFT, padx=10, pady=5)
|
||||
|
||||
# --- Frame 4: Actions & Info ---
|
||||
action_frame = ttk.Frame(parent)
|
||||
action_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=10)
|
||||
self.start_analysis_button = ttk.Button(
|
||||
action_frame,
|
||||
text="Start Flight Analysis",
|
||||
command=self.controller.start_flight_analysis,
|
||||
state=tk.DISABLED,
|
||||
)
|
||||
action_frame.grid(row=3, column=0, sticky="ew", padx=5, pady=10)
|
||||
self.start_analysis_button = ttk.Button(action_frame, text="Start Flight Analysis", command=self.controller.start_flight_analysis, state=tk.DISABLED)
|
||||
self.start_analysis_button.pack(side=tk.LEFT, padx=(0, 5))
|
||||
self.open_flight_folder_button = ttk.Button(
|
||||
action_frame,
|
||||
text="Open Flight Folder",
|
||||
command=self.controller.open_current_flight_folder,
|
||||
state=tk.DISABLED,
|
||||
)
|
||||
self.open_flight_folder_button = ttk.Button(action_frame, text="Open Flight Folder", command=self.controller.open_current_flight_folder, state=tk.DISABLED)
|
||||
self.open_flight_folder_button.pack(side=tk.LEFT, padx=5)
|
||||
info_label = ttk.Label(action_frame, textvariable=self.analyzer_info_var)
|
||||
info_label.pack(side=tk.LEFT, padx=20)
|
||||
|
||||
|
||||
# --- Frame 5: Progress ---
|
||||
progress_frame = ttk.Frame(parent)
|
||||
progress_frame.grid(row=3, column=0, sticky="ew", padx=5, pady=5)
|
||||
progress_frame.grid(row=4, column=0, sticky="ew", padx=5, pady=5)
|
||||
progress_frame.columnconfigure(1, weight=1)
|
||||
ttk.Label(progress_frame, text="Analysis Progress:").grid(
|
||||
row=0, column=0, sticky="w"
|
||||
)
|
||||
self.analyzer_progressbar = ttk.Progressbar(
|
||||
progress_frame, variable=self.analyzer_progress_var
|
||||
)
|
||||
ttk.Label(progress_frame, text="Analysis Progress:").grid(row=0, column=0, sticky="w")
|
||||
self.analyzer_progressbar = ttk.Progressbar(progress_frame, variable=self.analyzer_progress_var)
|
||||
self.analyzer_progressbar.grid(row=0, column=1, sticky="ew", padx=5)
|
||||
ttk.Label(progress_frame, textvariable=self.analyzer_progress_text_var).grid(
|
||||
row=0, column=2, sticky="w"
|
||||
)
|
||||
ttk.Label(progress_frame, textvariable=self.analyzer_progress_text_var).grid(row=0, column=2, sticky="w")
|
||||
|
||||
# --- Frame 6: Results ---
|
||||
results_frame = ttk.LabelFrame(parent, text="Flight Summary & Segments")
|
||||
results_frame.grid(row=4, column=0, sticky="nsew", padx=5, pady=5)
|
||||
results_frame.grid(row=5, column=0, sticky="nsew", padx=5, pady=5)
|
||||
results_frame.columnconfigure(0, weight=1)
|
||||
results_frame.rowconfigure(0, weight=1)
|
||||
|
||||
|
||||
self.flight_timeline_tree = ttk.Treeview(
|
||||
results_frame,
|
||||
columns=(
|
||||
"status",
|
||||
"start_batch",
|
||||
"end_batch",
|
||||
"batch_count",
|
||||
"duration",
|
||||
"start_file",
|
||||
"end_file",
|
||||
"file_count",
|
||||
),
|
||||
show="headings",
|
||||
selectmode="extended",
|
||||
columns=("status", "start_batch", "end_batch", "batch_count", "duration", "start_file", "end_file", "file_count"),
|
||||
show="headings", selectmode="extended"
|
||||
)
|
||||
self.flight_timeline_tree.heading("status", text="Segment (Mode | Scale | WF)")
|
||||
self.flight_timeline_tree.heading("start_batch", text="Start Batch")
|
||||
@ -247,32 +237,17 @@ class MainWindow(tk.Frame):
|
||||
self.flight_timeline_tree.column("end_file", width=200, stretch=True)
|
||||
self.flight_timeline_tree.column("file_count", width=60, anchor="center")
|
||||
self.flight_timeline_tree.grid(row=0, column=0, sticky="nsew")
|
||||
tree_scrollbar = ttk.Scrollbar(
|
||||
results_frame, orient="vertical", command=self.flight_timeline_tree.yview
|
||||
)
|
||||
tree_scrollbar = ttk.Scrollbar(results_frame, orient="vertical", command=self.flight_timeline_tree.yview)
|
||||
self.flight_timeline_tree.configure(yscrollcommand=tree_scrollbar.set)
|
||||
tree_scrollbar.grid(row=0, column=1, sticky="ns")
|
||||
|
||||
buttons_frame = ttk.Frame(results_frame)
|
||||
buttons_frame.grid(row=1, column=0, columnspan=2, sticky="ew", pady=5)
|
||||
ttk.Button(
|
||||
buttons_frame, text="Select All", command=self._select_all_segments
|
||||
).pack(side=tk.LEFT, padx=(0, 5))
|
||||
ttk.Button(
|
||||
buttons_frame, text="Select None", command=self._deselect_all_segments
|
||||
).pack(side=tk.LEFT)
|
||||
self.export_segment_button = ttk.Button(
|
||||
buttons_frame,
|
||||
text="Export Selected Segment(s)",
|
||||
state=tk.DISABLED,
|
||||
command=self.controller.start_segment_export,
|
||||
)
|
||||
ttk.Button(buttons_frame, text="Select All", command=self._select_all_segments).pack(side=tk.LEFT, padx=(0, 5))
|
||||
ttk.Button(buttons_frame, text="Select None", command=self._deselect_all_segments).pack(side=tk.LEFT)
|
||||
self.export_segment_button = ttk.Button(buttons_frame, text="Export Selected Segment(s)", state=tk.DISABLED, command=self.controller.start_segment_export)
|
||||
self.export_segment_button.pack(side=tk.RIGHT)
|
||||
configure_export_button = ttk.Button(
|
||||
buttons_frame,
|
||||
text="Configure Segment Export...",
|
||||
command=self.controller.open_export_config_editor,
|
||||
)
|
||||
configure_export_button = ttk.Button(buttons_frame, text="Configure Segment Export...", command=self.controller.open_export_config_editor)
|
||||
configure_export_button.pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
def _select_all_segments(self):
|
||||
|
||||
@ -99,6 +99,7 @@ class ConfigManager:
|
||||
"last_out_output_dir": "",
|
||||
"last_rec_output_dir": "",
|
||||
"last_flight_folder": "",
|
||||
"last_flight_workspace_parent_dir": "",
|
||||
"active_out_export_profile_name": "Default",
|
||||
"export_profiles": [default_export_profile.to_dict()],
|
||||
"cpp_converter_config": default_cpp_config,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user