Added normalization and detection.

This commit is contained in:
ivngrmk
2025-11-19 17:47:31 +03:00
parent 333ec5d196
commit 2b2e323fbf
3 changed files with 203 additions and 117 deletions

View File

@ -1,12 +1,16 @@
{
"open_air": true,
"axis": "abs",
"cut": 0.267,
"cut": 0.23,
"max": 1.5,
"gain": 1.0,
"start_freq": 470.0,
"stop_freq": 8800.0,
"clear_history": false,
"sigma": 4.28,
"sigma": 3.42,
"border_border_m": 0.26,
"if_normalize": false,
"if_draw_level": false,
"detection_level": 3.0,
"data_limit": 500
}

View File

@ -3,6 +3,6 @@
"y_max": 40,
"autoscale": true,
"show_magnitude": true,
"show_phase": true,
"show_phase": false,
"open_air": false
}

View File

@ -58,6 +58,10 @@ class BScanProcessor(BaseProcessor):
"stop_freq": 8800.0, # Stop frequency (MHz)
"clear_history": False, # UI button; not persisted
"sigma" : 0.01,
"border_border_m" : 0.5,
"if_normalize" : False,
"if_draw_level" : False,
"detection_level" : 5,
}
def get_ui_parameters(self) -> list[UIParameter]:
@ -120,6 +124,43 @@ class BScanProcessor(BaseProcessor):
value=cfg["stop_freq"],
options={"min": 100.0, "max": 8800.0, "step": 10.0, "dtype": "float"},
),
# Modern features
UIParameter(
name="sigma",
label="Степень сглаживания в abs режиме",
type="slider",
value=0.01,
options={"min": 0.01, "max": 5.0, "step": 0.01, "dtype": "float"},
),
UIParameter(
name="if_normalize",
label="Нормировка",
type="toggle",
value=False,
),
UIParameter(
name="border_border_m",
label="Глубина границы",
type="slider",
value=0.5,
options={"min": 0.0, "max": 2.5, "step": 0.01, "dtype": "float"},
),
UIParameter(
name="if_draw_level",
label="Детекция",
type="toggle",
value=False,
),
UIParameter(
name="detection_level",
label="Порог детекции,%",
type="slider",
value=5,
options={"min": 0.0, "max": 100.0, "step": 0.1, "dtype": "float"},
),
# Big botton
UIParameter(
name="clear_history",
label="Очистить историю",
@ -127,13 +168,6 @@ class BScanProcessor(BaseProcessor):
value=False,
options={"action": "Очистить накопленную историю графика"},
),
UIParameter(
name="sigma",
label="Степень сглаживания в abs режиме",
type="slider",
value=self._config.get("y_max", 10),
options={"min": 0.01, "max": 5.0, "step": 0.01, "dtype": "float"},
),
]
def update_config(self, updates: dict[str, Any]) -> None:
@ -340,19 +374,51 @@ class BScanProcessor(BaseProcessor):
},
}
Y_VALUE = self._config["border_border_m"]
# Build scatter-like heatmap (irregular grid) from history
x_coords: list[int] = []
y_coords: list[float] = []
z_values: list[float] = []
z_values_square = np.zeros((len(history[0]["distance_data"]),len(history)),dtype=float)
for sweep_index, item in enumerate(history, start=1):
depths = item["distance_data"]
amps = item["time_domain_data"]
for d, a in zip(depths, amps, strict=False):
if self._config['if_normalize']:
depth_mask = np.array(depths) < Y_VALUE
normalized_ampls = np.array(amps) / np.max(np.array(amps)[depth_mask])
else:
normalized_ampls = np.array(amps)
z_values_square[:,sweep_index-1] = normalized_ampls
for d, a in zip(depths, normalized_ampls, strict=False):
x_coords.append(sweep_index)
y_coords.append(d)
z_values.append(a)
z_values.append(float(a))
if self._config["if_draw_level"]:
detection_level_abs = np.percentile(z_values, 100 - self._config["detection_level"])
detected_points_mask = (np.array(z_values) > detection_level_abs) & (np.array(y_coords) > Y_VALUE)
detected_points_x = list([float(x) for x in np.array(x_coords)[detected_points_mask]])
detected_points_y = list([float(y) for y in np.array(y_coords)[detected_points_mask]])
detected_trace = {
"type": "scatter",
"mode": "markers",
"x": detected_points_x,
"y": detected_points_y,
"marker": {
"size": 8,
"color": "red",
"symbol": "circle",
},
"name": "Обнаруженные точки",
}
else:
detected_trace = None
# Colorscale selection
if self._config["axis"] == "abs":
@ -402,9 +468,32 @@ class BScanProcessor(BaseProcessor):
"height": 546,
"template": "plotly_dark",
"margin": {"t": 40, "r": 50, "b": 110, "l": 50},
"autosize": True
"autosize": True,
}
print(self._config['if_normalize'], self._config['if_draw_level'])
if self._config['if_normalize'] or self._config['if_draw_level']:
layout["shapes"] = layout.get("shapes", []) + [
{
"type": "line",
# по X — координаты "бумаги" (01 по всей ширине графика)
"xref": "paper",
# по Y — координаты данных (в метрах глубины)
"yref": "y",
"x0": 0,
"x1": 1,
"y0": Y_VALUE,
"y1": Y_VALUE,
"line": {
"width": 2,
"dash": "dash",
"color": "white",
},
}
]
if detected_trace is not None:
return {"data": [heatmap_trace,detected_trace], "layout": layout}
return {"data": [heatmap_trace], "layout": layout}
# -------------------------------------------------------------------------
@ -568,13 +657,8 @@ class BScanProcessor(BaseProcessor):
# Determine sigma for smoothing
if vna_config:
# calc_type = vna_config.get("axis", "abs")
# sigma = float(vna_config.get("sigma", 0.01))
calc_type = self._config["axis"]
sigma = self._config["sigma"]
pass
else:
calc_type = self._config["axis"]
sigma = self._config["sigma"]
@ -594,10 +678,8 @@ class BScanProcessor(BaseProcessor):
depth_out, time_out = self._apply_depth_processing(depth_m, time_response)
if calc_type == 'abs':
print('Filtering with sigma',sigma)
filtered_time_out = gaussian_filter1d(time_out, sigma=sigma)
else:
print("Not filtering")
filtered_time_out = time_out
return {