diff --git a/src/Python/_property.py b/src/Python/_property.py
deleted file mode 100644
index 151ce35bea817b2ccae296b1d7c6a2698b293911..0000000000000000000000000000000000000000
--- a/src/Python/_property.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import requests
-import json
-
-
-"""
-Helper classes for handling leversc settings changes
-"""
-class ChangeWrapper:
-    """
-    A wrapper class for bubbling property change updates to leversc class
-    """
-    def __init__(self, parent, incollection):
-        self._parent = parent
-        self._collection = incollection
-
-    def _property_updated(self, childprop):
-        self._parent._property_updated(self)
-
-    def __getitem__(self, keyidx):
-        elem = self._collection.__getitem__(keyidx)
-        if isinstance(elem, (dict,list)):
-            return __class__(self, elem)
-        else:
-            return elem
-    
-    def __setitem__(self, keyidx, v):
-        self._collection.__setitem__(keyidx,v)
-        self._property_updated(self)
-
-    """
-    Some Quality-of-life improvements for introspecting the wrappers
-    """
-    def __str__(self):
-        return str(self._collection)
-
-    def __repr__(self):
-        return "%s(%s)"%(__class__.__name__, repr(self._collection))
-
-
-class PropWrapper(ChangeWrapper):
-    """
-    Top-level property that runs setProperty (network send) on change updates
-    """
-    def __init__(self, lsc, propname, incollection):
-        self._leversc = lsc
-        self._propname = propname
-        super(__class__,self).__init__(self,incollection)
-
-    def unwrap(self):
-        """
-        Return an unwrapped version of this property (that can be edited without network overhead)
-        """
-        return self._collection
-
-    def _property_updated(self, childprop):
-        self._leversc.setProperty(self._propname, self._collection)
-
-    def __str__(self):
-        return str(self._collection)
-
-    def __repr__(self):
-        return "%s(%s)"%(__class__.__name__, repr(self._collection))
-
-
-# retrieves/sets viewParams, renderParams, uiParams, etc....
-def setProperty(self,propertyName,propertyStruct):
-    if isinstance(propertyStruct,PropWrapper):
-        propertyStruct = propertyStruct.unwrap()
-    URL = self._leversc_url("/"+propertyName)
-    response = requests.post(URL,json=propertyStruct)
-    
-def getProperty(self,propertyName):
-    URL = self._leversc_url("/"+propertyName)
-    response = requests.get(URL)
-    property = response.json()
-    if 'list'==type(property):
-        # view and render params come as 1 element list
-        property = property[0]
-    return PropWrapper(self,propertyName,property)
diff --git a/src/Python/leversc.py b/src/Python/leversc.py
deleted file mode 100644
index b3fbd6959889187b99c8318dd9129b880f4641b6..0000000000000000000000000000000000000000
--- a/src/Python/leversc.py
+++ /dev/null
@@ -1,396 +0,0 @@
-import math
-import json
-import struct
-import requests
-import numpy as np
-import os
-import sys
-import time
-import pkgutil
-import subprocess
-from imageio import imread
-
-class leversc:
-    """
-    A class wrapper to interface with the leversc viewer.
-
-    This class is built to function similarly to matplotlib and Matlab's figure() function,
-    the leversc object represents a single leversc viewer window with associated image metadata (imD)
-    and visualization parameters. Object methods allow changing rendering parameters programatically 
-    and send new images to view (with the same metadata).
-
-    Parameters
-    ----------
-    im : numpy.ndarray, optional
-        5-D image to send to viewer on startup, can also be sent using the show(im) method
-    imD : dict, optional
-        Leverjs image metadata, can be reset using the setImageData(imD) method
-    figNum : int, default=1
-        Figure number of the leversc viewer (default to 1)
-
-    Raises
-    ------
-    TypeError
-        If im is not None and is not of type numpy.ndarray
-
-    See Also
-    --------
-    show: Show 5-D image in the leversc viewer
-    """
-    def __init__(self, im=None, imD=None, figNumber=1,strDB=None):
-        self._host = "http://localhost"
-        self._base_port = 3000
-        self._npack = 4
-
-        self._figNumber = figNumber
-        self.setImageData(imD)
-        if strDB is not None:
-            self.showLEVER(strDB)
-        elif im is not None:
-            self.show(im)
-
-    def setImageData(self, imD=None):
-        """
-        Set the image metadata associated with this viewer window.
-
-        This function will set or reset (in the case of imD=None or no arguments) the leverjs metadata associated with
-        this leversc viewer window.
-
-        Parameters
-        ----------
-        imD : dict, optional
-            Leverjs image metadata
-            Important Keys:
-                "PhysicalPixelSize" - The resolution of each pixel dimension x,y,z (generally in um)
-                "ChannelNames" - The names of each channel in the image
-        """        
-        if imD is None:
-            self._CONSTANTS={}
-            self._imageData = {} 
-        elif 'imageData' in imD.keys():
-            # passed in a CONSTANTS struct - use CONSTANTS.imageData
-            self._CONSTANTS=imD
-            self._imageData = imD['imageData']
-        else:
-            self._CONSTANTS={}
-            self._imageData = imD
-
-
-    def setFigureNumber(self, figNumber):
-        """
-        Set the the figure number (leversc viewer) associated with this object
-
-        Parameters
-        ----------
-        figNumber : int
-            This is the figure number (leversc window) that the object will send images to
-
-        Raises
-        ------
-        ValueError
-            If figNumber is less than 1
-        """
-        if figNumber <= 0:
-            raise ValueError("Figure number must be greater than zero")
-        self._figNumber = figNumber
-
-    def captureImage(self):
-        if ( not self._check_leversc() ):
-            return None
-        # make sure leversc is ready
-        while (not self.drawComplete()):
-            time.sleep(0.1)
-        # do the capture
-        URL = self._leversc_url('screenCap')
-        im=imread(URL)
-        return im
-    
-    def drawComplete(self):
-        URL=self._leversc_url('drawComplete')
-        response=requests.get(URL)
-        bComplete=response.json()
-        return bComplete
-    def showLEVER(self,strDB):
-        """
-        Open a .LEVER file in the leversc viewer
-
-        Parameters
-        ----------
-        strDB : string
-            /path/to/myFile.LEVER
-
-        """
-        if ( not self._check_leversc() ):
-            if ( not self._init_leversc(strDB) ):
-                return
-        
-    def show(self, im):
-        """
-        Show a 5-D image in the leversc viewer
-
-        Sends a 5-D numpy array to the leversc viewer for display. Note: if the imageData has not been set
-        then this method will set default imageData based on the input image.
-
-        Parameters
-        ----------
-        im : numpy.ndarray
-            5-D image to send to viewer
-
-        Raises
-        ------
-        TypeError
-            If im is not of type numpy.ndarray
-        """
-        if type(im) is not np.ndarray:
-            raise TypeError("Image must be a numpy array")
-
-        if len(im.shape) < 3:
-            print("ERROR: 2D Images are not supported!")
-            return
-
-        # Launch leversc viewer if not alread up
-        if ( not self._check_leversc() ):
-            if ( not self._init_leversc() ):
-                return
-
-        # Normalize image access by creating an f_contiguous image view
-        imfctg = leversc._get_fcontig_imview(im)
-        if len(imfctg.shape) == 3:
-            imfctg = np.expand_dims(imfctg, axis=3)
-        # Normalize dimensions (make sure there are at least 4 (x,y,z,c))
-        def onepad_slice(tpl, size): return (tpl + (1,)*(size-len(tpl)))
-        dims = onepad_slice(imfctg.shape, 4)
-
-        if ( len(dims) > 4 and dims[4] > 1 ):
-            print('WARNING: Multi-frame images are not supported using frame 1!')
-            imfctg = imfctg[:,:,:,:,0]
-
-        # Convert im to uint8
-        chmax = np.amax(np.amax(np.amax(imfctg, axis=0, keepdims=True), axis=1, keepdims=True), axis=2, keepdims=True)
-        chim = ((255.0 * imfctg) / chmax).astype("uint8")
-
-        # Setup valid imageData
-        self._imageData = leversc._imd_from_im(imfctg,dims,self._imageData)
-
-        header_json,count_packs = self._make_header(dims)
-
-        # Multipart-post request send
-        multipart = [("header", (None, header_json, "application/json"))]
-        for i in range(count_packs):
-            multipart.append(("lbins",("lbin%d"%(i), self._im_to_lbin(chim,dims,i), "application/octet-stream")))
-
-        resp = requests.post(url=self._leversc_url("/loadfig"), files=multipart)
-
-        # if we have a CONSTANTS and a renderParams, set it
-        if self._CONSTANTS!={} and 'renderParams' in self._CONSTANTS.keys():
-            self.renderParams=self._CONSTANTS['renderParams']
-
-
-    def _im_to_lbin(self,im,dims,pidx):
-        choffset = pidx * self._npack
-        chsize = min(dims[3]-choffset, self._npack)
-
-        imsub = im[:,:,:,choffset:(choffset+chsize)]
-        lbin_size = 4*2 + np.prod(dims[:3])*chsize
-
-        outbytes = bytearray(lbin_size)
-        struct.pack_into("!HHHH", outbytes, 0, chsize,dims[0],dims[1],dims[2])
-        imout = np.frombuffer(memoryview(outbytes)[(4*2):], "uint8")
-
-        imout[:] = np.reshape(np.transpose(imsub, (3,0,1,2)), -1, order='F')
-        return outbytes
-
-
-    def _make_header(self, dims):
-        count_packs = math.ceil(dims[3] / self._npack)
-
-        # Make json metadata header
-        imdjson = json.dumps(self._imageData)
-        return imdjson,count_packs
-
-    def _check_leversc(self):
-        try:
-            resp = requests.get(url=self._leversc_url("/info"), timeout=0.5)
-        except requests.exceptions.ConnectTimeout as e:
-            return False
-        except requests.exceptions.ConnectionError as e:
-            return False
-        except Exception as e:
-            print("Unable to contact leversc server: %s (%s)" % (self._leversc_url("/info"), e))
-            return False
-        return True
-
-
-    def _leversc_url(self,reqpath):
-        if ('/' != reqpath[0]):
-            reqpath='/'+reqpath
-        return "%s:%s%s"%(self._host,self._base_port + self._figNumber, reqpath)
-
-
-    @staticmethod
-    def _get_fcontig_imview(im):
-        if im.flags.f_contiguous:
-            return im
-        else:
-            imflat = np.reshape(im, -1, order='A')
-            imfctg = np.reshape(imflat, im.shape[::-1], order='F')
-            return imfctg
-
-
-    @staticmethod
-    def _get_normalized_dims(im):
-        # Helper to pd im.shape out to required number of dimensions
-        def _opad_slice(tpl, size): return (tpl + (1,)*(size-len(tpl)))[:size]
-
-        # Reverse the dimension order depending of f/c_contiguous
-        if im.flags.f_contiguous:
-            # dims = _opad_slice(im.shape, 4)
-            dims = _opad_slice(im.shape, 4)
-        else:
-            dims = _opad_slice(im.shape[::-1], 4)
-        return dims
-
-
-    @staticmethod
-    def _imd_from_im(im, dims, imD):
-        # Make sure every channel has a name ("Channel %i" by default)
-        chnames = imD["ChannelNames"] if "ChannelNames" in imD else []
-        chnames = [chnames[x] if len(chnames) > x else "Channel %s"%(x+1) for x in range(dims[3])]
-
-        # Set valid pixel size for each x,y,z dim
-        pxsize = imD["PixelPhysicalSize"] if "PixelPhysicalSize" in imD else [1,1,1]
-        pxsize = [x if x > 0 else 1 for x in pxsize]
-
-        new_imD = {"Dimensions": dims[:3],
-            "NumberOfChannels": dims[3],
-            "ChannelNames": chnames,
-            "PixelPhysicalSize": pxsize,
-            "PixelFormat": "uint8"}
-        return new_imD
-
-
-    def _init_leversc(self,strDB=None):
-        leverpath = leversc._get_leverjs_path()
-        if ( not self._run_leversc(leverpath,strDB) ):
-            return False
-
-        # Try to contact leversc after launch
-        for _ in range(10):
-            time.sleep(0.5)
-            if ( self._check_leversc() ):
-                return True
-
-        print("Unable to contact Leversc app")
-        return False
-
-
-    def _run_leversc(self, leverpath,strDB):
-        runargs = None
-        if ( leverpath is None ):
-            # Try to run installed leversc from path
-            runargs = ["open","-a","leverjs.app","-n","--args"] if leversc._is_macos() else ["leverjs"]
-        else:
-            runargs = leversc._get_os_ljselectron_exec(leverpath)
-
-        if ( runargs is None ):
-            print("Unable to start Leversc app")
-            return False
-
-        if strDB is not None:
-            strDB=os.path.abspath(strDB)
-            runargs.append("--leverFile=%s" % strDB)
-        port = self._base_port + self._figNumber
-        runargs.append("--port=%s" % port)
-        runargs.append("--title=figure %s" % self._figNumber)
-        p = leversc._exec_bg_process(runargs)
-        if ( p is None):
-            return False
-        return True
-
-
-    @staticmethod
-    def _get_os_ljselectron_exec(leverpath):
-        runargs = None
-        if ( leversc._is_windows() ):
-            elec_path = os.path.join(leverpath,"node_modules","electron","dist","electron.exe")
-            mainjs_path = os.path.join(leverpath,"elever","main.js")
-            runargs = [elec_path, mainjs_path]
-        elif ( leversc._is_linux() or leversc._is_macos() ):
-            elec_path = os.path.join(leverpath,"node_modules",".bin","electron")
-            mainjs_path = os.path.join(leverpath,"elever","main.js")
-            runargs = [elec_path, mainjs_path]
-
-        return runargs
-
-
-    @staticmethod
-    def _exec_bg_process(args):
-        try:
-            if ( leversc._is_windows() ):
-                p = subprocess.Popen(args,
-                                    stdin=subprocess.DEVNULL,
-                                    stdout=subprocess.DEVNULL,
-                                    stderr=subprocess.DEVNULL,
-                                    creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
-            elif ( leversc._is_linux() or leversc._is_macos() ):
-                p = subprocess.Popen(args,
-                                    stdin=subprocess.DEVNULL,
-                                    stdout=subprocess.DEVNULL,
-                                    stderr=subprocess.DEVNULL,
-                                    start_new_session=True)
-            else:
-                return None
-        except Exception as e:
-            print("Unable to launch leversc: (%s)"%e)
-            return None
-        return p
-
-
-    @staticmethod
-    def _is_windows():
-        return (sys.platform == "win32")
-
-    @staticmethod
-    def _is_linux():
-        return (sys.platform == "linux" or sys.platform == "cygwin")
-
-    @staticmethod
-    def _is_macos():
-        return (sys.platform == "darwin")
-
-
-    @staticmethod
-    def _get_leverjs_path():
-        # Check if ljspath.py is on sys.path (e.g. PYTHONPATH)
-        chk_ldr = pkgutil.find_loader("ljspath")
-        if ( chk_ldr is None ):
-            return None
-        # Try to load the module
-        ljs_m = chk_ldr.load_module("ljspath")
-        if ( ljs_m is None ):
-            return None
-        return ljs_m.get_ljspath()
-
-    from _readImage import readImage
-    from _property import setProperty,getProperty
-    @property
-    def viewParams(self):
-        return self.getProperty('viewParams')
-    @viewParams.setter
-    def viewParams(self,VP):
-        self.setProperty('viewParams',VP)
-    @property
-    def renderParams(self):        
-        return self.getProperty('renderParams')
-    @renderParams.setter
-    def renderParams(self,RP):
-        self.setProperty('renderParams',RP)
-    @property
-    def uiParams(self):        
-        return self.getProperty('uiParams')
-    @uiParams.setter
-    def uiParams(self,UIP):
-        self.setProperty('uiParams',UIP)
-
-
-
diff --git a/src/Python/leversc/_property.py b/src/Python/leversc/_property.py
index bf7e7a53dc3f4f56ac3481e22f69832acfa264f0..151ce35bea817b2ccae296b1d7c6a2698b293911 100644
--- a/src/Python/leversc/_property.py
+++ b/src/Python/leversc/_property.py
@@ -1,8 +1,71 @@
 import requests
 import json
 
+
+"""
+Helper classes for handling leversc settings changes
+"""
+class ChangeWrapper:
+    """
+    A wrapper class for bubbling property change updates to leversc class
+    """
+    def __init__(self, parent, incollection):
+        self._parent = parent
+        self._collection = incollection
+
+    def _property_updated(self, childprop):
+        self._parent._property_updated(self)
+
+    def __getitem__(self, keyidx):
+        elem = self._collection.__getitem__(keyidx)
+        if isinstance(elem, (dict,list)):
+            return __class__(self, elem)
+        else:
+            return elem
+    
+    def __setitem__(self, keyidx, v):
+        self._collection.__setitem__(keyidx,v)
+        self._property_updated(self)
+
+    """
+    Some Quality-of-life improvements for introspecting the wrappers
+    """
+    def __str__(self):
+        return str(self._collection)
+
+    def __repr__(self):
+        return "%s(%s)"%(__class__.__name__, repr(self._collection))
+
+
+class PropWrapper(ChangeWrapper):
+    """
+    Top-level property that runs setProperty (network send) on change updates
+    """
+    def __init__(self, lsc, propname, incollection):
+        self._leversc = lsc
+        self._propname = propname
+        super(__class__,self).__init__(self,incollection)
+
+    def unwrap(self):
+        """
+        Return an unwrapped version of this property (that can be edited without network overhead)
+        """
+        return self._collection
+
+    def _property_updated(self, childprop):
+        self._leversc.setProperty(self._propname, self._collection)
+
+    def __str__(self):
+        return str(self._collection)
+
+    def __repr__(self):
+        return "%s(%s)"%(__class__.__name__, repr(self._collection))
+
+
 # retrieves/sets viewParams, renderParams, uiParams, etc....
-def setProperty(self,propertyName,propertyStruct):    
+def setProperty(self,propertyName,propertyStruct):
+    if isinstance(propertyStruct,PropWrapper):
+        propertyStruct = propertyStruct.unwrap()
     URL = self._leversc_url("/"+propertyName)
     response = requests.post(URL,json=propertyStruct)
     
@@ -13,4 +76,4 @@ def getProperty(self,propertyName):
     if 'list'==type(property):
         # view and render params come as 1 element list
         property = property[0]
-    return property
+    return PropWrapper(self,propertyName,property)
diff --git a/src/Python/leversc/leversc.py b/src/Python/leversc/leversc.py
index a643794c1ccb892ac18dd97d67b093c421724096..b3fbd6959889187b99c8318dd9129b880f4641b6 100644
--- a/src/Python/leversc/leversc.py
+++ b/src/Python/leversc/leversc.py
@@ -342,7 +342,6 @@ class leversc:
                 return None
         except Exception as e:
             print("Unable to launch leversc: (%s)"%e)
-            print("please check the app is properly installed. see https://leverjs.net/leversc for details.")
             return None
         return p
 
@@ -372,11 +371,11 @@ class leversc:
             return None
         return ljs_m.get_ljspath()
 
-    from leversc._readImage import readImage
-    from leversc._property import setProperty,getProperty
+    from _readImage import readImage
+    from _property import setProperty,getProperty
     @property
     def viewParams(self):
-        return self.getProperty('viewParams')    
+        return self.getProperty('viewParams')
     @viewParams.setter
     def viewParams(self,VP):
         self.setProperty('viewParams',VP)