# Export heart motion to CFD/FSI

**URL:** <https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913>\
**Category:** Support\
**Tags:** registration, fem\
**Created:** [April 11, 2022, 6:54pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913 "2022-04-11T18:54:07Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 11, 2022, 6:54pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/1 "2022-04-11T18:54:07Z")

</div>

Hello, I have a really similar question to this. I want to get the coordinates of the segmented heart’s surface.  
I used the Sequence Registration and the module Transform to transform a model generated by the module Segmentation. I want to export the time-varying coordinates information of meshing points (vertices) on that 3D model surface, so that I can use the motion of boundary to run CFD/FSI.  
I tried to add the meshing points as nodes in the module Markups. But there are more than 20,000 points so that seems impossible to add them all as markups.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 11, 2022, 7:03pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/2 "2022-04-11T19:03:58Z")

</div>



---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 11, 2022, 7:08pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/3 "2022-04-11T19:08:48Z")

</div>

You can get mesh point positions as a numpy array using [`slicer.util.arrayFromModelPoints`](https://slicer.readthedocs.io/en/latest/developer_guide/slicer.html#slicer.util.arrayFromModelPoints). Note that you need to harden the transform on the model node to get the transformed coordinates in the array.

Once you have the mesh point positions in a numpy array, you can then write the values into any format that your CFD/FSI engine can digest.

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 11, 2022, 7:50pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/4 "2022-04-11T19:50:43Z")

</div>

Thanks for your reply!  
I’m quite a newie to Slicer and Python. Do I need to run the complete code in Python in order to get the array or I can just run slicer.util.arrayFromModelPoints( _modelNode_ ) using the Python Interactor in the 3D Slicer?  
Btw, does the modelNode mean the MRML ID shown in Data?

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 11, 2022, 7:51pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/5 "2022-04-11T19:51:06Z")

</div>

Thanks for your reply!  
I’m quite a newie to Slicer and Python. Do I need to run the complete code in Python in order to get the array or I can just run slicer.util.arrayFromModelPoints( _modelNode_ ) using the Python Interactor in the 3D Slicer?  
Btw, does the modelNode mean the MRML ID shown in Data?

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 11, 2022, 8:04pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/6 "2022-04-11T20:04:03Z")

</div>

You open the Python console in Slicer (or use Jupyter notebook interface via [SlicerJupyter](https://github.com/Slicer/SlicerJupyter#slicerjupyter)) and run `slicer.util.arrayFromModelPoints` there. You can get `modelNode` using `slicer.util.getNode()` function. You can find many useful code snippets in the [script repository](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html).

To get started with Python programming in Slicer, you can check out the [PerkLab Slicer programming tutorial](https://github.com/PerkLab/PerkLabBootcamp/blob/master/Doc/day3_2_SlicerProgramming.pptx?raw=true).

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 14, 2022, 8:51pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/7 "2022-04-14T20:51:34Z")

</div>

Hi Lasso,

Sorry to bother you again, but I’m really a newie to Python and I still got some confusions regarding the mesh point positions.

I got this numpy array using the method you suggested, however, I don’t think I understand what does this array actually mean. I think the three numbers in each line mean the position of one mesh point, but I just don’t know what is the corresponding time point of these coordinates. In addition, are these RAS coordinates or LAS coordinates?

I’d like to write these values into a table-like format. For example, t=0s: coordinates of each mesh point are [x1,y1,z1] [x2,y2,z2] …; t=1s: coordinates of each mesh point are [x1’,y1’,z1’] [x2’,y2’,z2’] …

Do you know what should I do? Thanks a lot!

 ![Screenshot 2022-04-14 163619](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/8/d/8dacb43e801233a8bf6d4d8f26156816464e002a.jpeg)

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 14, 2022, 9:25pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/8 "2022-04-14T21:25:20Z")

</div>

A quick update. I saved the numpy array as a csv file and found that there are 91933 coordinates, which is exactly the number of mesh points. So I think this is only the coordinates at time=0s? How can I get the coordinates in different time points?

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 14, 2022, 11:13pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/9 "2022-04-14T23:13:28Z")

</div>

You can step through the time sequence and export coordinates at each timepoint. You can find an example of how to step through all timepoints [here](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#browse-a-sequence-and-access-currently-displayed-nodes).

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 5:30pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/10 "2022-04-15T17:30:41Z")

</div>

I read through that sample and realized that in order to step through all timepoints, it needs to browse a sequence. I copied a part of the sample code below, does it mean that I can only get the coordinates of the volume at different time points? But instead I’d like to get the coordinates of a model, not the volume.  
Thanks!

**# Get currently displayed volume node voxels as numpy array**  
volumeNode = browserNode.GetProxyNode(sequenceNode)  
voxelArray = slicer.util.arrayFromVolume(volumeNode)

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 5:30pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/11 "2022-04-15T17:30:50Z")

</div>

I read through that sample and realized that in order to step through all timepoints, it needs to browse a sequence. I copied a part of the sample code below, does it mean that I can only get the coordinates of the volume at different time points? But instead I’d like to get the coordinates of a model, not the volume.  
Thanks!

**# Get currently displayed volume node voxels as numpy array**  
volumeNode = browserNode.GetProxyNode(sequenceNode)  
voxelArray = slicer.util.arrayFromVolume(volumeNode)

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 15, 2022, 6:07pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/12 "2022-04-15T18:07:07Z")

</div>

The browser node iterates through all the associated sequences - volumes, transforms, models, etc.

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 7:46pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/13 "2022-04-15T19:46:57Z")

</div>

Sorry but I can’t really get it. How can I connect my `modelNode` to the `sequenceNode` or `browserNode`?  
When I jumped to a selected sequence item using `browserNode.SetSelectedItemNumber()`, and tried to get currently displayed model node using `slicer.util.getNode()` and `slicer.util.arrayFromModelPoints()`, it still output the coordinates at the initial time point.

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 7:47pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/14 "2022-04-15T19:47:11Z")

</div>

Sorry but I can’t really get it. How can I connect my `modelNode` to the `sequenceNode` or `browserNode` ?  
When I jumped to a selected sequence item using `browserNode.SetSelectedItemNumber()` , and tried to get currently displayed model node using `slicer.util.getNode()` and `slicer.util.arrayFromModelPoints()` , it still output the coordinates at the initial time point.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 15, 2022, 8:01pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/15 "2022-04-15T20:01:15Z")

</div>

I don’t think you have a model sequence. I guess you have a transform sequence, so you would iterate through that. At each timepoint you clone your model node (to keep the original non-transformed point coordinates), apply the current transform to the model, then save the transformed model.

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 8:29pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/16 "2022-04-15T20:29:08Z")

</div>

@lassoan  
I found an example [here](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#export-nodes-warped-by-transform-sequence), so I need to jump to each selected sequence item using `browserNode.SetSelectedItemNumber()` and apply the transform? Do I need to firstly convert the model into segmentation in order to apply the transform? Thanks a lot.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 15, 2022, 9:50pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/17 "2022-04-15T21:50:23Z")

</div>

That example is perfect. It does not clone the model node but resets the model node content from the segmentation node at each timepoint.

You don’t have to use the browser node, you can just get the transform node from the sequence as it is shown in the example.

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 15, 2022, 11:12pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/18 "2022-04-15T23:12:38Z")

</div>

@lassoan

When I try to run the `for` loop in that example, I met some Attribute Errors as shown below. I can’t really get it, what do these errors indicate? I used exactly the same code as that [example](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#export-nodes-warped-by-transform-sequence).

`AttributeError: 'MRMLCorePython.vtkMRMLTransformNode' object has no attribute 'GetNumberOfDataNodes'`

`AttributeError: 'MRMLCorePython.vtkMRMLTransformNode' object has no attribute 'GetNthDataNode'`

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [April 16, 2022, 1:19am UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/19 "2022-04-16T01:19:46Z")

</div>

The code is correct. You got the error because as `transformSequenceNode` you provided a simple transform node.

This transform node that you got from the scene is most likely a “proxy node” for the transform sequence, i.e., a node that exposes the transform at the selected timepoint in the scene. You can get the sequence node from a proxy node like this:

```python
proxyNode = getNode(...)
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForProxyNode(proxyNode)
sequenceNode = browserNode.GetSequenceNode(proxyNode)

```

---

<div class="post-metadata">

**Author:** ![Gening\_Dong](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/gening_dong/32/14706_2.png) [@Gening\_Dong](https://discourse.slicer.org/u/Gening_Dong)\
**Post date:** [April 21, 2022, 2:34pm UTC](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913/20 "2022-04-21T14:34:02Z")

</div>

Hi @lassoan , thanks for your help with the position extracting. However I met another problem right now: I want to calculate strain tensor of the boundary. I read your suggestion [here](https://discourse.slicer.org/t/4d-cardiac-ct-strain-analysis/22789/3) so I’m trying to export the displacement field.

I found an example for extracting displacement field [here](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html#export-the-displacement-magnitude-of-the-transform-as-a-volume). However, I only want the displacement field in the segmentation/model, but not the entire volume. Can I transfer a segmentation into a new volume so that I can export the displacement magnitude of the transform as a volume and visualize it? Or do you have any other ideas to get the displacement field of a model?

Thanks a lot!

[Next page](https://discourse.slicer.org/t/export-heart-motion-to-cfd-fsi/22913.md?page=2)
