%load_ext autoreload
%autoreload 2

%reload_ext XTIPython

vImaris.GetVersion()

%matplotlib inline

import matplotlib
import matplotlib.pyplot as plt

import numpy as np

"""
Explanation: Testing memory transfer between Imaris and Python
This notebook highlights the difference between transfering 8 bit and 16 bit datasets, from Imaris to Python and vice versa.
Edit: As of Imaris 9.2.0, here's the score on my test dataset (2688x2200x131 stack, Windows 8.1 64 bit, E5-2650 v4, 32GB RAM). This includes added array conversion when sending volume data from Python to Imaris.
|          |Imaris → Python|Python → Imaris|
|----------|---------------|---------------|
| 8 bit|5s             |9s             |
|16 bit|115s           |15s            |
End of explanation
"""


%imaris_screenshot

"""
Explanation: For info, this is what the dataset looks like (fly embryo).
Original dataset is 16 bit, reduced to 8 bit using FIJI
End of explanation
"""


nx = vDataSet.GetSizeX()
ny = vDataSet.GetSizeY()
nz = vDataSet.GetSizeZ()
dtype = BridgeLib.GetType(vDataSet)

print nz,ny,nx,dtype

"""
Explanation: 8 bit transfer
End of explanation
"""


import time
t = time.time()
arr = BridgeLib.GetDataVolume(vDataSet,0,0)
print "Operation took %.1fs"%(time.time()-t),arr.shape,arr.dtype

vmin,vmax = vDataSet.GetChannelRangeMin(0),vDataSet.GetChannelRangeMax(0)
p = plt.imshow(np.max(arr,axis=0),origin='lower',vmin=vmin,vmax=vmax)

"""
Explanation: Let's fetch the data volume and check how long it takes
End of explanation
"""


arr = arr.astype(np.float32)

vDataSet.SetSizeC(2)
t = time.time()
BridgeLib.SetDataVolume(vDataSet,arr,1,0)
print "Operation took %.1fs"%(time.time()-t)

"""
Explanation: This next step tests type conversion in BridgeLib.SetDataVolume()
BridgeLib.SetDataVolume() automatically handles type conversion, so here we're converting the dataset array to float32 first, then sending it back to Imaris.
End of explanation
"""


%imaris_sync

nx = vDataSet.GetSizeX()
ny = vDataSet.GetSizeY()
nz = vDataSet.GetSizeZ()
dtype = BridgeLib.GetType(vDataSet)

print nz,ny,nx,dtype

"""
Explanation: Testing data transfer with a 16 bit dataset
Motivation:
For 8 bit data, we can just grab the volume data into Python using GetDataVolumeAs1DArrayBytes() / numpy.frombuffer() and the operation is quite fast.
For 16 bit datasets however, fetching the volume array in one go doesn't seem to be possible. On three different machines I tested this on, 32GB of RAM wasn't enough and Imaris just hung with all the RAM taken up.
The next best thing when fetching data from Imaris is to reconstruct the 3-D array slice by slice (in the Z direction) using vDataSet.GetDataSubVolumeAs1DArrayShorts (or vDataSet.GetDataSubVolumeAs1DArrayFloats for 32 bit data).
At this point, the 16 bit dataset was loaded in Imaris.
End of explanation
"""


import time
t = time.time()
arr = BridgeLib.GetDataVolume(vDataSet,0,0)
print "Operation took %.1fs"%(time.time()-t),arr.shape,arr.dtype

vmin,vmax = vDataSet.GetChannelRangeMin(0),vDataSet.GetChannelRangeMax(0)
p = plt.imshow(np.max(arr,axis=0),origin='lower',vmin=vmin,vmax=vmax)

"""
Explanation: Let's fetch the data volume and check how long it takes
End of explanation
"""


arr = arr.astype(np.float32)

vDataSet.SetSizeC(2)
t = time.time()
BridgeLib.SetDataVolume(vDataSet,arr,1,0)
print "Operation took %.1fs"%(time.time()-t)

"""
Explanation: This next step tests type conversion in BridgeLib.SetDataVolume()
BridgeLib.SetDataVolume() automatically handles type conversion, so here we're converting the dataset array to float32 first, then sending it back to Imaris.
End of explanation
"""


