diff --git a/timeseriesviewer/ui/icons/icon.png b/timeseriesviewer/ui/icons/icon.png
index c0d802915cae1e3eb14b24e988a0f7833401f023..2b55fc08c55705329159aceaf26b3cf3d81f3207 100644
Binary files a/timeseriesviewer/ui/icons/icon.png and b/timeseriesviewer/ui/icons/icon.png differ
diff --git a/timeseriesviewer/ui/icons/icon.svg b/timeseriesviewer/ui/icons/icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..43ee2e2e8612b5f9361504310fc15210a343ac5f
--- /dev/null
+++ b/timeseriesviewer/ui/icons/icon.svg
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   height="19.500002"
+   width="19.500002"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="icon.svg"
+   inkscape:export-filename="/Users/benjamin.jakimow/Repositories/QGIS_Plugins/hub-timeseriesviewer/timeseriesviewer/ui/icons/icon.png"
+   inkscape:export-xdpi="119.99998"
+   inkscape:export-ydpi="119.99998">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8">
+    <inkscape:perspective
+       id="perspective3486"
+       inkscape:persp3d-origin="16 : 10.666667 : 1"
+       inkscape:vp_z="32 : 16 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 16 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective3496" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective3600" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective7871" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective8710" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective9811" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 0.5 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="1 : 0.5 : 1"
+       inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+       id="perspective4762" />
+    <clipPath
+       id="clipPath26">
+      <path
+         d="M 2362.38,3289.96 3754.11,6.80078 3641.8,151.695 2640.37,2534.35 3412.13,445.691 3334.48,520.086 2556,2631.38 3172.66,695.02 l -18.02,-0.004 -48.52,39.734 -622.04,1973.96 477.78,-1855.796 -59.5,44.93 -489.59,1907.296 353.27,-1804.34 -55.73,34.08 -355.81,1835.76 209.8,-1746.44 -51.89,28.52 -207.45,1766.52 72.29,-1692.23 -53.51,24.09 -66.25,1704.29 -86.87,-1635.36 -48.91,16.08 94.6,1658.46 -257.22,-1604.98 -45.65,12.57 259.68,1627.16 -445.14,-1576.09 -50.91,8.91 455.88,1590.29 -656.68,-1555.14 -53.13,2.14 666.01,1572.08 -928.64,-1561.46 -47.53,1.93 1056.19,1777.98 193.21,0 z"
+         inkscape:connector-curvature="0"
+         id="path28" />
+    </clipPath>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1276"
+     inkscape:window-height="756"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="6.6775233"
+     inkscape:cx="5.9280981"
+     inkscape:cy="7.5000031"
+     inkscape:window-x="4"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <rect
+     style="fill:none;stroke:none"
+     id="rect6554"
+     width="19.499998"
+     height="19.499998"
+     x="0"
+     y="0" />
+  <rect
+     style="fill:#6e97c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419"
+     width="6.499999"
+     height="6.499999"
+     x="6.5"
+     y="0" />
+  <rect
+     style="display:inline;fill:#253e5b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-6"
+     width="6.499999"
+     height="6.499999"
+     x="13.000004"
+     y="0" />
+  <rect
+     style="display:inline;fill:#253e5b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-6-9"
+     width="6.499999"
+     height="6.499999"
+     x="6.5"
+     y="6.5"
+     inkscape:transform-center-x="-3.2499991"
+     inkscape:transform-center-y="-4.3333322" />
+  <rect
+     style="display:inline;fill:#6d97c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-0"
+     width="6.499999"
+     height="6.499999"
+     x="13.000004"
+     y="6.5" />
+  <rect
+     style="display:inline;fill:#253e5b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-6-7"
+     width="6.499999"
+     height="6.499999"
+     x="0"
+     y="0" />
+  <rect
+     style="display:inline;fill:#6d97c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-3"
+     width="6.499999"
+     height="6.499999"
+     x="0"
+     y="6.5" />
+  <rect
+     style="display:inline;fill:#6d97c4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-5"
+     width="6.499999"
+     height="6.499999"
+     x="6.5"
+     y="13.000004" />
+  <rect
+     style="display:inline;fill:#253e5b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="rect6419-6-6"
+     width="6.499999"
+     height="6.499999"
+     x="0"
+     y="13.000004" />
+  <rect
+     y="13.000004"
+     x="13.000004"
+     height="6.499999"
+     width="6.499999"
+     id="rect8225"
+     style="display:inline;fill:#253e5b;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <g
+     id="g5821"
+     transform="translate(0.00243209,-0.24814311)"
+     style="fill:none;stroke:#ffffff;stroke-opacity:1">
+    <ellipse
+       ry="6.8272738"
+       rx="7.0345278"
+       cy="9.75"
+       cx="9.75"
+       id="path8227"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.89999998;stroke-opacity:1" />
+    <path
+       sodipodi:nodetypes="ccc"
+       inkscape:connector-curvature="0"
+       id="path8235"
+       d="m 12.364602,11.360681 -2.331606,0 -2.901555,-3.212435"
+       style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+  </g>
+</svg>
diff --git a/timeseriesviewer/virtualrasters.py b/timeseriesviewer/virtualrasters.py
index d59059e823d06f7a77bf0140f66d150e52fb365a..3dfb050f99195c50c4b9692d7098ecc23d5d9940 100644
--- a/timeseriesviewer/virtualrasters.py
+++ b/timeseriesviewer/virtualrasters.py
@@ -21,7 +21,20 @@ class VirtualBand(object):
     def addSourceBand(self, path, bandIndex):
         self.sources.append(VirtualBandInputSource(path, bandIndex))
 
+    def removeSourceBand(self, bandOrIndex):
+        """
+        Removes a virtual band
+        :param bandOrIndex: int | VirtualBand
+        :return: The VirtualBand that was removed
+        """
+        if not isinstance(bandOrIndex, VirtualBand):
+            bandOrIndex = self.sources[bandOrIndex]
+        return self.sources.remove(bandOrIndex)
+
     def sourceFiles(self):
+        """
+        :return: list of file-paths to all source files
+        """
         files = set([inputSource.path for inputSource in self.sources])
         return sorted(list(files))
 
@@ -38,19 +51,85 @@ class VirtualRasterBuilder(object):
         self.vBands = []
         self.vMetadata = dict()
 
+
     def addVirtualBand(self, virtualBand):
+        """
+        Adds a virtual band
+        :param virtualBand: the VirtualBand to be added
+        :return: VirtualBand
+        """
         assert isinstance(virtualBand, VirtualBand)
         self.vBands.append(virtualBand)
+        return self[-1]
+
 
     def insertVirtualBand(self, i, virtualBand):
+        """
+        Inserts a VirtualBand
+        :param i: the insert position
+        :param virtualBand: the VirtualBand to be inserted
+        :return: the VirtualBand
+        """
         assert isinstance(virtualBand, VirtualBand)
         self.vBands.insert(i, virtualBand)
+        return self[i]
+
+
+
+    def removeVirtualBands(self, bandsOrIndices):
+        assert isinstance(bandsOrIndices, list)
+        to_remove = []
+        for bandOrIndex in bandsOrIndices:
+            if not isinstance(bandOrIndex, VirtualBand):
+                bandOrIndex = self.vBands[bandOrIndex]
+            to_remove.append(bandOrIndex)
+
+        for band in to_remove:
+            self.vBands.remove(band)
+        return to_remove
+
+
+    def removeVirtualBand(self, bandOrIndex):
+        r = self.removeVirtualBands([bandOrIndex])
+        return r[0]
 
     def addFilesAsMosaic(self, files):
-        pass
+        """
+        Shortcut to mosaic all input files. All bands will maintain their band position in the virtual file.
+        :param files: [list-of-file-paths]
+        """
+
+        for file in files:
+            ds = gdal.Open(file)
+            assert isinstance(ds, gdal.Dataset)
+            nb = ds.RasterCount
+            for b in range(nb):
+                if b+1 < len(self):
+                    #add new virtual band
+                    self.addVirtualBand(VirtualBand())
+                vBand = self[b]
+                assert isinstance(vBand, VirtualBand)
+                vBand.addSourceBand(file, b)
+        return self
 
     def addFilesAsStack(self, files):
-        pass
+        """
+        Shortcut to stack all input files, i.e. each band of an input file will be a new virtual band.
+        Bands in the virtual file will be ordered as file1-band1, file1-band n, file2-band1, file2-band,...
+        :param files: [list-of-file-paths]
+        :return: self
+        """
+        for file in files:
+            ds = gdal.Open(file)
+            assert isinstance(ds, gdal.Dataset)
+            nb = ds.RasterCount
+            ds = None
+            for b in range(nb):
+                #each new band is a new virtual band
+                vBand = self.addVirtualBand(VirtualBand())
+                assert isinstance(vBand, VirtualBand)
+                vBand.addSourceBand(file, b)
+        return self
 
     def sourceFiles(self):
         files = set()
@@ -59,7 +138,32 @@ class VirtualRasterBuilder(object):
             files.update(set(vBand.sourceFiles()))
         return sorted(list(files))
 
-    def saveVRT(self, pathVRT):
+    def saveVRT(self, pathVRT, **kwds):
+        """
+        :param pathVRT: path to VRT that is created
+        :param options --- can be be an array of strings, a string or let empty and filled from other keywords..
+        :param resolution --- 'highest', 'lowest', 'average', 'user'.
+        :param outputBounds --- output bounds as (minX, minY, maxX, maxY) in target SRS.
+        :param xRes, yRes --- output resolution in target SRS.
+        :param targetAlignedPixels --- whether to force output bounds to be multiple of output resolution.
+        :param bandList --- array of band numbers (index start at 1).
+        :param addAlpha --- whether to add an alpha mask band to the VRT when the source raster have none.
+        :param resampleAlg --- resampling mode.
+        :param outputSRS --- assigned output SRS.
+        :param allowProjectionDifference --- whether to accept input datasets have not the same projection. Note: they will *not* be reprojected.
+        :param srcNodata --- source nodata value(s).
+        :param callback --- callback method.
+        :param callback_data --- user data for callback.
+        :return: gdal.DataSet(pathVRT)
+        """
+
+        _kwds = dict()
+        supported = ['options','resolution','outputBounds','xRes','yRes','targetAlignedPixels','addAlpha','resampleAlg',
+        'outputSRS','allowProjectionDifference','srcNodata','VRTNodata','hideNodata','callback', 'callback_data']
+        for k in kwds.keys():
+            if k in supported:
+                _kwds[k] = kwds[k]
+
 
         dn = os.path.dirname(pathVRT)
         if not os.path.isdir(dn):
@@ -74,8 +178,7 @@ class VirtualRasterBuilder(object):
             if noData and srcNodata is None:
                 srcNodata = noData
 
-        vro = gdal.BuildVRTOptions(separate=True,
-                                   srcNodata=srcNodata)
+        vro = gdal.BuildVRTOptions(separate=True, **_kwds)
         #1. build a temporary VRT that described the spatial shifts of all input sources
         gdal.BuildVRT(pathVRT, srcFiles, options=vro)
         dsVRTDst = gdal.Open(pathVRT)
@@ -142,6 +245,22 @@ class VirtualRasterBuilder(object):
             info.append(str(vBand))
         return '\n'.join(info)
 
+    def __len__(self):
+        return len(self.vBands)
+
+    def __getitem__(self, slice):
+        return self.vBands[slice]
+
+    def __delitem__(self, slice):
+        self.removeVirtualBands(self[slice])
+
+    def __contains__(self, item):
+        return item in self.vBands
+
+
+    def __iter__(self):
+        return iter(self.mClasses)
+
 def createVirtualBandMosaic(bandFiles, pathVRT):
     drv = gdal.GetDriverByName('VRT')
 
@@ -175,7 +294,7 @@ def createVirtualBandStack(bandFiles, pathVRT):
 
     vrtOptions = gdal.BuildVRTOptions(
         # here we can use the options known from http://www.gdal.org/gdalbuildvrt.html
-        separate=True
+        separate=True,
     )
     vrtDS = gdal.BuildVRT(pathVRT, bandFiles, options=vrtOptions)
     vrtDS.FlushCache()
@@ -193,102 +312,3 @@ def createVirtualBandStack(bandFiles, pathVRT):
 
     return vrtDS
 
-
-def groupRapidEyeTiles(dirIn, dirOut):
-    """
-
-    :param dirIn:
-    :param dirOut:
-    :return:
-    """
-
-    files = file_search(dirIn, '*_RE*_3A_*2.tif', recursive=True)
-
-    if not os.path.exists(dirOut):
-        os.mkdir(dirOut)
-
-    sources = dict()
-    for file in files:
-        if not file.endswith('.tif'):
-            continue
-        dn = os.path.dirname(file)
-        bn = os.path.basename(file)
-        print(bn)
-        id, date, sensor, product, _ = tuple(bn.split('_'))
-
-        if not date in sources.keys():
-            sources[date] = []
-        sources[date].append(file)
-    for date, files in sources.items():
-        pathVRT = os.path.join(dirOut, 're_{}.vrt'.format(date))
-        createVirtualBandMosaic(files, pathVRT)
-
-def groupCBERS(dirIn, dirOut):
-    files = file_search(dirIn, 'CBERS*.tif', recursive=True)
-
-    if not os.path.exists(dirOut):
-        os.mkdir(dirOut)
-
-    CONTAINERS = dict()
-    for file in files:
-        dn = os.path.dirname(file)
-        bn = os.path.basename(file)
-        #basenames like CBERS_4_MUX_20150603_167_107_L4_BAND5_GRID_SURFACE.tif
-        splitted = bn.split('_')
-        id = '_'.join(splitted[:4])
-        bandName = splitted[7]
-
-        if id not in CONTAINERS.keys():
-            CONTAINERS[id] = dict()
-
-        bandSources = CONTAINERS[id]
-        if bandName not in bandSources.keys():
-            bandSources[bandName] = list()
-        bandSources[bandName].append(file)
-
-    #mosaic all scenes of same date
-    # and stack all bands related to the same channel
-    for id, bandSources in CONTAINERS.items():
-
-        pathVRT = id + '.vrt'
-        pathVRT = os.path.join(dirOut, pathVRT)
-        V = VirtualRasterBuilder()
-
-        #vrt = createVirtualBandStack(bandSources, pathVRT)
-        #add bands in sorted order
-        for bandName in sorted(bandSources.keys()):
-            vBandSources = bandSources[bandName]
-            VB = VirtualBand(name=bandName)
-            for path in vBandSources:
-                VB.addSourceBand(path, 0) #it's always one band only
-
-            V.addVirtualBand(VB)
-        #print(V)
-        V.saveVRT(pathVRT)
-        s = ""
-        #add ISO time stamp
-
-    pass
-
-def groupLandsat(dirIn, dirOut):
-
-    pass
-
-
-if __name__ == '__main__':
-    if True:
-        dirIn = r'H:\CBERS\hugo\Download20170523'
-        dirOut = r'H:\CBERS\VRTs'
-
-        groupCBERS(dirIn, dirOut)
-        exit(0)
-
-    if True:
-        dirIn = r'H:\CBERS\hugo\Download20170523'
-        dirOut = r'H:\CBERS\VRTs'
-        groupCBERS(dirIn, dirOut)
-
-    if True:
-        dirIn = r'H:\RapidEye\3A'
-        dirOut = r'H:\RapidEye\VRTs'
-        groupRapidEyeTiles(dirIn, dirOut)
\ No newline at end of file