Skip to content

Commit 93c7b3e

Browse files
committed
update: add comments
1 parent 7dcac2f commit 93c7b3e

10 files changed

Lines changed: 57 additions & 22 deletions

File tree

assets/applications/input_files_templates/python/espresso/processing:fit_esp_polar.pyi

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,27 @@ X = np.linspace(0, 1, len(Y))
2525
{% endif %}{% endraw %}
2626

2727
N = len(Y)
28-
MARGIN_FRACTION = 0.10
29-
MIN_REGION_POINTS = 10
28+
MARGIN_FRACTION = 0.10 # Exclude 10% from edges to avoid surface effects
29+
MIN_REGION_POINTS = 10 # Minimum points needed for linear fit
3030

3131

3232
def detect_interface_position(y_data, x_data):
33+
"""Find interface position by locating maximum gradient in ESP profile.
34+
35+
Uses gradient smoothing to identify the steepest change, which indicates
36+
the interface between two materials.
37+
"""
3338
n = len(y_data)
3439
margin = max(int(n * MARGIN_FRACTION), MIN_REGION_POINTS)
3540
if 2 * margin >= n:
3641
return x_data[n // 2], n // 2
42+
43+
# Calculate smoothed gradient to find interface
3744
gradient = np.abs(np.gradient(y_data))
3845
window = max(n // 20, 3)
3946
smoothed = np.convolve(gradient, np.ones(window) / window, mode="same")
47+
48+
# Search for maximum gradient (interface) excluding margins
4049
search_start = margin
4150
search_end = n - margin
4251
search_region = smoothed[search_start:search_end]
@@ -47,52 +56,78 @@ def detect_interface_position(y_data, x_data):
4756

4857

4958
def get_bulk_regions(n_points, interface_idx):
59+
"""Determine bulk-like regions on left and right sides for linear fitting.
60+
61+
Ensures regions are far enough from interface and edges to capture
62+
representative bulk behavior.
63+
"""
5064
margin = max(int(n_points * MARGIN_FRACTION), MIN_REGION_POINTS // 2)
65+
66+
# Left bulk region: between left margin and interface
5167
left_start = margin
5268
left_end = max(left_start + MIN_REGION_POINTS, interface_idx - margin)
5369
if left_end <= left_start:
5470
left_end = min(interface_idx, left_start + MIN_REGION_POINTS)
71+
72+
# Right bulk region: between interface and right margin
5573
right_start = min(interface_idx + margin, n_points - margin - MIN_REGION_POINTS)
5674
right_end = n_points - margin
5775
if right_end <= right_start:
5876
right_start = max(interface_idx, right_end - MIN_REGION_POINTS)
77+
78+
# Ensure bounds are valid
5979
left_start = max(0, left_start)
6080
left_end = min(n_points, left_end)
6181
right_start = max(0, right_start)
6282
right_end = min(n_points, right_end)
83+
84+
# Final fallback for edge cases
6385
if left_end <= left_start:
6486
left_start = 0
6587
left_end = min(MIN_REGION_POINTS, interface_idx)
6688
if right_end <= right_start:
6789
right_start = max(interface_idx, n_points - MIN_REGION_POINTS)
6890
right_end = n_points
91+
6992
return (left_start, left_end), (right_start, right_end)
7093

7194

7295
def fit_linear_region(x_data, y_data, start_idx, end_idx):
96+
"""Fit linear regression to ESP data in specified region.
97+
98+
Returns slope and intercept. For non-polar materials, slope ≈ 0.
99+
For polar materials, slope represents internal electric field.
100+
"""
73101
start_idx = max(0, int(start_idx))
74102
end_idx = min(len(x_data), int(end_idx))
75103
if end_idx <= start_idx:
76104
end_idx = start_idx + MIN_REGION_POINTS
105+
77106
x_region = x_data[start_idx:end_idx]
78107
y_region = y_data[start_idx:end_idx]
108+
109+
# Fallback for insufficient data: return flat line at mean
79110
if len(x_region) < 2:
80111
return {"slope": 0.0, "intercept": float(np.mean(y_data)), "r_squared": 0.0}
112+
81113
slope, intercept, r_value, _, _ = linregress(x_region, y_region)
82114
return {"slope": slope, "intercept": intercept, "r_squared": r_value**2}
83115

84116

117+
# Main calculation: fit lines to bulk regions and extrapolate to interface
85118
interface_x, interface_idx = detect_interface_position(Y, X)
86119
left_region, right_region = get_bulk_regions(N, interface_idx)
87120
left_fit = fit_linear_region(X, Y, left_region[0], left_region[1])
88121
right_fit = fit_linear_region(X, Y, right_region[0], right_region[1])
122+
123+
# Extrapolate fitted lines to interface position to get ESP values
89124
left_value_at_interface = left_fit["slope"] * interface_x + left_fit["intercept"]
90125
right_value_at_interface = right_fit["slope"] * interface_x + right_fit["intercept"]
91126

127+
# Output in same format as find_extrema.pyi for compatibility
92128
result = {
93129
"minima": [float(left_value_at_interface), float(right_value_at_interface)],
94130
"maxima": [],
95131
}
96132

97133
print(json.dumps(result, indent=4))
98-

data/workflows/subworkflows/espresso/average_electrostatic_potential_fit_polar.json

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

data/workflows/workflows/espresso/valence_band_offset_polar.json

Lines changed: 9 additions & 9 deletions
Large diffs are not rendered by default.

dist/js/runtime_data/applications/executableFlavorMapByApplication.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/js/runtime_data/applications/templatesList.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/js/runtime_data/subworkflows.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/js/runtime_data/workflows.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/js/runtime_data/workflows/workflowSubworkflowMapByApplication.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/py/mat3ra/standata/data/subworkflows.py

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/py/mat3ra/standata/data/workflows.py

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)