mosta02 commited on
Commit
8a6ed71
·
verified ·
1 Parent(s): 3c5d44e

Upload endograft_script.py

Browse files
Files changed (1) hide show
  1. endograft_script.py +117 -113
endograft_script.py CHANGED
@@ -2,104 +2,107 @@ import vtk
2
  import numpy as np
3
  import tempfile
4
 
5
- def arc_length(centerline):
6
- arc_lengths = np.zeros(len(centerline))
7
- for i in range(1, len(centerline)):
8
- arc_lengths[i] = arc_lengths[i-1] + np.linalg.norm(centerline[i] - centerline[i-1])
9
- return arc_lengths
10
 
11
  def compute_parallel_frames(centerline):
12
  frames = []
13
 
14
- tangent_0 = centerline[1] - centerline[0]
15
- tangent_0 /= np.linalg.norm(tangent_0)
16
 
17
- reference_vector = np.array([0, 0, 1]) # selecting z-axis as reference for calculating initial normal
18
- if abs(np.dot(tangent_0, reference_vector)) > 0.9:
19
- reference_vector = np.array([1, 0, 0])
20
 
21
- normal_0 = np.cross(tangent_0, reference_vector)
22
- normal_0 /= np.linalg.norm(normal_0)
23
- binormal_0 = np.cross(tangent_0, normal_0)
24
 
25
- frames.append((tangent_0, normal_0, binormal_0))
26
 
27
- for point_idx in range(1, len(centerline)):
28
- tangent_point = centerline[point_idx] - centerline[point_idx-1]
29
- tangent_point /= np.linalg.norm(tangent_point)
30
 
31
- tangent_prev, normal_prev, binormal_prev = frames[-1]
32
- rotation_axis = np.cross(tangent_prev, tangent_point)
33
 
34
- if np.linalg.norm(rotation_axis) < 1e-6:
35
- frames.append((tangent_point, normal_prev, binormal_prev))
36
  continue
37
 
38
- rotation_axis /= np.linalg.norm(rotation_axis)
39
- angle = np.arccos(np.clip(np.dot(tangent_prev, tangent_point), -1, 1))
40
 
41
- def rotate_vector(vector):
42
- return (vector * np.cos(angle) + np.cross(rotation_axis, vector) * np.sin(angle) + rotation_axis * np.dot(rotation_axis, vector) * (1 - np.cos(angle)))
43
 
44
- frames.append((tangent_point, rotate_vector(normal_prev), rotate_vector(binormal_prev)))
45
 
46
  return frames
47
 
48
- def project_point_to_surface(point, locator):
49
-
 
 
 
50
  closest = [0.0, 0.0, 0.0]
51
  cellId = vtk.mutable(0)
52
  subId = vtk.mutable(0)
53
  dist2 = vtk.mutable(0.0)
54
 
55
- locator.FindClosestPoint(point, closest, cellId, subId, dist2)
56
  return np.array(closest)
57
 
58
- def sample_centerline_by_distance(centerline, arc_lengths, frames, query_distance):
 
59
 
60
- idx = np.searchsorted(arc_lengths, query_distance)
61
  if idx <= 0:
62
  return centerline[0], frames[0]
63
  if idx >= len(centerline):
64
  return centerline[-1], frames[-1]
65
 
66
- arc_length_0, arc_length_1 = arc_lengths[idx-1], arc_lengths[idx]
67
- point_0, point_1 = centerline[idx-1], centerline[idx]
68
- tangent = (query_distance - arc_length_0) / (arc_length_1 - arc_length_0 + 1e-12)
69
 
70
- point = (1 - tangent) * point_0 + tangent * point_1
71
 
72
- tangent_0, normal_0, binormal_0 = frames[idx-1]
73
- tangent_1, normal_1, binormal_1 = frames[idx]
74
 
75
- tangent_vector = (1 - tangent) * tangent_0 + tangent * tangent_1
76
- normal_vector = (1 - tangent) * normal_0 + tangent * normal_1
77
- binormal_vector = (1 - tangent) * binormal_0 + tangent * binormal_1
78
 
79
- tangent_vector /= np.linalg.norm(tangent_vector)
80
- normal_vector /= np.linalg.norm(normal_vector)
81
- binormal_vector /= np.linalg.norm(binormal_vector)
82
 
83
- return point, (tangent_vector, normal_vector, binormal_vector)
84
 
85
- # Fabric Component
86
- def create_component_fabric(centerline, frames, start_position, length, diameter, start_amplitude_pp=2.0, waves=8):
87
  # shift centerline sampling
88
  shifted_centerline = centerline.copy()
89
 
90
- arc_lengths = arc_length(centerline)
91
 
92
  pts = vtk.vtkPoints()
93
  polys = vtk.vtkCellArray()
94
  rings = []
95
 
96
- A = start_amplitude_pp / 2.0
97
  n_sections = 180
98
  n_theta = 64
99
 
100
  for i in range(n_sections):
101
- distance_base = start_position + length * i / (n_sections - 1)
102
- point_base, (tangent, normal, binormal) = sample_centerline_by_distance(centerline, arc_lengths, frames, distance_base)
103
 
104
  ring = []
105
 
@@ -107,14 +110,14 @@ def create_component_fabric(centerline, frames, start_position, length, diameter
107
  theta = 2 * np.pi * j / n_theta
108
  axial_offset = 0.0
109
 
110
- if i == 0 and start_amplitude_pp > 0:
111
  axial_offset = A * np.sin(waves * theta) - A
112
 
113
- point = point_base + axial_offset * tangent
114
  r = diameter / 2.0
115
- position = point + r * (np.cos(theta) * normal + np.sin(theta) * binormal)
116
 
117
- ring.append(pts.InsertNextPoint(position))
118
 
119
  rings.append(ring)
120
 
@@ -135,13 +138,14 @@ def create_component_fabric(centerline, frames, start_position, length, diameter
135
 
136
  # Struts
137
 
138
- def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_diam_mm, length, main_fabric, peak_to_peak_amplitude=15.0,
139
- peak_spacing=7.0, component_type="proximal", wire_radius=0.35, waves=8, samples=240):
 
140
 
141
- arc_lengths = arc_length(centerline)
142
  append = vtk.vtkAppendPolyData()
143
 
144
- # build fabric normals & locator once
145
  normal_gen = vtk.vtkPolyDataNormals()
146
  normal_gen.SetInputData(main_fabric)
147
  normal_gen.ComputePointNormalsOn()
@@ -150,35 +154,38 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
150
  normal_gen.Update()
151
  fabric_normals = normal_gen.GetOutput().GetPointData().GetNormals()
152
 
153
- point_locator = vtk.vtkPointLocator()
154
- point_locator.SetDataSet(main_fabric)
155
- point_locator.BuildLocator()
 
156
 
157
- A = peak_to_peak_amplitude # peak-peak amplitude = 15
158
  r = main_diam_mm / 2.0
159
  gap = peak_spacing
160
  step = A + gap
161
 
162
  n_crowns = int(np.ceil(length / step))
163
- distance_peaks = [fabric_start_distance + 1.0 + i * step for i in range(n_crowns)]
164
- if ((component_type == "distal" or component_type == "extension") and (len(distance_peaks) > 4)):
165
- distance_peaks = distance_peaks[3:]
166
-
167
- # fication strut
168
- A_extra = peak_to_peak_amplitude / 2.0 # 7.5 mm height
 
 
169
  extra_top = -1e-10 # peak at -7.5
170
 
171
  if component_type == "proximal":
172
- point_0 = centerline[0]
173
- tangent_0, normal_0, binormal_0 = frames[0]
174
- point = point_0 + extra_top * tangent_0 # extrapolate backward
175
- tangent, normal, binormal = tangent_0, normal_0, binormal_0
176
 
177
  elif component_type == "distal":
178
- point, (tangent, normal, binormal) = sample_centerline_by_distance(centerline, arc_lengths, frames, fabric_start_distance + length - extra_top)
179
 
180
  else:
181
- point, (tangent, normal, binormal) = sample_centerline_by_distance(centerline, arc_lengths, frames, extra_top)
182
 
183
  pts = vtk.vtkPoints()
184
  lines = vtk.vtkCellArray()
@@ -189,22 +196,22 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
189
  # keep ONLY negative or positive half of sine
190
  if component_type == "proximal":
191
  axial_offset = A_extra * min(0.0, np.sin(waves * theta))
192
- raw_position = (point
193
- + (r + wire_radius) * (np.cos(theta)*normal + np.sin(theta)*binormal)
194
- + axial_offset * tangent)
195
  elif (component_type == "distal" and length != 0):
196
  axial_offset = A_extra * max(0.0, np.sin(waves * theta))
197
 
198
- raw_position = (point
199
- + (r + wire_radius) * (np.cos(theta)*normal + np.sin(theta)*binormal)
200
- + axial_offset * tangent)
201
  else:
202
  continue
203
 
204
- radial = (np.cos(theta)*normal + np.sin(theta)*binormal)
205
  radial /= np.linalg.norm(radial)
206
 
207
- pos = point + (r + wire_radius) * radial + axial_offset * tangent
208
  pts.InsertNextPoint(pos)
209
 
210
  if i > 0:
@@ -225,17 +232,14 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
225
  tube.Update()
226
 
227
  append.AddInputData(tube.GetOutput())
228
-
229
- # normal struts along the graft body
230
-
231
- cell_locator = vtk.vtkCellLocator()
232
- cell_locator.SetDataSet(main_fabric)
233
- cell_locator.BuildLocator()
234
 
235
- for distance_peak in distance_peaks:
236
- point, (tangent, normal, binormal) = sample_centerline_by_distance(centerline, arc_lengths, frames, distance_peak)
237
 
238
- points = vtk.vtkPoints()
239
  lines = vtk.vtkCellArray()
240
 
241
  for i in range(samples + 1):
@@ -243,19 +247,19 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
243
 
244
  axial_offset = A * (1 + np.sin(waves * theta)) / 2.0
245
 
246
- raw_position = (point
247
- + (r + wire_radius) * (np.cos(theta)*normal + np.sin(theta)*binormal)
248
- + axial_offset * tangent)
249
 
250
- surface_point = project_point_to_surface(raw_position, cell_locator)
251
 
252
- pid = point_locator.FindClosestPoint(surface_point)
253
- normal = np.array(fabric_normals.GetTuple(pid))
254
- normal /= np.linalg.norm(normal)
255
 
256
- position = surface_point + wire_radius * normal
257
 
258
- points.InsertNextPoint(position)
259
 
260
  if i > 0:
261
  l = vtk.vtkLine()
@@ -264,7 +268,7 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
264
  lines.InsertNextCell(l)
265
 
266
  poly = vtk.vtkPolyData()
267
- poly.SetPoints(points)
268
  poly.SetLines(lines)
269
 
270
  tube = vtk.vtkTubeFilter()
@@ -279,9 +283,9 @@ def create_proximal_bare_stent(centerline, frames, fabric_start_distance, main_d
279
  append.Update()
280
  return append.GetOutput()
281
 
282
- def create_component_stents(centerline, frames, fabric_start_distance, length, diameter, fabric, peak_to_peak=15.0, peak_spacing=7.0, component_type="proximal"):
283
 
284
- stents = create_proximal_bare_stent(centerline, frames, fabric_start_distance, diameter, length, fabric, peak_to_peak, peak_spacing, component_type)
285
 
286
  return stents
287
 
@@ -299,7 +303,7 @@ def merge_components(proximal, extension, distal):
299
 
300
  return clean
301
 
302
- def create_endograft(centerline, diameter, proximal_length, extension_length, distal_length, proximal_gap, extension_gap, distal_gap):
303
  frames = compute_parallel_frames(centerline)
304
  peak_to_peak = 15.0
305
 
@@ -307,11 +311,11 @@ def create_endograft(centerline, diameter, proximal_length, extension_length, di
307
  # PROXIMAL COMPONENT
308
  # -------------------------
309
 
310
- proximal_start = 0.0
311
 
312
- proximal_fabric = create_component_fabric(centerline, frames, proximal_start, proximal_length, diameter, start_amplitude_pp=2.0)
313
 
314
- proximal_stents = create_component_stents(centerline, frames, proximal_start, proximal_length, diameter, proximal_fabric, peak_spacing=proximal_gap, component_type="proximal")
315
 
316
 
317
  # -------------------------
@@ -322,8 +326,8 @@ def create_endograft(centerline, diameter, proximal_length, extension_length, di
322
  else:
323
  prox_extension_overlap = 2*peak_to_peak + extension_gap
324
 
325
- extension_start = proximal_length - prox_extension_overlap
326
- extension_fabric = create_component_fabric(centerline, frames, extension_start, extension_length, diameter, start_amplitude_pp=0.0)
327
 
328
  extension_stents = create_component_stents(centerline, frames, extension_start, extension_length, diameter, extension_fabric, peak_spacing=extension_gap, component_type="extension")
329
 
@@ -331,14 +335,14 @@ def create_endograft(centerline, diameter, proximal_length, extension_length, di
331
  # DISTAL COMPONENT
332
  # -------------------------
333
  distal_overlap = 3*peak_to_peak + 2*distal_gap
334
- distal_start = proximal_length + extension_length - prox_extension_overlap - distal_overlap
335
- distal_fabric = create_component_fabric(centerline, frames, distal_start, distal_length, diameter, start_amplitude_pp=0.0)
336
  distal_stents = create_component_stents(centerline, frames, distal_start, distal_length, diameter, distal_fabric, peak_spacing=distal_gap, component_type="distal")
337
  # -------------------------
338
  # MERGE COMPONENTS
339
  # -------------------------
340
- fabric_part = merge_components(proximal_fabric, extension_fabric, distal_fabric)
341
- stent_part = merge_components(proximal_stents, extension_stents, distal_stents)
342
 
343
  endograft = vtk.vtkAppendPolyData()
344
 
 
2
  import numpy as np
3
  import tempfile
4
 
5
+ def arc_length(cl):
6
+ s = np.zeros(len(cl))
7
+ for i in range(1, len(cl)):
8
+ s[i] = s[i-1] + np.linalg.norm(cl[i] - cl[i-1])
9
+ return s
10
 
11
  def compute_parallel_frames(centerline):
12
  frames = []
13
 
14
+ t0 = centerline[1] - centerline[0]
15
+ t0 /= np.linalg.norm(t0)
16
 
17
+ ref = np.array([0, 0, 1])
18
+ if abs(np.dot(t0, ref)) > 0.9:
19
+ ref = np.array([1, 0, 0])
20
 
21
+ n0 = np.cross(t0, ref)
22
+ n0 /= np.linalg.norm(n0)
23
+ b0 = np.cross(t0, n0)
24
 
25
+ frames.append((t0, n0, b0))
26
 
27
+ for i in range(1, len(centerline)):
28
+ ti = centerline[i] - centerline[i-1]
29
+ ti /= np.linalg.norm(ti)
30
 
31
+ t_prev, n_prev, b_prev = frames[-1]
32
+ v = np.cross(t_prev, ti)
33
 
34
+ if np.linalg.norm(v) < 1e-6:
35
+ frames.append((ti, n_prev, b_prev))
36
  continue
37
 
38
+ v /= np.linalg.norm(v)
39
+ angle = np.arccos(np.clip(np.dot(t_prev, ti), -1, 1))
40
 
41
+ def rot(vec):
42
+ return (vec * np.cos(angle) + np.cross(v, vec) * np.sin(angle) + v * np.dot(v, vec) * (1 - np.cos(angle)))
43
 
44
+ frames.append((ti, rot(n_prev), rot(b_prev)))
45
 
46
  return frames
47
 
48
+ def project_point_to_surface(p, surface_poly):
49
+ locator = vtk.vtkCellLocator()
50
+ locator.SetDataSet(surface_poly)
51
+ locator.BuildLocator()
52
+
53
  closest = [0.0, 0.0, 0.0]
54
  cellId = vtk.mutable(0)
55
  subId = vtk.mutable(0)
56
  dist2 = vtk.mutable(0.0)
57
 
58
+ locator.FindClosestPoint(p, closest, cellId, subId, dist2)
59
  return np.array(closest)
60
 
61
+ def sample_centerline_by_s(centerline, s_cl, frames, s):
62
+ idx = np.searchsorted(s_cl, s)
63
 
 
64
  if idx <= 0:
65
  return centerline[0], frames[0]
66
  if idx >= len(centerline):
67
  return centerline[-1], frames[-1]
68
 
69
+ s0, s1 = s_cl[idx-1], s_cl[idx]
70
+ P0, P1 = centerline[idx-1], centerline[idx]
71
+ t = (s - s0) / (s1 - s0 + 1e-12)
72
 
73
+ P = (1 - t) * P0 + t * P1
74
 
75
+ t0, N0, B0 = frames[idx-1]
76
+ t1, N1, B1 = frames[idx]
77
 
78
+ t_vec = (1 - t) * t0 + t * t1
79
+ N_vec = (1 - t) * N0 + t * N1
80
+ B_vec = (1 - t) * B0 + t * B1
81
 
82
+ t_vec /= np.linalg.norm(t_vec)
83
+ N_vec /= np.linalg.norm(N_vec)
84
+ B_vec /= np.linalg.norm(B_vec)
85
 
86
+ return P, (t_vec, N_vec, B_vec)
87
 
88
+ # Fabric
89
+ def create_component_fabric(centerline, frames, start_s, length, diameter, start_amp_pp=2.0, waves=8):
90
  # shift centerline sampling
91
  shifted_centerline = centerline.copy()
92
 
93
+ s_cl = arc_length(centerline)
94
 
95
  pts = vtk.vtkPoints()
96
  polys = vtk.vtkCellArray()
97
  rings = []
98
 
99
+ A = start_amp_pp / 2.0
100
  n_sections = 180
101
  n_theta = 64
102
 
103
  for i in range(n_sections):
104
+ s_base = start_s + length * i / (n_sections - 1)
105
+ P_base, (t, N, B) = sample_centerline_by_s(centerline, s_cl, frames, s_base)
106
 
107
  ring = []
108
 
 
110
  theta = 2 * np.pi * j / n_theta
111
  axial_offset = 0.0
112
 
113
+ if i == 0 and start_amp_pp > 0:
114
  axial_offset = A * np.sin(waves * theta) - A
115
 
116
+ P = P_base + axial_offset * t
117
  r = diameter / 2.0
118
+ pos = P + r * (np.cos(theta) * N + np.sin(theta) * B)
119
 
120
+ ring.append(pts.InsertNextPoint(pos))
121
 
122
  rings.append(ring)
123
 
 
138
 
139
  # Struts
140
 
141
+ def create_proximal_bare_stent(centerline, frames, fabric_start_s, main_diam_mm, length, main_fabric, peak_to_peak=15.0,
142
+ peak_spacing=7.0, component_type="proximal", wire_radius=0.35, waves=8, samples=240
143
+ ):
144
 
145
+ s_cl = arc_length(centerline)
146
  append = vtk.vtkAppendPolyData()
147
 
148
+ # --- build fabric normals & locator ONCE ---
149
  normal_gen = vtk.vtkPolyDataNormals()
150
  normal_gen.SetInputData(main_fabric)
151
  normal_gen.ComputePointNormalsOn()
 
154
  normal_gen.Update()
155
  fabric_normals = normal_gen.GetOutput().GetPointData().GetNormals()
156
 
157
+ locator = vtk.vtkPointLocator()
158
+ locator.SetDataSet(main_fabric)
159
+ locator.BuildLocator()
160
+ # -----------------------------------------
161
 
162
+ A = peak_to_peak # peak-peak amplitude = 15
163
  r = main_diam_mm / 2.0
164
  gap = peak_spacing
165
  step = A + gap
166
 
167
  n_crowns = int(np.ceil(length / step))
168
+ s_peaks = [fabric_start_s + 1.0 + i * step for i in range(n_crowns)]
169
+ if ((component_type == "distal" or component_type == "extension") and (len(s_peaks) > 4)):
170
+ s_peaks = s_peaks[3:]
171
+
172
+ # =========================================================
173
+ # ===== EXTRA CLIPPED HALF sin =================
174
+ # =========================================================
175
+ A_extra = peak_to_peak / 2.0 # 7.5 mm height
176
  extra_top = -1e-10 # peak at -7.5
177
 
178
  if component_type == "proximal":
179
+ P0 = centerline[0]
180
+ t0, N0, B0 = frames[0]
181
+ P = P0 + extra_top * t0 # extrapolate backward
182
+ t, N, B = t0, N0, B0
183
 
184
  elif component_type == "distal":
185
+ P, (t, N, B) = sample_centerline_by_s(centerline, s_cl, frames, fabric_start_s + length - extra_top)
186
 
187
  else:
188
+ P, (t, N, B) = sample_centerline_by_s(centerline, s_cl, frames, extra_top)
189
 
190
  pts = vtk.vtkPoints()
191
  lines = vtk.vtkCellArray()
 
196
  # keep ONLY negative or positive half of sine
197
  if component_type == "proximal":
198
  axial_offset = A_extra * min(0.0, np.sin(waves * theta))
199
+ raw_pos = (P
200
+ + (r + wire_radius) * (np.cos(theta)*N + np.sin(theta)*B)
201
+ + axial_offset * t)
202
  elif (component_type == "distal" and length != 0):
203
  axial_offset = A_extra * max(0.0, np.sin(waves * theta))
204
 
205
+ raw_pos = (P
206
+ + (r + wire_radius) * (np.cos(theta)*N + np.sin(theta)*B)
207
+ + axial_offset * t)
208
  else:
209
  continue
210
 
211
+ radial = (np.cos(theta)*N + np.sin(theta)*B)
212
  radial /= np.linalg.norm(radial)
213
 
214
+ pos = P + (r + wire_radius) * radial + axial_offset * t
215
  pts.InsertNextPoint(pos)
216
 
217
  if i > 0:
 
232
  tube.Update()
233
 
234
  append.AddInputData(tube.GetOutput())
235
+ # =========================================================
236
+ # ================= NORMAL FULL struts ====================
237
+ # =========================================================
 
 
 
238
 
239
+ for s0 in s_peaks:
240
+ P, (t, N, B) = sample_centerline_by_s(centerline, s_cl, frames, s0)
241
 
242
+ pts = vtk.vtkPoints()
243
  lines = vtk.vtkCellArray()
244
 
245
  for i in range(samples + 1):
 
247
 
248
  axial_offset = A * (1 + np.sin(waves * theta)) / 2.0
249
 
250
+ raw_pos = (P
251
+ + (r + wire_radius) * (np.cos(theta)*N + np.sin(theta)*B)
252
+ + axial_offset * t)
253
 
254
+ surf_p = project_point_to_surface(raw_pos, main_fabric)
255
 
256
+ pid = locator.FindClosestPoint(surf_p)
257
+ n = np.array(fabric_normals.GetTuple(pid))
258
+ n /= np.linalg.norm(n)
259
 
260
+ pos = surf_p + wire_radius * n
261
 
262
+ pts.InsertNextPoint(pos)
263
 
264
  if i > 0:
265
  l = vtk.vtkLine()
 
268
  lines.InsertNextCell(l)
269
 
270
  poly = vtk.vtkPolyData()
271
+ poly.SetPoints(pts)
272
  poly.SetLines(lines)
273
 
274
  tube = vtk.vtkTubeFilter()
 
283
  append.Update()
284
  return append.GetOutput()
285
 
286
+ def create_component_stents(centerline, frames, fabric_start_s, length, diameter, fabric, peak_to_peak=15.0, peak_spacing=7.0, component_type="proximal"):
287
 
288
+ stents = create_proximal_bare_stent(centerline, frames, fabric_start_s, diameter, length, fabric, peak_to_peak, peak_spacing, component_type)
289
 
290
  return stents
291
 
 
303
 
304
  return clean
305
 
306
+ def create_endograft(centerline, diameter, prox_length,extension_length, distal_length, prox_gap, extension_gap, distal_gap):
307
  frames = compute_parallel_frames(centerline)
308
  peak_to_peak = 15.0
309
 
 
311
  # PROXIMAL COMPONENT
312
  # -------------------------
313
 
314
+ prox_start = 0.0
315
 
316
+ prox_fabric = create_component_fabric(centerline, frames, prox_start, prox_length, diameter, start_amp_pp=2.0)
317
 
318
+ prox_stents = create_component_stents(centerline, frames, prox_start, prox_length, diameter, prox_fabric, peak_spacing=prox_gap, component_type="proximal")
319
 
320
 
321
  # -------------------------
 
326
  else:
327
  prox_extension_overlap = 2*peak_to_peak + extension_gap
328
 
329
+ extension_start = prox_length - prox_extension_overlap
330
+ extension_fabric = create_component_fabric(centerline, frames, extension_start, extension_length, diameter, start_amp_pp=0.0)
331
 
332
  extension_stents = create_component_stents(centerline, frames, extension_start, extension_length, diameter, extension_fabric, peak_spacing=extension_gap, component_type="extension")
333
 
 
335
  # DISTAL COMPONENT
336
  # -------------------------
337
  distal_overlap = 3*peak_to_peak + 2*distal_gap
338
+ distal_start = prox_length + extension_length - prox_extension_overlap - distal_overlap
339
+ distal_fabric = create_component_fabric(centerline, frames, distal_start, distal_length, diameter, start_amp_pp=0.0)
340
  distal_stents = create_component_stents(centerline, frames, distal_start, distal_length, diameter, distal_fabric, peak_spacing=distal_gap, component_type="distal")
341
  # -------------------------
342
  # MERGE COMPONENTS
343
  # -------------------------
344
+ fabric_part = merge_components(prox_fabric, extension_fabric, distal_fabric)
345
+ stent_part = merge_components(prox_stents, extension_stents, distal_stents)
346
 
347
  endograft = vtk.vtkAppendPolyData()
348