Skip to content

Commit c82d538

Browse files
committed
push probelms
1 parent a5bbb70 commit c82d538

19 files changed

Lines changed: 164 additions & 97 deletions

examples/compare_interfaces.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ def run_final_comparison(img_path='data/example.tif'):
9999
ax3 = fig.add_subplot(gs[0, 2])
100100
# Plotting Correlation Scatter
101101
ax3.scatter(P_bayes_z[valid_p], P_lap_z[valid_p], alpha=0.5, c='k', s=10)
102-
ax3.set_xlabel("Bayesian P"); ax3.set_ylabel("Laplace P")
102+
ax3.set_xlabel("Bayesian P")
103+
ax3.set_ylabel("Laplace P")
103104
ax3.set_title(f"Pressure Correlation: {corr_p:.2f}")
104105
ax3.grid(True, alpha=0.3)
105106

@@ -118,7 +119,8 @@ def run_final_comparison(img_path='data/example.tif'):
118119
ax6.text(0.5, 0.5, "Laplace Tension is Constant\n(No Correlation)", ha='center', va='center')
119120
else:
120121
ax6.scatter(T_bayes_aligned, T_lap_aligned, alpha=0.5, c='k', s=10)
121-
ax6.set_xlabel("Bayesian T"); ax6.set_ylabel("Laplace T")
122+
ax6.set_xlabel("Bayesian T")
123+
ax6.set_ylabel("Laplace T")
122124
ax6.set_title(t_title)
123125
ax6.grid(True, alpha=0.3)
124126

@@ -136,7 +138,8 @@ def get_interface_tensions(tissue, tensions):
136138
"""
137139
mapping = {}
138140
for i, (c1, c2) in enumerate(tissue.E_cells):
139-
if c1 == 0 or c2 == 0: continue # Skip boundary
141+
if c1 == 0 or c2 == 0:
142+
continue # Skip boundary
140143
# Sort to ensure (1,2) is same as (2,1)
141144
key = tuple(sorted((c1, c2)))
142145
mapping[key] = tensions[i]
@@ -145,17 +148,20 @@ def get_interface_tensions(tissue, tensions):
145148
def normalize_z(data):
146149
"""Robust Z-score normalization"""
147150
valid = data[data != 0]
148-
if len(valid) == 0: return data
151+
if len(valid) == 0:
152+
return data
149153
std = np.std(valid)
150-
if std < 1e-9: return np.zeros_like(data)
154+
if std < 1e-9:
155+
return np.zeros_like(data)
151156
return (data - np.mean(valid)) / std
152157

153158
def plot_cells(ax, tissue, values, title):
154159
ax.imshow(tissue.labels, cmap='gray', alpha=0.3)
155160
centroids = tissue.C_centroids
156161

157162
# Filter
158-
if len(values) > len(centroids): values = values[:len(centroids)]
163+
if len(values) > len(centroids):
164+
values = values[:len(centroids)]
159165
valid_idx = np.where(values != 0)[0]
160166

161167
# Robust Scale

examples/compare_methods.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import numpy as np
22
import matplotlib.pyplot as plt
3-
from skimage import io
43
import logging
54
import os
65

@@ -17,7 +16,8 @@ def run_comparison_demo(img_path='data/test_image.tif'):
1716
# ---------------------------------------------------------
1817
print("\n--- Running Bayesian Inference ---")
1918
tissue_bayes = topology.extract_topology(labels, min_edge_len=4.0, clean=True, trace_pixels=False)
20-
if tissue_bayes is None: return
19+
if tissue_bayes is None:
20+
return
2121
res_bayes = solvers.solve_bayesian(tissue_bayes, mu=1.0)
2222

2323
# ---------------------------------------------------------
@@ -100,10 +100,12 @@ def run_comparison_demo(img_path='data/test_image.tif'):
100100
def normalize(data):
101101
"""Returns Z-score. Handles constant data by returning zeros."""
102102
valid = data[data != 0]
103-
if len(valid) == 0: return data
103+
if len(valid) == 0:
104+
return data
104105

105106
std = np.std(valid)
106-
if std < 1e-6: return np.zeros_like(data)
107+
if std < 1e-6:
108+
return np.zeros_like(data)
107109

108110
return (data - np.mean(valid)) / std
109111

@@ -123,9 +125,11 @@ def get_cell_mean_tensions(tissue, edge_tensions):
123125
if not np.isfinite(val):
124126
continue
125127
if c1 > 0:
126-
cell_tensions[c1-1] += val; cell_counts[c1-1] += 1
128+
cell_tensions[c1-1] += val
129+
cell_counts[c1-1] += 1
127130
if c2 > 0:
128-
cell_tensions[c2-1] += val; cell_counts[c2-1] += 1
131+
cell_tensions[c2-1] += val
132+
cell_counts[c2-1] += 1
129133

130134
mask = cell_counts > 0
131135
cell_tensions[mask] /= cell_counts[mask]
@@ -134,10 +138,10 @@ def get_cell_mean_tensions(tissue, edge_tensions):
134138
def plot_map(ax, tissue, values, title, cmap='viridis'):
135139
"""Plots cell values. Handles constant values gracefully."""
136140
ax.imshow(tissue.labels, cmap='gray', alpha=0.3)
137-
138141
centroids = tissue.C_centroids
139-
if len(values) > len(centroids): values = values[:len(centroids)]
140-
142+
if len(values) > len(centroids):
143+
values = values[:len(centroids)]
144+
141145
# Robust scaling
142146
if np.ptp(values) < 1e-6:
143147
# Constant data (e.g. Laplace Tension)

examples/demo_2d_bayesian.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import tifffile
55

6-
from force_inference import segmentation, topology, solvers, visualization
6+
from force_inference import segmentation, solvers, visualization
77
from force_inference.topology_label import extract_topology_label
88

99
def run_demo():

examples/demo_laplace.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import numpy as np
55
import tifffile
66
from force_inference.topology_label import extract_topology_label
7-
from force_inference import geometry, segmentation, solvers, topology, visualization
7+
from force_inference import geometry, segmentation, solvers, visualization
88

99

1010
def _load_membrane_binary(filename):

examples/demo_stress_analysis.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import matplotlib.pyplot as plt
2-
import numpy as np
32
import os
43

54
from force_inference import segmentation, topology, solvers, geometry, visualization

examples/diagnose_junctions.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
Usage:
88
python diagnose_junctions.py --tif test.tif --out /tmp/junc
99
"""
10-
import argparse, os
10+
import argparse
11+
import os
1112
import numpy as np
1213
from PIL import Image
1314
from skimage import morphology
@@ -26,9 +27,12 @@ def load_tif_2d(path):
2627
except ImportError:
2728
arr = np.array(Image.open(path).convert('L'))
2829
if arr.ndim == 3:
29-
if arr.shape[0] <= 4: arr = arr[0]
30-
elif arr.shape[2] <= 4: arr = (0.299*arr[:,:,0]+0.587*arr[:,:,1]+0.114*arr[:,:,2]).astype(arr.dtype)
31-
else: arr = arr.max(axis=0)
30+
if arr.shape[0] <= 4:
31+
arr = arr[0]
32+
elif arr.shape[2] <= 4:
33+
arr = (0.299*arr[:,:,0]+0.587*arr[:,:,1]+0.114*arr[:,:,2]).astype(arr.dtype)
34+
else:
35+
arr = arr.max(axis=0)
3236
return arr
3337

3438

@@ -38,20 +42,23 @@ def skeleton_stats(binary, dilation_r=0):
3842
if dilation_r > 0:
3943
mask = morphology.dilation(mask, morphology.disk(dilation_r))
4044
skel = morphology.skeletonize(mask)
41-
kernel = np.ones((3,3), dtype=np.uint8); kernel[1,1] = 0
45+
kernel = np.ones((3,3), dtype=np.uint8)
46+
kernel[1,1] = 0
4247
nc = convolve(skel.astype(np.uint8), kernel, mode='constant', cval=0)
4348
branch_mask = skel & (nc >= 3)
4449
by, bx = np.where(branch_mask)
4550
return skel, branch_mask, nc, np.column_stack((bx.astype(float), by.astype(float))) if len(by) else np.zeros((0,2))
4651

4752

4853
def cluster(coords, r=4.0):
49-
if len(coords) == 0: return coords
54+
if len(coords) == 0:
55+
return coords
5056
tree = cKDTree(coords)
5157
visited = np.zeros(len(coords), dtype=bool)
5258
out = []
5359
for i in range(len(coords)):
54-
if visited[i]: continue
60+
if visited[i]:
61+
continue
5562
nb = tree.query_ball_point(coords[i], r)
5663
out.append(coords[nb].mean(axis=0))
5764
visited[nb] = True
@@ -93,7 +100,8 @@ def main():
93100
'(red=branch, green=edge, blue=endpoint, yellow=clustered vertex)', fontsize=11)
94101
plt.tight_layout()
95102
p = os.path.join(args.out, 'dilation_comparison.png')
96-
plt.savefig(p, dpi=130, bbox_inches='tight'); plt.close()
103+
plt.savefig(p, dpi=130, bbox_inches='tight')
104+
plt.close()
97105
print(f"Saved: {p}")
98106

99107
# ── Figure 2: zoom into missed junctions (low-branch regions) ────────
@@ -118,7 +126,7 @@ def main():
118126
top_idx = np.argsort(scores)[::-1][:9]
119127
top_junctions = ep_clustered[top_idx]
120128

121-
print(f"\nTop missed junction candidates (by nearby endpoint count):")
129+
print("\nTop missed junction candidates (by nearby endpoint count):")
122130
for i, (cx, cy) in enumerate(top_junctions):
123131
print(f" [{i}] center=({cx:.0f},{cy:.0f}) nearby_endpoints={scores[top_idx[i]]}")
124132

@@ -139,21 +147,26 @@ def main():
139147

140148
# Overlay dilation=0 skeleton (green)
141149
crop0 = skel0[y0:y1, x0:x1]
142-
ys0, xs0 = np.where(crop0); ax.scatter(xs0, ys0, c='lime', s=2, alpha=0.7)
150+
ys0, xs0 = np.where(crop0)
151+
ax.scatter(xs0, ys0, c='lime', s=2, alpha=0.7)
143152

144153
# Overlay dilation=1 skeleton (magenta) for comparison
145154
crop1 = skel1[y0:y1, x0:x1]
146-
ys1, xs1 = np.where(crop1); ax.scatter(xs1, ys1, c='magenta', s=2, alpha=0.5)
155+
ys1, xs1 = np.where(crop1)
156+
ax.scatter(xs1, ys1, c='magenta', s=2, alpha=0.5)
147157

148158
# Branch pixels (dilation=0): red; dilation=1: yellow
149-
br0c = bm0[y0:y1, x0:x1]; yb0,xb0 = np.where(br0c)
150-
br1c = bm1[y0:y1, x0:x1]; yb1,xb1 = np.where(br1c)
159+
br0c = bm0[y0:y1, x0:x1]
160+
yb0,xb0 = np.where(br0c)
161+
br1c = bm1[y0:y1, x0:x1]
162+
yb1,xb1 = np.where(br1c)
151163
ax.scatter(xb0, yb0, c='red', s=20, zorder=10)
152164
ax.scatter(xb1, yb1, c='yellow', s=20, zorder=10, marker='*')
153165

154166
ax.set_title(f'Junction {i} ({cx},{cy})\n'
155167
f'red=branch(d=0) yellow★=branch(d=1)', fontsize=8)
156-
ax.set_xlim(0, x1-x0); ax.set_ylim(y1-y0, 0)
168+
ax.set_xlim(0, x1-x0)
169+
ax.set_ylim(y1-y0, 0)
157170
ax.axis('off')
158171

159172
for j in range(n_show, len(axes)):
@@ -168,7 +181,8 @@ def main():
168181
'yellow stars = branches recovered by disk(1) dilation', fontsize=11)
169182
plt.tight_layout()
170183
p2 = os.path.join(args.out, 'missed_junctions_zoom.png')
171-
plt.savefig(p2, dpi=130, bbox_inches='tight'); plt.close()
184+
plt.savefig(p2, dpi=130, bbox_inches='tight')
185+
plt.close()
172186
print(f"Saved: {p2}")
173187

174188
# ── Print recommendation ──────────────────────────────────────────────
@@ -179,7 +193,7 @@ def main():
179193
print(f"\nVertex counts by dilation: {dict(zip(dils, counts))}")
180194
best = dils[int(np.argmax(counts))]
181195
print(f"→ Recommended dilation: disk({best}) (maximizes vertex count)")
182-
print(f"\nIn topology.py _labels_to_boundary or extract_topology, add:")
196+
print("\nIn topology.py _labels_to_boundary or extract_topology, add:")
183197
print(f" boundary = morphology.dilation(boundary, morphology.disk({best}))")
184198

185199

examples/diagnose_tif_vs_jpg.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import numpy as np
1414
from PIL import Image
1515
from skimage import morphology
16-
from scipy.ndimage import convolve, label as nd_label
16+
from scipy.ndimage import convolve
1717
from scipy.spatial import cKDTree
1818
import matplotlib
1919
matplotlib.use('Agg')
@@ -69,7 +69,8 @@ def labels_to_boundary_thin(labels):
6969

7070

7171
def count_branch_points(skel):
72-
kernel = np.ones((3, 3), dtype=np.uint8); kernel[1, 1] = 0
72+
kernel = np.ones((3, 3), dtype=np.uint8)
73+
kernel[1, 1] = 0
7374
nc = convolve(skel.astype(np.uint8), kernel, mode='constant', cval=0)
7475
return skel & (nc >= 3), nc
7576

@@ -83,7 +84,8 @@ def cluster_count(branch_mask, r=3.0):
8384
visited = np.zeros(len(coords), dtype=bool)
8485
n = 0
8586
for i in range(len(coords)):
86-
if visited[i]: continue
87+
if visited[i]:
88+
continue
8789
nb = tree.query_ball_point(coords[i], r)
8890
visited[nb] = True
8991
n += 1
@@ -111,7 +113,7 @@ def analyze(name, boundary, ax_row):
111113
ax_row[0].set_title(f'{name}\nboundary ({np.sum(boundary)} px)')
112114

113115
ax_row[1].imshow(disp)
114-
ax_row[1].set_title(f'Skeleton\ngreen=edge red=branch blue=endpoint')
116+
ax_row[1].set_title('Skeleton\ngreen=edge red=branch blue=endpoint')
115117

116118
by, bx = np.where(branch_mask)
117119
ax_row[2].imshow(skel, cmap='gray', alpha=0.4)
@@ -131,17 +133,21 @@ def analyze(name, boundary, ax_row):
131133
# membrane thickness estimate
132134
col = boundary[:, boundary.shape[1]//2]
133135
runs = []
134-
in_run = False; run_len = 0
136+
in_run = False
137+
run_len = 0
135138
for v in col:
136139
if v:
137-
in_run = True; run_len += 1
140+
in_run = True
141+
run_len += 1
138142
elif in_run:
139-
runs.append(run_len); in_run = False; run_len = 0
143+
runs.append(run_len)
144+
in_run = False
145+
run_len = 0
140146
if runs:
141147
print(f" membrane thickness (mid-col): "
142148
f"mean={np.mean(runs):.1f}px max={max(runs)}px min={min(runs)}px")
143149
else:
144-
print(f" membrane thickness: (no runs found in mid column)")
150+
print(" membrane thickness: (no runs found in mid column)")
145151

146152
return skel, branch_mask
147153

examples/topocheck.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import matplotlib.pyplot as plt
2-
import matplotlib.image as mpimg
32
import os
43
import logging
54
import numpy as np
65
from matplotlib.patches import Polygon
76
from matplotlib.collections import PatchCollection
87
import tifffile
98

10-
from force_inference import segmentation, topology, visualization
9+
from force_inference import segmentation, topology
1110

1211
logging.basicConfig(level=logging.INFO)
1312

examples/verify_correction.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def plot_map(ax, tissue, values, title):
4040

4141
# Normalize for view
4242
val_disp = values[values!=0]
43-
if len(val_disp)==0: return
43+
if len(val_disp)==0:
44+
return
4445
v_min, v_max = np.percentile(val_disp, [2, 98])
4546

4647
sc = ax.scatter(cents[:,0], cents[:,1], c=values[:len(cents)],

force_inference/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import numpy as np
2-
from dataclasses import dataclass, field
2+
from dataclasses import dataclass
33
from typing import List, Optional
44

55
@dataclass

0 commit comments

Comments
 (0)