diff --git a/test/test_mapcanvas.py b/test/test_mapcanvas.py
index c27642cc55a833c61078d1641af9c73e95e95371..cebeb5143ec0ac54681705d4cef605e2e7165dd4 100644
--- a/test/test_mapcanvas.py
+++ b/test/test_mapcanvas.py
@@ -21,7 +21,8 @@
 from timeseriesviewer.utils import initQgisApplication
 from PyQt5.QtGui import *
 from PyQt5.QtCore import *
-import unittest
+import unittest, tempfile
+
 from timeseriesviewer.mapcanvas import *
 
 QGIS_APP = initQgisApplication()
@@ -46,7 +47,7 @@ class testclassDialogTest(unittest.TestCase):
 
         self.assertIsInstance(m.mLayerModel, MapCanvasLayerModel)
 
-
+        m.saveAsImage()
 
 
 if __name__ == "__main__":
diff --git a/test/test_utils.py b/test/test_utils.py
index 01c4a909c114b200304ec5b67d2b3792b9897c50..cd7ede914fe9e0b1758adc219673307143c7dcff 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -48,7 +48,13 @@ class testclassUtilityTests(unittest.TestCase):
         self.assertIsInstance(center, SpatialPoint)
         self.assertEqual(ext.spatialCenter(), center)
 
+    def test_others(self):
 
+        p = 'This is a §$%& formed file path+§"^1'
+
+        p2 = saveFilePath(p)
+
+        s = ""
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/timeseriesviewer/main.py b/timeseriesviewer/main.py
index de024009648d02644bd7c9be9dff482e7916e918..d399574ef98c6b6a757c506f1510df9226ba87e9 100644
--- a/timeseriesviewer/main.py
+++ b/timeseriesviewer/main.py
@@ -541,7 +541,7 @@ class TimeSeriesViewer(QgisInterface, QObject):
         filters = "CSV (*.csv *.txt);;" + \
                   "All files (*.*)"
 
-        path, filter = QFileDialog.getOpenFileName(caption='Load Time Series definition', directory=defDir, filters=filters)
+        path, filter = QFileDialog.getOpenFileName(caption='Load Time Series definition', directory=defDir, filter=filters)
         if path is not None and os.path.exists(path):
             s.setValue('file_ts_definition', path)
             M = self.ui.dockTimeSeries.tableView_TimeSeries.model()
diff --git a/timeseriesviewer/mapcanvas.py b/timeseriesviewer/mapcanvas.py
index ad05494e3cfb46686443aef01f53de0180eeead4..7767465f563245b705c361f2c6402383f588a6c9 100644
--- a/timeseriesviewer/mapcanvas.py
+++ b/timeseriesviewer/mapcanvas.py
@@ -912,7 +912,7 @@ class MapCanvas(QgsMapCanvas):
         else:
             path = 'mapcanvas'
         path = jp(lastDir, '{}.{}'.format(path, fileType.lower()))
-        path = QFileDialog.getSaveFileName(self, 'Save map as {}'.format(fileType), path)
+        path, _ = QFileDialog.getSaveFileName(self, 'Save map as {}'.format(fileType), path)
         if len(path) > 0:
             self.saveAsImage(path, None, fileType)
             SETTINGS.setValue('CANVAS_SAVE_IMG_DIR', os.path.dirname(path))
@@ -1126,5 +1126,7 @@ if __name__ == '__main__':
     c.setExtent(lyr1.extent())
     c.setCrs(QgsCoordinateReferenceSystem('EPSG:32632'))
     c.setExtent(c.spatialExtentHint())
+
+
     c.refresh()
     qgsApp.exec_()
\ No newline at end of file
diff --git a/timeseriesviewer/mapvisualization.py b/timeseriesviewer/mapvisualization.py
index 47473ae815ac6d9235d43d7ddf1a4453e61359ba..8c9da339e5adfe3c0ca577c12b61cb6a47e5c2b8 100644
--- a/timeseriesviewer/mapvisualization.py
+++ b/timeseriesviewer/mapvisualization.py
@@ -111,8 +111,8 @@ class MapViewUI(QFrame, loadUI('mapviewdefinition.ui')):
 
         #l = self.renderSettingsLayout
         l = self.gbRasterRendering.layout()
-        l.removeWidget(sensorSettings.ui)
-        sensorSettings.ui.close()
+        l.removeWidget(sensorSettings)
+        sensorSettings.close()
         #self.resize(self.sizeHint())
 
 
@@ -2260,7 +2260,7 @@ class DateViewCollection(QObject):
         for DV in toRemove:
             self.mViews.remove(DV)
 
-            for mapCanvas in DV.mapCanvases.values():
+            for mapCanvas in DV.mMapCanvases.values():
                 toRemove = mapCanvas.layers()
                 mapCanvas.setLayers([])
                 toRemove = [l for l in toRemove if isinstance(l, QgsRasterLayer)]
diff --git a/timeseriesviewer/profilevisualization.py b/timeseriesviewer/profilevisualization.py
index 2416b522e6845332116c71a4cb3a9efeb70c4d5b..59c498a35bcee3b30280672fc644d0d84cc5e6e1 100644
--- a/timeseriesviewer/profilevisualization.py
+++ b/timeseriesviewer/profilevisualization.py
@@ -2221,7 +2221,9 @@ if __name__ == '__main__':
         STVis.createNewPlotStyle3D()
         STVis.ui.listWidget.setCurrentRow(1)
 
-        STVis.loadCoordinate(cpND)
+        STVis.loadCoordinate(cpND, backgroundProcess=False)
+
+        STVis.tpCollection.mTemporalProfiles[0].setName('My Name')
 
         from example import  exampleEvents
         #STVis.loadCoordinatesFromOgr(exampleEvents)
diff --git a/timeseriesviewer/spectrallibraries.py b/timeseriesviewer/spectrallibraries.py
index 611af5f30cc5df46e8659da970b74e532fe7b328..ea72ff5e5922edfc182170cb778339b230f60692 100644
--- a/timeseriesviewer/spectrallibraries.py
+++ b/timeseriesviewer/spectrallibraries.py
@@ -169,11 +169,24 @@ class SpectralLibraryTableView(QTableView):
         return [m.idx2profile(m.createIndex(r, 0)) for r in rows]
 
     def onSetColor(self):
-        c = QColorDialog.getColor()
-        if isinstance(c, QColor):
-            model = self.model()
-            for idx in self.selectedRowsIndexes():
-                model.setData(model.createIndex(idx, 1), c, Qt.BackgroundRole)
+        model = self.model()
+        c0 = None
+        for r in self.selectedRowsIndexes():
+            idx = model.createIndex(r, 1)
+            c0 = model.data(idx, Qt.BackgroundRole)
+            break
+
+        if not isinstance(c0, QColor):
+            c0 = None
+
+        c = QColorDialog(c0, self)
+        c.exec_()
+
+        if c.result() == QDialog.Accepted:
+            c = c.currentColor()
+            if isinstance(c, QColor):
+                for r in self.selectedRowsIndexes():
+                    model.setData(model.createIndex(r, 1), c, Qt.BackgroundRole)
 
     def setCheckState(self, checkState):
         model = self.model()
diff --git a/timeseriesviewer/temporalprofiles2d.py b/timeseriesviewer/temporalprofiles2d.py
index 2820ba0df15fd088cf1418ae4e782d78ad6a4117..86a9b461d2b7b9e5f82185a6f650a83ead3465c5 100644
--- a/timeseriesviewer/temporalprofiles2d.py
+++ b/timeseriesviewer/temporalprofiles2d.py
@@ -1131,10 +1131,16 @@ class TemporalProfileCollection(QAbstractTableModel):
         self.mColumNames = [self.mcnName, self.mcnLoaded, self.mcnCoordinate]
 
         crs = QgsCoordinateReferenceSystem('EPSG:4862')
-        uri = 'Point?crs={}'.format(crs.authid())
+        uri = 'Point?crs={}&field=id:integer&field=name:string(120)'.format(crs.authid())
+        self.mLocations = QgsVectorLayer(uri, 'LOCATIONS', 'memory')
+        symbol = QgsFillSymbol.createSimple({'style': 'no', 'color': 'red', 'outline_color': 'black'})
+        self.mLocations.renderer().setSymbol(symbol)
 
         self.TS = None
-        self.mLocations = QgsVectorLayer(uri, 'LOCATIONS', 'memory')
+
+
+
+
         self.mTemporalProfiles = []
         self.mTPLookupSpatialPoint = {}
         self.mTPLookupID = {}
@@ -1274,6 +1280,8 @@ class TemporalProfileCollection(QAbstractTableModel):
             self.prune(nMax=self.mMaxProfiles - l)
 
             self.beginInsertRows(QModelIndex(), i, i + l - 1)
+
+            features = []
             for temporalProfile in temporalProfiles:
                 assert isinstance(temporalProfile, TemporalProfile)
                 id = self.nextID
@@ -1282,9 +1290,21 @@ class TemporalProfileCollection(QAbstractTableModel):
                 self.mTemporalProfiles.insert(i, temporalProfile)
                 self.mTPLookupID[id] = temporalProfile
                 self.mTPLookupSpatialPoint[temporalProfile.mCoordinate] = temporalProfile
+
+                f = QgsFeature(self.mLocations.fields())
+                f.setFields(self.mLocations.fields())
+                f.setAttribute('id', QVariant(id))
+                f.setAttribute('name', QVariant(temporalProfile.name()))
+                f.setGeometry(QgsGeometry.fromPointXY(temporalProfile.coordinate()))
+                features.append(f)
+
+
                 temporalProfile.sigDataChanged.connect(lambda: self.onUpdate(temporalProfile))
-                temporalProfile.sigNameChanged.connect(lambda: self.onUpdate(temporalProfile))
+                temporalProfile.sigNameChanged.connect(lambda: self.onUpdateName(temporalProfile))
                 i += 1
+            self.mLocations.startEditing()
+            assert self.mLocations.dataProvider().addFeatures(features)
+            assert self.mLocations.commitChanges()
             self.endInsertRows()
 
             self.sigTemporalProfilesAdded.emit(temporalProfiles)
@@ -1302,6 +1322,19 @@ class TemporalProfileCollection(QAbstractTableModel):
         else:
             return None
 
+    def temporalProfileFromFeature(self, feature):
+
+        return None
+
+    def temporalProfileToLocationFeature(self, tp:TemporalProfile):
+
+        self.mLocations.selectByIds([tp.id()])
+        for f in self.mLocations.selectedFeatures():
+            assert isinstance(f, QgsFeature)
+            return f
+
+        return None
+
     def id(self, temporalProfile):
         """
         Returns the id of an TemporalProfile
@@ -1429,9 +1462,26 @@ class TemporalProfileCollection(QAbstractTableModel):
 
         if tp in self.mTemporalProfiles:
             idx0 = self.tp2idx(tp)
-            idx1 = self.createIndex(idx0.row(), self.rowCount())
+            idx1 = self.createIndex(idx0.row(), self.columnCount())
             self.dataChanged.emit(idx0, idx1, [Qt.DisplayRole])
 
+
+
+    def onUpdateName(self, tp):
+        assert isinstance(tp, TemporalProfile)
+
+        if tp in self.mTemporalProfiles:
+            idx0 = self.tp2idx(tp)
+            c = self.mColumNames.index(self.mcnName)
+            idx = self.createIndex(idx0.row(), c)
+            self.dataChanged.emit(idx, idx, [Qt.DisplayRole])
+
+            f = self.temporalProfileToLocationFeature(tp)
+
+            if isinstance(f, QgsFeature):
+                f.setAttribute('name', tp.name())
+
+
     def sort(self, col, order):
         if self.rowCount() == 0:
             return
@@ -1540,7 +1590,7 @@ if __name__ == '__main__':
     qgsApp = utils.initQgisApplication()
     DEBUG = False
 
-    w = TemporalProfilePlotStyle3DWidget()
+    w = TemporalProfile2DPlotStyle()
     w.show()
     print(w.plotStyle())
 
diff --git a/timeseriesviewer/ui/profileviewdock.ui b/timeseriesviewer/ui/profileviewdock.ui
index 21c9f24dedf2a7594d50ff941f6f2ea9c4743b30..8faeb074149713fa07d519421db5a7359e98a71a 100644
--- a/timeseriesviewer/ui/profileviewdock.ui
+++ b/timeseriesviewer/ui/profileviewdock.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>885</width>
-    <height>331</height>
+    <height>442</height>
    </rect>
   </property>
   <property name="features">
diff --git a/timeseriesviewer/utils.py b/timeseriesviewer/utils.py
index 9ee3699d8242ab7884fd05f69100672911d39740..49211d69de9b25593076ac18dfbbeddd35b846de 100644
--- a/timeseriesviewer/utils.py
+++ b/timeseriesviewer/utils.py
@@ -531,15 +531,13 @@ class SpatialExtent(QgsRectangle):
 
 
 
-def saveFilePath(text):
+def saveFilePath(text : str):
     """
     Normalizes string, converts to lowercase, removes non-alpha characters,
     and converts spaces to hyphens.
     see https://stackoverflow.com/questions/295135/turn-a-string-into-a-valid-filename
     :return: path
     """
-    import unicodedata
-    text = unicodedata.normalize('NFKD', text).encode('ascii', 'ignore')
     text = re.sub(r'[^\w\s.-]', '', text).strip().lower()
     text = re.sub(r'[-\s]+', '_', text)
     return re.sub(r'[ ]+]','',text)