Switch to side-by-side view

--- a
+++ b/CLI/MusculoskeletalAnalysisCLITools/thickness.py
@@ -0,0 +1,41 @@
+def findSpheres(mask):
+    """Calculates thickness by finding the largest sphere containing each point."""
+    import numpy as np
+    from math import floor
+    from scipy.ndimage import distance_transform_edt
+
+    dist = distance_transform_edt(mask)
+    rads = dist.copy()
+
+    a,b,c=np.nonzero(mask)
+    order = np.argsort(dist[a,b,c])
+    for n in order:
+        # For each point, find the thickness radius at that point from the distance map
+        x=a[n]
+        y=b[n]
+        z=c[n]
+
+        r=dist[x,y,z]
+        rf = floor(r)
+        # Check that ranges are inside boundaries
+        xr0=min(rf,x)
+        xr1=min(rf, dist.shape[0]-x-1)
+        yr0=min(rf,y)
+        yr1=min(rf, dist.shape[1]-y-1)
+        zr0=min(rf,z)
+        zr1=min(rf, dist.shape[2]-z-1)
+        # Creates a cubic view of the region of interest
+        roi=rads[x-xr0:x+xr1+1, y-yr0:y+yr1+1, z-zr0:z+zr1+1]
+        # Creates mask of sphere within radius
+        i,j,k=np.mgrid[-xr0:xr1+1,-yr0:yr1+1,-zr0:zr1+1]
+        mask = approxLTE(i**2 + j**2 + k**2, np.full_like(roi, r**2)) 
+        mask = np.bitwise_and(mask, roi>0)
+        # Sets all values inside region of interest and sphere mask to the radius if it is higher than their current value
+        mask = mask * r
+        roi[:,:,:] = np.maximum(roi, mask)
+    return rads[np.nonzero(rads)]
+
+def approxLTE(a, b):
+    # Peforms array elementwise less than or equal comparisons with some tolerance for floating point values
+    import numpy as np
+    return np.bitwise_or(a <= b, np.isclose(a,b))