diff --git a/timeseriesviewer/sandbox.py b/timeseriesviewer/sandbox.py
index e15b8a535c485c43721381a95b692b55f919f8e8..ce923bae5373e9bdf83655146439742a3ee20435 100644
--- a/timeseriesviewer/sandbox.py
+++ b/timeseriesviewer/sandbox.py
@@ -1,5 +1,5 @@
 from __future__ import absolute_import
-import six, sys, os, gc, re, collections, site, inspect
+import six, sys, os, gc, re, collections, site, inspect, time
 from osgeo import gdal, ogr
 
 from qgis import *
@@ -8,6 +8,7 @@ from qgis.gui import *
 from PyQt4.QtGui import *
 from PyQt4.QtCore import *
 
+from timeseriesviewer import DIR_EXAMPLES, jp, dprint
 
 class HiddenCanvas(QgsMapCanvas):
 
@@ -17,43 +18,6 @@ class HiddenCanvas(QgsMapCanvas):
 
 
 
-class LayerLoaderR(QRunnable):
-
-    layerReady = pyqtSignal(QgsRasterLayer)
-    finished = pyqtSignal(list)
-    def __init__(self):
-        super(LayerLoader, self).__init__()
-
-    def loadLayers(self, paths):
-        lyrs = []
-        for path in paths:
-            print('Load '+path)
-            lyr = QgsRasterLayer(path)
-            if lyr:
-                self.layerReady.emit(lyr)
-                lyrs.append(lyr)
-
-        self.finished.emit(lyrs)
-
-class LayerLoader(QObject):
-
-    layerReady = pyqtSignal(QgsRasterLayer)
-    finished = pyqtSignal(list)
-    def __init__(self):
-        super(LayerLoader, self).__init__()
-
-    def loadLayers(self, paths):
-        lyrs = []
-        for path in paths:
-            print('Load '+path)
-            lyr = QgsRasterLayer(path)
-            if lyr:
-                self.layerReady.emit(lyr)
-                lyrs.append(lyr)
-
-        self.finished.emit(lyrs)
-
-
 def getLoadedLayer(layer):
     print('LAYER READY')
     print(layer)
@@ -66,6 +30,16 @@ def getLoadedLayers(layers):
 def loadingDone():
     print('DONE')
 
+
+from itertools import izip_longest
+
+def grouper(iterable, n, fillvalue=None):
+    args = [iter(iterable)] * n
+    return izip_longest(*args, fillvalue=fillvalue)
+
+def waitForThreads():
+    print "Waiting for thread pool"
+    pool.waitForDone()
 if __name__ == '__main__':
     import site, sys
     #add site-packages to sys.path as done by enmapboxplugin.py
@@ -76,7 +50,7 @@ if __name__ == '__main__':
     #prepare QGIS environment
     if sys.platform == 'darwin':
         PATH_QGS = r'/Applications/QGIS.app/Contents/MacOS'
-        os.environ['GDAL_DATA'] = r'/usr/local/Cellar/gdal/1.11.3_1/share'
+        #os.environ['GDAL_DATA'] = r'/usr/local/Cellar/gdal/1.11.3_1/share'
     else:
         # assume OSGeo4W startup
         PATH_QGS = os.environ['QGIS_PREFIX_PATH']
@@ -88,34 +62,56 @@ if __name__ == '__main__':
     qgsApp.setPrefixPath(PATH_QGS, True)
     qgsApp.initQgis()
 
-    from timeseriesviewer import file_search
-    paths = file_search(r'C:\Users\geo_beja\Repositories\QGIS_Plugins\SenseCarbonTSViewer\example\Images',
-                        '*.bsq')
-    #run
-    import numpy as np
-    pool = QThreadPool()
-    pool.maxThreadCount(3)
+    from timeseriesviewer import file_search, PATH_EXAMPLE_TIMESERIES
+    from timeseriesviewer.timeseries import TimeSeries, TimeSeriesDatum
+    pathTestTS = jp(DIR_EXAMPLES, 'ExampleTimeSeries.csv')
+    TS = TimeSeries()
+    if False or not os.path.exists(pathTestTS):
+        paths = file_search(jp(DIR_EXAMPLES, 'Images'), '*.bsq')
 
-    pool.start()
+        TS.addFiles(paths)
+        TS.saveToFile(PATH_EXAMPLE_TIMESERIES)
+    else:
+        TS.loadFromFile(PATH_EXAMPLE_TIMESERIES)
+
+    drvMEM = gdal.GetDriverByName('MEM')
+    ds = gdal.Open(TS.data[0].pathImg)
+    ds = drvMEM.CreateCopy('',ds)
+
+    lyr = QgsRasterLayer(paths[0])
+    finalLayerList = []
+    def callback(result):
+        assert isinstance(result, QgsRasterLayer)
+        print(result)
+        finalLayerList.append(result)
+        s =  ""
+    cnt = 0
+    def callbackFin():
+        cnt-=1
 
-    t0 = np.datetime64('now')
-    #paths = []
-    objThread = QThread()
-    loader = LayerLoader()
-    #loader.loadLayers(paths)
-    loader.moveToThread(objThread)
-    loader.finished.connect(objThread.quit)
-    #loader.layerReady.connect(getLoadedLayer)
-    objThread.started.connect(lambda:loader.loadLayers(paths))
+    #run
+    #LL = LayerLoaderR(paths)
+    #LL.signales.sigLayerLoaded.connect(callback)
+    #r = LL.run()
 
-    objThread.finished.connect(loadingDone)
-    objThread.start()
+    import numpy as np
+    #pool = QThreadPool()
+    pool = QThreadPool.globalInstance()
+    pool.setMaxThreadCount(4)
+    for files in grouper(paths, 3):
 
-    while not objThread.isFinished():
+        LL = TSDLoader([f for f in files if f is not None])
+        cnt += 1
+        LL.signals.sigRasterLayerLoaded.connect(callback)
+        LL.signals.sigFinished.connect(callbackFin)
+        pool.start(LL)
 
+    t0 = np.datetime64('now')
+    pool.waitForDone()
 
-    print('DT: {}'.format(np.datetime64('now') - t0))
 
     #close QGIS
+
+    qgsApp.aboutToQuit.connect(waitForThreads)
     qgsApp.exec_()
     qgsApp.exitQgis()