<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 GetSurfaceDataLayout()
Returns the layout of the surface, that is the 
Step1:  GetSurfaceData()
Returns a dataset of type UInt16 containing signed int16 values. Values below zero are outside the surface, above zero is inside. A sub-voxel precise surface can be reconstructed by linearly interpolating the values around zero.
!! data values are placed on the border as well, voxel size is (mExtendMax - mExtendMin) / (mSize - 1) !!
Step2:  GetSurfaceNormals()
3 channels image of type uint8 treated as signed in the range [-127, 127] for symmetry.
!! data values are placed on the border as well, voxel size is (mExtendMax - mExtendMin) / (mSize - 1) !!
<ASSISTANT_TASK:>
Python Code:
sl = s.GetSurfaceDataLayout(0)
print(sl)
Explanation: GetSurfaceDataLayout()
Returns the layout of the surface, that is the : public and the size of the return value of GetData().
!! Due to the sub-pixel resolution of the surfaces, the actual minimum and maximum coordinates of the vertices of the triangulated representation of the surface are typically included and not equal to the : public of the layout !!
End of explanation
arr = np.swapaxes(np.array(s.GetSurfaceData(0).GetDataShorts())[0,0,...],0,2)
print(arr.shape)
vx = (sl.mExtendMaxX-sl.mExtendMinX)/(sl.mSizeX-1)
vy = (sl.mExtendMaxY-sl.mExtendMinY)/(sl.mSizeY-1)
vz = (sl.mExtendMaxZ-sl.mExtendMinZ)/(sl.mSizeZ-1)
print(vx,vy,vz)
Explanation: GetSurfaceData()
Returns a dataset of type UInt16 containing signed int16 values. Values below zero are outside the surface, above zero is inside. A sub-voxel precise surface can be reconstructed by linearly interpolating the values around zero.
!! data values are placed on the border as well, voxel size is (mExtendMax - mExtendMin) / (mSize - 1) !!
End of explanation
normals = np.swapaxes(np.array(s.GetSurfaceNormals(0).GetDataShorts())[0,0,...],0,2)
print(normals.shape)
verts, faces, normals, values = measure.marching_cubes_lewiner(arr, 0, spacing=(vz, vy, vx))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 2]+sl.mExtendMinX, verts[:,1]+sl.mExtendMinY, faces, verts[:, 0]+sl.mExtendMinZ,
                lw=1, 
                antialiased=True)
plt.show()
Explanation: GetSurfaceNormals()
3 channels image of type uint8 treated as signed in the range [-127, 127] for symmetry.
!! data values are placed on the border as well, voxel size is (mExtendMax - mExtendMin) / (mSize - 1) !!
End of explanation
<END_TASK>