# Add storageNode to volumeNode created from a numpy array

**URL:** <https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374>\
**Category:** Support\
**Created:** [May 11, 2022, 3:59pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374 "2022-05-11T15:59:14Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marc-3d](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/marc-3d/32/14931_2.png) [@Marc-3d](https://discourse.slicer.org/u/Marc-3d)\
**Post date:** [May 11, 2022, 3:59pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374/1 "2022-05-11T15:59:14Z")

</div>

Hello,

I am creating a volumeNode and populating it with data from a 3D numpy array.

```auto
 volumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')
 slicer.util.updateVolumeFromArray(volumeNode, data)

```

Later in my code, I expect all volumes to have a storageNode() and a fileName.

I tried both:

```auto
   storageNode = volumeNode.createDefaultStorageNode();
   storageNode.setFileName('path/to/the/file/that/contains/the/data')

```

and

```auto
    storageNode = slicer.vtkMRMLVolumeArchetypeStorageNode()
    storageNode.SetFileName( 'path/to/the/file/that/contains/the/data' )   
    volumeNode.AddAndObserveStorageNodeID( storageNode.GetID() )

```

but in both cases when I try to get the storage node from the volumes I get nothing.

```auto
    volumeNode.getStorageNode() #returns a NoneType

```

Any idea on how to add a storageNode successfully?

Thank you in advance 🙂  
Marc

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 11, 2022, 4:49pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374/2 "2022-05-11T16:49:01Z")

</div>

Hi -

Looks like you are close. My suggestion is to make reproducible snippets that anyone can paste into a freshly started Slicer instance and reproduce your question. Disconnected lines of code are really impossible to debug, but I can tell they aren’t part of a real program because of syntax errors like `setFileName` instead of `SetFileName`. Formulating such concise and reproducible examples can often help you find the issues yourself. We often point to this page for guidance: [http://sscce.org/](http://sscce.org/)

---

<div class="post-metadata">

**Author:** ![Marc-3d](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/marc-3d/32/14931_2.png) [@Marc-3d](https://discourse.slicer.org/u/Marc-3d)\
**Post date:** [May 11, 2022, 6:07pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374/3 "2022-05-11T18:07:38Z")

</div>

Hi, my bad. Here is reproducible code that you should be able to copy into Slicer’s Python Interactor.

```python
# Method 1
import numpy as np
data = np.random.rand( 50, 50, 50 ); # dummy data. In reality I am loading czi files, ex "C:/users/marc/data.czi"
volumeNode1 = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode');
slicer.util.updateVolumeFromArray(volumeNode1, data );
storageNode1 = slicer.vtkMRMLVolumeArchetypeStorageNode() # creating storageNode separeate from volumeNode
storageNode1.SetFileName( "C:/users/marc/data.czi" ) 
volumeNode1.AddAndObserveStorageNodeID( storageNode1.GetID() ) # AddAndObserve to link storageNode to volumeNode
print( "Method 1", volumeNode1.GetStorageNode() )

```

And the other version:

```python
# Method 2
import numpy as np
data = np.random.rand( 50, 50, 50 ); # dummy data. In reality I am loading czi files, ex "C:/users/marc/data.czi"
volumeNode2 = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode');
slicer.util.updateVolumeFromArray(volumeNode2, data );
storageNode2 = volumeNode2.CreateDefaultStorageNode() # Creating storageNode from volumeNode. I don't think AddAndObserve is required.
storageNode2.SetFileName( "C:/users/marc/data.czi" )
print( "Method 2", volumeNode2.GetStorageNode() )

```

---

<div class="post-metadata">

**Author:** ![Marc-3d](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/marc-3d/32/14931_2.png) [@Marc-3d](https://discourse.slicer.org/u/Marc-3d)\
**Post date:** [May 11, 2022, 6:18pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374/4 "2022-05-11T18:18:29Z")

</div>

I found the problem: In method 1, I needed to add the storageNode to the scene… otherwise the storageNode.GetID() is not available to the rest of nodes, and it cannot be “AddedAndObserved”.

This now works:

```python
import numpy as np
data = np.random.rand( 50, 50, 50 ); 
volumeNode1 = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode');
slicer.util.updateVolumeFromArray(volumeNode1, data );
storageNode1 = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLVolumeArchetypeStorageNode') # this creates storageNode and adds it to the scene
storageNode1.SetFileName( "C:/users/marc/data.czi" ) 
volumeNode1.AddAndObserveStorageNodeID( storageNode1.GetID() )
print( "Method 1", volumeNode1.GetStorageNode() )

```

---

<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:** [May 12, 2022, 12:39pm UTC](https://discourse.slicer.org/t/add-storagenode-to-volumenode-created-from-a-numpy-array/23374/5 "2022-05-12T12:39:43Z")

</div>

You can simplify this even further (based on examples in the [script repository](https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html)):

```python
import numpy as np
voxelArray = np.random.rand(50, 50, 50)

volumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')
slicer.util.updateVolumeFromArray(volumeNode, voxelArray)
volumeNode.AddDefaultStorageNode()
volumeNode.GetStorageNode().SetFileName( "C:/users/marc/volume.nrrd" ) 

```

Or, if you want to immediately save to file:

```python
import numpy as np
voxelArray = np.random.rand(50, 50, 50)

volumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')
slicer.util.updateVolumeFromArray(volumeNode, voxelArray)
slicer.util.saveNode(volumeNode, "C:/users/marc/volume.nrrd") 

```
