mosta02 commited on
Commit
57dc781
Β·
verified Β·
1 Parent(s): 21a4c35

Upload centerline_extraction.py

Browse files
Files changed (1) hide show
  1. centerline_extraction.py +49 -17
centerline_extraction.py CHANGED
@@ -2141,28 +2141,60 @@ def _deduplicate_bifurcation_points(bif_points, threshold_mm=5.0):
2141
  def _orient_artery_segments(segments):
2142
  """Ensure artery (non-Aorta) segments are ordered bifurcation β†’ endpoint.
2143
 
2144
- After splitting at bifurcation points, one end of each artery segment
2145
- is touching an Aorta segment (the bifurcation end) and the other is
2146
- the branch tip. We want the first point to be at the bifurcation
2147
- so that the frontend tangent (next βˆ’ prev) naturally points away from
2148
- the aorta.
2149
-
2150
- Heuristic: the bifurcation end has a larger radius (closer to the
2151
- trunk). If the first point's radius is *smaller* than the last
2152
- point's, reverse the segment.
 
 
 
 
 
2153
  """
 
 
2154
  for seg in segments:
2155
- if seg['label'] == 'Aorta':
2156
  continue
2157
- pts = seg['points']
 
 
 
 
 
 
 
 
 
 
2158
  if len(pts) < 2:
2159
  continue
2160
- # Compare radii at both ends. Bifurcation end is thicker.
2161
- r_first = pts[0]['radius']
2162
- r_last = pts[-1]['radius']
2163
- if r_first < r_last:
2164
- # First point is the thin (tip) end β†’ reverse so bif comes first
2165
- pts.reverse()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2166
 
2167
 
2168
  # Build Frontend response JSON
 
2141
  def _orient_artery_segments(segments):
2142
  """Ensure artery (non-Aorta) segments are ordered bifurcation β†’ endpoint.
2143
 
2144
+ Strategy (preferred): the bifurcation end of a branch is physically
2145
+ touching an Aorta segment endpoint (they share the same VMTK network
2146
+ node, so the distance is β‰ˆ 0 mm). We check both ends of each artery
2147
+ segment against all Aorta segment endpoints; whichever end is closest
2148
+ to any aorta endpoint is the bifurcation end and must come first.
2149
+
2150
+ Fallback: if no Aorta segments exist yet (very rare), fall back to the
2151
+ radius heuristic β€” the bifurcation end is typically thicker.
2152
+
2153
+ Why not radius alone? After 1 mm resampling the Voronoi radius at the
2154
+ resampled endpoints can be slightly different from the exact bifurcation
2155
+ radius, causing the heuristic to flip segments that should stay and
2156
+ vice-versa. Proximity to an Aorta endpoint is exact (same VTK point ID
2157
+ β†’ same x,y,z coordinates) and therefore completely reliable.
2158
  """
2159
+ # Collect all Aorta segment endpoints (first and last point of each Aorta seg)
2160
+ aorta_eps = []
2161
  for seg in segments:
2162
+ if seg.get('label') != 'Aorta':
2163
  continue
2164
+ pts = seg.get('points', [])
2165
+ if not pts:
2166
+ continue
2167
+ aorta_eps.append(pts[0])
2168
+ if len(pts) > 1:
2169
+ aorta_eps.append(pts[-1])
2170
+
2171
+ for seg in segments:
2172
+ if seg.get('label') == 'Aorta':
2173
+ continue
2174
+ pts = seg.get('points', [])
2175
  if len(pts) < 2:
2176
  continue
2177
+
2178
+ if aorta_eps:
2179
+ # Proximity check: which end is closest to any Aorta endpoint?
2180
+ p0, p_last = pts[0], pts[-1]
2181
+ min_dist_start = min(
2182
+ (p0['x'] - ae['x']) ** 2 + (p0['y'] - ae['y']) ** 2 + (p0['z'] - ae['z']) ** 2
2183
+ for ae in aorta_eps
2184
+ )
2185
+ min_dist_end = min(
2186
+ (p_last['x'] - ae['x']) ** 2 + (p_last['y'] - ae['y']) ** 2 + (p_last['z'] - ae['z']) ** 2
2187
+ for ae in aorta_eps
2188
+ )
2189
+ # If the END is closer to the aorta, the segment is backwards β†’ reverse it
2190
+ if min_dist_end < min_dist_start:
2191
+ pts.reverse()
2192
+ else:
2193
+ # Fallback: radius heuristic (bifurcation end is thicker)
2194
+ r_first = pts[0]['radius']
2195
+ r_last = pts[-1]['radius']
2196
+ if r_first < r_last:
2197
+ pts.reverse()
2198
 
2199
 
2200
  # Build Frontend response JSON