diff --git a/metavis/BitInspector.cpp b/metavis/BitInspector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b04d49506662c7c765ce7d757a8e40bcc8aed46
--- /dev/null
+++ b/metavis/BitInspector.cpp
@@ -0,0 +1,99 @@
+#include "pch.h"
+#include "BitInspector.h"
+
+#define ItemWidth 20
+#define FieldStart 170
+#define EmptySpaceRight 5
+#define EmptySpaceBottom 40
+#define HeaderSpace 0
+
+BitInspector::BitInspector(QWidget* parent)
+	: QWidget(parent)
+{
+	//DummyData
+	//std::vector< SolutionPointData>* dummyVec = new std::vector< SolutionPointData>();
+	//SolutionPointData data;
+	//data.iteration = 20;
+	//data.bitVec.push_back(true);
+	//data.objectiveFunction = 230.234;
+	//data.particleNumber = 120;
+	//dummyVec->push_back(data);
+	//begin = dummyVec->begin();
+	//end = dummyVec->end();
+}
+
+BitInspector::~BitInspector()
+{
+	
+}
+
+void BitInspector::updateData(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end)
+{
+	this->begin = begin;
+	this->end = end;
+	setMinimumSize(FieldStart + begin->bitVec.size() * 1 + EmptySpaceRight, std::distance(begin, end) * ItemWidth + EmptySpaceBottom + HeaderSpace);
+	update();
+}
+
+void BitInspector::clear()
+{
+	begin = std::vector<SolutionPointData>::iterator();
+	end = std::vector<SolutionPointData>::iterator();
+	update();
+}
+
+
+void BitInspector::keyPressEvent(QKeyEvent* event)
+{
+
+}
+
+void BitInspector::paintEvent(QPaintEvent* event)
+{
+	if (begin == end) {
+		return;
+	}
+	int value = (parentWidget()->size().width() - FieldStart - EmptySpaceRight) / begin->bitVec.size();
+
+	if (value > 1) {
+		sizePerBit = value;
+	}
+	else {
+		sizePerBit = 1;
+	}
+	//PaintList
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
+	painter.setFont(QFont("Arial", 8));
+	painter.setPen(QColor(0, 0, 0));
+	QRect rect(event->rect());
+	rect.moveTop(rect.top() - parentWidget()->size().height());
+	int minimumY = rect.top() - parentWidget()->size().height();
+	int maximumY = rect.bottom() + parentWidget()->size().height();
+
+	QPen blackPen(QColor(0, 0, 0));
+	QPen whitePen(QColor(255, 255, 255));
+	int iteration = 0;
+	int drawSize = (sizePerBit > 1)? sizePerBit - 1: 1;
+	if (begin != end) {
+		painter.fillRect(QRect(FieldStart -1 , 0, begin->bitVec.size() * sizePerBit, std::distance(begin, end) * ItemWidth), Qt::lightGray);
+		int width = FieldStart + begin->bitVec.size() * sizePerBit;
+		for (auto iter = begin; iter != end; iter++) {
+			int startY = (iteration++) * ItemWidth + HeaderSpace;
+			if (startY <= minimumY) continue;
+			if (startY >= maximumY) break;
+			QRect textRect(0, startY, 40, ItemWidth);
+			painter.drawText(textRect, Qt::AlignCenter, QString::number(iter->iteration));
+			textRect.moveLeft(40);
+			painter.drawText(textRect, Qt::AlignCenter, QString::number(iter->particleNumber));
+			textRect.moveLeft(80);
+			textRect.setWidth(90);
+			painter.drawText(textRect, Qt::AlignCenter, QString::number(iter->objectiveFunction, 'f', 1));
+			//painter.setPen(blackPen);
+			for (int j = 0; j < iter->bitVec.size(); j++) {
+				painter.fillRect(FieldStart + j * sizePerBit, startY, drawSize, ItemWidth, (iter->bitVec[j]) ? blackPen.color() : whitePen.color());
+			}
+			painter.fillRect(FieldStart, startY, width - FieldStart, 1 ,QColor(140,140,140));
+		}
+	}
+}
diff --git a/metavis/BitInspector.h b/metavis/BitInspector.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4f993711c22a2bb8278a9c1e3daea25298585a9
--- /dev/null
+++ b/metavis/BitInspector.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <QWidget>
+#include "RunData.h"
+#include <QString>
+#include <vector>
+
+
+
+class BitInspector : public QWidget
+{
+	Q_OBJECT
+
+public:
+	std::vector<SolutionPointData>::iterator begin;
+	std::vector<SolutionPointData>::iterator end;
+	int sizePerBit = 3;
+
+	QPixmap map;
+	BitInspector(QWidget *parent);
+	~BitInspector();
+	void updateData(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end);
+	void clear();
+private:
+	void keyPressEvent(QKeyEvent* event) override;
+	void paintEvent(QPaintEvent* event) override;
+};
diff --git a/metavis/BitInspectorPanel.cpp b/metavis/BitInspectorPanel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cec2144576f853780fd1ce331b20517d80a30ebd
--- /dev/null
+++ b/metavis/BitInspectorPanel.cpp
@@ -0,0 +1,78 @@
+#include "pch.h"
+#include "BitInspectorPanel.h"
+#include <QScrollArea>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QSettings>
+#include <QApplication>
+#include <QDesktopWidget>
+
+BitInspectorPanel::BitInspectorPanel(QWidget *parent)
+	: QWidget(parent), inspector(new BitInspector(this))
+{
+	QScrollArea* scrollArea = new QScrollArea(this);
+	scrollArea->setWidget(inspector);
+	scrollArea->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
+	scrollArea->setWidgetResizable(true);
+	QVBoxLayout* layout = new QVBoxLayout(this);
+	layout->setContentsMargins(0, 0, 0, 0);
+	layout->setSpacing(0);
+	topPanel = new QHBoxLayout();
+	topPanel->setContentsMargins(0, 0, 0, 0);
+	topPanel->setSpacing(0);
+	topPanel->addWidget(new QLabel("Iteration"));
+	topPanel->addSpacing(2);
+	topPanel->addWidget(new QLabel("Number"));
+	topPanel->addSpacing(2);
+	topPanel->addWidget(new QLabel("ObjectiveFunction"));
+	topPanel->addSpacing(2);
+	topPanel->addWidget(new QLabel("Binary"));
+	topPanel->addStretch();
+	runNameLabel = new QLabel("");
+	topPanel->addWidget(runNameLabel);
+
+	layout->addLayout(topPanel);
+	layout->addWidget(scrollArea);
+	popupWidget->setInformation("<h3><u>Inspector</u></h3> Shows all solution of a round. Each solution gets displayed in a row.<br><br><b>Iteration:</b> Show the iteration the solution is generated.<br><b>Number:</b> Show which individual in the popullation is represent.<br><b>Objective Function:</b> Describes how well the solution is, it depends on the problem if a low or high value is desired.<br><b>Binary:</b> Shows the bitstring of the solution. White rectangle represents the bit is <i>false<i> and black <i>true<i>.");
+	informationButton->setMinimumSize(20, 20);
+	informationButton->setMaximumSize(20, 20);
+	informationButton->setIcon(QIcon(":/metavis/Resources/information_icon.svg"));
+	informationButton->setHoveredIcon(QIcon(":/metavis/Resources/information_icon_hovered.svg"));
+	informationButton->setAttribute(Qt::WA_TranslucentBackground);
+	informationButton->setStyleSheet(informationButton->styleSheet() + "border: none;");
+	informationButton->setToolTip("Information");
+	connect(informationButton, &QPushButton::released, this, &BitInspectorPanel::showInformation);
+	topPanel->addWidget(informationButton);
+}
+
+BitInspectorPanel::~BitInspectorPanel()
+{
+}
+
+void BitInspectorPanel::setRunName(std::string& string)
+{
+	runNameLabel->setText("\"" + QString::fromStdString(string) + "\"");
+}
+
+void BitInspectorPanel::removeRun()
+{
+	inspector->clear();
+	runNameLabel->setText("");
+}
+
+void BitInspectorPanel::showInformation()
+{
+	QPoint position = QCursor::pos();
+	popupWidget->width();
+	QRect screen = QApplication::desktop()->screenGeometry();
+	if (position.x() + popupWidget->width() > screen.width()) {
+		popupWidget->move(screen.width() - popupWidget->width(), position.y());
+	}
+	else {
+		popupWidget->move(position.x(), position.y());
+
+	}
+	popupWidget->show();
+
+}
\ No newline at end of file
diff --git a/metavis/BitInspectorPanel.h b/metavis/BitInspectorPanel.h
new file mode 100644
index 0000000000000000000000000000000000000000..d311e303968b592d56db682a166fd5d8b468b4dd
--- /dev/null
+++ b/metavis/BitInspectorPanel.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QWidget>
+#include "BitInspector.h"
+#include <string>
+#include "HoverButton.h"
+#include "InformationPopUp.h"
+class BitInspectorPanel : public QWidget
+{
+	Q_OBJECT
+
+public:
+	BitInspectorPanel(QWidget *parent);
+	~BitInspectorPanel();
+	BitInspector* inspector;
+	QLabel* runNameLabel;
+	void setRunName(std::string& string);
+	void removeRun();
+	void showInformation();
+protected:
+	HoverButton* informationButton = new HoverButton();
+	InformationPopUp* popupWidget = new InformationPopUp(nullptr);
+	QHBoxLayout* topPanel;
+};
diff --git a/metavis/Bitfield.cpp b/metavis/Bitfield.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e152e08962e062f5824870ad6485524dd8308b0c
--- /dev/null
+++ b/metavis/Bitfield.cpp
@@ -0,0 +1,143 @@
+#include "pch.h"
+#include "Bitfield.h"
+#include <QSlider>
+#include <QTimer>
+#include <QCursor>
+
+
+Bitfield::Bitfield(QWidget *parent)
+	: SearchSpacePlott(parent)
+{
+	setAxisLegend("Position", "#SetBits");
+}
+
+Bitfield::~Bitfield()
+{
+	
+}
+
+void Bitfield::frameGraphInView()
+{
+	setVisibleWindow(0, 1, 0, maxAmountOfSetBits);
+	window.ZoomOut(0.05);
+	update();
+}
+
+
+
+void Bitfield::drawData(QPainter& painter)
+{
+	painter.setPen(Qt::lightGray);
+	painter.setBrush(Qt::Dense4Pattern);
+	painter.drawRect(this->getDisplayRect());
+	painter.setPen(Qt::black);
+	painter.setBrush(Qt::NoBrush);
+	painter.fillRect(QRectF(transformGraphToView(QPointF(0, maxAmountOfSetBits)), transformGraphToView(QPointF(1, 0))), Qt::white);
+	painter.drawRect(QRectF(transformGraphToView(QPointF(0, maxAmountOfSetBits)), transformGraphToView(QPointF(1, 0))));
+
+	//Draw Dots
+	QPen linePen;
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+
+	for (const GraphPlottSeries& graphSeries : seriesVec) {
+		if (!graphSeries.data) {
+			qDebug() << "Pointer to nothing pls help";
+			continue;
+		}
+		if (graphSeries.data->empty() || graphSeries.hide) continue;
+		linePen.setWidth(2);
+		linePen.setColor(Qt::transparent);
+		painter.setPen(linePen);
+		for (auto data : *graphSeries.data) {
+			if (data.orginalPoint->iteration < minIter) {
+				continue;
+			}
+			if (data.orginalPoint->iteration > maxIter) {
+				break;
+			}
+			QColor color = data.color;
+			color.setAlphaF(this->transparentAlphaValue);
+			linePen.setColor(Qt::transparent);
+			painter.setPen(linePen);
+			painter.setBrush(color);
+			if (window.inBound(data.toQPointF())) {
+				painter.drawEllipse(transformGraphToView(data.toQPointF(), stregth_factorX, stregth_factorY, translation), circleSize, circleSize);
+			}
+		}
+		painter.setBrush(Qt::BrushStyle::NoBrush);
+	}
+}
+
+
+
+
+
+void Bitfield::searchForPointUnderCursor()
+{
+	//check if mouse stayed still
+	QPoint globalPosition = QCursor::pos();
+	QPointF pos = this->mapFromGlobal(globalPosition);
+
+	if (pos != lastPosition){
+		return;
+	}
+	if (seriesVec.empty() || seriesVec[0].data->empty()) {
+		return;
+	}
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+
+	const GraphDataPoint* min = &seriesVec[0].data->at(0);
+	double minSqaredDistance = sqaredDistance(transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
+	std::vector<GraphPlottSeries>::iterator actualBestSeries = seriesVec.begin();
+	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
+		for (const GraphDataPoint& point : *seriesIter->data) {
+			if (point.orginalPoint->iteration < minIter) {
+				continue;
+			}
+			if (point.orginalPoint->iteration > maxIter) {
+				break;
+			}
+			double distance = sqaredDistance(transformGraphToView(point.toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
+			if (distance < minSqaredDistance) {
+				minSqaredDistance = distance;
+				min = &point;
+				actualBestSeries = seriesIter;
+			}
+		}
+	}
+	//if curser is radius + 3pixel away
+	if (minSqaredDistance <= circleSize * circleSize + 9) {
+		QPointF pointInWidget = transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation);
+		QToolTip::showText(this->mapToGlobal(QPoint(pointInWidget.x(), pointInWidget.y())) - QPoint(0, 35), QString::fromStdString(min->orginalPoint->bitstringToStdString()));
+	}
+}
+
+void Bitfield::addPointsInWindowToScratchPad(VisibleWindow& window)
+{
+	if (!pad) {
+		qDebug() << "NoPad";
+		return;
+	}
+	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
+		if (seriesIter->hide) continue;
+		for (const GraphDataPoint& point : *seriesIter->data) {
+			if (point.orginalPoint->iteration < minIter) {
+				continue;
+			}
+			if (point.orginalPoint->iteration > maxIter) {
+				break;
+			}
+			if (window.inBound(point.toQPointF()) && point.existLink()) {
+				pad->addPoint(*point.orginalPoint);
+			}
+		}
+	}
+}
+
+
diff --git a/metavis/Bitfield.h b/metavis/Bitfield.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2c957f25f04bd64fd0de9788fb5df3bf0f73f0a
--- /dev/null
+++ b/metavis/Bitfield.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "SearchSpacePlott.h"
+
+class Bitfield : public SearchSpacePlott
+{
+	Q_OBJECT
+
+public:
+	unsigned int maxAmountOfSetBits = 5;
+	Bitfield(QWidget *parent);
+	~Bitfield();
+	void frameGraphInView() override;
+protected:
+	void drawData(QPainter& painter) override;
+	void searchForPointUnderCursor() override;
+	void addPointsInWindowToScratchPad(VisibleWindow& window) override;
+private:
+	
+
+};
diff --git a/metavis/BitfieldControlPanel.cpp b/metavis/BitfieldControlPanel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b704d5543c59c50a56f7ed566397a718341c048c
--- /dev/null
+++ b/metavis/BitfieldControlPanel.cpp
@@ -0,0 +1,88 @@
+#include "pch.h"
+#include "BitfieldControlPanel.h"
+#include <QSettings>
+
+BitfieldControlPanel::BitfieldControlPanel(QWidget *parent)
+	: QWidget(parent)
+{
+	QVBoxLayout* layout = new QVBoxLayout(this);
+	layout->setContentsMargins(0, 0, 0, 0);
+
+	layout->addWidget(field);
+	field->setAxisLegend("Position", "#SetBits");
+	showOptionsButton = new QPushButton("Hide Options");
+	layout->addWidget(showOptionsButton);
+	connect(showOptionsButton, &QPushButton::pressed, this, &BitfieldControlPanel::toggleOptions);
+	layout->addWidget(slider);
+	slider->setTitle("Iteration:");
+	
+	//Connect slider with field
+	connect(slider, &RangeSlider::maxChanged, field, &Bitfield::setMaximumIterationToDispaly);
+	connect(slider, &RangeSlider::minChanged, field, &Bitfield::setMinimumIterationToDispaly);
+	connect(gradient, &ColorGradient::gradientChanged, this, &BitfieldControlPanel::updateDotColorsFromDisplayedRun);
+
+	layout->addWidget(gradient);
+	field->frameGraphInView();
+
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("BitField");
+	if (settings.value("hideOptions", true).toBool()) {
+		toggleOptions();
+	}
+	settings.endGroup();
+}
+
+BitfieldControlPanel::~BitfieldControlPanel()
+{
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("BitField");
+	settings.setValue("hideOptions",this->isOptionHidden);
+	settings.endGroup();
+}
+
+void BitfieldControlPanel::updateDotColorsFromDisplayedRun()
+{
+	if (!displayedRun || displayedRun->dotsForBitField.empty() || !displayedRun->dotsForBitField.back().existLink()) {
+		return;
+	}
+	for (GraphDataPoint& dot : displayedRun->dotsForBitField) {
+		dot.color = gradient->getColorFromValue(dot.orginalPoint->objectiveFunction);
+	}
+	field->update();
+}
+
+void BitfieldControlPanel::displaySingleRun(SingleRun* run)
+{
+	displayedRun = run;
+	updateDotColorsFromDisplayedRun();
+	field->removeAll();
+	field->addSeries(&run->dotsForBitField, run->name, "", QColor(Qt::black), GraphPlottSeries::SeriesType::Dot);
+	if (!run->dotsForBitField.empty() && run->dotsForBitField.back().existLink()) {
+		field->maxAmountOfSetBits = run->dotsForBitField.back().orginalPoint->bitVec.size();
+		if (run->dotsForBitField.front().orginalPoint->iteration < slider->getMinRange()) {
+			slider->setMinRange(run->dotsForBitField.front().orginalPoint->iteration);
+		}
+		if (run->dotsForBitField.back().orginalPoint->iteration > slider->getMaxRange()) {
+			slider->setMaxRange(run->dotsForBitField.back().orginalPoint->iteration);
+		}
+		
+	}
+	
+	field->frameGraphInView();
+}
+
+void BitfieldControlPanel::clearRun()
+{
+	displayedRun = nullptr;
+	field->removeAll();
+}
+
+void BitfieldControlPanel::toggleOptions()
+{
+	this->isOptionHidden = !this->isOptionHidden;
+	showOptionsButton->setText(this->isOptionHidden ? "More Options" : "Hide Options");
+	this->slider->setHidden(this->isOptionHidden);
+	this->gradient->setHidden(this->isOptionHidden);
+}
diff --git a/metavis/BitfieldControlPanel.h b/metavis/BitfieldControlPanel.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdc8bf5b355cb3c158eb3f187feb80b3c49b6816
--- /dev/null
+++ b/metavis/BitfieldControlPanel.h
@@ -0,0 +1,29 @@
+#pragma once
+#include <QWidget>
+#include <QPushButton>
+#include "Bitfield.h"
+#include "RangeSlider.h"
+#include "ColorGradient.h"
+#include "RunData.h"
+
+
+class BitfieldControlPanel : public QWidget
+{
+	Q_OBJECT
+
+public:
+	BitfieldControlPanel(QWidget *parent);
+	~BitfieldControlPanel();
+	void updateDotColorsFromDisplayedRun();
+	void displaySingleRun(SingleRun* run);
+	void clearRun();
+	Bitfield* field = new Bitfield(this);
+protected:
+	RangeSlider* slider = new RangeSlider(this);
+	ColorGradient* gradient = new ColorGradient(this);
+	bool isOptionHidden = false;
+	void toggleOptions();
+private:
+	QPushButton* showOptionsButton;
+	SingleRun* displayedRun = nullptr;
+};
diff --git a/metavis/ColorButton.cpp b/metavis/ColorButton.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1f80d2ccdf4ada2441035a587dead76a89891eb7
--- /dev/null
+++ b/metavis/ColorButton.cpp
@@ -0,0 +1,57 @@
+#include "pch.h"
+#include "ColorButton.h"
+#include <QColorDialog>
+#include <QPixmap>
+
+ColorButton::ColorButton(QWidget *parent, QColor color)
+	: QPushButton(parent), color(color)
+{
+	//setText("Set Color");
+	
+	//setContentsMargins(0, 0, 0, 0);
+	//this->setStyleSheet(this->styleSheet() + "border: 1px solid white; background-color: red");
+	updateVisual();
+	setToolTip("Set Color");
+	connect(this, &QPushButton::pressed, this, &ColorButton::openColorMenu);
+}
+
+ColorButton::~ColorButton()
+{
+}
+
+QColor ColorButton::getColor()
+{
+	return color;
+}
+
+void ColorButton::updateVisual()
+{
+	QPixmap pixmap(100, 14);
+	pixmap.fill(color);
+	QIcon redIcon(pixmap);
+	setIcon(QIcon(redIcon));
+	setIconSize(QSize(100, 14));
+}
+
+void ColorButton::resizeEvent(QResizeEvent* event)
+{
+}
+
+void ColorButton::openColorMenu()
+{
+	QColor color = QColorDialog::getColor(this->color, this, "Set Color", QColorDialog::ShowAlphaChannel);
+	if (!color.isValid()) return;
+	this->color = color;
+	updateVisual();
+	emit colorChanged(this->color);
+}
+
+void ColorButton::setColor(QColor color)
+{
+	this->color = color;
+	updateVisual();
+}
+
+
+
+
diff --git a/metavis/ColorButton.h b/metavis/ColorButton.h
new file mode 100644
index 0000000000000000000000000000000000000000..f618019dda50a1631034f2252f91b7b9c270601d
--- /dev/null
+++ b/metavis/ColorButton.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <QPushButton>
+#include <QColor>
+class ColorButton : public QPushButton
+{
+	Q_OBJECT
+
+
+public:
+	ColorButton(QWidget *parent, QColor color);
+	~ColorButton();
+	QColor getColor();
+private:
+	QColor color;
+	void updateVisual();
+	void resizeEvent(QResizeEvent* event) override;
+	void openColorMenu();
+public slots:
+	void setColor(QColor color);
+signals:
+	void colorChanged(QColor color);
+};
diff --git a/metavis/ColorGradient.cpp b/metavis/ColorGradient.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d7dd6acc8953b6dc1b266f5110ea8093a293a4b
--- /dev/null
+++ b/metavis/ColorGradient.cpp
@@ -0,0 +1,424 @@
+#include "pch.h"
+#include <QLayout>
+#include <QDoubleValidator>
+#include "ColorGradient.h"
+#include "util.h"
+#define LeftRightGap 10
+#define ColorExampleStart 30
+#define ColorExmapleHeight 80
+#define SliderBeginHeight 83
+#define SliderBody 14
+#define SliderPeak 6
+#define SelectedPreview 20
+#define SelectedHeight 115
+ColorGradient::ColorGradient(QWidget *parent)
+	: QWidget(parent)
+{
+	interpolationCombobox = new QComboBox(this);
+	interpolationCombobox->addItem("RGB");
+	interpolationCombobox->addItem("HLS");
+	connect(interpolationCombobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+		this, [this](int index) {this->setInterpolationMode((ColorGradient::ColorInterpolationMode)index); });
+	modeCombobox = new QComboBox(this);
+	modeCombobox->addItem("Interpolate");
+	modeCombobox->addItem("Discrete");
+	connect(modeCombobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+		this, [this](int index) {this->setMode((ColorGradient::ColorMode)index);});
+	colorButton = new ColorButton(this, QColor(0,0,0));
+	
+	connect(colorButton, &ColorButton::colorChanged, this, [this](QColor color) {
+		if (selected != nullptr) setColorPointColor(*selected, color);
+		});
+	QVBoxLayout* vBoxLayout = new QVBoxLayout(this);
+	vBoxLayout->setContentsMargins(0,0,0,0);
+	QGridLayout* layoutTop = new QGridLayout();
+	vBoxLayout->addLayout(layoutTop);
+	layoutTop->setContentsMargins(0, 0, 0, 0);
+	layoutTop->setAlignment(Qt::AlignTop);
+	spacerH = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
+	layoutTop->addWidget(new QLabel("ObjectiveFunction-Gradient:", this), 0, 0);
+	layoutTop->addItem(spacerH, 0, 1);
+
+	layoutTop->addWidget(modeCombobox, 0, 6);
+	layoutTop->addWidget(interpolationCombobox, 0, 7);
+	QGridLayout* layoutBottom = new QGridLayout();
+	vBoxLayout->addLayout(layoutBottom);
+	layoutBottom->setContentsMargins(0, 0, 0, 0);
+	layoutBottom->setAlignment(Qt::AlignBottom);
+	layoutBottom->addItem(new QSpacerItem(10, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 0);
+	colorLabel = new QLabel("Color:");
+	layoutBottom->addWidget(colorLabel, 0, 1);
+	layoutBottom->addWidget(colorButton, 0, 2);
+	alphaLabel = new QLabel("Alpha:");
+	layoutBottom->addWidget(alphaLabel, 0, 3);
+	
+	
+
+	layoutTop->addWidget(new QLabel("ValueRange:"), 0, 2);
+	minEdit = new  QLineEdit();
+	minEdit->setMaximumWidth(80);
+	layoutTop->addWidget(minEdit, 0, 3);
+	layoutTop->addWidget(new QLabel(":"), 0, 4);
+	maxEdit = new  QLineEdit();
+	maxEdit->setMaximumWidth(80);
+	layoutTop->addWidget(maxEdit, 0, 5);
+	valueLabel = new QLabel("Value:");
+	layoutBottom->addWidget(valueLabel, 0,5);
+
+
+	QRegExp rxMinMax("[+-]?[0-9]*(\\.[0-9]{0,6})?");
+	QRegExpValidator* validatorMinMax = new QRegExpValidator(rxMinMax, 0);
+	minEdit->setValidator(validatorMinMax);
+	maxEdit->setValidator(validatorMinMax);
+	minEdit->setText(QString::number(minValue));
+	maxEdit->setText(QString::number(maxValue));
+	connect(minEdit, &QLineEdit::editingFinished, this, &ColorGradient::minEditChangeEvent);	
+	connect(maxEdit, &QLineEdit::editingFinished, this, &ColorGradient::maxEditChangeEvent);
+
+	alphaLineEdit = new QLineEdit(this);
+	alphaLineEdit->setMaximumWidth(80);
+	layoutBottom->addWidget(alphaLineEdit, 0, 4);
+
+	valueEdit = new  QLineEdit();
+	valueEdit->setMaximumWidth(80);
+	valueEdit->setValidator(validatorMinMax);
+	connect(valueEdit, &QLineEdit::editingFinished, this, &ColorGradient::setValueOfSelected);
+	layoutBottom->addWidget(valueEdit, 0, 6);
+
+	QRegExp rx("0(\\.[0-9]{0,6})?|1(\\.0*)?");
+	QRegExpValidator* v = new QRegExpValidator(rx, 0);
+	alphaLineEdit->setValidator(v);
+	connect(alphaLineEdit, &QLineEdit::editingFinished, this, &ColorGradient::setAlphaOfSelected);
+
+
+	layoutBottom->addItem(new QSpacerItem(10, 20, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 7);
+
+	//this->setMinimumHeight(150);
+	this->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+	
+	this->setMinimumHeight(150);
+	//Dummy Data
+	//TODO(ColorGradient #1) get gradient from last time or save project
+	pointList.push_back(ColorPoint(0.0, QColor(0, 100, 200)));
+	pointList.push_back(ColorPoint(0.5, QColor(0, 100, 50)));
+	pointList.push_back(ColorPoint(1.0, QColor(200, 10, 10)));
+	//select first
+	selectColorPoint(&pointList.front());
+}
+
+ColorGradient::~ColorGradient()
+{
+
+}
+
+QColor ColorGradient::getColorFromAlpha(double alpha)
+{
+	alpha = std::clamp(alpha, 0.0, 1.0);
+	switch(mode) {
+	case ColorMode::Discrete: {
+		QColor result(255,255,255);
+		for (ColorPoint& point : pointList) {
+			if (point.alpha >= alpha) {
+				result = point.color;
+				break;
+			}
+		}
+		return result;
+	}
+	case ColorMode::Interpolate: {
+		ColorPoint before(0.0, QColor(255, 255, 255));
+		ColorPoint last(1.0, QColor(255, 255, 255));
+		ColorPoint* first = &before;
+		ColorPoint* second = &last;
+		for (ColorPoint& point : pointList) {
+			if (point.alpha >= alpha) {
+				second = &point;
+				break;
+			}
+			first = &point;
+		}
+		double alphaBetween = util::inverseLinearInterpolation(first->alpha, second->alpha, alpha);
+		switch (interpolationMode) {
+		case ColorInterpolationMode::HSL:
+			return util::interpolateHSL(first->color, second->color, alphaBetween);
+		case ColorInterpolationMode::RGB:
+		default:
+			return util::interpolateRGB(first->color, second->color, alphaBetween);
+		}
+		
+	}
+	default: {
+		return QColor(0, 0, 0);
+	}
+	}
+	
+}
+
+QColor ColorGradient::getColorFromValue(double value)
+{
+	double alpha = util::inverseLinearInterpolation(minValue, maxValue, value);
+	return getColorFromAlpha(alpha);
+}
+
+void ColorGradient::addColorPoint(double alpha)
+{
+	auto iter = pointList.begin();
+	for (; iter != pointList.end(); iter++) {
+		if (iter->alpha >= alpha) {
+			break;
+		}
+	}
+	selectColorPoint(&*pointList.insert(iter, ColorPoint(alpha, getColorFromAlpha(alpha))));
+	emit gradientChanged();
+}
+
+void ColorGradient::removeColorPoint(ColorPoint& pointToRemove)
+{
+	pointList.erase(std::remove_if(pointList.begin(), pointList.end(),
+			[&pointToRemove](ColorPoint& point) {return &point == &pointToRemove; }));
+	//colorButton->setVisible(false);
+	selected = nullptr;
+	hideSelectionEdit(true);
+	emit gradientChanged();
+}
+
+void ColorGradient::setColorPointAlpha(ColorPoint& point, double alpha)
+{
+	alpha = std::clamp(alpha, 0.0, 1.0);
+	if (alpha == point.alpha) return;
+	point.alpha = alpha;
+	pointList.sort([](ColorPoint& a, ColorPoint& b) {
+		return a.alpha < b.alpha;
+		});
+	if (&point == selected) {
+		alphaLineEdit->setText(QString::number(alpha));
+		valueEdit->setText(QString::number(util::linearInterpolate(minValue, maxValue, alpha)));
+	}
+	emit gradientChanged();
+	update();
+}
+
+void ColorGradient::setColorPointColor(ColorPoint& point, QColor newColor)
+{
+	if (newColor == point.color) return;
+	point.color = newColor;
+	emit gradientChanged();
+	update();
+}
+
+void ColorGradient::setMode(ColorMode mode)
+{
+	this->mode = mode;
+	update();
+	emit gradientChanged();
+	interpolationCombobox->setEnabled(mode != ColorGradient::ColorMode::Discrete);
+}
+
+void ColorGradient::setInterpolationMode(ColorInterpolationMode mode)
+{
+	this->interpolationMode = mode;
+	update();
+	emit gradientChanged();
+}
+
+void ColorGradient::setMinValue(double value)
+{
+	if (value > maxValue) {
+		minValue = maxValue;
+		maxValue = value;
+		minEdit->setText(QString::number(minValue));
+		maxEdit->setText(QString::number(maxValue));
+	}
+	else {
+		minValue = value;
+		minEdit->setText(QString::number(minValue));
+	}
+	if (selected != nullptr) {
+		valueEdit->setText(QString::number(util::linearInterpolate(minValue, maxValue, selected->alpha)));
+	}
+	emit gradientChanged();
+}
+
+void ColorGradient::setMaxValue(double value)
+{
+	if (value < minValue) {
+		maxValue = minValue;
+		minValue = value;
+		minEdit->setText(QString::number(minValue));
+		maxEdit->setText(QString::number(maxValue));
+	}
+	else {
+		maxValue = value;
+		maxEdit->setText(QString::number(maxValue));
+	}
+	if (selected != nullptr) {
+		valueEdit->setText(QString::number(util::linearInterpolate(minValue, maxValue, selected->alpha)));
+	}
+	emit gradientChanged();
+}
+
+void ColorGradient::hideSelectionEdit(bool value)
+{
+	colorButton->setHidden(value);
+	alphaLineEdit->setHidden(value);
+	alphaLabel->setHidden(value);
+	colorLabel->setHidden(value);
+	valueEdit->setHidden(value);
+	valueLabel->setHidden(value);
+}
+
+void ColorGradient::setAlphaOfSelected()
+{
+	if (selected == nullptr) return;
+	bool success = false;
+	double alpha = alphaLineEdit->text().toDouble(&success);
+	if (success) {
+		setColorPointAlpha(*selected, alpha);
+	}
+
+}
+
+void ColorGradient::setValueOfSelected()
+{
+	if (selected == nullptr) return;
+	bool success = false;
+	double value = valueEdit->text().toDouble(&success);
+	
+	if (success) {
+		if (value < minValue) {
+			value = minValue;
+		}
+		else if (value > maxValue) {
+			value = maxValue;
+		}
+		setColorPointAlpha(*selected, util::inverseLinearInterpolation(minValue, maxValue, value));
+	}
+}
+
+void ColorGradient::selectColorPoint(ColorPoint* point)
+{
+	selected = point;
+	colorButton->setColor(selected->color);
+	alphaLineEdit->setText(QString::number(selected->alpha));
+	valueEdit->setText(QString::number(util::linearInterpolate(minValue, maxValue, selected->alpha)));
+	hideSelectionEdit(false);
+}
+
+void ColorGradient::paintEvent(QPaintEvent* event)
+{
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
+	QRect colorExampleRect(QPoint(rect().left() + LeftRightGap, ColorExampleStart), QPoint(rect().right() - LeftRightGap, ColorExmapleHeight));
+	painter.drawRect(colorExampleRect);
+	//drawSliders
+	QPen sliderPen;
+	sliderPen.setWidth(2);
+	painter.setPen(Qt::NoPen);
+	
+	
+	for (ColorPoint& point : pointList) {
+		QPainterPath slider;
+		if (&point == selected) {
+			sliderPen.setColor(QColor(0, 0, 0));
+			painter.setPen(sliderPen);
+		}
+		painter.setBrush(point.color);
+		int middlePosition = util::linearInterpolate(colorExampleRect.left(), colorExampleRect.right(), point.alpha);
+		slider.moveTo(middlePosition, SliderBeginHeight);
+		slider.lineTo(middlePosition - SliderPeak, SliderBeginHeight + SliderPeak);
+		slider.lineTo(middlePosition - SliderPeak, SliderBeginHeight + SliderPeak + SliderBody);
+		slider.lineTo(middlePosition + SliderPeak, SliderBeginHeight + SliderPeak + SliderBody);
+		slider.lineTo(middlePosition + SliderPeak, SliderBeginHeight + SliderPeak);
+		slider.closeSubpath();
+		painter.drawPath(slider);
+		if (&point == selected) {
+			painter.setPen(Qt::NoPen);
+		}
+	}
+	for (int pixelX = colorExampleRect.left() + 1; pixelX < colorExampleRect.right()+1; pixelX++) {
+		double alpha = util::inverseLinearInterpolation(colorExampleRect.left(), colorExampleRect.right()+1, pixelX);
+		QColor color = getColorFromAlpha(alpha);
+		painter.setPen(color);
+		painter.drawLine(pixelX, colorExampleRect.top() + 1, pixelX, colorExampleRect.bottom());
+	}
+	
+
+
+
+
+}
+
+void ColorGradient::mousePressEvent(QMouseEvent* event)
+{
+	if (childAt(event->pos()) != nullptr) {
+		return;
+	}
+	QPoint mousePos = event->pos();
+	QRect area(QPoint(rect().left() + LeftRightGap, ColorExmapleHeight), QPoint(rect().right() - LeftRightGap, ColorExmapleHeight+SliderBody+SliderPeak));
+	QRect responisveArea(QPoint(area.left() - SliderPeak * 2, area.top()), QPoint(area.right() + SliderPeak * 2, area.bottom()));
+	if (responisveArea.contains(mousePos)) {
+
+		// Check for existing color point
+		// Select with left mouse Button
+		// Remove Point with right mouse Button
+		for (ColorPoint& point : pointList) {
+			double posX = util::linearInterpolate(area.left(), area.right() + 1, point.alpha);
+			if (posX - SliderPeak * 2 < mousePos.x() && mousePos.x() < posX + SliderPeak * 2) {
+				if (event->buttons() & Qt::LeftButton) {
+					selectColorPoint(&point);
+				}
+				else if(event->buttons() & Qt::RightButton){
+					removeColorPoint(point);
+					
+				}
+				update();
+				return;
+			}
+		}
+		
+
+		// Insert new Color Point
+		if (event->buttons() & Qt::LeftButton) {
+			double alpha = util::inverseLinearInterpolation(area.left(), area.right() + 1, mousePos.x());
+			addColorPoint(alpha);
+
+			update();
+		}
+	}
+}
+
+void ColorGradient::mouseMoveEvent(QMouseEvent* event)
+{
+	if (selected == nullptr) return;
+	if (childAt(event->pos()) != nullptr) {
+		return;
+	}
+	//TODO(Bug #1) when mouse press button mouse move gets emitted and move the selected
+	//currently a workarround to not move the selected colorpoint when selecting a button
+	//if (event->pos().y() < ColorExmapleHeight) return;
+
+	QPoint mousePos = event->pos();
+	QRect area(QPoint(rect().left() + LeftRightGap, ColorExmapleHeight), QPoint(rect().right() - LeftRightGap, ColorExmapleHeight + SliderBody + SliderPeak));
+	double alpha = util::inverseLinearInterpolation(area.left(), area.right() + 1, mousePos.x());
+	this->setColorPointAlpha(*selected, alpha);
+
+
+}
+
+void ColorGradient::minEditChangeEvent()
+{
+	bool success = false;
+	double value = minEdit->text().toDouble(&success);
+	if (success) {
+		this->setMinValue(value);
+	}
+}
+
+void ColorGradient::maxEditChangeEvent()
+{
+	bool success = false;
+	double value = maxEdit->text().toDouble(&success);
+	if (success) {
+		this->setMaxValue(value);
+	}
+}
diff --git a/metavis/ColorGradient.h b/metavis/ColorGradient.h
new file mode 100644
index 0000000000000000000000000000000000000000..599fa1431a9cc36b526abde2fbc4107e1eaade70
--- /dev/null
+++ b/metavis/ColorGradient.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <QWidget>
+#include <QColor>
+#include <QComboBox>
+#include <list>
+#include <QLineEdit>
+#include "ColorButton.h"
+
+struct ColorPoint {
+	double alpha;
+	QColor color;
+	ColorPoint(double alpha, QColor color) : alpha(std::clamp(alpha, 0.0, 1.0)), color(color) {}
+};
+
+
+class ColorGradient : public QWidget
+{
+	Q_OBJECT
+
+public:
+	enum ColorInterpolationMode{ RGB, HSL};
+	enum ColorMode{ Interpolate, Discrete};
+	ColorGradient(QWidget *parent);
+	~ColorGradient();
+	QColor getColorFromAlpha(double alpha);
+	QColor getColorFromValue(double value);
+	void addColorPoint(double alpha);
+	void removeColorPoint(ColorPoint& point);
+	void setColorPointAlpha(ColorPoint& point, double newAlpha);
+	void setColorPointColor(ColorPoint& point, QColor newColor);
+	void setMode(ColorMode mode);
+	void setInterpolationMode(ColorInterpolationMode mode);
+	void setMinValue(double value);
+	void setMaxValue(double value);
+private:
+	double minValue = 0, maxValue = 100;
+	ColorMode mode = ColorMode::Interpolate;
+	ColorInterpolationMode interpolationMode = ColorInterpolationMode::RGB;
+	std::list<ColorPoint> pointList;
+	//UI
+	QLineEdit* minEdit;
+	QLineEdit* maxEdit;
+	ColorPoint* selected = nullptr;
+	QComboBox* interpolationCombobox = nullptr;
+	QComboBox* modeCombobox = nullptr;
+	QSpacerItem* spacerH = nullptr;
+	QLineEdit* alphaLineEdit = nullptr;
+	ColorButton* colorButton = nullptr;
+	QLineEdit* valueEdit;
+	QLabel* colorLabel;
+	QLabel* alphaLabel; 
+	QLabel* valueLabel;
+	void hideSelectionEdit(bool value);
+	void setAlphaOfSelected();
+	void setValueOfSelected();
+	void selectColorPoint(ColorPoint* point);
+	void paintEvent(QPaintEvent* event) override;
+	void mousePressEvent(QMouseEvent* event) override;
+	void mouseMoveEvent(QMouseEvent* event) override;
+
+	void minEditChangeEvent();
+	void maxEditChangeEvent();
+
+
+signals:
+	void gradientChanged();
+};
diff --git a/metavis/Concurrent.cpp b/metavis/Concurrent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15d10f9021502020261caa5bac63e0505211424e
--- /dev/null
+++ b/metavis/Concurrent.cpp
@@ -0,0 +1,65 @@
+#include "pch.h"
+#include "Concurrent.h"
+#include <QDebug>
+
+Concurrent::Concurrent()
+{
+}
+
+Concurrent::~Concurrent()
+{
+	reset();
+}
+
+void Concurrent::start()
+{
+	qDebug() << "Hello Start";
+	if (thread != nullptr) reset();
+	qDebug() << "Start after reset";
+	thread = new std::thread(&Concurrent::run, this);
+	qDebug() << "Start end";
+}
+
+void Concurrent::pause()
+{
+	paused = !paused;
+	cv.notify_one();
+}
+
+void Concurrent::reset()
+{
+	qDebug() << "Hello Reset";
+	cancel = true;
+	paused = false;
+	cv.notify_one();
+	if (thread != nullptr) {
+		thread->join();
+		delete thread;
+		thread = nullptr;
+	}
+	cancel = false;
+}
+
+
+
+void Concurrent::run()
+{
+	for (;false;) {
+		checkPaused();
+		if (checkCancel()) { break; }
+	}
+}
+
+bool Concurrent::checkCancel()
+{
+	return cancel;
+}
+
+void Concurrent::checkPaused()
+{
+	std::unique_lock<std::mutex> lck(mutex);
+	while (paused) {
+		qDebug() << "while";
+		cv.wait(lck);
+	}
+}
diff --git a/metavis/Concurrent.h b/metavis/Concurrent.h
new file mode 100644
index 0000000000000000000000000000000000000000..c57c00ddb244010e2fea7e4625dc3f0989b06f65
--- /dev/null
+++ b/metavis/Concurrent.h
@@ -0,0 +1,28 @@
+#pragma once
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+class Concurrent
+{
+public:
+	Concurrent();
+	~Concurrent();
+	void start();
+	void pause();
+	void reset();
+
+protected:
+	bool checkCancel();
+	void checkPaused();
+
+
+private:
+	bool paused = false;
+	bool cancel = false;
+	std::thread* thread = nullptr;
+	std::mutex mutex;
+	std::condition_variable cv;
+	void virtual run();
+};
+
diff --git a/metavis/DockableGraphView.cpp b/metavis/DockableGraphView.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b65ba9943d8d804bf0ded9a50eb4096f0d01c94
--- /dev/null
+++ b/metavis/DockableGraphView.cpp
@@ -0,0 +1,39 @@
+#include "pch.h"
+#include "DockableGraphView.h"
+#include <QIcon>
+#include <QStyle>
+#include <QPushButton>
+#include <QLayout>
+#include <QGridLayout>
+
+
+DockableGraphView::DockableGraphView(QWidget *parent, QString title)
+	: QDockWidget(parent)
+{
+	view = new GraphView(this, Bound(0, 100, -1.0, 101.0));
+	view->setUseFixedBound(true);
+	view->setMinimumSize(200, 200);
+	//dialog = new GraphViewSettingDialog(view, title + " Settings", this);
+	QWidget* widget = new QWidget(this);
+	QGridLayout* layout = new QGridLayout;
+	QPushButton* button = new QPushButton();
+	button->setMinimumSize(20, 20);
+	button->setMaximumSize(20, 20);
+	button->setIcon(QIcon(":/metavis/Resources/settingIcon.svg"));
+	button->setAttribute(Qt::WA_TranslucentBackground);
+	button->setStyleSheet(button->styleSheet() + "border: none;");
+	button->setToolTip("Settings");
+	
+	//connect(button, &QPushButton::released, dialog, &GraphViewSettingDialog::openDialog);
+	layout->addWidget(view, 0, 0, 4, 4);
+	layout->addWidget(button,0, 3, 1, 1);
+	layout->setContentsMargins(0, 0, 0, 0);
+	widget->setLayout(layout);
+	this->setWindowTitle(title);
+	this->setAllowedAreas(Qt::AllDockWidgetAreas);
+	this->setWidget(widget);
+}
+
+DockableGraphView::~DockableGraphView()
+{
+}
diff --git a/metavis/DockableGraphView.h b/metavis/DockableGraphView.h
new file mode 100644
index 0000000000000000000000000000000000000000..7bcad2adc477de93df6b2c5c7ce04fc22d3bc635
--- /dev/null
+++ b/metavis/DockableGraphView.h
@@ -0,0 +1,16 @@
+#pragma once
+#include <QDockWidget>
+#include <QString>
+#include "GraphView.h"
+#include "GraphViewSettingDialog.h"
+class DockableGraphView : public QDockWidget
+{
+	Q_OBJECT
+public:
+	GraphView* view;
+	//GraphViewSettingDialog* dialog = nullptr;
+public:
+	DockableGraphView(QWidget *parent, QString title);
+	~DockableGraphView();
+public:
+};
diff --git a/metavis/GraphPlott.cpp b/metavis/GraphPlott.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..affe879a0894770c506e8b5819f96d710ecaff74
--- /dev/null
+++ b/metavis/GraphPlott.cpp
@@ -0,0 +1,358 @@
+#include "pch.h"
+#include "GraphPlott.h"
+#include <QDebug>
+#include <QPen>
+#include <QPushButton>
+#include <QLayout>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include "HoverButton.h"
+#include <QApplication>
+#include <QDesktopWidget>
+
+
+GraphPlott::GraphPlott(QWidget* parent, bool showSettingsButton, bool showInformationButton, bool showGridButton)
+	: Plott(parent)
+{
+	QVBoxLayout* layoutOuter = new QVBoxLayout(this);
+	buttonPanel = new QHBoxLayout();
+	dialog = new GraphViewSettingDialog(this, "Settings");
+	this->setMouseTracking(true);
+
+
+	buttonPanel->insertStretch(0);
+	displayLabel = new QLabel("");
+	buttonPanel->addWidget(displayLabel);
+
+	HoverButton* frameButton = new HoverButton();
+	frameButton->setMinimumSize(20, 20);
+	frameButton->setMaximumSize(20, 20);
+	frameButton->setIcon(QIcon(":/metavis/Resources/frame.svg"));
+	frameButton->setHoveredIcon(QIcon(":/metavis/Resources/frame_hovered.svg"));
+	frameButton->setAttribute(Qt::WA_TranslucentBackground);
+	frameButton->setStyleSheet(frameButton->styleSheet() + "border: none;");
+	frameButton->setToolTip("Frame");
+	buttonPanel->addWidget(frameButton);
+	connect(frameButton, &QPushButton::released, this, &GraphPlott::frameGraphInView);
+
+
+	if (showGridButton) {
+		HoverButton* gridButton = new HoverButton();
+		gridButton->setMinimumSize(20, 20);
+		gridButton->setMaximumSize(20, 20);
+		gridButton->setIcon(QIcon(":/metavis/Resources/gridIcon.svg"));
+		gridButton->setHoveredIcon(QIcon(":/metavis/Resources/gridIcon_hovered.svg"));
+		gridButton->setAttribute(Qt::WA_TranslucentBackground);
+		gridButton->setStyleSheet(gridButton->styleSheet() + "border: none;");
+		gridButton->setToolTip("Toggle Grid");
+		buttonPanel->addWidget(gridButton);
+		connect(gridButton, &QPushButton::released, this, [this]() {this->enableGrid = !this->enableGrid; update(); });
+	}
+	if (showInformationButton) {
+		
+		informationButton->setMinimumSize(20, 20);
+		informationButton->setMaximumSize(20, 20);
+		informationButton->setIcon(QIcon(":/metavis/Resources/information_icon.svg"));
+		informationButton->setHoveredIcon(QIcon(":/metavis/Resources/information_icon_hovered.svg"));
+		informationButton->setAttribute(Qt::WA_TranslucentBackground);
+		informationButton->setStyleSheet(informationButton->styleSheet() + "border: none;");
+		informationButton->setToolTip("Information");
+		connect(informationButton, &QPushButton::released, this, &GraphPlott::showInformation);
+		buttonPanel->addWidget(informationButton);
+	}
+	
+	if (showSettingsButton) {
+		HoverButton* settingsButton = new HoverButton();
+		settingsButton->setMinimumSize(20, 20);
+		settingsButton->setMaximumSize(20, 20);
+		settingsButton->setIcon(QIcon(":/metavis/Resources/settingIcon.svg"));
+		settingsButton->setHoveredIcon(QIcon(":/metavis/Resources/settingIcon_hovered.svg"));
+		settingsButton->setAttribute(Qt::WA_TranslucentBackground);
+		settingsButton->setStyleSheet(settingsButton->styleSheet() + "border: none;");
+		settingsButton->setToolTip("Settings");
+		buttonPanel->addWidget(settingsButton);
+		connect(settingsButton, &QPushButton::released, dialog, &GraphViewSettingDialog::openDialog);
+	}
+
+
+
+
+	buttonPanel->setSpacing(0);
+	buttonPanel->setContentsMargins(0, 0, 0, 0);
+	layoutOuter->addLayout(buttonPanel);
+	layoutOuter->insertStretch(1);
+	layoutOuter->setContentsMargins(0, 0, 0, 0);
+
+	//QMenu
+	selectMenu->addAction(displayAreaAction);
+	selectMenu->addAction(scratchpadAction);
+	displayAreaAction->setShortcut(QKeySequence(Qt::CTRL));
+	scratchpadAction->setShortcut(QKeySequence(Qt::ALT));
+	scratchpadAction->setEnabled(false);
+	//setUpTimer
+	timer->setSingleShot(true);
+	connect(timer, &QTimer::timeout, this, &GraphPlott::searchForPointUnderCursor);
+
+}
+
+GraphPlott::~GraphPlott()
+{
+}
+
+void GraphPlott::addSeries(std::vector<GraphDataPoint>* line, std::string runName, QString description, QColor color, GraphPlottSeries::SeriesType type)
+{
+	if (line->empty()) {
+		qDebug() << "Series is empty!";
+		return;
+	}
+	GraphPlottSeries lgs;
+	lgs.runName = runName;
+	lgs.description = description;
+	lgs.data = line;
+	lgs.type = type;
+	lgs.color = color;
+	//set min max x y
+	auto pairX = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.x < b.x; });
+	lgs.xMin = pairX.first->x;
+	lgs.xMax = pairX.second->x;
+	auto pairY = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.y < b.y; });
+	lgs.yMin = pairY.first->y;
+	lgs.yMax = pairY.second->y;
+	seriesVec.push_back(lgs);
+}
+
+
+
+
+void GraphPlott::removeRunData(RunData* run)
+{
+	//Remove all series with this rundata
+	auto iter = std::remove_if(seriesVec.begin(), seriesVec.end(), [run](GraphPlottSeries& series) {return (run->name == series.runName); });
+	seriesVec.erase(iter, seriesVec.end());
+	displayLabel->setText("");
+}
+
+void GraphPlott::removeAll()
+{
+	seriesVec.clear();
+}
+
+void GraphPlott::setInformation(QString information)
+{
+	this->informationButtonString = information;
+	popupWidget->setInformation(information);
+}
+
+std::vector<GraphPlottSeries>& GraphPlott::getSeriesVector()
+{
+	return seriesVec;
+}
+
+void GraphPlott::resetToDefaultWindow()
+{
+	frameGraphInView();
+}
+
+void GraphPlott::frameGraphInView()
+{
+	if(seriesVec.empty()) return;
+	window.xMin = std::min_element(std::begin(seriesVec), std::end(seriesVec), [](const GraphPlottSeries& a, const GraphPlottSeries& b) -> bool {return a.xMin < b.xMin; })->xMin;
+	window.xMax = std::max_element(std::begin(seriesVec), std::end(seriesVec), [](const GraphPlottSeries& a, const GraphPlottSeries& b) -> bool {return a.xMax < b.xMax; })->xMax;
+	window.yMin = std::min_element(std::begin(seriesVec), std::end(seriesVec), [](const GraphPlottSeries& a, const GraphPlottSeries& b) -> bool {return a.yMin < b.yMin; })->yMin;
+	window.yMax = std::max_element(std::begin(seriesVec), std::end(seriesVec), [](const GraphPlottSeries& a, const GraphPlottSeries& b) -> bool {return a.yMax < b.yMax; })->yMax;
+	window.ZoomOut(0.05);
+	update();
+}
+
+void GraphPlott::setDisplayLabel(QString file)
+{
+	displayLabel->setText("\"" + file + "\"   ");
+}
+
+void GraphPlott::setScratchpad(Scratchpad* pad)
+{
+	this->pad = pad;
+	scratchpadAction->setEnabled(true);
+}
+
+
+void GraphPlott::showInformation()
+{
+	QPoint position = QCursor::pos();
+	popupWidget->setInformation(informationButtonString + graphplottInformation);
+	popupWidget->width();
+	QRect screen = QApplication::desktop()->screenGeometry();
+	if (position.x() + popupWidget->width() > screen.width()) {
+		popupWidget->move(screen.width() - popupWidget->width(), position.y());
+	}
+	else {
+		popupWidget->move(position.x(), position.y());
+
+	}
+	popupWidget->show();
+
+}
+
+void GraphPlott::drawData(QPainter& painter)
+{
+	QPen linePen;
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+
+	for (const GraphPlottSeries& graphSeries : seriesVec) {
+		if (!graphSeries.data) {
+			qDebug() << "Pointer to nothing pls help";
+		}
+		if (graphSeries.data->empty() || graphSeries.hide) continue;
+		linePen.setColor(graphSeries.color);
+
+		if (graphSeries.type == GraphPlottSeries::SeriesType::Line || graphSeries.type == GraphPlottSeries::SeriesType::LineDot) {
+			linePen.setWidth(graphSeries.lineWidth/* + ((&graphSeries == highlightSeries) ? 5 : 0)*/);
+			painter.setPen(linePen);
+			QPainterPath painterPath;
+
+			QPointF oldpoint = graphSeries.data->at(0).toQPointF();
+			painterPath.moveTo(transformGraphToView(oldpoint, stregth_factorX, stregth_factorY, translation));
+			for (int i = 1; i < graphSeries.data->size(); i++) {
+				QPointF newpoint = graphSeries.data->at(i).toQPointF();
+				bool inBoundOldPoint = window.inBoundX(oldpoint);
+				bool inBoundNewPoint = window.inBoundX(newpoint);
+				if (!inBoundOldPoint && !inBoundNewPoint) {
+
+				}
+				else if (!inBoundOldPoint && inBoundNewPoint) {
+					painterPath.moveTo(transformGraphToView(oldpoint, stregth_factorX, stregth_factorY, translation));
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+				}
+				else if (inBoundOldPoint && inBoundNewPoint) {
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+				}
+				else if (inBoundOldPoint && !inBoundNewPoint) {
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+					break;
+				}
+				oldpoint = newpoint;
+			}
+
+			//painterPath.translate(translation);
+			painter.drawPath(painterPath);
+		}
+		if (graphSeries.type == GraphPlottSeries::SeriesType::Dot || graphSeries.type == GraphPlottSeries::SeriesType::LineDot) {
+			linePen.setWidth(2);
+			linePen.setColor(Qt::transparent);
+			painter.setPen(linePen);
+			painter.setBrush(graphSeries.color);
+			const bool useColor = graphSeries.useDataPointColor;
+			for (auto data : *graphSeries.data) {
+				if (useColor){
+					linePen.setColor(data.color);
+					painter.setPen(linePen);
+					painter.setBrush(data.color);
+				}
+				if (window.inBound(data.toQPointF())) {
+					painter.drawEllipse(transformGraphToView(data.toQPointF(), stregth_factorX, stregth_factorY, translation), graphSeries.circleRadius, graphSeries.circleRadius);
+				}
+			}
+			painter.setBrush(Qt::BrushStyle::NoBrush);
+		}
+	}
+}
+
+void GraphPlott::mouseMoveEvent(QMouseEvent* event)
+{
+	Plott::mouseMoveEvent(event);
+	lastPosition = event->pos();
+	timer->start(stayStillTimeMS);
+	QToolTip::hideText();
+}
+
+void GraphPlott::handleSelectedWindow(VisibleWindow& window, QMouseEvent* event)
+{
+	if (event->modifiers() & Qt::ControlModifier) {
+		setWindow(window);
+	}
+	else if (event->modifiers() & Qt::AltModifier) {
+		addPointsInWindowToScratchPad(window);
+	}
+	else {
+		QAction* used = selectMenu->exec(this->mapToGlobal(event->pos()));
+		if(used == displayAreaAction){
+			setWindow(window);
+		}
+		else if (used == scratchpadAction) {
+			addPointsInWindowToScratchPad(window);
+		}
+	}
+	
+}
+
+void GraphPlott::searchForPointUnderCursor()
+{
+	//check if mouse stayed still
+	QPoint globalPosition = QCursor::pos();
+	QPointF pos = this->mapFromGlobal(globalPosition);
+	if (pos != lastPosition) {
+		return;
+	}
+	if (seriesVec.empty() || seriesVec[0].data->empty()) {
+		return;
+	}
+
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+
+	const GraphDataPoint* min = &seriesVec[0].data->at(0);
+	double minSqaredDistance = sqaredDistance(transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
+	std::vector<GraphPlottSeries>::iterator actualBestSeries = seriesVec.begin();
+	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
+		for (const GraphDataPoint& point : *seriesIter->data) {
+			double distance = sqaredDistance(transformGraphToView(point.toQPointF(), stregth_factorX, stregth_factorY, translation), pos);
+			if (distance <= minSqaredDistance) {
+				minSqaredDistance = distance;
+				min = &point;
+				actualBestSeries = seriesIter;
+			}
+		}
+	}
+	if (minSqaredDistance <= 20) {
+		QPointF pointInWidget = transformGraphToView(min->toQPointF(), stregth_factorX, stregth_factorY, translation);
+		QToolTip::showText(this->mapToGlobal(QPoint(pointInWidget.x(), pointInWidget.y())) - QPoint(0, 35), actualBestSeries->description);
+	}
+}
+
+double GraphPlott::sqaredDistance(const QPointF& a, const QPointF& b)
+{
+	return std::pow(a.x() - b.x(), 2) + std::pow(a.y() - b.y(), 2);
+}
+
+void GraphPlott::addPointsInWindowToScratchPad(VisibleWindow& window)
+{
+	if (!pad) {
+		qDebug() << "NoPad";
+		return;
+	}
+	for (auto seriesIter = seriesVec.begin(); seriesIter != seriesVec.end(); seriesIter++) {
+		if (seriesIter->hide) continue;
+		for (const GraphDataPoint& point : *seriesIter->data) {
+			if (window.inBound(point.toQPointF()) && point.existLink()) {
+				pad->addPoint(*point.orginalPoint);
+			}
+		}
+	}
+}
+
+void GraphPlott::keyPressEvent(QKeyEvent* event)
+{
+	Plott::keyPressEvent(event);
+	switch (event->key()) {
+	case Qt::Key_T:
+		frameGraphInView();
+		break;
+	default:
+		break;
+	}
+}
diff --git a/metavis/GraphPlott.h b/metavis/GraphPlott.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e7b9c040b6b4518b7d043d1119a6f7b26e5a566
--- /dev/null
+++ b/metavis/GraphPlott.h
@@ -0,0 +1,79 @@
+#pragma once
+#include <vector>
+
+#include "Plott.h"
+#include "RunData.h"
+#include "GraphViewSettingDialog.h"
+#include <QString>
+#include <QLabel>
+#include <string>
+#include "Scratchpad.h"
+#include "HoverButton.h"
+#include "InformationPopUp.h"
+class GraphViewSettingDialog;
+
+struct GraphPlottSeries {
+	std::vector<GraphDataPoint>* data;
+	double xMin, xMax;
+	double yMin, yMax;
+	std::string runName;
+
+
+
+	//Settings for visual
+	QString description;
+	QColor color;
+	int lineWidth = 2;
+	double circleRadius = 2.0;
+	enum class SeriesType { Line, Dot, LineDot };
+	bool useDataPointColor = false;
+	SeriesType type;
+	bool hide = false;
+};
+
+class GraphPlott : public Plott
+{
+	Q_OBJECT
+
+public:
+
+	GraphPlott(QWidget *parent,bool settingsButton = true, bool informationButton = true, bool gridButton = true);
+	~GraphPlott();
+	void addSeries(std::vector<GraphDataPoint>* line, std::string runName, QString description, QColor color, GraphPlottSeries::SeriesType type);
+	void removeRunData(RunData* run);
+	void removeAll();
+	void setInformation(QString information);
+	std::vector<GraphPlottSeries>& getSeriesVector();
+	void virtual resetToDefaultWindow() override;
+	void virtual frameGraphInView();
+	void setDisplayLabel(QString file);
+	void setScratchpad(Scratchpad* pad);
+protected:
+	QHBoxLayout* buttonPanel;
+	void showInformation();
+	void drawData(QPainter& painter) override;
+	void mouseMoveEvent(QMouseEvent* event) override;
+	std::vector<GraphPlottSeries> seriesVec;
+	virtual void handleSelectedWindow(VisibleWindow& window, QMouseEvent* event) override;
+
+	int stayStillTimeMS = 300;
+	virtual void searchForPointUnderCursor();
+	virtual void addPointsInWindowToScratchPad(VisibleWindow& window);
+	//Help Function:
+	double sqaredDistance(const QPointF& a, const QPointF& b);
+	QPoint lastPosition;
+	QTimer* timer = new QTimer(this);
+	Scratchpad* pad = nullptr;
+	HoverButton* informationButton = new HoverButton();
+	InformationPopUp* popupWidget = new InformationPopUp(nullptr);
+private:
+	QMenu* selectMenu = new QMenu(this);
+	QAction* displayAreaAction = new QAction("Display this area", this);
+	QAction* scratchpadAction = new QAction("Add points to Scratchpad", this);
+	GraphViewSettingDialog* dialog;
+	QString displayNameOfDataThatIsDisplayed = "";
+	QString informationButtonString = "No information.";
+	QString graphplottInformation = "<h3><u>Control:</u></h3><b>Scrolling:</b> Zoom in and out.<br><b>Scrolling + CTRL:</b> Zoom only the X Axis in and out.<br><b>Scrolling + SHIFT:</b> Zoom only the Y Axis in and out.<br><b>Drag & Drop LMB:</b> Moves the visible area.<br><b>Drag & Drop RMB:</b> Select area to display or adds solutions to Scratchpad.<br><b>Drag & Drop RMB + CTRL:</b> Select area to display.<br><b>Drag & Drop RMB + ALT:</b> Adds solutions to Scratchpad.<br><b>Arrow Keys:</b> Moves the visible area<br><b>Page Up:</b> Zoom in.<br><b>Page Down:</b> Zoom out.<br><b>CTRL + R:</b> Resetts the visible area.<br>";
+	QLabel* displayLabel;
+	virtual void keyPressEvent(QKeyEvent* event) override;
+};
diff --git a/metavis/GraphView.cpp b/metavis/GraphView.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a0bc623d069f03c50fbe5855d5316a8db9a7518
--- /dev/null
+++ b/metavis/GraphView.cpp
@@ -0,0 +1,827 @@
+#include "pch.h"
+#include "GraphView.h"
+
+#include <QDebug>
+#include <QPushButton>
+#include <QBrush>
+#include <random>
+#include <algorithm>
+#include <chrono>
+#include "util.h"
+
+#define X_AXIS_GAP_AMOUNT 5
+#define Y_AXIS_GAP_AMOUNT 10
+#define X_AXIS_NUMBER_LINE_LENGTH 5
+#define Y_AXIS_NUMBER_LINE_LENGTH 5
+#define X_AXIS_NUMBER_GAP_LENGTH 10
+#define Y_AXIS_NUMBER_GAP_LENGTH 30
+
+#define MARGIN_TOP 10
+#define MARGIN_BOTTOM 20
+#define MARGIN_LEFT 50
+#define MARGIN_RIGHT 10
+
+
+
+GraphView::GraphView(QWidget* parent, Bound fixedBound):QWidget(parent), fixedBound(fixedBound), linePen(Qt::blue), rectPen(QColor(255,255,255,255)), axisPen(Qt::black)
+{
+	
+	linePen.setJoinStyle(Qt::PenJoinStyle::RoundJoin);
+	rectPen.setWidth(0);
+
+	////generate Random number for starting color
+	//std::random_device rd;  //Will be used to obtain a seed for the random number engine
+	//std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
+	//std::uniform_real_distribution<double> doubleDistr(0.0, 1.0);
+	//hueoffset = doubleDistr(gen);
+	hueoffset = 0.5;
+	setFocusPolicy(Qt::ClickFocus);
+}
+
+GraphView::~GraphView()
+{
+}
+
+void GraphView::paintEvent(QPaintEvent* event)
+{
+	std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
+	if (graphSeriesVec.empty() && yDoubleDoubleValuesAmount == 0) {
+		painter.setPen(axisPen);
+		painter.setFont(QFont("Arial", 12, QFont::Bold));
+		painter.drawText(rect(), Qt::AlignCenter, "No Data connected");
+		return;
+	}
+	//Calculate LineRect
+	QRect graphDisplayRect(rect());
+	graphDisplayRect.setBottom(graphDisplayRect.bottom() - MARGIN_BOTTOM);
+	graphDisplayRect.setLeft(graphDisplayRect.left() + MARGIN_LEFT);
+	graphDisplayRect.setTop(graphDisplayRect.top() + MARGIN_TOP);
+	graphDisplayRect.setRight(graphDisplayRect.right() - MARGIN_RIGHT);
+	graphDisplayRect.setWidth(graphDisplayRect.width() - (graphDisplayRect.width() % X_AXIS_GAP_AMOUNT) + 1);
+	graphDisplayRect.setHeight(graphDisplayRect.height() - (graphDisplayRect.height() % Y_AXIS_GAP_AMOUNT) + 1);
+
+	painter.setBrush(rectPen.color());
+	painter.drawRect(graphDisplayRect);
+	painter.setBrush(Qt::BrushStyle::NoBrush);
+
+	double stregth_factorX = graphDisplayRect.width() / rangeGraphX;
+	double stregth_factorY = graphDisplayRect.height() / rangeGraphY;
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	for (const GraphSeries& graphSeries : graphSeriesVec) {
+		if (!graphSeries.data) {
+			qDebug() << "Pointer to nothing pls help";
+		}
+		if (graphSeries.data->empty() || graphSeries.hide) continue;
+		linePen.setColor(graphSeries.color);
+
+		if (graphSeries.type == GraphSeries::SeriesType::Line || graphSeries.type == GraphSeries::SeriesType::LineDot) {
+			linePen.setWidth(graphSeries.lineWidth + ((&graphSeries == highlightSeries) ? 5 : 0));
+			painter.setPen(linePen);
+			QPainterPath painterPath;
+
+			QPointF oldpoint = graphSeries.data->at(0).toQPointF();
+			painterPath.moveTo(transformGraphToView(oldpoint, stregth_factorX, stregth_factorY, translation));
+			for (int i = 1; i < graphSeries.data->size(); i++) {
+				QPointF newpoint = graphSeries.data->at(i).toQPointF();
+				if (!inBoundX(oldpoint) && !inBoundX(newpoint)) {
+					
+				}
+				else if (!inBoundX(oldpoint) && inBoundX(newpoint)) {
+					painterPath.moveTo(transformGraphToView(oldpoint, stregth_factorX, stregth_factorY, translation));
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+				}
+				else if (inBoundX(oldpoint) && inBoundX(newpoint)) {
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+				}
+				else if (inBoundX(oldpoint) && !inBoundX(newpoint)) {
+					painterPath.lineTo(transformGraphToView(newpoint, stregth_factorX, stregth_factorY, translation));
+					break;
+				}
+				oldpoint = newpoint;
+			}
+
+			//painterPath.translate(translation);
+			painter.drawPath(painterPath);
+		}
+		if (graphSeries.type == GraphSeries::SeriesType::Dot || graphSeries.type == GraphSeries::SeriesType::LineDot) {
+			linePen.setWidth(2);
+			painter.setPen(linePen);
+			painter.setBrush(graphSeries.color);
+			for (auto data: *graphSeries.data) {
+				if (useInterval) {
+					if (data.orginalPoint->iteration < minIter) {
+						continue;
+					}
+					if (data.orginalPoint->iteration > maxIter) {
+						break;
+					}
+				}
+				if (graphSeries.useDataPointColor) {
+					linePen.setColor(data.color);
+					painter.setPen(linePen);
+					painter.setBrush(data.color);
+				}
+				if (inBound(data.toQPointF())) {
+					painter.drawEllipse(transformGraphToView(data.toQPointF(), stregth_factorX, stregth_factorY, translation), graphSeries.circleRadius, graphSeries.circleRadius);
+				}
+			}
+			painter.setBrush(Qt::BrushStyle::NoBrush);
+		}
+	}
+
+	if (yDoubleDoubleValuesAmount > 0) {
+		linePen.setWidth(2);
+		linePen.setColor(QColor(0,100,200, 0));
+		painter.setPen(linePen);
+		painter.setBrush(QColor(0, 100, 200, 0));
+		for (int i = 0; i < yDoubleDoubleValuesAmount; i++) {
+			painter.setBrush(pointColors[i]);
+			painter.drawEllipse(transformGraphToView(QPointF(yArray[2 * i], yArray[2 * i + 1]), stregth_factorX, stregth_factorY, translation), 3, 3);
+		}
+		painter.setBrush(Qt::BrushStyle::NoBrush);
+	}
+
+
+
+
+	if (drawTotalBound) {
+		painter.setPen(axisPen);
+		QRectF bounds(transformGraphToView(QPointF(totalBound.minX, totalBound.maxY), stregth_factorX, stregth_factorY, translation), transformGraphToView(QPointF(totalBound.maxX, totalBound.minY), stregth_factorX, stregth_factorY, translation));
+		painter.drawRect(bounds);
+	}
+
+
+
+
+	//Draw White Rect for axis
+	painter.setPen(rectPen);
+
+	painter.setBrush(rectPen.color());
+	QRect leftRect(rect().topLeft(), QPoint(graphDisplayRect.left() - 1, rect().bottom()));
+	QRect topRect(rect().topLeft(), QPoint(rect().right(), graphDisplayRect.top() - 1));
+	QRect bottomRect(QPoint(rect().left(), graphDisplayRect.bottom()), rect().bottomRight());
+	QRect rightRect(QPoint(graphDisplayRect.right(), rect().top()), rect().bottomRight());
+	painter.drawRect(leftRect);
+	painter.drawRect(topRect);
+	painter.drawRect(bottomRect);
+	painter.drawRect(rightRect);
+	painter.setBrush(Qt::BrushStyle::NoBrush);
+	
+	
+	
+	
+	
+	//Font for Axis;
+	painter.setFont(QFont("Arial", 8));
+	//draw X-Axis
+	painter.setPen(axisPen);
+	QRect xAxisRect(QPoint(graphDisplayRect.left(), graphDisplayRect.bottom()), QPoint(graphDisplayRect.right(), rect().bottom()));
+	QPainterPath xAxisPath;
+	xAxisPath.moveTo(xAxisRect.left(), xAxisRect.top());
+	xAxisPath.lineTo(xAxisRect.right(), xAxisRect.top());
+
+	int xGap = xAxisRect.width() / X_AXIS_GAP_AMOUNT;
+	QRect textRect(0, 0, 40, 9);
+
+	for (int i = 0; i < 11; i++) {
+		xAxisPath.moveTo(xAxisRect.left() + i * xGap, xAxisRect.top() + X_AXIS_NUMBER_LINE_LENGTH);
+		xAxisPath.lineTo(xAxisRect.left() + i * xGap, xAxisRect.top());
+		textRect.moveCenter(QPoint(xAxisRect.left() + i * xGap, xAxisRect.top() + X_AXIS_NUMBER_GAP_LENGTH));
+		painter.drawText(textRect, Qt::AlignCenter, xAxisNumbers[i]);
+	}
+	painter.drawPath(xAxisPath);
+
+	//draw Y-Axis
+	QRect yAxisRect(QPoint(rect().left(), graphDisplayRect.top()), QPoint(graphDisplayRect.left(), graphDisplayRect.bottom()));
+	QPainterPath yAxisPath;
+	yAxisPath.moveTo(yAxisRect.right(), yAxisRect.bottom());
+	yAxisPath.lineTo(yAxisRect.right(), yAxisRect.top());
+	int yGap = yAxisRect.height() / Y_AXIS_GAP_AMOUNT;
+	for (int i = 0; i < 11; i++) {
+		yAxisPath.moveTo(yAxisRect.right() - Y_AXIS_NUMBER_LINE_LENGTH, yAxisRect.bottom() - i * yGap);
+		yAxisPath.lineTo(yAxisRect.right(), yAxisRect.bottom() - i * yGap);
+		textRect.moveCenter(QPoint(yAxisRect.right() - Y_AXIS_NUMBER_GAP_LENGTH, yAxisRect.bottom() - i * yGap));
+		painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, yAxisNumbers[i]);
+	}
+	painter.drawPath(yAxisPath);
+	std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
+	std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+
+
+	//Mouse:
+	if (mousePressed) {
+		QColor blue(0, 122, 204);
+		QColor gray(120, 120, 120);
+		//QPointF value = transformViewToGraph(oldPositionForMouseEvent);
+		QPointF viewPoint = transformGraphToView(mousePressedValue, stregth_factorX, stregth_factorY, translation);
+		if (graphDisplayRect.top() <= viewPoint.y() && viewPoint.y() <= graphDisplayRect.bottom()) {
+			painter.setPen(gray);
+			painter.drawLine(QPointF(graphDisplayRect.left() - Y_AXIS_NUMBER_LINE_LENGTH, viewPoint.y()), QPointF(graphDisplayRect.right(), viewPoint.y()));
+			textRect.moveCenter(QPoint(graphDisplayRect.left() - Y_AXIS_NUMBER_GAP_LENGTH, viewPoint.y()));
+			painter.fillRect(textRect, rectPen.color());
+			painter.setPen(blue);
+			painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, QString::number(mousePressedValue.y(), 'f', 1));
+		}
+		if (graphDisplayRect.left() <= viewPoint.x() && viewPoint.x() <= graphDisplayRect.right()) {
+			painter.setPen(gray);
+			painter.drawLine(QPointF(viewPoint.x(), graphDisplayRect.top()), QPointF(viewPoint.x(), graphDisplayRect.bottom() + X_AXIS_NUMBER_LINE_LENGTH));
+			textRect.moveCenter(QPoint(viewPoint.x(), graphDisplayRect.bottom() + X_AXIS_NUMBER_GAP_LENGTH));
+			painter.fillRect(textRect, rectPen.color());
+			painter.setPen(blue);
+			painter.drawText(textRect, Qt::AlignCenter, QString::number(mousePressedValue.x(), 'f', 1));
+		}
+	}
+
+
+	qDebug() << "PaintTime: " << time.count() << "ms";
+	/*for (GraphSeries& series : graphSeriesVec) {
+		qDebug() << "BEGIN  ---------";
+		for (GraphDataPoint point : *series.data) {
+			qDebug() << "QPoint(" << point.x << "," << point.y << ")";
+		}
+		qDebug() << "END  ---------";
+	}*/
+}
+
+
+
+QPointF GraphView::transformGraphToView(QPointF& point, double stregth_factorX, double stregth_factorY, QPointF& translation) const
+{
+	return QPointF((point.x() - actualBound.minX) * stregth_factorX, (actualBound.maxY - point.y()) * stregth_factorY) + translation;
+}
+
+
+QPointF GraphView::transformViewToGraph(QPointF& point) const
+{
+	QRect graphDisplayRect(rect());
+	graphDisplayRect.setBottom(graphDisplayRect.bottom() - MARGIN_BOTTOM);
+	graphDisplayRect.setLeft(graphDisplayRect.left() + MARGIN_LEFT);
+	graphDisplayRect.setTop(graphDisplayRect.top() + MARGIN_TOP);
+	graphDisplayRect.setRight(graphDisplayRect.right() - MARGIN_RIGHT);
+	graphDisplayRect.setWidth(graphDisplayRect.width() - (graphDisplayRect.width() % X_AXIS_GAP_AMOUNT) + 1);
+	graphDisplayRect.setHeight(graphDisplayRect.height() - (graphDisplayRect.height() % Y_AXIS_GAP_AMOUNT) + 1);
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / rangeGraphX;
+	double stregth_factorY = graphDisplayRect.height() / rangeGraphY;
+	return QPointF(((point.x()-translation.x())/stregth_factorX)+ actualBound.minX, actualBound.maxY - ((point.y()-translation.y())/stregth_factorY));
+}
+
+GraphDataPoint GraphView::findNearestGraphDataPointFromGraphCoordinate(QPointF& graphpoint)
+{
+	if (graphSeriesVec.empty() || graphSeriesVec[0].data->empty()) {
+		return GraphDataPoint();
+	}
+	GraphDataPoint min = graphSeriesVec[0].data->at(0);
+	double minSqaredDistance = min.squaredDistance(graphpoint);
+	for (GraphSeries& series : graphSeriesVec) {
+		for (const GraphDataPoint point : *series.data) {
+			double distance = point.squaredDistance(graphpoint);
+			if (distance < minSqaredDistance) {
+				minSqaredDistance = distance;
+				min = point;
+				highlightSeries = &series;
+			}
+		}
+	}
+	return min;
+}
+
+//Help Function:
+double sqaredDistance(const QPointF& a, const QPointF& b)
+{
+	return std::pow(a.x() - b.x(), 2) + std::pow(a.y() - b.y(), 2);
+}
+
+
+GraphDataPoint GraphView::findNearestGraphDataPointFromViewCordinate(QPointF& viewpoint)
+{
+	if (graphSeriesVec.empty()) {
+		return GraphDataPoint();
+	}
+	QRect graphDisplayRect(rect());
+	graphDisplayRect.setBottom(graphDisplayRect.bottom() - MARGIN_BOTTOM);
+	graphDisplayRect.setLeft(graphDisplayRect.left() + MARGIN_LEFT);
+	graphDisplayRect.setTop(graphDisplayRect.top() + MARGIN_TOP);
+	graphDisplayRect.setRight(graphDisplayRect.right() - MARGIN_RIGHT);
+	graphDisplayRect.setWidth(graphDisplayRect.width() - (graphDisplayRect.width() % X_AXIS_GAP_AMOUNT) + 1);
+	graphDisplayRect.setHeight(graphDisplayRect.height() - (graphDisplayRect.height() % Y_AXIS_GAP_AMOUNT) + 1);
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / rangeGraphX;
+	double stregth_factorY = graphDisplayRect.height() / rangeGraphY;
+
+	GraphDataPoint min = graphSeriesVec[0].data->at(0);
+	double minSqaredDistance = sqaredDistance(min.toQPointF(), viewpoint);
+	std::vector<GraphSeries>::iterator actualBestSeries = graphSeriesVec.begin();
+	for (auto seriesIter = graphSeriesVec.begin(); seriesIter != graphSeriesVec.end(); seriesIter++) {
+		for (const GraphDataPoint point : *seriesIter->data) {
+			double distance = sqaredDistance(transformGraphToView(point.toQPointF(), stregth_factorX, stregth_factorY, translation), viewpoint);
+			if (distance < minSqaredDistance) {
+				minSqaredDistance = distance;
+				min = point;
+				//highlightSeries = &*seriesIter;
+				actualBestSeries = seriesIter;
+			}
+		}
+	}
+	std::rotate(graphSeriesVec.begin(), actualBestSeries + 1, graphSeriesVec.end());
+	highlightSeries = &graphSeriesVec.back();
+	return min;
+}
+
+
+
+
+bool GraphView::inBoundX(QPointF& point)
+{
+
+	return point.x() >= actualBound.minX && point.x() <= actualBound.maxX;
+}
+
+bool GraphView::inBoundY(QPointF& point)
+{
+	return point.y() >= actualBound.minY && point.y() <= actualBound.maxY;;
+}
+
+bool GraphView::inBound(QPointF& point)
+{
+	return inBoundX(point) && inBoundY(point);
+}
+
+void GraphView::keyPressEvent(QKeyEvent* event)
+{
+	switch (event->key()) {
+	case Qt::Key_Up:
+		fixedBound.move(this, Bound::Change::MoveUp);
+		break;
+	case Qt::Key_Right:
+		fixedBound.move(this, Bound::Change::MoveRight);
+		break;
+	case Qt::Key_Left:
+		fixedBound.move(this, Bound::Change::MoveLeft);
+		break;
+	case Qt::Key_Down:
+		fixedBound.move(this, Bound::Change::MoveDown);
+		break;
+	case Qt::Key_PageUp:
+	case Qt::Key_Plus:
+		if (event->modifiers() & Qt::ShiftModifier) {
+			fixedBound.move(this, Bound::Change::ZoomInY);
+		}
+		else if (event->modifiers() & Qt::ControlModifier) {
+			fixedBound.move(this, Bound::Change::ZoomInX);
+		}
+		else {
+			fixedBound.move(this, Bound::Change::ZoomIn);
+		}
+		break;
+	case Qt::Key_PageDown:
+	case Qt::Key_Minus:
+		if (event->modifiers() & Qt::ShiftModifier) {
+			fixedBound.move(this, Bound::Change::ZoomOutY);
+		}
+		else if (event->modifiers() & Qt::ControlModifier) {
+			fixedBound.move(this, Bound::Change::ZoomOutX);
+		}
+		else {
+			fixedBound.move(this, Bound::Change::ZoomOut);
+		}
+		break;
+	case Qt::Key_R:
+		resetBound();
+		update();
+	default:
+		QWidget::keyPressEvent(event);
+	}
+	//If not reacted forward:
+	QWidget::keyPressEvent(event);
+}
+
+void GraphView::resetBound()
+{
+	calculateTotalMatrixBound();
+	fixedBound = totalBound;
+	calculateRangeXY();
+	generateAxisNumberStrings();
+}
+
+void GraphView::wheelEvent(QWheelEvent* event)
+{
+	QPoint numPixels = event->pixelDelta();
+	QPoint numDegrees = event->angleDelta() / 8;
+
+	if (!numPixels.isNull()) {
+		//scrollWithPixels(numPixels);
+		switch (numPixels.y()) {
+		case -1:
+			fixedBound.move(this, Bound::Change::ZoomIn);
+			break;
+		case 1:
+			fixedBound.move(this, Bound::Change::ZoomOut);
+		default:
+			break;
+		}
+	}
+	else if (!numDegrees.isNull()) {
+		QPoint numSteps = numDegrees / 15;
+		switch (numSteps.y()) {
+		case 1:
+			if (event->modifiers() & Qt::ShiftModifier) {
+				fixedBound.move(this, Bound::Change::ZoomInY);
+			}
+			else if (event->modifiers() & Qt::ControlModifier) {
+				fixedBound.move(this, Bound::Change::ZoomInX);
+			}
+			else {
+				fixedBound.move(this, Bound::Change::ZoomIn);
+			}
+			break;
+		case -1:
+			if (event->modifiers() & Qt::ShiftModifier) {
+				fixedBound.move(this, Bound::Change::ZoomOutY);
+			}
+			else if (event->modifiers() & Qt::ControlModifier) {
+				fixedBound.move(this, Bound::Change::ZoomOutX);
+			}
+			else {
+				fixedBound.move(this, Bound::Change::ZoomOut);
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	event->accept();
+}
+
+void GraphView::mouseMoveEvent(QMouseEvent* event)
+{
+	//QToolTip::showText(event->globalPos(), "Hello", this);
+	QPointF delta = event->pos() - oldPositionForMouseEvent;
+	oldPositionForMouseEvent = event->pos();
+	double rangeX = std::abs(actualBound.maxX - actualBound.minX);
+	int width =  (rect().right() - 10) - (rect().left() + 50);
+	width -= (width % X_AXIS_GAP_AMOUNT) + 1;
+	double pixelWidthX = rangeX / (double)width ;
+	double rangeY = std::abs(actualBound.maxY - actualBound.minY);
+	int height = (rect().bottom() - 20) - (rect().top() + 20);
+	height -= (height % Y_AXIS_GAP_AMOUNT) + 1;
+	double pixelWidthY = rangeY / (double)height;
+
+
+
+	fixedBound.move(this, delta, pixelWidthX, pixelWidthY);
+
+}
+
+void GraphView::mousePressEvent(QMouseEvent* event)
+{
+	mousePressed = true;
+	//To calculate the delta for mouse move  event
+	oldPositionForMouseEvent = event->pos();
+	mousePressedValue = transformViewToGraph(oldPositionForMouseEvent);
+	GraphDataPoint nearestPoint = findNearestGraphDataPointFromViewCordinate(oldPositionForMouseEvent);
+	QString metaFileName;
+	if (highlightSeries && highlightSeries->run)
+	{
+		metaFileName = " " + QString::fromStdString(highlightSeries->run->name);
+	}
+	QString string =metaFileName;
+	QToolTip::showText(event->globalPos() - QPoint(0, 35), string);
+}
+
+void GraphView::mouseReleaseEvent(QMouseEvent* event)
+{
+	highlightSeries = nullptr;
+	mousePressed = false;
+	update();
+}
+
+void GraphView::update()
+{
+	calculateRangeXY();
+	generateAxisNumberStrings();
+	QWidget::update();
+}
+
+void GraphView::setDrawBound(bool value)
+{
+	drawTotalBound = value;
+}
+/**
+ *  Delete all series.
+ *
+ */
+void GraphView::reset()
+{
+	graphSeriesVec.clear();
+}
+
+
+void GraphView::calculateTotalMatrixBound()
+{
+	if (yDoubleDoubleValuesAmount > 0) {
+		/*double maxX, maxY;
+		double minX = maxX = yArray[0], minY = maxY = yArray[1];
+		for (int i = 1; i < yDoubleDoubleValuesAmount; i++) {
+			
+			if (yArray[2 * i] < minX) {
+				minX = yArray[2 * i];
+			}else if (yArray[2 * i] > maxX) {
+				maxX = yArray[2 * i];
+			}
+			if (yArray[2 * i + 1] < minY) {
+				minY = yArray[2 * i + 1];
+			}
+			else if (yArray[2 * i + 1] > maxY) {
+				maxY = yArray[2 * i + 1];
+			}
+		}
+		totalBound.minX = minX;
+		totalBound.minY = minY;
+		totalBound.maxX = maxX;
+		totalBound.maxY = maxY;*/
+
+		// Calculate AveragePoint of Matrix
+		
+		
+		
+		
+	}
+}
+
+void GraphView::calculateTotalGraphBound()
+{
+	totalBound.minX = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minX < b.minX; })->minX;
+	totalBound.maxX = std::max_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.maxX < b.maxX; })->maxX;
+	totalBound.minY = std::min_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.minY < b.minY; })->minY;
+	totalBound.maxY = std::max_element(std::begin(graphSeriesVec), std::end(graphSeriesVec), [](const GraphSeries& a, const GraphSeries& b) -> bool {return a.maxY < b.maxY; })->maxY;
+	
+}
+
+
+
+void GraphView::calculateRangeXY()
+{
+	actualBound = fixedBound;
+	rangeGraphX = std::abs(actualBound.maxX - actualBound.minX);
+	rangeGraphY = std::abs(actualBound.maxY - actualBound.minY);
+	if (std::abs(rangeGraphX) < 0.0001) {
+		actualBound.minX -= 1.0;
+		actualBound.maxX += 1.0;
+		rangeGraphX = 2;
+	}
+	if (std::abs(rangeGraphY) < 0.0001) {
+		actualBound.minY -= 1.0;
+		actualBound.maxY += 1.0;
+		rangeGraphY = 2;
+	}
+}
+
+//TODO: graphview 
+void GraphView::calculateMinMaxXY(GraphSeries& lgs)
+{
+	auto pairX = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.x < b.x; });
+	lgs.minX = pairX.first->x;
+	lgs.maxX = pairX.second->x;
+	auto pairY = std::minmax_element(lgs.data->begin(), lgs.data->end(), [](const GraphDataPoint& a, const GraphDataPoint& b) -> bool {return a.y < b.y; });
+	lgs.minY = pairY.first->y;
+	lgs.maxY = pairY.second->y;
+}
+
+void GraphView::addSeries(std::vector<GraphDataPoint>* line, RunData* run, QColor color, GraphSeries::SeriesType type)
+{
+	if (line->empty()) {
+		qDebug() << "Series is empty!";
+		return;
+	}
+	GraphSeries lgs;
+	lgs.run = run;
+	lgs.data = line;
+	lgs.type = type;
+	calculateMinMaxXY(lgs);
+	lgs.color = color;
+	graphSeriesVec.push_back(lgs);
+	calculateTotalGraphBound();
+	if (!useFixedBound) calculateRangeXY();
+	generateAxisNumberStrings();
+}
+
+QColor GraphView::generateNextColorForGraph()
+{
+	/* http://devmag.org.za/2012/07/29/how-to-choose-colours-procedurally-algorithms/
+		use golden ratio 0.618033988749895f
+	*/
+	hueoffset = std::fmod(hueoffset + 0.618033988749895f, 1.0);
+	return QColor::fromHsvF(hueoffset, 0.83, 1.0);
+}
+
+
+QColor interpolate(QColor& first, QColor& second, double alpha)
+{
+	double firstH, firstS, firstL;
+	double secondH, secondS, secondL;
+
+	first.getHslF(&firstH, &firstS, &firstL);
+	second.getHslF(&secondH, &secondS, &secondL);
+
+	const double h = util::linearInterpolate(firstH, secondH, alpha);
+	const double s = util::linearInterpolate(firstS, secondS, alpha);
+	const double l = util::linearInterpolate(firstL, secondL, alpha);
+
+	return QColor::fromHslF(h, s, l);
+}
+
+
+
+void GraphView::addYMatrix(double* yArray, std::vector<SolutionPointData>& solVec)
+{
+	this->yArray = yArray; yDoubleDoubleValuesAmount = solVec.size();
+	this->solVec = &solVec;
+	if (pointColors != nullptr) delete pointColors;
+	pointColors = new QColor[yDoubleDoubleValuesAmount];
+}
+void GraphView::autoZoomOut()
+{
+	if (yDoubleDoubleValuesAmount == 0) return;
+	QPointF sumDistance(0, 0);
+	for (int i = 0; i < yDoubleDoubleValuesAmount; i++) {
+		sumDistance += QPointF(std::abs(yArray[2 * i]), std::abs(yArray[2 * i + 1]));
+	}
+	QPointF avgDistance(sumDistance.x() / yDoubleDoubleValuesAmount,
+		sumDistance.y() / yDoubleDoubleValuesAmount);
+	double scalar = 3;
+	double addScalar = 1;
+	if (fixedBound.maxX < avgDistance.x() * scalar) {
+		fixedBound.minX = -avgDistance.x() * scalar * addScalar;
+		fixedBound.maxX = avgDistance.x() * scalar * addScalar;
+		fixedBound.minY = -avgDistance.y() * scalar * addScalar;
+		fixedBound.maxY = avgDistance.y() * scalar * addScalar;
+	}
+}
+
+void GraphView::updateGraphColors(ColorGradient& gradient)
+{
+	if (yDoubleDoubleValuesAmount == 0) return;
+	double bestValue = 0;
+	double worstValue = 100;
+	for (int i = 0; i < solVec->size(); i++) {
+		pointColors[i] = gradient.getColorFromAlpha( std::clamp(util::inverseLinearInterpolation(bestValue, worstValue, solVec->at(i).objectiveFunction), 0.0, 1.0));
+	}
+}
+
+void GraphView::generateAxisNumberStrings()
+{
+	for (int i = 0; i < 11; i++) {
+		xAxisNumbers[i] = QString::number(actualBound.minX + i * (rangeGraphX / (double)X_AXIS_GAP_AMOUNT), 'f', 1);
+		yAxisNumbers[i] = QString::number(actualBound.minY + i * (rangeGraphY / (double)Y_AXIS_GAP_AMOUNT), 'f', 1);
+	}
+}
+
+void GraphView::setUseFixedBound(bool value)
+{
+	//if value == other update else do nothing
+	if (useFixedBound != value) {
+		useFixedBound = value;
+		calculateRangeXY();
+		actualBound = fixedBound;
+		generateAxisNumberStrings();
+	}
+}
+
+void GraphView::generateAndAddRandomLine()
+{
+	std::random_device rd;  //Will be used to obtain a seed for the random number engine
+	std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
+
+
+	std::uniform_real_distribution<double> realDistr(-30, 30);
+	std::uniform_int_distribution<int> intScaleDistr(1, 3);
+
+	for (int randomSeries = 0; randomSeries < 1; randomSeries++) {
+		std::vector<GraphDataPoint> randomPointVec(101);
+		int scale = intScaleDistr(gen);
+		for (int i = 0; i < randomPointVec.size(); i++) {
+			randomPointVec[i] = GraphDataPoint(i + 500, i * scale + realDistr(gen));
+		}
+		addLine(&randomPointVec, nullptr);
+	}
+}
+
+void GraphView::addLine(std::vector<GraphDataPoint>* line, RunData* run)
+{
+	addSeries(line, run,generateNextColorForGraph(), GraphSeries::SeriesType::Line);
+}
+
+void GraphView::addLine(std::vector<GraphDataPoint>* line, RunData* run, QColor color)
+{
+	addSeries(line, run, color, GraphSeries::SeriesType::Line);
+}
+
+void GraphView::addDots(std::vector<GraphDataPoint>* dots, RunData* run)
+{
+	addSeries(dots, run, generateNextColorForGraph(), GraphSeries::SeriesType::Dot);
+}
+
+void GraphView::addDots(std::vector<GraphDataPoint>* dots, RunData* run, QColor color)
+{
+	addSeries(dots, run, color, GraphSeries::SeriesType::Dot);
+}
+
+void GraphView::removeAllSeriesWithRundata(RunData* run)
+{
+	//TODO not implemented jet
+	//std::for_each(graphSeriesVec);
+}
+
+void GraphView::removeAllSeries()
+{
+}
+void GraphView::setMinIter(int value)
+{
+	minIter = value;
+	update();
+}
+void GraphView::setMaxIter(int value)
+{
+	maxIter = value;
+	update();
+}
+
+void Bound::move(GraphView* widget,const Change& type, const double changePercentage)
+{
+	double changeX = std::abs(minX - maxX) * changePercentage;
+	double changeY = std::abs(minY - maxY) * changePercentage;
+	switch (type) {
+	case Change::MoveLeft:
+		minX -= changeX;
+		maxX -= changeX;
+		break;
+	case Change::MoveRight:
+		minX += changeX;
+		maxX += changeX;
+		break;
+	case Change::MoveUp:
+		minY += changeY;
+		maxY += changeY;
+		break;
+	case Change::MoveDown:
+		minY -= changeY;
+		maxY -= changeY;
+		break;
+	case Change::ZoomOut:
+		minY -= changeY;
+		maxY += changeY;
+		minX -= changeX;
+		maxX += changeX;
+		break;
+	case Change::ZoomIn:
+		minY += changeY;
+		maxY -= changeY;
+		minX += changeX;
+		maxX -= changeX;
+		break;
+	case Change::ZoomInX:
+		minX += changeX;
+		maxX -= changeX;
+		break;
+	case Change::ZoomInY:
+		minY += changeY;
+		maxY -= changeY;
+		break;
+	case Change::ZoomOutX:
+		minX -= changeX;
+		maxX += changeX;
+		break;
+	case Change::ZoomOutY:
+		minY -= changeY;
+		maxY += changeY;
+		break;
+	default:
+		break;
+	}
+	//TODO: Move out of bound in calculate widget
+	widget->update();
+}
+
+void Bound::move(GraphView* widget, QPointF& delta, double realPixelWidthX, double realPixelWidthY)
+{
+	minX += -delta.x() * realPixelWidthX;
+	maxX += -delta.x() * realPixelWidthX;
+	minY += delta.y() * realPixelWidthY;
+	maxY += delta.y() * realPixelWidthY;
+	widget->update();
+}
+
+void Bound::move(GraphView* widget, QPointF& targetPoint)
+{
+	//Calculate MiddlePoint
+	QPointF actualMiddlePoint((maxX - minX) / 2.0, (maxY - minY) / 2.0);
+	QPointF dif = targetPoint - actualMiddlePoint;
+	minX += dif.x();
+	maxX += dif.x();
+	minY += dif.y();
+	maxY += dif.y();
+}
diff --git a/metavis/GraphView.h b/metavis/GraphView.h
new file mode 100644
index 0000000000000000000000000000000000000000..0fa77296efa715f879e155b8f151b6f4475aabf4
--- /dev/null
+++ b/metavis/GraphView.h
@@ -0,0 +1,139 @@
+#pragma once
+#include <QWidget>
+#include <QPaintEvent>
+#include <QAbstractListModel>
+#include <QPen>
+#include <QPainter>
+#include <vector>
+#include "RunData.h"
+#include "ColorGradient.h"
+
+class GraphView;
+class RunData;
+struct SolutionPointData;
+
+
+
+
+struct GraphSeries {
+	std::vector<GraphDataPoint>* data;
+	double minX, maxX;
+	double minY, maxY;
+	RunData* run;
+
+
+
+	//Settings for visual
+	QString name;
+	QColor color;
+	int lineWidth = 2;
+	double circleRadius = 2.0;
+	enum class SeriesType{ Line, Dot, LineDot};
+	bool useDataPointColor = false;
+	SeriesType type;
+	bool hide = false;
+};
+
+struct Bound {
+	double minX = 0, minY = 0, maxX = 0, maxY = 0;
+	enum class Change{MoveLeft, MoveRight, MoveUp, MoveDown, ZoomOut, ZoomIn, ZoomInX, ZoomInY, ZoomOutX, ZoomOutY, Reset};
+	Bound() {}
+	Bound(double minX, double maxX, double minY, double maxY):minX(minX), maxX(maxX), minY(minY), maxY(maxY){}
+	void move(GraphView* widget,const Change& type, const double changePercentage = 0.1);
+	void move(GraphView* widget, QPointF& delta, double realPixelWidthX, double realPixelWidthY);
+	void move(GraphView* widget, QPointF& targetPoint);
+};
+
+class GraphView :public QWidget
+{
+	Q_OBJECT
+
+public:
+	GraphView(QWidget* parent, Bound fixedBound = Bound());
+	~GraphView();
+	QString title;
+	Bound fixedBound;
+	//TODO: make fancy
+	bool useInterval = false;
+	int maxIter = 0;
+	int minIter = 0;
+	std::vector<GraphSeries> graphSeriesVec;
+
+private:
+	bool useFixedBound;
+	//Data
+	Bound totalBound;
+	Bound actualBound = totalBound;
+	bool drawTotalBound = false;
+	double rangeGraphX = 0, rangeGraphY = 0;
+
+	double* yArray = nullptr;
+	QColor* pointColors = nullptr;
+	std::vector<SolutionPointData>* solVec = nullptr;
+	int yDoubleDoubleValuesAmount = 0;
+	
+
+
+
+	//Visualization
+	QString xAxisNumbers[11];
+	QString yAxisNumbers[11];
+	double hueoffset;
+	QPen linePen, rectPen, axisPen;
+	GraphSeries* highlightSeries = nullptr;
+	//Control
+	QPointF oldPositionForMouseEvent;
+	QPointF mousePressedValue;
+	bool mousePressed = false;
+
+
+
+public:
+	void setUseFixedBound(bool value);
+	void generateAndAddRandomLine();
+	void addLine(std::vector<GraphDataPoint>* line, RunData* run);
+	void addLine(std::vector<GraphDataPoint>* line, RunData* run, QColor color);
+	void addDots(std::vector<GraphDataPoint>* dots, RunData* run);
+	void addDots(std::vector<GraphDataPoint>* dots, RunData* run, QColor color);
+	void removeAllSeriesWithRundata(RunData* run);
+	void removeAllSeries();
+	void reset();
+	void calculateRangeXY();
+	void generateAxisNumberStrings();
+	void update();
+	void setDrawBound(bool value);
+	QColor generateNextColorForGraph();
+	void resetBound();
+	void addYMatrix(double* yArray, std::vector<SolutionPointData>& solVec);
+	void autoZoomOut();
+	void updateGraphColors(ColorGradient& gradient);
+
+
+
+
+
+private:
+	void calculateTotalMatrixBound();
+	void calculateTotalGraphBound();
+	void GraphView::calculateMinMaxXY(GraphSeries& lgs);
+	void addSeries(std::vector<GraphDataPoint>* line, RunData* run, QColor color, GraphSeries::SeriesType type);
+	QPointF transformGraphToView(QPointF& graphpoint, double stregth_factorX, double stregth_factorY, QPointF& translation) const;
+	QPointF transformViewToGraph(QPointF& viewpoint) const;
+	GraphDataPoint findNearestGraphDataPointFromGraphCoordinate(QPointF& graphpoint);
+	GraphDataPoint findNearestGraphDataPointFromViewCordinate(QPointF& viewpoint);
+	bool inBoundX(QPointF& point);
+	bool inBoundY(QPointF& point);
+	bool inBound(QPointF& point);
+
+	//overrides
+	void keyPressEvent(QKeyEvent* event) override;
+	void wheelEvent(QWheelEvent* event) override;
+	void mouseMoveEvent(QMouseEvent* event) override;
+	void mousePressEvent(QMouseEvent* event) override;
+	void mouseReleaseEvent(QMouseEvent* event) override;
+	void paintEvent(QPaintEvent* event) override;
+public slots:
+	void setMaxIter(int value);
+	void setMinIter(int value);
+};
+
diff --git a/metavis/GraphViewSettingDialog.cpp b/metavis/GraphViewSettingDialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1418b0611bfb7efe679e09253b99c9e993029bb6
--- /dev/null
+++ b/metavis/GraphViewSettingDialog.cpp
@@ -0,0 +1,55 @@
+#include "pch.h"
+#include "GraphViewSettingDialog.h"
+#include <QListWidgetItem>
+#include <QPushButton>
+#include "GraphViewSettingItem.h"
+#include <QScrollArea>
+
+
+
+GraphViewSettingDialog::GraphViewSettingDialog(GraphPlott* view, QString title)
+	: QDialog(view, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowType::WindowCloseButtonHint), view(view)
+{
+	ui.setupUi(this);
+	setWindowTitle(title);
+	QWidget* toScroll = new QWidget(this);
+	layout = new QVBoxLayout(this);
+	layout->setContentsMargins(3, 0, 3, 0);
+	toScroll->setLayout(layout);
+	QVBoxLayout* myLayout = new QVBoxLayout(this);
+	myLayout->setContentsMargins(0, 0, 0, 0);
+	QScrollArea* scrollArea = new QScrollArea;
+	scrollArea->setWidgetResizable(true);
+	scrollArea->setWidget(toScroll);
+	myLayout->addWidget(scrollArea);
+	this->setLayout(myLayout);
+}
+
+GraphViewSettingDialog::~GraphViewSettingDialog()
+{
+}
+
+void GraphViewSettingDialog::openDialog()
+{
+	//Generate Buttons
+	//qDebug() << "vecsize " << vecsize << "     view->getSeriesVector().size() " << view->getSeriesVector().size();
+	if (vecsize == view->getSeriesVector().size()) {
+		this->activateWindow();
+		this->setFocus();
+		this->show();
+		return;
+	}
+	else {
+		vecsize = view->getSeriesVector().size();
+		QLayoutItem* item;
+		while ((item = layout->takeAt(0)))
+			delete item;
+	}
+
+	for (auto iter = view->getSeriesVector().begin(); iter != view->getSeriesVector().end(); iter++) {
+		GraphViewSettingItem* handle = new GraphViewSettingItem(view, &*iter, this);
+		layout->addWidget(handle);
+	}
+	this->show();
+}
+
diff --git a/metavis/GraphViewSettingDialog.h b/metavis/GraphViewSettingDialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ef08f66ae75fe1e009f777bb38f9a912c6254a7
--- /dev/null
+++ b/metavis/GraphViewSettingDialog.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <QDialog>
+#include "GraphPlott.h"
+#include "ui_GraphViewSettingDialog.h"
+class GraphPlott;
+
+
+class GraphViewSettingDialog : public QDialog
+{
+	Q_OBJECT
+
+public:
+	GraphPlott* view;
+	GraphViewSettingDialog(GraphPlott* view, QString title);
+	~GraphViewSettingDialog();
+public slots:
+	void openDialog();
+private:
+	int vecsize = 0;
+	Ui::GraphViewSettingDialog ui;
+	QVBoxLayout* layout;
+};
diff --git a/metavis/GraphViewSettingDialog.ui b/metavis/GraphViewSettingDialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..7d5d58c9d03b9d1226c3e562bfdb0f873a7dc327
--- /dev/null
+++ b/metavis/GraphViewSettingDialog.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GraphViewSettingDialog</class>
+ <widget class="QDialog" name="GraphViewSettingDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>695</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>GraphViewSettingDialog</string>
+  </property>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/metavis/GraphViewSettingItem.cpp b/metavis/GraphViewSettingItem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..729bcc299e8d8cce15f03d61adb48b9133ce0fab
--- /dev/null
+++ b/metavis/GraphViewSettingItem.cpp
@@ -0,0 +1,91 @@
+#include "pch.h"
+#include "GraphViewSettingItem.h"
+#include <QColorDialog>
+
+GraphViewSettingItem::GraphViewSettingItem(GraphPlott* view, GraphPlottSeries* series, QWidget *parent) : QWidget(parent), series(series), view(view), colorButton(new ColorButton(this, series->color))
+{
+	ui.setupUi(this);
+	// Init
+	switch (series->type) {
+	case GraphPlottSeries::SeriesType::Dot:
+		ui.SytleComboBox->setCurrentIndex(1);
+		break;
+	case GraphPlottSeries::SeriesType::LineDot:
+		ui.SytleComboBox->setCurrentIndex(2);
+		break;
+	case GraphPlottSeries::SeriesType::Line:
+	default:
+		ui.SytleComboBox->setCurrentIndex(0);
+		break;
+	}
+	ui.LineSlider->setValue(series->lineWidth);
+	ui.CircleSlider->setValue(series->circleRadius);
+	dissableSlidersOnType();
+	updateGroupBoxTitle();
+	ui.RightFormLayout->setWidget(1, QFormLayout::FieldRole, colorButton);
+
+	
+	//Connect
+	connect(ui.LineSlider, &QSlider::valueChanged, [=](const int& newValue) { series->lineWidth = newValue; view->update(); });
+	connect(ui.CircleSlider, &QSlider::valueChanged, [=](const int& newValue) { series->circleRadius = newValue; view->update(); });
+	connect(ui.SytleComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](const int& newValue) { setType(newValue);dissableSlidersOnType();view->update(); });
+	connect(ui.HideCheckbox, &QCheckBox::stateChanged, [=](const int& newValue) { series->hide = (newValue==2); view->update(); });
+	//connect(ui.SetColorButton, &QPushButton::pressed, this, &GraphViewSettingItem::setColor);
+	connect(colorButton, &ColorButton::colorChanged, this, &GraphViewSettingItem::setColor);
+	connect(ui.NameEdit, &QLineEdit::textChanged, [=](const QString& text) { series->description = text; updateGroupBoxTitle(); });
+}
+
+GraphViewSettingItem::~GraphViewSettingItem()
+{
+}
+
+void GraphViewSettingItem::dissableSlidersOnType()
+{
+	switch (series->type) {
+	case GraphPlottSeries::SeriesType::Line:
+		ui.LineSlider->setEnabled(true);
+		ui.CircleSlider->setEnabled(false);
+		break;
+	case GraphPlottSeries::SeriesType::Dot:
+		ui.LineSlider->setEnabled(false);
+		ui.CircleSlider->setEnabled(true);
+		break;
+	case GraphPlottSeries::SeriesType::LineDot:
+		ui.LineSlider->setEnabled(true);
+		ui.CircleSlider->setEnabled(true);
+		break;
+	default:
+		break;
+	}
+}
+
+void GraphViewSettingItem::setType(int type)
+{
+	switch (type) {
+	case 0:
+		series->type = GraphPlottSeries::SeriesType::Line;
+		break;
+	case 1:
+		series->type = GraphPlottSeries::SeriesType::Dot;
+		break;
+	case 2:
+		series->type = GraphPlottSeries::SeriesType::LineDot;
+		break;
+	default:
+		break;
+	}
+}
+
+void GraphViewSettingItem::setColor(QColor color)
+{
+	series->color = color;
+	updateGroupBoxTitle();
+	view->update();
+}
+
+void GraphViewSettingItem::updateGroupBoxTitle()
+{
+	ui.GroupBox->setTitle("Series: " + series->description);
+	QString style = "QGroupBox { color: rgb(%1, %2, %3); };";
+	ui.GroupBox->setStyleSheet(style.arg(series->color.red()).arg(series->color.green()).arg(series->color.blue()));
+}
diff --git a/metavis/GraphViewSettingItem.h b/metavis/GraphViewSettingItem.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f48f0220de007dfcab3def17e23ef00c1d53d9b
--- /dev/null
+++ b/metavis/GraphViewSettingItem.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <QWidget>
+#include "ui_GraphViewSettingItem.h"
+#include "GraphPlott.h"
+#include "ColorButton.h"
+class GraphPlott;
+
+class GraphViewSettingItem : public QWidget
+{
+	Q_OBJECT
+
+public:
+	GraphViewSettingItem(GraphPlott* view, GraphPlottSeries* series, QWidget *parent = Q_NULLPTR);
+	~GraphViewSettingItem();
+
+private:
+	Ui::GraphViewSettingItem ui;
+	GraphPlottSeries* series;
+	GraphPlott* view;
+	ColorButton* colorButton;
+	void dissableSlidersOnType();
+	void setType(int type);
+	void setColor(QColor color);
+	void updateGroupBoxTitle();
+};
diff --git a/metavis/GraphViewSettingItem.ui b/metavis/GraphViewSettingItem.ui
new file mode 100644
index 0000000000000000000000000000000000000000..4a075220b08f7815b1a3bdb0f61aa6cac9d069ca
--- /dev/null
+++ b/metavis/GraphViewSettingItem.ui
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GraphViewSettingItem</class>
+ <widget class="QWidget" name="GraphViewSettingItem">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>645</width>
+    <height>520</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>GraphViewSettingItem</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="GroupBox">
+     <property name="title">
+      <string>GroupBox</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_3">
+      <property name="leftMargin">
+       <number>9</number>
+      </property>
+      <item row="0" column="0">
+       <layout class="QFormLayout" name="LeftFormLayout">
+        <item row="0" column="0">
+         <widget class="QLabel" name="NameLabel">
+          <property name="text">
+           <string>Name</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QLineEdit" name="NameEdit"/>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="LineLabel">
+          <property name="text">
+           <string>Line</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0">
+         <widget class="QLabel" name="CircleLabel">
+          <property name="text">
+           <string>Circle</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1">
+         <widget class="QSlider" name="CircleSlider">
+          <property name="minimum">
+           <number>1</number>
+          </property>
+          <property name="maximum">
+           <number>16</number>
+          </property>
+          <property name="value">
+           <number>1</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickPosition">
+           <enum>QSlider::TicksBelow</enum>
+          </property>
+          <property name="tickInterval">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="QSlider" name="LineSlider">
+          <property name="minimum">
+           <number>1</number>
+          </property>
+          <property name="maximum">
+           <number>16</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickPosition">
+           <enum>QSlider::TicksBelow</enum>
+          </property>
+          <property name="tickInterval">
+           <number>1</number>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="0" column="1">
+       <spacer name="spacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Preferred</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>10</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="0" column="2">
+       <layout class="QFormLayout" name="RightFormLayout">
+        <item row="0" column="0">
+         <widget class="QLabel" name="StyleLabel">
+          <property name="text">
+           <string>Style</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="QComboBox" name="SytleComboBox">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <item>
+           <property name="text">
+            <string>Line</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>Dot</string>
+           </property>
+          </item>
+          <item>
+           <property name="text">
+            <string>Line&amp;Dot</string>
+           </property>
+          </item>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="ColorLabel">
+          <property name="text">
+           <string>Color</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1">
+         <widget class="QCheckBox" name="HideCheckbox">
+          <property name="text">
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0">
+         <widget class="QLabel" name="HideLabel">
+          <property name="text">
+           <string>Hide</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/metavis/HoverButton.cpp b/metavis/HoverButton.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..313ebc34be18be42346b679f4bfe8ebc49d96d87
--- /dev/null
+++ b/metavis/HoverButton.cpp
@@ -0,0 +1,27 @@
+#include "pch.h"
+#include "HoverButton.h"
+
+HoverButton::HoverButton(QWidget *parent)
+	: QPushButton(parent)
+{
+}
+
+HoverButton::~HoverButton()
+{
+}
+
+void HoverButton::setHoveredIcon(const QIcon& icon)
+{
+	hoveredIcon = icon;
+}
+
+void HoverButton::enterEvent(QEvent*)
+{
+	normalIcon = this->icon();
+	this->setIcon(hoveredIcon);
+}
+
+void HoverButton::leaveEvent(QEvent*)
+{
+	this->setIcon(normalIcon);
+}
diff --git a/metavis/HoverButton.h b/metavis/HoverButton.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0c4c721c3b35a1d10187bff1971228437c12899
--- /dev/null
+++ b/metavis/HoverButton.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QPushButton>
+#include <QPalette>
+#include <QColor>
+#include <QDebug>
+#include <QIcon>
+
+class HoverButton : public QPushButton
+{
+	Q_OBJECT
+
+public:
+	HoverButton(QWidget *parent = nullptr);
+	~HoverButton();
+	void setHoveredIcon(const QIcon& icon);
+
+protected:
+    virtual void enterEvent(QEvent*);
+	virtual void leaveEvent(QEvent*);
+private:
+	QIcon normalIcon;
+	QIcon hoveredIcon;
+};
diff --git a/metavis/InformationPopUp.cpp b/metavis/InformationPopUp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a4d3e8cf7c89b1d8848d389c773e578de3a6a2d
--- /dev/null
+++ b/metavis/InformationPopUp.cpp
@@ -0,0 +1,27 @@
+#include "pch.h"
+#include "InformationPopUp.h"
+
+InformationPopUp::InformationPopUp(QWidget *parent)
+	: QWidget(parent)
+{
+	this->setWindowFlag(Qt::Popup);
+	QVBoxLayout* layout = new QVBoxLayout(this);
+	setContentsMargins(3, 3, 3, 3);
+	informationLabel->setTextFormat(Qt::RichText);
+	layout->addWidget(informationLabel);
+}
+
+InformationPopUp::~InformationPopUp()
+{
+}
+
+void InformationPopUp::setInformation(QString information)
+{
+	informationLabel->setText(information);
+	update();
+}
+
+QString InformationPopUp::getInformation() const
+{
+	return informationLabel->text();
+}
diff --git a/metavis/InformationPopUp.h b/metavis/InformationPopUp.h
new file mode 100644
index 0000000000000000000000000000000000000000..916f4de3f6d216d758a97a34f3799c56bb41f0f5
--- /dev/null
+++ b/metavis/InformationPopUp.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <QWidget>
+#include <QString>
+#include <QLabel>
+class InformationPopUp : public QWidget
+{
+	Q_OBJECT
+
+public:
+	InformationPopUp(QWidget *parent);
+	~InformationPopUp();
+	void setInformation(QString information);
+	QString getInformation() const;
+private:
+	QLabel* informationLabel = new QLabel();
+};
diff --git a/metavis/MetalogManagerItem.cpp b/metavis/MetalogManagerItem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..71df02f00213a6abbbb8e4b8dff2782ccefc3c2f
--- /dev/null
+++ b/metavis/MetalogManagerItem.cpp
@@ -0,0 +1,13 @@
+#include "pch.h"
+#include "MetalogManagerItem.h"
+
+MetalogManagerItem::MetalogManagerItem(QWidget *parent)
+	: QWidget(parent)
+{
+	ui.setupUi(this);
+}
+
+MetalogManagerItem::~MetalogManagerItem()
+{
+	
+}
diff --git a/metavis/MetalogManagerItem.h b/metavis/MetalogManagerItem.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3b4f9e27904ba1e61d3d06ecd14eeddf2e0a57a
--- /dev/null
+++ b/metavis/MetalogManagerItem.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <QWidget>
+#include "ui_MetalogManagerItem.h"
+
+class MetalogManagerItem : public QWidget
+{
+	Q_OBJECT
+
+public:
+	MetalogManagerItem(QWidget *parent = Q_NULLPTR);
+	~MetalogManagerItem();
+
+private:
+	Ui::MetalogManagerItem ui;
+};
diff --git a/metavis/MetalogManagerItem.ui b/metavis/MetalogManagerItem.ui
new file mode 100644
index 0000000000000000000000000000000000000000..78cc98476a785af231c07900c45fefdfadd50e4a
--- /dev/null
+++ b/metavis/MetalogManagerItem.ui
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MetalogManagerItem</class>
+ <widget class="QWidget" name="MetalogManagerItem">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>475</width>
+    <height>78</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MetalogManagerItem</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="leftMargin">
+    <number>3</number>
+   </property>
+   <property name="topMargin">
+    <number>3</number>
+   </property>
+   <property name="rightMargin">
+    <number>3</number>
+   </property>
+   <property name="bottomMargin">
+    <number>3</number>
+   </property>
+   <property name="horizontalSpacing">
+    <number>6</number>
+   </property>
+   <item row="2" column="0">
+    <widget class="QGroupBox" name="GroupBox">
+     <property name="title">
+      <string/>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0,0">
+      <property name="leftMargin">
+       <number>3</number>
+      </property>
+      <property name="topMargin">
+       <number>3</number>
+      </property>
+      <property name="rightMargin">
+       <number>3</number>
+      </property>
+      <property name="bottomMargin">
+       <number>3</number>
+      </property>
+      <property name="horizontalSpacing">
+       <number>0</number>
+      </property>
+      <property name="verticalSpacing">
+       <number>2</number>
+      </property>
+      <item row="0" column="2">
+       <widget class="QPushButton" name="AssigneButton">
+        <property name="text">
+         <string>Assign</string>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normalon>:/metavis/Resources/assignButton.svg</normalon>
+         </iconset>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>40</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="3" column="3">
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>40</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="0" column="0">
+       <widget class="QLabel" name="MetalogFileLabel">
+        <property name="text">
+         <string>Langer File Name Test Lorem Ipsum Lorem Ipsum</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="3">
+       <widget class="QPushButton" name="RemoveButton">
+        <property name="toolTip">
+         <string>Remove metalog file</string>
+        </property>
+        <property name="styleSheet">
+         <string notr="true"/>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset>
+          <normalon>:/metavis/Resources/close.svg</normalon>
+         </iconset>
+        </property>
+        <property name="autoDefault">
+         <bool>false</bool>
+        </property>
+        <property name="default">
+         <bool>false</bool>
+        </property>
+        <property name="flat">
+         <bool>false</bool>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0" colspan="4">
+       <widget class="QProgressBar" name="progressBar">
+        <property name="value">
+         <number>100</number>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+        </property>
+        <property name="textVisible">
+         <bool>true</bool>
+        </property>
+        <property name="invertedAppearance">
+         <bool>false</bool>
+        </property>
+        <property name="format">
+         <string>%p%</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2" colspan="2">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>Status: Ready</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+  <include location="metavis.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/metavis/Plott.cpp b/metavis/Plott.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..de4bbcb885d57e286f57c99fda73fdb9432ac670
--- /dev/null
+++ b/metavis/Plott.cpp
@@ -0,0 +1,520 @@
+#include "pch.h"
+#include "Plott.h"
+#include "util.h"
+
+
+
+#include <chrono>
+
+#define X_AXIS_GAP_AMOUNT 5
+#define Y_AXIS_GAP_AMOUNT 10
+#define X_AXIS_NUMBER_LINE_LENGTH 5
+#define Y_AXIS_NUMBER_LINE_LENGTH 5
+#define X_AXIS_NUMBER_GAP_LENGTH 10
+#define Y_AXIS_NUMBER_GAP_LENGTH 30
+#define X_AXIS_LEGEND_TOP_BEGIN 12
+#define Y_AXIS_LEGEND_LEFT_BEGIN 12
+
+#define MARGIN_TOP 20
+#define MARGIN_BOTTOM 25
+#define MARGIN_LEFT 50
+#define MARGIN_RIGHT 10
+
+
+
+Plott::Plott(QWidget *parent)
+	: QWidget(parent)
+{
+	setFocusPolicy(Qt::ClickFocus);
+}
+
+Plott::~Plott()
+{
+}
+void Plott::setVisibleWindow(double xMin, double xMax, double yMin, double yMax)
+{
+	window.xMin = xMin;
+	window.xMax = xMax;
+	window.yMin = yMin;
+	window.yMax = yMax;
+}
+void Plott::setDefaultVisibleWindow(double xMin, double xMax, double yMin, double yMax)
+{
+	defaultWindow.xMin = xMin;
+	defaultWindow.xMax = xMax;
+	defaultWindow.yMin = yMin;
+	defaultWindow.yMax = yMax;
+}
+void Plott::resetToDefaultWindow()
+{
+	window.xMin = defaultWindow.xMin;
+	window.xMax = defaultWindow.xMax;
+	window.yMin = defaultWindow.yMin;
+	window.yMax = defaultWindow.yMax;
+}
+void Plott::setAxisLegend(QString xAxisLegend, QString yAxisLegend)
+{
+	this->xAxisLegend = xAxisLegend;
+	this->yAxisLegend = yAxisLegend;
+}
+QPointF Plott::transformGraphToView(QPointF graphpoint) const
+{
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+	return QPointF((graphpoint.x() - window.xMin) * stregth_factorX, (window.yMax - graphpoint.y()) * stregth_factorY) + translation;
+}
+QPointF Plott::transformGraphToView(QPointF graphpoint, double stregth_factorX, double stregth_factorY, QPointF translation) const
+{
+	return QPointF((graphpoint.x() - window.xMin) * stregth_factorX, (window.yMax - graphpoint.y()) * stregth_factorY) + translation;
+}
+QPointF Plott::transformViewToGraph(QPointF viewpoint) const
+{
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+	return QPointF(((viewpoint.x() - translation.x()) / stregth_factorX) + window.xMin, window.yMax - ((viewpoint.y() - translation.y()) / stregth_factorY));
+}
+
+QPointF Plott::transformViewToGraph(QPointF viewpoint, double stregth_factorX, double stregth_factorY, QPointF translation) const
+{
+	return QPointF(((viewpoint.x() - translation.x()) / stregth_factorX) + window.xMin, window.yMax - ((viewpoint.y() - translation.y()) / stregth_factorY));
+}
+
+
+
+
+void Plott::drawData(QPainter& painter)
+{
+}
+
+QRect Plott::getDisplayRect() const
+{
+	QRect graphDisplayRect(rect());
+
+	graphDisplayRect.setBottom(graphDisplayRect.bottom() - MARGIN_BOTTOM);
+	graphDisplayRect.setLeft(graphDisplayRect.left() + MARGIN_LEFT);
+	graphDisplayRect.setTop(graphDisplayRect.top() + MARGIN_TOP);
+	graphDisplayRect.setRight(graphDisplayRect.right() - MARGIN_RIGHT);
+	graphDisplayRect.setWidth(graphDisplayRect.width() - (graphDisplayRect.width() % X_AXIS_GAP_AMOUNT) + 1);
+	graphDisplayRect.setHeight(graphDisplayRect.height() - (graphDisplayRect.height() % Y_AXIS_GAP_AMOUNT) + 1);
+	return graphDisplayRect;
+}
+
+
+// Draws the axis
+void Plott::paintEvent(QPaintEvent* event)
+{
+	std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
+	
+	QRect graphDisplayRect = getDisplayRect();
+	int xGap = graphDisplayRect.width() / X_AXIS_GAP_AMOUNT;
+	int yGap = graphDisplayRect.height() / Y_AXIS_GAP_AMOUNT;
+	if(enableGrid){
+		QPainterPath gridPath;
+		for (int i = 1; i < X_AXIS_GAP_AMOUNT; i++) {
+			gridPath.moveTo(graphDisplayRect.left() + i * xGap, graphDisplayRect.top());
+			gridPath.lineTo(graphDisplayRect.left() + i * xGap, graphDisplayRect.bottom());
+		}
+		
+		for (int i = 0; i < Y_AXIS_GAP_AMOUNT + 1; i++) {
+			gridPath.moveTo(graphDisplayRect.left(), graphDisplayRect.bottom() - i * yGap);
+			gridPath.lineTo(graphDisplayRect.right(), graphDisplayRect.bottom() - i * yGap);
+		}
+		QPen graypen(QColor(150, 150, 150));
+		painter.setPen(graypen);
+		painter.drawPath(gridPath);
+	}
+	
+	drawData(painter);
+	
+	//Draw White Rect for axis
+	QPen blackpen(QColor(0, 0, 0));
+	blackpen.setWidth(1);
+	QPen whitePen(QColor(255, 255, 255));
+	whitePen.setWidth(1);
+	painter.setPen(whitePen);
+	painter.setBrush(whitePen.color());
+	QRect leftRect(rect().topLeft(), QPoint(graphDisplayRect.left() - 1, rect().bottom()));
+	QRect topRect(rect().topLeft(), QPoint(rect().right(), graphDisplayRect.top() - 1));
+	QRect bottomRect(QPoint(rect().left(), graphDisplayRect.bottom()), rect().bottomRight());
+	QRect rightRect(QPoint(graphDisplayRect.right(), rect().top()), rect().bottomRight());
+	painter.drawRect(leftRect);
+	painter.drawRect(topRect);
+	painter.drawRect(bottomRect);
+	painter.drawRect(rightRect);
+	painter.setBrush(Qt::BrushStyle::NoBrush);
+
+
+
+
+	//Font for Axis;
+	painter.setFont(QFont("Arial", 8));
+	//draw X-Axis
+	painter.setPen(blackpen);
+	QRect xAxisRect(QPoint(graphDisplayRect.left(), graphDisplayRect.bottom()), QPoint(graphDisplayRect.right(), rect().bottom()));
+	QPainterPath xAxisPath;
+	xAxisPath.moveTo(xAxisRect.left(), xAxisRect.top());
+	xAxisPath.lineTo(xAxisRect.right(), xAxisRect.top());
+
+	QRect textRect(0, 0, 40, 9);
+
+	for (int i = 0; i < X_AXIS_GAP_AMOUNT + 1; i++) {
+		xAxisPath.moveTo(xAxisRect.left() + i * xGap, xAxisRect.top() + X_AXIS_NUMBER_LINE_LENGTH);
+		xAxisPath.lineTo(xAxisRect.left() + i * xGap, xAxisRect.top());
+		textRect.moveCenter(QPoint(xAxisRect.left() + i * xGap, xAxisRect.top() + X_AXIS_NUMBER_GAP_LENGTH));
+		painter.drawText(textRect, Qt::AlignCenter, QString::number(util::linearInterpolate(window.xMin, window.xMax, (1/ (double)X_AXIS_GAP_AMOUNT )*i), 'f', 1));
+	}
+	
+	painter.drawPath(xAxisPath);
+	//Draw XAxisLegend
+	QRect xAxisLegendRect(QPoint(xAxisRect.left(), rect().bottom() - X_AXIS_LEGEND_TOP_BEGIN), rect().bottomRight());
+	painter.drawText(xAxisLegendRect, Qt::AlignCenter, xAxisLegend);
+
+	//draw Y-Axis
+	QRect yAxisRect(QPoint(rect().left(), graphDisplayRect.top()), QPoint(graphDisplayRect.left(), graphDisplayRect.bottom()));
+	QPainterPath yAxisPath;
+	yAxisPath.moveTo(yAxisRect.right(), yAxisRect.bottom());
+	yAxisPath.lineTo(yAxisRect.right(), yAxisRect.top());
+	
+	for (int i = 0; i < Y_AXIS_GAP_AMOUNT + 1; i++) {
+		yAxisPath.moveTo(yAxisRect.right() - Y_AXIS_NUMBER_LINE_LENGTH, yAxisRect.bottom() - i * yGap);
+		yAxisPath.lineTo(yAxisRect.right(), yAxisRect.bottom() - i * yGap);
+		textRect.moveCenter(QPoint(yAxisRect.right() - Y_AXIS_NUMBER_GAP_LENGTH, yAxisRect.bottom() - i * yGap));
+		painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, QString::number(util::linearInterpolate(window.yMin, window.yMax, (1 / (double)Y_AXIS_GAP_AMOUNT) * i), 'f', 1));
+	}
+	painter.drawPath(yAxisPath);
+	//Draw YAxisLegend
+	//to draw vertical the painter have to translated and rotated (order is crucial)
+	QRect yAxisLegendRect(0, 0, graphDisplayRect.bottom(), Y_AXIS_LEGEND_LEFT_BEGIN);
+	painter.translate(0,graphDisplayRect.bottom());
+	painter.rotate(-90.0);
+	painter.drawText(yAxisLegendRect, Qt::AlignCenter, yAxisLegend);
+	painter.rotate(+90.0);
+	painter.translate(0, -graphDisplayRect.bottom());
+
+
+
+	if (isLeftMousePressed) {
+		QColor blue(0, 122, 204);
+		QColor gray(120, 120, 120);
+		//QPointF value = transformViewToGraph(oldPositionForMouseEvent);
+		QPointF viewPoint = transformGraphToView(mousePressedValue);
+		if (graphDisplayRect.top() <= viewPoint.y() && viewPoint.y() <= graphDisplayRect.bottom()) {
+			painter.setPen(gray);
+			painter.drawLine(QPointF(graphDisplayRect.left() - Y_AXIS_NUMBER_LINE_LENGTH, viewPoint.y()), QPointF(graphDisplayRect.right(), viewPoint.y()));
+			textRect.moveCenter(QPoint(graphDisplayRect.left() - Y_AXIS_NUMBER_GAP_LENGTH, viewPoint.y()));
+			painter.fillRect(textRect, whitePen.color());
+			painter.setPen(blue);
+			painter.drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, QString::number(mousePressedValue.y(), 'f', 1));
+		}
+		if (graphDisplayRect.left() <= viewPoint.x() && viewPoint.x() <= graphDisplayRect.right()) {
+			painter.setPen(gray);
+			painter.drawLine(QPointF(viewPoint.x(), graphDisplayRect.top()), QPointF(viewPoint.x(), graphDisplayRect.bottom() + X_AXIS_NUMBER_LINE_LENGTH));
+			textRect.moveCenter(QPoint(viewPoint.x(), graphDisplayRect.bottom() + X_AXIS_NUMBER_GAP_LENGTH));
+			painter.fillRect(textRect, whitePen.color());
+			painter.setPen(blue);
+			painter.drawText(textRect, Qt::AlignCenter, QString::number(mousePressedValue.x(), 'f', 1));
+		}
+	}
+	if (isRightMousePressed) {
+		QColor blue(0, 122, 204);
+		painter.setPen(blue);
+		painter.drawRect(QRectF(transformGraphToView(this->mousePressedValue), oldPositionForMouseEvent));
+	}
+	std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
+	std::chrono::milliseconds timeElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+	
+}
+
+void Plott::keyPressEvent(QKeyEvent* event)
+{
+	double percent = 0.1;
+	switch (event->key()) {
+	case Qt::Key_Up:
+		window.moveUp(percent);
+		break;
+	case Qt::Key_Right:
+		window.moveRight(percent);
+		break;
+	case Qt::Key_Left:
+		window.moveLeft(percent);
+		break;
+	case Qt::Key_Down:
+		window.moveDown(percent);
+		break;
+	case Qt::Key_PageUp:
+	case Qt::Key_Plus:
+		if (event->modifiers() & Qt::ShiftModifier) {
+			//ZoomInY
+			window.ZoomInY(percent);
+		}
+		else if (event->modifiers() & Qt::ControlModifier) {
+			//ZoomInX
+			window.ZoomInX(percent);
+		}
+		else {
+			//Zoom
+			window.ZoomIn(percent);
+		}
+		break;
+	case Qt::Key_PageDown:
+	case Qt::Key_Minus:
+		if (event->modifiers() & Qt::ShiftModifier) {
+			//ZoomOutX
+			window.ZoomOutY(percent);
+		}
+		else if (event->modifiers() & Qt::ControlModifier) {
+			//ZoomOutX
+			window.ZoomOutX(percent);
+		}
+		else {
+			//ZoomOut
+			window.ZoomOut(percent);
+		}
+		break;
+	case Qt::Key_R:
+		resetToDefaultWindow();
+	default:
+		QWidget::keyPressEvent(event);
+	}
+	update();
+}
+
+void Plott::wheelEvent(QWheelEvent* event)
+{
+	double percent = 0.1;
+	QPoint numDegrees = event->angleDelta() / 8;
+	if (!numDegrees.isNull()) {
+		QPoint numSteps = numDegrees / 15;
+		switch (numSteps.y()) {
+		case 1:
+			if (event->modifiers() & Qt::ShiftModifier) {
+				window.ZoomInY(percent);
+			}
+			else if (event->modifiers() & Qt::ControlModifier) {
+				window.ZoomInX(percent);
+			}
+			else {
+				window.ZoomIn(percent);
+			}
+			break;
+		case -1:
+			if (event->modifiers() & Qt::ShiftModifier) {
+				window.ZoomOutY(percent);
+			}
+			else if (event->modifiers() & Qt::ControlModifier) {
+				window.ZoomOutX(percent);
+			}
+			else {
+				window.ZoomOut(percent);
+			}
+			break;
+		default:
+			break;
+		}
+		update();
+	}
+
+	event->accept();
+}
+
+void Plott::mouseMoveEvent(QMouseEvent* event)
+{
+	if (isLeftMousePressed) {
+		//Move window by calculating the change in visibleWindow
+		QPointF delta = event->pos() - oldPositionForMouseEvent;
+		oldPositionForMouseEvent = event->pos();
+		double rangeX = window.rangeX();
+		int width = (rect().right() - 10) - (rect().left() + 50);
+		width -= (width % X_AXIS_GAP_AMOUNT) + 1;
+		double pixelWidthX = rangeX / (double)width;
+		double rangeY = window.rangeY();
+		int height = (rect().bottom() - 20) - (rect().top() + 20);
+		height -= (height % Y_AXIS_GAP_AMOUNT) + 1;
+		double pixelWidthY = rangeY / (double)height;
+	
+		window.xMin += -delta.x() * pixelWidthX;
+		window.xMax += -delta.x() * pixelWidthX;
+		window.yMin += delta.y() * pixelWidthY;
+		window.yMax += delta.y() * pixelWidthY;
+		update();
+	}
+	else if (isRightMousePressed) {
+
+		oldPositionForMouseEvent = event->pos();
+		update();
+	}
+	
+}
+
+void Plott::mousePressEvent(QMouseEvent* event)
+{
+	if (event->buttons() == Qt::LeftButton) {
+		isLeftMousePressed = true;
+	}
+	else if (event->buttons() == Qt::RightButton) {
+		isRightMousePressed = true;
+	}
+	//To calculate the delta for mouse move  event
+	oldPositionForMouseEvent = event->pos();
+	mousePressedValue = transformViewToGraph(oldPositionForMouseEvent);
+	update();
+}
+
+void Plott::mouseReleaseEvent(QMouseEvent* event)
+{
+	if (isRightMousePressed) {
+		QPointF mouseViewPostion = transformGraphToView(mousePressedValue);
+		if (std::abs(mouseViewPostion.x() - oldPositionForMouseEvent.x()) > 0 || std::abs(mouseViewPostion.y() - oldPositionForMouseEvent.y()) > 0) {
+					//set visible window to selection 
+					VisibleWindow selectedWindow(0,0,0,0);
+					QPointF endPosition = transformViewToGraph(oldPositionForMouseEvent);
+					bool pressedIsLowerX = mousePressedValue.x() < endPosition.x();
+					selectedWindow.xMin = pressedIsLowerX? mousePressedValue.x() : endPosition.x();
+					selectedWindow.xMax = pressedIsLowerX ? endPosition.x() : mousePressedValue.x();
+
+					bool pressedIsLowerY = mousePressedValue.y() < endPosition.y();
+					selectedWindow.yMin = pressedIsLowerY ? mousePressedValue.y() : endPosition.y();
+					selectedWindow.yMax = pressedIsLowerY ? endPosition.y() : mousePressedValue.y();
+					handleSelectedWindow(selectedWindow, event);
+		}
+	}
+	isLeftMousePressed = false;
+	isRightMousePressed = false;
+	
+	update();
+}
+
+void Plott::handleSelectedWindow(VisibleWindow& window, QMouseEvent* event)
+{
+	setWindow(window);
+}
+
+void Plott::setWindow(VisibleWindow& window)
+{
+	this->window = window;
+	update();
+}
+
+void VisibleWindow::moveUp(double percent)
+{
+	double range = rangeY();
+	yMin += percent * range;
+	yMax += percent * range;
+
+}
+
+void VisibleWindow::moveDown(double percent)
+{
+	double range = rangeY();
+	yMin -= percent * range;
+	yMax -= percent * range;
+}
+
+void VisibleWindow::moveLeft(double percent)
+{
+	double range = rangeX();
+	xMin -= percent * range;
+	xMax -= percent * range;
+}
+
+void VisibleWindow::moveRight(double percent)
+{
+	double range = rangeX();
+	xMin += percent * range;
+	xMax += percent * range;
+}
+
+void VisibleWindow::ZoomIn(double percent)
+{
+	//Both sides same percentage
+	percent /= 2; 
+	double Xrange = rangeX();
+	if (Xrange == 0) Xrange = 1.0;
+	xMin += percent * Xrange;
+	xMax -= percent * Xrange;
+	double Yrange = rangeY();
+	if (Yrange == 0) Yrange = 1.0;
+	yMin += percent * Yrange;
+	yMax -= percent * Yrange;
+}
+
+void VisibleWindow::ZoomInX(double percent)
+{
+	percent /= 2;
+	double Xrange = rangeX();
+	if (Xrange == 0) Xrange = 1.0;
+	xMin += percent * Xrange;
+	xMax -= percent * Xrange;
+}
+
+void VisibleWindow::ZoomInY(double percent)
+{
+	percent /= 2;
+	double Yrange = rangeY();
+	if (Yrange == 0) Yrange = 1.0;
+	yMin += percent * Yrange;
+	yMax -= percent * Yrange;
+}
+
+void VisibleWindow::ZoomOut(double percent)
+{
+	//Both sides same percentage
+	percent /= 2;
+	double Xrange = rangeX();
+	if (Xrange == 0) Xrange = 1.0;
+	xMin -= percent * Xrange;
+	xMax += percent * Xrange;
+	double Yrange = rangeY();
+	if (Yrange == 0) Yrange = 1.0;
+	yMin -= percent * Yrange;
+	yMax += percent * Yrange;
+}
+
+void VisibleWindow::ZoomOutX(double percent)
+{
+	percent /= 2;
+	double Xrange = rangeX();
+	if (Xrange == 0) Xrange = 1.0;
+	xMin -= percent * Xrange;
+	xMax += percent * Xrange;
+}
+
+void VisibleWindow::ZoomOutY(double percent)
+{
+	percent /= 2;
+	double Yrange = rangeY();
+	if (Yrange == 0) Yrange = 1.0;
+	yMin -= percent * Yrange;
+	yMax += percent * Yrange;
+}
+
+double VisibleWindow::rangeX() const
+{
+	return xMax - xMin;
+}
+
+double VisibleWindow::rangeY() const
+{
+	return yMax - yMin;
+}
+
+bool VisibleWindow::inBoundX(QPointF point) const
+{
+	return point.x() >= xMin && point.x() <= xMax;
+}
+
+bool VisibleWindow::inBoundY(QPointF point) const
+{
+	return point.y() >= yMin && point.y() <= yMax;
+}
+
+bool VisibleWindow::inBound(QPointF point) const
+{
+	return inBoundX(point) && inBoundY(point);
+}
diff --git a/metavis/Plott.h b/metavis/Plott.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4d44f714eb148fb0a621f837c89a0082f78551d
--- /dev/null
+++ b/metavis/Plott.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <QWidget>
+#include <QPointF>
+#include <QPainter>
+#include <QMenu>
+
+
+
+struct VisibleWindow {
+	double xMin, xMax, yMin, yMax;
+	VisibleWindow(double xMin, double xMax, double yMin, double yMax):
+	xMin(xMin), xMax(xMax), yMin(yMin), yMax(yMax){}
+	void moveUp(double percent);
+	void moveDown(double percent);
+	void moveLeft(double percent);
+	void moveRight(double percent);
+	void ZoomIn(double percent);
+	void ZoomInX(double percent);
+	void ZoomInY(double percent);
+	void ZoomOut(double percent);
+	void ZoomOutX(double percent);
+	void ZoomOutY(double percent);
+	double rangeX() const;
+	double rangeY() const;
+	bool inBoundX(QPointF point) const;
+	bool inBoundY(QPointF point) const;
+	bool inBound(QPointF point) const;
+};
+
+class Plott : public QWidget
+{
+	Q_OBJECT
+
+public:
+	//Grid
+	bool enableGrid = false;
+
+	Plott(QWidget *parent);
+	~Plott();
+	//Setter
+	void setVisibleWindow(double xMin, double xMax, double yMin, double yMax);
+	void setDefaultVisibleWindow(double xMin, double xMax, double yMin, double yMax);
+	void setAxisLegend(QString xAxisLegend, QString yAxisLegend);
+	//sets the window to the default window
+	void virtual resetToDefaultWindow();
+
+	QPointF transformGraphToView(QPointF graphpoint) const;
+	QPointF transformGraphToView(QPointF graphpoint, double stregth_factorX, double stregth_factorY, QPointF translation) const;
+	QPointF transformViewToGraph(QPointF viewpoint) const;
+	QPointF transformViewToGraph(QPointF viewpoint, double stregth_factorX, double stregth_factorY, QPointF translation) const;
+protected:
+	//Represent the visual area in graph space that is shown in view space
+	VisibleWindow window = VisibleWindow(0.0, 10, 0, 10);
+	VisibleWindow defaultWindow = VisibleWindow(0.0, 10, 0, 10);
+
+
+
+	virtual void drawData(QPainter& painter);
+	//Returns the area in view space where 
+	QRect getDisplayRect() const;
+	
+	//Display
+	virtual void paintEvent(QPaintEvent* event) override;
+	//Process user input events
+	virtual void keyPressEvent(QKeyEvent* event) override;
+	virtual void wheelEvent(QWheelEvent* event) override;
+	virtual void mouseMoveEvent(QMouseEvent* event) override;
+	virtual void mousePressEvent(QMouseEvent* event) override;
+	virtual void mouseReleaseEvent(QMouseEvent* event) override;
+
+	virtual void handleSelectedWindow(VisibleWindow& window, QMouseEvent* event);
+	void setWindow(VisibleWindow& window);
+private:
+	
+	//Axis Legends
+	QString xAxisLegend = "X Legende", yAxisLegend = "Y Legend";
+	//MouseControl
+	bool isLeftMousePressed = false;
+	bool isRightMousePressed = false;
+	QPointF oldPositionForMouseEvent;
+	QPointF mousePressedValue;
+};
diff --git a/metavis/Project.cpp b/metavis/Project.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..574e7b4322a60009f36cbae499e6fb30120ee9c5
--- /dev/null
+++ b/metavis/Project.cpp
@@ -0,0 +1,43 @@
+#include "pch.h"
+#include "Project.h"
+
+void Project::addFile(std::string metaLogFile)
+{
+	//If file exist and can be open
+	runList.push_back(metaLogFile);
+}
+
+void Project::removeRunData(RunData* data)
+{
+	//Remove all series with this rundata
+	auto iter = std::remove_if(runList.begin(), runList.end(), [data](RunData& run) {return (data == &run); });
+	runList.erase(iter, runList.end());
+}
+
+
+
+void Project::removeLastData()
+{
+	if(!runList.empty()) runList.pop_back();
+}
+
+void Project::removeIndex(int index)
+{
+	//TODO 
+}
+
+void Project::removeName(std::string fileName)
+{
+	auto iter = std::remove_if(runList.begin(), runList.end(), [fileName](RunData& series) {return (fileName == series.name); });
+	runList.erase(iter, runList.end());
+}
+
+void Project::clearDataList()
+{	
+	runList.clear();
+}
+
+std::list<RunData>& Project::getRunList()
+{
+	return runList;
+}
diff --git a/metavis/Project.h b/metavis/Project.h
new file mode 100644
index 0000000000000000000000000000000000000000..56f3d09d7b4123e609c65a29c4feac58e512d61d
--- /dev/null
+++ b/metavis/Project.h
@@ -0,0 +1,20 @@
+#pragma once
+#include <vector>
+#include <string>
+#include "RunData.h"
+
+
+class Project
+{
+public:	
+	void addFile(std::string fileName);
+	void removeRunData(RunData* data);
+	void removeLastData();
+	void removeIndex(int index);
+	void removeName(std::string fileName);
+	void clearDataList();
+	std::list<RunData>& getRunList();
+private:
+	std::list<RunData> runList;
+};
+
diff --git a/metavis/ProjectManager.cpp b/metavis/ProjectManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..171db3771089c1e05119a3d64936300db4b15f32
--- /dev/null
+++ b/metavis/ProjectManager.cpp
@@ -0,0 +1,229 @@
+#include "pch.h"
+#include <QTreeWidget>
+#include <QAction>
+#include <QMenu>
+#include "ProjectManager.h"
+#include <QtConcurrent>
+
+ProjectManager::ProjectManager(metavis* owner)
+	: QWidget(owner), owner(owner)
+{
+	QGridLayout* gridlayout = new QGridLayout();
+	gridlayout->setContentsMargins(0, 0, 0, 0);
+	treeWidget = new QTreeWidget();
+	treeWidget->setColumnCount(1);
+	treeWidget->setHeaderHidden(true);
+	treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+	connect(treeWidget, &QTreeWidget::customContextMenuRequested, this, &ProjectManager::prepareMenu);
+	connect(treeWidget, &QTreeWidget::itemActivated, this, &ProjectManager::itemClicked);
+	projectItem = new QTreeWidgetItem(treeWidget, QStringList("Project"), ProjectManager::Types::ProjectHeader);
+	projectItem->setExpanded(true);
+	gridlayout->addWidget(treeWidget);
+	this->setLayout(gridlayout);
+
+
+	//Create Menus
+	projectMenu = new QMenu(this);
+	QAction* metaLogAddAction = new QAction("Add .csv-File...");
+	QIcon test(":/metavis/Resources/file.svg");
+	metaLogAddAction->setIcon(test);
+	connect(metaLogAddAction, &QAction::triggered, this, &ProjectManager::openFileDialog);
+	//connect(metaLogAddAction, &QAction::triggered, this, [this]() { project.addFile(); });
+	QAction* removeAllFilesAction = new QAction("Remove all .csv-Files");
+	removeAllFilesAction->setIcon(QIcon(":/metavis/Resources/csv_remove.svg"));
+	connect(removeAllFilesAction, &QAction::triggered, this, [this]() {
+		for (RunData& data : project.getRunList()) {
+			this->owner->removeRunDataFromAllViews(&data);
+		}
+		project.clearDataList();
+		createTreeWidget();
+		});
+	projectMenu->addAction(metaLogAddAction);
+	projectMenu->addAction(removeAllFilesAction);
+	
+	metalogFileMenu = new QMenu(this);
+	QIcon removeIcon(":/metavis/Resources/close_big_red.svg");
+	removeMetalogFileAction = new QAction("Remove");
+	removeMetalogFileAction->setIcon(removeIcon);
+	//connect(removeMetalogFileAction, &QAction::triggered, this, [this]() {project.clearDataList(); });
+	selectAction = new QAction("Show");
+	selectAction->setIcon(QIcon(":/metavis/Resources/arrow_right.svg"));
+	metalogFileMenu->addAction(selectAction);
+	metalogFileMenu->addAction(removeMetalogFileAction);
+	singleRunMenu = new QMenu(this);
+	singleRunMenu->addAction(selectAction);
+	connect(&watcher, &QFutureWatcher<void>::finished, this, &ProjectManager::displayNewFile);
+	
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("ProjectManager");
+	lastPath = settings.value("path", "").toString();
+	settings.endGroup();
+}
+
+ProjectManager::~ProjectManager()
+{
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("ProjectManager");
+	settings.setValue("path", lastPath);
+	settings.endGroup();
+}
+
+
+
+
+void ProjectManager::openFileDialog()
+{
+	qDebug() << "openFile";
+	this->lastPath != "";
+	QStringList pathList = QFileDialog::getOpenFileNames(this, "Open logFile",(this->lastPath != "")? lastPath :QStandardPaths::displayName(QStandardPaths::DesktopLocation), "Logfile (*.csv)");
+	if (pathList.isEmpty()) {
+		qDebug() << "No file selected";
+		return;
+	}
+	QDir d = QFileInfo(pathList.front()).absoluteDir();
+	lastPath = d.absolutePath();
+	owner->showStatusBarLoading();
+	//this->loadingFuture = std::async(std::launch::async, static_cast<void(ProjectManager::*)(std::list<QString>)>(&ProjectManager::openFiles), this, stdList);
+	future = QtConcurrent::run(this, &ProjectManager::openFiles, pathList);
+	watcher.setFuture(future);
+}
+
+
+void ProjectManager::openFiles(QStringList pathList)
+{
+	int size = project.getRunList().size();
+	for (QString& string: pathList) {
+		qDebug() << "file:" << string;
+		project.addFile(string.toStdString());
+	}
+	for (std::list<RunData>::iterator iter = std::next(project.getRunList().begin(), size); iter != project.getRunList().end(); iter++) {
+		//owner->addRunDataToCompareViews(&*iter);
+	}
+}
+
+void ProjectManager::displayNewFile()
+{
+	owner->selectRunData(&project.getRunList().back());
+	owner->selectSingleRun(&project.getRunList().back().singleRunList.front());
+	createTreeWidget();
+	owner->clearStatusBar();
+}
+
+
+
+
+
+void ProjectManager::createTreeWidget()
+{
+	//remove all clidren
+	for (QTreeWidgetItem* item : projectItem->takeChildren()) {
+		delete item;
+	}
+	for (RunData& run : project.getRunList()) {
+		qDebug() << "RunList add" << QString::fromStdString(run.name);
+		QTreeWidgetItem* item = new QTreeWidgetItem(projectItem, QStringList(QString::fromStdString(run.name)), ProjectManager::Types::LogFile);
+		QVariant variant(QVariant::fromValue(static_cast<void*>(&run)));
+		item->setData(1, Qt::UserRole, variant);
+		item->setExpanded(true);
+		int count = 0;
+		for (SingleRun& srun : run.singleRunList) {
+			QTreeWidgetItem* runitem = new QTreeWidgetItem(item, QStringList(QString::fromStdString(run.name) + "[" + QString::number(count) + "]"), ProjectManager::Types::Run);
+			QVariant srunVariant(QVariant::fromValue(static_cast<void*>(&srun)));
+			runitem->setData(1, Qt::UserRole, srunVariant);
+			count++;
+		}
+	}
+	
+}
+
+void ProjectManager::showItem(QTreeWidgetItem* item)
+{
+	switch (item->type()) {
+	case LogFile:
+	{
+		RunData* data = static_cast<RunData*>(item->data(1, Qt::UserRole).value<void*>());
+		if (data != nullptr) {
+			owner->selectRunData(data);
+		}
+		break;
+	}
+	case Run:
+	{
+		SingleRun* data = static_cast<SingleRun*>(item->data(1, Qt::UserRole).value<void*>());
+		if (data != nullptr) {
+			owner->selectSingleRun(data);
+		}
+		break;
+	}		
+	default:
+		break;
+	}
+	
+}
+
+
+
+
+
+void ProjectManager::itemClicked(QTreeWidgetItem* item, int column)
+{
+	switch (item->type()) {
+	case Types::Graph:
+		break;
+	case Types::GraphManger:
+		break;
+	case Types::LogFile:
+	case Types::Run:
+		showItem(item);
+		break;
+	case Types::LogManger:
+		break;
+	default:
+		break;
+	}
+}
+
+
+void ProjectManager::prepareMenu(const QPoint& pos) {
+	QTreeWidgetItem* item = treeWidget->itemAt(pos);
+	if (item == nullptr) return;
+	switch (item->type()) {
+	case Types::Graph:
+		//graphMenu->exec(treeWidget->mapToGlobal(pos));
+		break;
+	case Types::GraphManger:
+		break;
+	case Types::Run:
+	{
+		QAction* used = singleRunMenu->exec(treeWidget->mapToGlobal(pos));
+		if (used == selectAction) {
+			showItem(item);
+		}
+		break;
+	}
+	case Types::LogFile:
+	{
+		QAction* used = metalogFileMenu->exec(treeWidget->mapToGlobal(pos));
+		if (used == removeMetalogFileAction) {
+			RunData* data = static_cast<RunData*>(item->data(1, Qt::UserRole).value<void*>());
+			owner->removeRunDataFromAllViews(data);
+			project.removeRunData(data);
+			createTreeWidget();
+		}
+		else if (used == selectAction) {
+			showItem(item);
+		}
+		break;
+	}
+	
+	case Types::ProjectHeader:
+		projectMenu->exec(treeWidget->mapToGlobal(pos));
+		break;
+	default:
+		break;
+	}
+
+}
+
diff --git a/metavis/ProjectManager.h b/metavis/ProjectManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..54515ced0362bc6b5170b573aa50fc675490e237
--- /dev/null
+++ b/metavis/ProjectManager.h
@@ -0,0 +1,45 @@
+#pragma once
+#include <QTreeWidget>
+#include <QWidget>
+#include <list>
+#include "metavis.h"
+#include <future>
+#include <QStringList>
+#include <QFuture>
+#include <QFutureWatcher>
+#include "Project.h"
+class metavis;
+
+class ProjectManager : public QWidget
+{
+	Q_OBJECT
+
+public:
+	ProjectManager(metavis* owner);
+	~ProjectManager();
+
+
+	Project project;
+	void openFileDialog();
+	void openFiles(QStringList pathlist);
+	QMenu* projectMenu;
+private:
+	std::future<void> loadingFuture = std::async(std::launch::async, []() {});
+	QFuture<void> future;
+	QFutureWatcher<void> watcher = QFutureWatcher<void>(this);
+	metavis* owner;
+	QTreeWidget* treeWidget;
+	QTreeWidgetItem* projectItem;
+	void displayNewFile();
+	QMenu* metalogFileMenu;
+	QMenu* singleRunMenu;
+	QAction* removeMetalogFileAction;
+	QAction* selectAction;
+	enum Types{ LogManger = 1001, LogFile, Run, GraphManger, Graph, ProjectHeader};
+	QString lastPath;
+	void createTreeWidget();
+	void showItem(QTreeWidgetItem* item);
+private slots:
+	void prepareMenu(const QPoint& pos);
+	void itemClicked(QTreeWidgetItem* item, int column);
+};
diff --git a/metavis/RangeSlider.cpp b/metavis/RangeSlider.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5035ec76ed42712c8fdc503806d6d94de16b2515
--- /dev/null
+++ b/metavis/RangeSlider.cpp
@@ -0,0 +1,256 @@
+#include "pch.h"
+#include "RangeSlider.h"
+#include <QDebug>
+#include <QComboBox>
+
+#include "util.h"
+
+RangeSlider::RangeSlider(QWidget *parent)
+	: QWidget(parent), sliderRangeColor(200,200,200), rangeColor(0,122,204)
+{
+	QVBoxLayout* layoutOuter = new QVBoxLayout(this);
+	layoutOuter->setContentsMargins(0, 0, 0, 0);
+	QHBoxLayout* buttonPanelLayout = new QHBoxLayout();
+	buttonPanelLayout->setContentsMargins(0, 0, 0, 0);
+	layoutOuter->addLayout(buttonPanelLayout);
+	layoutOuter->insertStretch(1);
+	titleLabel = new QLabel("Title");
+	buttonPanelLayout->addWidget(titleLabel);
+	buttonPanelLayout->insertStretch(1);
+	
+	QComboBox* combobox = new QComboBox(this);
+	combobox->addItem("Range");
+	combobox->addItem("Iteration");
+	connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+		this, [this](int index) {this->setMode((DisplayMode)index); });
+	buttonPanelLayout->addWidget(combobox);
+	this->setMaximumHeight(70);
+	this->setMinimumHeight(70);
+}
+
+RangeSlider::~RangeSlider()
+{
+}
+
+void RangeSlider::setMinSliderValue(int value)
+{
+	value = std::clamp(value, minRange, maxRange);
+	if (value > maxSliderValue) {
+		minSliderValue = maxSliderValue;
+		maxSliderValue = value;
+		emit minChanged(minSliderValue);
+		emit maxChanged(maxSliderValue);
+	}
+	else {
+		minSliderValue = value;
+		emit minChanged(minSliderValue);
+	}
+}
+
+void RangeSlider::setMaxSliderValue(int value)
+{
+	value = std::clamp(value, minRange, maxRange);
+	if (value < minSliderValue) {
+		maxSliderValue = minSliderValue;
+		minSliderValue = value;
+		emit minChanged(minSliderValue);
+		emit maxChanged(maxSliderValue);
+	}
+	else {
+		maxSliderValue = value;
+		emit maxChanged(maxSliderValue);
+	}
+}
+
+void RangeSlider::setItertionSliderValue(int value)
+{
+	value = std::clamp(value, minRange, maxRange);
+	itertionSliderValue = value;
+	emit minChanged(itertionSliderValue);
+	emit maxChanged(itertionSliderValue);
+}
+
+void RangeSlider::setRange(int min, int max)
+{
+	if (min > max) {
+		std::swap(min, max);
+	}
+	minRange = min;
+	maxRange = max;
+}
+
+int RangeSlider::getMinRange() const
+{
+	return minRange;
+}
+
+int RangeSlider::getMaxRange() const
+{
+	return maxRange;
+}
+
+void RangeSlider::setMinRange(int value)
+{
+	if (value > maxRange) {
+		minRange = maxRange;
+		maxRange = value;
+	}
+	else {
+		minRange = value;
+	}
+	emit minChanged(minSliderValue);
+}
+
+void RangeSlider::setMaxRange(int value)
+{
+	if (value < minRange) {
+		maxRange = minRange;
+		minRange = value;
+	}
+	else {
+		maxRange = value;
+	}
+	emit maxChanged(maxSliderValue);
+}
+
+void RangeSlider::setMode(DisplayMode mode)
+{
+	this->mode = mode;
+	switch (mode) {
+	case Iteration:
+		emit minChanged(itertionSliderValue);
+		emit maxChanged(itertionSliderValue);
+		break;
+	default:
+	case Range:
+		emit minChanged(minSliderValue);
+		emit maxChanged(maxSliderValue);
+		break;
+	}
+	update();
+}
+
+void RangeSlider::setTitle(QString string)
+{
+	titleLabel->setText(string);
+}
+
+void RangeSlider::paintEvent(QPaintEvent* event)
+{
+	QPainter painter(this);
+	painter.setRenderHint(QPainter::RenderHint::HighQualityAntialiasing);
+	painter.setPen(sliderRangeColor);
+	//painter.setBrush(sliderRangeColor);
+	//FindMiddle
+	int middle = 35;
+	painter.drawRect(QRect(QPoint(minPos(), middle + 2), QPoint(maxPos(), middle - 2)));
+	painter.setPen(Qt::black);
+	painter.setFont(QFont("Arial", 8));
+	QRect textRect(0, 0, 30, 9);
+	textRect.moveCenter(QPoint(minPos(), middle + 20));
+	painter.drawText(textRect, Qt::AlignCenter, QString::number(this->minRange, 'f', 0));
+	textRect.moveCenter(QPoint(maxPos(), middle + 20));
+	painter.drawText(textRect, Qt::AlignCenter, QString::number(this->maxRange, 'f', 0));
+	
+	
+
+	
+	//DrawSlider
+	QPen pen(rangeColor);
+	pen.setWidth(2);
+	painter.setPen(pen);
+	painter.setBrush(sliderRangeColor);
+	switch (mode) {
+	case Iteration:
+	{
+		double itertionSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, itertionSliderValue);
+		double itertionSliderPos = util::linearInterpolate(minPos(), maxPos(), itertionSliderAlpha);
+
+		painter.drawEllipse(QPointF(itertionSliderPos, (double)middle + 1), 10, 10);
+		painter.setPen(Qt::black);
+		textRect.moveCenter(QPoint(itertionSliderPos, middle + 20));
+		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->itertionSliderValue, 'f', 0));
+		break;
+	}
+	default:
+	case Range:
+	{
+		double minSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, minSliderValue);
+		double minSliderPos = util::linearInterpolate(minPos(), maxPos(), minSliderAlpha);
+
+		double maxSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, maxSliderValue);
+		double maxSliderPos = util::linearInterpolate(minPos(), maxPos(), maxSliderAlpha);
+		//DrawRange
+		painter.fillRect(QRectF(QPointF(minSliderPos, (double)middle - 2), QPointF(maxSliderPos, (double)middle + 2)), rangeColor);
+		painter.drawEllipse(QPointF(minSliderPos, (double)middle + 1), 10, 10);
+		painter.drawEllipse(QPointF(maxSliderPos, (double)middle + 1), 10, 10);
+		painter.setPen(Qt::black);
+		textRect.moveCenter(QPoint(minSliderPos, middle + 20));
+		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->minSliderValue, 'f', 0));
+		textRect.moveCenter(QPoint(maxSliderPos, middle + 20));
+		painter.drawText(textRect, Qt::AlignCenter, QString::number(this->maxSliderValue, 'f', 0));
+		break;
+	}
+	}
+}
+
+void RangeSlider::mouseMoveEvent(QMouseEvent* event)
+{
+	if (childAt(event->pos()) != nullptr) {
+		return;
+	}
+	updateSliderPosition(event);
+}
+
+void RangeSlider::mousePressEvent(QMouseEvent* event)
+{
+	if (childAt(event->pos()) != nullptr) {
+		return;
+	}
+	updateSliderPosition(event);
+}
+
+
+void RangeSlider::updateSliderPosition(QMouseEvent* event)
+{
+	
+	
+	
+	//pos to alpha
+	double alpha = util::inverseLinearInterpolation(minPos(), maxPos(), event->pos().x());
+	double minSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, minSliderValue);
+	double maxSliderAlpha = util::inverseLinearInterpolation(minRange, maxRange, maxSliderValue);
+
+
+
+	double value = util::linearInterpolate(minRange, maxRange, alpha);
+	switch (mode) {
+	case Iteration:
+		setItertionSliderValue(value);
+		break;
+	default:
+	case Range:
+		double distanceToMin = std::abs(minSliderValue - value);
+		double distanceToMax = std::abs(maxSliderValue - value);
+		if (distanceToMin < distanceToMax) {
+			setMinSliderValue(value);
+		}
+		else {
+			setMaxSliderValue(value);
+		}
+		break;
+	}
+	
+	update();
+}
+
+int RangeSlider::maxPos()
+{
+	return rect().right() - 11;
+}
+
+int RangeSlider::minPos()
+{
+	return rect().left() + 11;
+}
+
diff --git a/metavis/RangeSlider.h b/metavis/RangeSlider.h
new file mode 100644
index 0000000000000000000000000000000000000000..4860c17cd485a6d463e09a5423a0916c3fee692e
--- /dev/null
+++ b/metavis/RangeSlider.h
@@ -0,0 +1,46 @@
+#pragma once
+#include <QColor>
+#include <QWidget>
+#include <QString>
+#include <QLabel>
+
+
+
+class RangeSlider : public QWidget
+{
+	Q_OBJECT
+
+	
+public:
+	enum DisplayMode{ Range, Iteration};
+	RangeSlider(QWidget *parent);
+	~RangeSlider();
+	void setMinSliderValue(int value);
+	void setMaxSliderValue(int value);
+	void setItertionSliderValue(int value);
+	void setRange(int min, int max);
+	int getMinRange() const;
+	int getMaxRange() const;
+	void setMinRange(int value);
+	void setMaxRange(int value);
+	void setMode(DisplayMode mode);
+	void setTitle(QString string);
+	//Visual Settings:
+	void setRangeColor(QColor color);
+	void setSliderRangeColor(QColor color);
+private:
+	int minRange = 0, maxRange = 100, minSliderValue = 0, maxSliderValue = 100, itertionSliderValue = 50;
+	QColor rangeColor, sliderRangeColor;
+	DisplayMode mode = DisplayMode::Range;
+	void paintEvent(QPaintEvent* event) override;
+	void mouseMoveEvent(QMouseEvent* event) override;
+	void mousePressEvent(QMouseEvent* event) override;
+	void updateSliderPosition(QMouseEvent* event);
+	QLabel* titleLabel;
+	int maxPos();
+	int minPos();
+
+signals:
+	void maxChanged(int max);
+	void minChanged(int min);
+};
diff --git a/metavis/Resources/3-up-triangle.svg b/metavis/Resources/3-up-triangle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dac8cf75bf82f8fda999650cc77ab14af3700e0a
--- /dev/null
+++ b/metavis/Resources/3-up-triangle.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--U+25B3-->
+<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="-40 0 640 180">
+   <polygon points="20 153  90 38  160 153" fill="none" stroke="#000" stroke-width="20" />  
+   <polygon points="220 153  290 38  360 153" fill="none" stroke="#000" stroke-width="20" />
+   <polygon points="420 153  490 38  560 153" fill="none" stroke="#000" stroke-width="20" />
+</svg>
\ No newline at end of file
diff --git a/metavis/Resources/arrow_right.svg b/metavis/Resources/arrow_right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7df925e87c0ad7d66bf25108920cd0ffff9b3610
--- /dev/null
+++ b/metavis/Resources/arrow_right.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="95.312px" height="95.312px" viewBox="0 0 95.312 95.312" style="enable-background:new 0 0 95.312 95.312;"
+	 xml:space="preserve">
+<g>
+	<path d="M63.408,89.924V77.131c0-1.021-0.828-1.849-1.849-1.849H33.137v0.006h-1.333c-8.453,0-15.33-6.875-15.33-15.33
+		c0-8.451,6.877-15.329,15.33-15.329l34.397-0.025L52.9,57.854c-0.688,0.686-0.688,1.901,0,2.588l8.267,8.266
+		c0.343,0.344,0.81,0.537,1.294,0.537s0.951-0.193,1.294-0.537l31.021-31.022c0.717-0.715,0.717-1.873,0-2.589L63.755,4.076
+		c-0.716-0.714-1.873-0.714-2.588,0L52.9,12.341c-0.344,0.343-0.537,0.809-0.537,1.294s0.193,0.951,0.537,1.295l13.301,13.202
+		l-34.396,0.023C14.268,28.155,0,42.422,0,59.958c0,17.537,14.268,31.806,31.805,31.806l29.756,0.009
+		C62.58,91.772,63.408,90.944,63.408,89.924z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/assignButton.svg b/metavis/Resources/assignButton.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bf45e00ad277879130cad9dc7b02c0d78161f9d8
--- /dev/null
+++ b/metavis/Resources/assignButton.svg
@@ -0,0 +1 @@
+<?xml version="1.0" ?><svg data-name="Layer 1" id="Layer_1" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:#000000;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</style></defs><title/><path class="cls-1" d="M52.74,27.78c1.95,1,2,2.73,0,3.77L15.53,51.45c-1.95,1-3.53.09-3.53-2.11V10c0-2.21,1.58-3.15,3.53-2.11Z"/></svg>
\ No newline at end of file
diff --git a/metavis/Resources/binaryIcon.svg b/metavis/Resources/binaryIcon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e73bcd5c3e4131a45c545fcf75cf33ed3ec8ce76
--- /dev/null
+++ b/metavis/Resources/binaryIcon.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 261.501 261.501" style="enable-background:new 0 0 261.501 261.501;" xml:space="preserve">
+<g>
+	<path d="M37.984,161.696c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5v-58.627c0-3.034-1.827-5.768-4.63-6.929
+		c-2.801-1.16-6.028-0.519-8.173,1.626L21.177,116.77c-2.929,2.929-2.929,7.678,0,10.606c2.929,2.929,7.678,2.929,10.606,0
+		l6.201-6.201V161.696z"/>
+	<path d="M82.279,31.807l6.201-6.201v40.521c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5V7.5c0-3.034-1.827-5.768-4.63-6.929
+		c-2.801-1.16-6.028-0.519-8.173,1.626L71.673,21.201c-2.929,2.929-2.929,7.678,0,10.606C74.602,34.736,79.351,34.736,82.279,31.807
+		z"/>
+	<path d="M167.815,96.14c-2.801-1.16-6.028-0.519-8.173,1.626l-19.004,19.004c-2.929,2.929-2.929,7.678,0,10.606
+		c2.929,2.929,7.678,2.929,10.606,0l6.201-6.201v40.521c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5v-58.627
+		C172.445,100.036,170.618,97.301,167.815,96.14z"/>
+	<path d="M135.217,188.445c-2.801-1.16-6.028-0.519-8.173,1.626l-19.004,19.004c-2.929,2.929-2.929,7.678,0,10.606
+		c2.929,2.929,7.678,2.929,10.606,0l6.201-6.201v22.197c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5v-40.303
+		C139.847,192.34,138.02,189.606,135.217,188.445z"/>
+	<path d="M122.504,143.42v-22.074c0-14.213-11.563-25.776-25.776-25.776h-0.369c-14.213,0-25.776,11.563-25.776,25.776v22.074
+		c0,14.213,11.563,25.776,25.776,25.776h0.369C110.941,169.196,122.504,157.633,122.504,143.42z M107.504,143.42
+		c0,5.942-4.834,10.776-10.776,10.776h-0.369c-5.942,0-10.776-4.834-10.776-10.776v-22.074c0-5.942,4.834-10.776,10.776-10.776
+		h0.369c5.942,0,10.776,4.834,10.776,10.776V143.42z"/>
+	<path d="M216.745,95.569h-0.369c-14.213,0-25.776,11.563-25.776,25.776v22.074c0,14.213,11.563,25.776,25.776,25.776h0.369
+		c14.213,0,25.776-11.563,25.776-25.776v-22.074C242.521,107.133,230.958,95.569,216.745,95.569z M227.521,143.42
+		c0,5.942-4.834,10.776-10.776,10.776h-0.369c-5.942,0-10.776-4.834-10.776-10.776v-22.074c0-5.942,4.834-10.776,10.776-10.776
+		h0.369c5.942,0,10.776,4.834,10.776,10.776V143.42z"/>
+	<path d="M147.224,0h-0.369c-14.213,0-25.776,11.563-25.776,25.776v22.074c0,14.213,11.563,25.776,25.776,25.776h0.369
+		c4.142,0,7.5-3.358,7.5-7.5s-3.358-7.5-7.5-7.5h-0.369c-5.942,0-10.776-4.834-10.776-10.776V25.776
+		c0-5.942,4.834-10.776,10.776-10.776h0.369c5.942,0,10.776,4.834,10.776,10.776c0,4.142,3.358,7.5,7.5,7.5s7.5-3.358,7.5-7.5
+		C173.001,11.563,161.438,0,147.224,0z"/>
+	<path d="M216.745,0h-0.369c-14.213,0-25.776,11.563-25.776,25.776v22.074c0,14.213,11.563,25.776,25.776,25.776h0.369
+		c14.213,0,25.776-11.563,25.776-25.776V25.776C242.521,11.563,230.958,0,216.745,0z M227.521,47.851
+		c0,5.942-4.834,10.776-10.776,10.776h-0.369c-5.942,0-10.776-4.834-10.776-10.776V25.776c0-5.942,4.834-10.776,10.776-10.776h0.369
+		c5.942,0,10.776,4.834,10.776,10.776V47.851z"/>
+	<path d="M61.682,187.874h-0.369c-14.213,0-25.776,11.563-25.776,25.776v22.074c0,14.213,11.563,25.776,25.776,25.776h0.369
+		c14.213,0,25.776-11.563,25.776-25.776V213.65C87.459,199.438,75.896,187.874,61.682,187.874z M72.459,235.725
+		c0,5.942-4.834,10.776-10.776,10.776h-0.369c-5.942,0-10.776-4.834-10.776-10.776V213.65c0-5.942,4.834-10.776,10.776-10.776h0.369
+		c5.942,0,10.776,4.834,10.776,10.776V235.725z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/close.svg b/metavis/Resources/close.svg
new file mode 100644
index 0000000000000000000000000000000000000000..858c231cf359d2f8699b1bd2ff8433590c9628b5
--- /dev/null
+++ b/metavis/Resources/close.svg
@@ -0,0 +1 @@
+<svg id="Capa_1" enable-background="new 0 0 413.348 413.348"  viewBox="0 0 413.348 413.348"  xmlns="http://www.w3.org/2000/svg"><path d="m413.348 24.354-24.354-24.354-182.32 182.32-182.32-182.32-24.354 24.354 182.32 182.32-182.32 182.32 24.354 24.354 182.32-182.32 182.32 182.32 24.354-24.354-182.32-182.32z"/></svg>
\ No newline at end of file
diff --git a/metavis/Resources/close_Big.svg b/metavis/Resources/close_Big.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9a22cc364f05f55360ad9e78b6dead1ceecfdbc6
--- /dev/null
+++ b/metavis/Resources/close_Big.svg
@@ -0,0 +1 @@
+<svg id="Capa_1" enable-background="new 0 0 386.667 386.667" height="512" viewBox="0 0 386.667 386.667" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m386.667 45.564-45.564-45.564-147.77 147.769-147.769-147.769-45.564 45.564 147.769 147.769-147.769 147.77 45.564 45.564 147.769-147.769 147.769 147.769 45.564-45.564-147.768-147.77z"/></svg>
\ No newline at end of file
diff --git a/metavis/Resources/close_big_red.svg b/metavis/Resources/close_big_red.svg
new file mode 100644
index 0000000000000000000000000000000000000000..583a25e785f39d1fd21fd1fc3dd6a73415bb1c57
--- /dev/null
+++ b/metavis/Resources/close_big_red.svg
@@ -0,0 +1,3 @@
+<svg id="Capa_1" enable-background="new 0 0 386.667 386.667" viewBox="-100 -100 486.667 486.667" xmlns="http://www.w3.org/2000/svg">
+<path fill="#cc0000" d="m386.667 45.564-45.564-45.564-147.77 147.769-147.769-147.769-45.564 45.564 147.769 147.769-147.769 147.77 45.564 45.564 147.769-147.769 147.769 147.769 45.564-45.564-147.768-147.77z"/>
+</svg>
\ No newline at end of file
diff --git a/metavis/Resources/close_red.svg b/metavis/Resources/close_red.svg
new file mode 100644
index 0000000000000000000000000000000000000000..346ba8dd9cbff3b6a4c7026b6db6c281a7b5d2ae
--- /dev/null
+++ b/metavis/Resources/close_red.svg
@@ -0,0 +1,3 @@
+<svg id="Capa_1" enable-background="new 0 0 1000 1000"  viewBox="0 0 413.348 413.348"  xmlns="http://www.w3.org/2000/svg">
+<path d="m413.348 24.354-24.354-24.354-182.32 182.32-182.32-182.32-24.354 24.354 182.32 182.32-182.32 182.32 24.354 24.354 182.32-182.32 182.32 182.32 24.354-24.354-182.32-182.32z"/>
+</svg>
\ No newline at end of file
diff --git a/metavis/Resources/csv.svg b/metavis/Resources/csv.svg
new file mode 100644
index 0000000000000000000000000000000000000000..0071098ba6abc86d33e4f22191e135e0b611009f
--- /dev/null
+++ b/metavis/Resources/csv.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 318.188 318.188" style="enable-background:new 0 0 318.188 318.188;" xml:space="preserve">
+<g>
+	<g>
+		<g>
+			
+			<polygon points="112.09,123.663 112.09,123.662 118.286,113.621 124.548,123.662 134.588,123.662 123.647,107.909 133.82,91.54 
+				123.911,91.54 118.33,101.472 112.53,91.54 102.906,91.54 112.925,107.228 102.269,123.663 			"/>
+			<path d="M201.02,249.514c-0.339,1.27-0.73,3.015-1.174,5.236c-0.445,2.222-0.741,4.073-0.889,5.555
+				c-0.127-2.053-0.847-5.691-2.158-10.918l-6.316-23.519h-14.092l15.139,46.401h14.759l15.202-46.401h-14.027L201.02,249.514z"/>
+			
+			<path d="M283.149,52.723L232.624,2.197C231.218,0.79,229.311,0,227.321,0H40.342c-4.142,0-7.5,3.358-7.5,7.5v303.188
+				c0,4.142,3.358,7.5,7.5,7.5h237.504c4.142,0,7.5-3.358,7.5-7.5V58.025C285.346,56.036,284.556,54.129,283.149,52.723z
+				 M234.821,25.606l24.918,24.919h-24.918V25.606z M47.842,15h171.979v10.263H47.842V15z M47.842,303.188V40.263h171.979v17.763
+				c0,4.143,3.358,7.5,7.5,7.5h43.024v237.662H47.842z"/>
+			
+			<path d="M122.372,235.484c1.969,0,3.809,0.275,5.523,0.826c1.713,0.55,3.428,1.227,5.141,2.031l3.841-9.871
+				c-4.57-2.18-9.362-3.27-14.378-3.27c-4.591,0-8.585,0.98-11.98,2.937c-3.396,1.957-5.999,4.755-7.808,8.395
+				c-1.81,3.64-2.714,7.86-2.714,12.663c0,7.682,1.867,13.553,5.602,17.615c3.734,4.063,9.104,6.094,16.107,6.094
+				c4.888,0,9.268-0.857,13.14-2.57v-10.602c-1.947,0.805-3.883,1.492-5.808,2.063c-1.926,0.571-3.915,0.857-5.967,0.857
+				c-6.793,0-10.188-4.464-10.188-13.393c0-4.295,0.836-7.665,2.507-10.109C117.062,236.707,119.39,235.484,122.372,235.484z"/>
+			<path d="M163.57,244.594c-4.169-1.904-6.724-3.216-7.665-3.936c-0.942-0.719-1.412-1.533-1.412-2.443
+				c-0.002-0.847,0.368-1.556,1.11-2.127c0.74-0.571,1.925-0.857,3.555-0.857c3.152,0,6.897,0.995,11.234,2.984l3.841-9.681
+				c-4.994-2.222-9.892-3.333-14.694-3.333c-5.439,0-9.713,1.196-12.822,3.587c-3.111,2.392-4.666,5.724-4.666,9.997
+				c0,2.285,0.365,4.264,1.095,5.936s1.851,3.152,3.364,4.443s3.782,2.624,6.809,3.999c3.343,1.503,5.4,2.497,6.173,2.983
+				c0.771,0.486,1.333,0.968,1.682,1.444c0.35,0.476,0.524,1.031,0.524,1.666c0,1.016-0.435,1.847-1.302,2.491
+				c-0.868,0.647-2.233,0.969-4.095,0.969c-2.158,0-4.527-0.344-7.109-1.032c-2.581-0.687-5.067-1.645-7.458-2.872v11.172
+				c2.264,1.079,4.443,1.836,6.538,2.27c2.095,0.434,4.687,0.65,7.775,0.65c3.703,0,6.93-0.619,9.681-1.856
+				c2.75-1.238,4.856-2.973,6.315-5.205c1.461-2.232,2.191-4.787,2.191-7.665c0-3.131-0.777-5.729-2.333-7.792
+				C170.346,248.323,167.569,246.393,163.57,244.594z"/>
+	
+		</g>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/csv_remove.svg b/metavis/Resources/csv_remove.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1148d35d047129f13d2434d03e1814c2a77f45ba
--- /dev/null
+++ b/metavis/Resources/csv_remove.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 318.188 318.188" style="enable-background:new 0 0 318.188 318.188;" xml:space="preserve">
+<g>
+	<g>
+		<g>
+			<rect x="182.882" y="155.008" width="33.713" height="15"/>
+			<rect x="101.592" y="132.689" width="33.713" height="15"/>
+			<rect x="182.882" y="132.689" width="33.713" height="15"/>
+			<rect x="182.882" y="88.053" width="33.713" height="15"/>
+			<rect x="182.882" y="110.371" width="33.713" height="15"/>
+			<rect x="101.592" y="155.008" width="33.713" height="15"/>
+			<polygon points="112.09,123.663 112.09,123.662 118.286,113.621 124.548,123.662 134.588,123.662 123.647,107.909 133.82,91.54 
+				123.911,91.54 118.33,101.472 112.53,91.54 102.906,91.54 112.925,107.228 102.269,123.663 			"/>
+			<path d="M201.02,249.514c-0.339,1.27-0.73,3.015-1.174,5.236c-0.445,2.222-0.741,4.073-0.889,5.555
+				c-0.127-2.053-0.847-5.691-2.158-10.918l-6.316-23.519h-14.092l15.139,46.401h14.759l15.202-46.401h-14.027L201.02,249.514z"/>
+			<rect x="142.457" y="110.371" width="33.713" height="15"/>
+			<rect x="142.457" y="88.053" width="33.713" height="15"/>
+			<path d="M283.149,52.723L232.624,2.197C231.218,0.79,229.311,0,227.321,0H40.342c-4.142,0-7.5,3.358-7.5,7.5v303.188
+				c0,4.142,3.358,7.5,7.5,7.5h237.504c4.142,0,7.5-3.358,7.5-7.5V58.025C285.346,56.036,284.556,54.129,283.149,52.723z
+				 M234.821,25.606l24.918,24.919h-24.918V25.606z M47.842,15h171.979v10.263H47.842V15z M47.842,303.188V40.263h171.979v17.763
+				c0,4.143,3.358,7.5,7.5,7.5h43.024v237.662H47.842z"/>
+			<rect x="142.457" y="132.689" width="33.713" height="15"/>
+			<path d="M122.372,235.484c1.969,0,3.809,0.275,5.523,0.826c1.713,0.55,3.428,1.227,5.141,2.031l3.841-9.871
+				c-4.57-2.18-9.362-3.27-14.378-3.27c-4.591,0-8.585,0.98-11.98,2.937c-3.396,1.957-5.999,4.755-7.808,8.395
+				c-1.81,3.64-2.714,7.86-2.714,12.663c0,7.682,1.867,13.553,5.602,17.615c3.734,4.063,9.104,6.094,16.107,6.094
+				c4.888,0,9.268-0.857,13.14-2.57v-10.602c-1.947,0.805-3.883,1.492-5.808,2.063c-1.926,0.571-3.915,0.857-5.967,0.857
+				c-6.793,0-10.188-4.464-10.188-13.393c0-4.295,0.836-7.665,2.507-10.109C117.062,236.707,119.39,235.484,122.372,235.484z"/>
+			<path d="M163.57,244.594c-4.169-1.904-6.724-3.216-7.665-3.936c-0.942-0.719-1.412-1.533-1.412-2.443
+				c-0.002-0.847,0.368-1.556,1.11-2.127c0.74-0.571,1.925-0.857,3.555-0.857c3.152,0,6.897,0.995,11.234,2.984l3.841-9.681
+				c-4.994-2.222-9.892-3.333-14.694-3.333c-5.439,0-9.713,1.196-12.822,3.587c-3.111,2.392-4.666,5.724-4.666,9.997
+				c0,2.285,0.365,4.264,1.095,5.936s1.851,3.152,3.364,4.443s3.782,2.624,6.809,3.999c3.343,1.503,5.4,2.497,6.173,2.983
+				c0.771,0.486,1.333,0.968,1.682,1.444c0.35,0.476,0.524,1.031,0.524,1.666c0,1.016-0.435,1.847-1.302,2.491
+				c-0.868,0.647-2.233,0.969-4.095,0.969c-2.158,0-4.527-0.344-7.109-1.032c-2.581-0.687-5.067-1.645-7.458-2.872v11.172
+				c2.264,1.079,4.443,1.836,6.538,2.27c2.095,0.434,4.687,0.65,7.775,0.65c3.703,0,6.93-0.619,9.681-1.856
+				c2.75-1.238,4.856-2.973,6.315-5.205c1.461-2.232,2.191-4.787,2.191-7.665c0-3.131-0.777-5.729-2.333-7.792
+				C170.346,248.323,167.569,246.393,163.57,244.594z"/>
+			<rect x="142.457" y="155.008" width="33.713" height="15"/>
+			<polygon fill="#EF2D56" transform="translate(150.0 2.0), scale(0.3)" points="386.813,0 245,141.812 103.188,0 0,103.188 141.813,245 0,386.812 103.187,489.999 245,348.187 386.813,490 
+			490,386.812 348.187,244.999 490,103.187 "/>
+		</g>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/file.svg b/metavis/Resources/file.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2b4141f372d49d20f1b3f33556d9468863a073bf
--- /dev/null
+++ b/metavis/Resources/file.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 450 450" style="enable-background:new 0 0 450 450;" xml:space="preserve">
+<g>
+	<path d="M281.213,0H60v450h330V108.787L281.213,0z M290,51.213L338.787,100H290V51.213z M90,420V30h170v100h100v290H90z"/>
+	
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/frame.svg b/metavis/Resources/frame.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a3760ae3cd797867c81f1919abf83b6a3557ab07
--- /dev/null
+++ b/metavis/Resources/frame.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+	<g>
+		<polygon points="426.056,79.367 466.119,79.367 406.387,19.664 346.669,79.367 386.728,79.367 386.728,287.698 346.669,287.698 
+			406.387,347.401 466.119,287.698 426.056,287.698 		"/>
+	</g>
+</g>
+<g>
+	<g>
+		<polygon points="314.626,452.282 254.922,392.55 254.922,432.613 112.139,432.613 112.139,392.55 52.436,452.282 112.139,512 
+			112.139,471.941 254.922,471.941 254.922,512 		"/>
+	</g>
+</g>
+<g>
+	<g>
+		<path d="M45.881,0v367.065H321.18V0H45.881z M281.852,327.737H85.21V39.328h196.642V327.737z"/>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/frame_hovered.svg b/metavis/Resources/frame_hovered.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2a6206bd843384d4e03f7e667da1be0eab9049c1
--- /dev/null
+++ b/metavis/Resources/frame_hovered.svg
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+	<g>
+		<polygon points="426.056,79.367 466.119,79.367 406.387,19.664 346.669,79.367 386.728,79.367 386.728,287.698 346.669,287.698 
+			406.387,347.401 466.119,287.698 426.056,287.698 		"/>
+	</g>
+</g>
+<g>
+	<g>
+		<polygon points="314.626,452.282 254.922,392.55 254.922,432.613 112.139,432.613 112.139,392.55 52.436,452.282 112.139,512 
+			112.139,471.941 254.922,471.941 254.922,512 		"/>
+	</g>
+</g>
+<g>
+	<g>
+		<path d="M45.881,0v367.065H321.18V0H45.881z M281.852,327.737H85.21V39.328h196.642V327.737z"/>
+		<path fill="#ff9f00" d="M281.852,327.737H85.21V39.328h196.642V327.737z"/>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/gridIcon.svg b/metavis/Resources/gridIcon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e47984f5637f29f98fc732db74ec116098d1bcd1
--- /dev/null
+++ b/metavis/Resources/gridIcon.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 460.002 460.002" style="enable-background:new 0 0 460.002 460.002;" xml:space="preserve">
+<g>
+	<g>
+		<path d="M427.137,0H32.865C14.743,0,0,14.743,0,32.865v394.272c0,18.122,14.743,32.865,32.865,32.865h394.272
+			c18.122,0,32.865-14.743,32.865-32.865V32.865C460.002,14.743,445.259,0,427.137,0z M137.305,399.443c0,8.284-6.716,15-15,15
+			H56.251c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V399.443z M137.305,263.028
+			c0,8.284-6.716,15-15,15H56.251c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z
+			 M137.305,126.613c0,8.284-6.716,15-15,15H56.251c-8.284-0.001-15-6.717-15-15.001V60.559c0-8.284,6.716-15,15-15h66.054
+			c8.284,0,15,6.716,15,15V126.613z M277.071,399.443c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054
+			c0-8.284,6.715-15,15-15h66.054c8.284,0,15,6.716,15,15V399.443z M277.071,263.028c0,8.284-6.716,15-15,15h-66.054
+			c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.715-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z M277.071,126.613
+			c0,8.284-6.716,15-15,15h-66.054c-8.285-0.001-15-6.717-15-15.001V60.559c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15
+			V126.613z M418.751,399.443c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054
+			c8.284,0,15,6.716,15,15V399.443z M418.751,263.028c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054
+			c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z M418.751,126.612c0,8.284-6.716,15-15,15h-66.054
+			c-8.284,0-15-6.716-15-15V60.559c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V126.612z"/>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/gridIcon_hovered.svg b/metavis/Resources/gridIcon_hovered.svg
new file mode 100644
index 0000000000000000000000000000000000000000..dc8e4190ca258706ba32fc8063e6adfa27ecdbc6
--- /dev/null
+++ b/metavis/Resources/gridIcon_hovered.svg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 460.002 460.002" style="enable-background:new 0 0 460.002 460.002;" xml:space="preserve">
+<g>
+	<g>
+		<path fill="#ff9f00" d="M427.137,0H32.865C14.743,0,0,14.743,0,32.865v394.272c0,18.122,14.743,32.865,32.865,32.865h394.272
+			c18.122,0,32.865-14.743,32.865-32.865V32.865C460.002,14.743,445.259,0,427.137,0z"/>
+		<path d="M427.137,0H32.865C14.743,0,0,14.743,0,32.865v394.272c0,18.122,14.743,32.865,32.865,32.865h394.272
+			c18.122,0,32.865-14.743,32.865-32.865V32.865C460.002,14.743,445.259,0,427.137,0z M137.305,399.443c0,8.284-6.716,15-15,15
+			H56.251c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V399.443z M137.305,263.028
+			c0,8.284-6.716,15-15,15H56.251c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z
+			 M137.305,126.613c0,8.284-6.716,15-15,15H56.251c-8.284-0.001-15-6.717-15-15.001V60.559c0-8.284,6.716-15,15-15h66.054
+			c8.284,0,15,6.716,15,15V126.613z M277.071,399.443c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054
+			c0-8.284,6.715-15,15-15h66.054c8.284,0,15,6.716,15,15V399.443z M277.071,263.028c0,8.284-6.716,15-15,15h-66.054
+			c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.715-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z M277.071,126.613
+			c0,8.284-6.716,15-15,15h-66.054c-8.285-0.001-15-6.717-15-15.001V60.559c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15
+			V126.613z M418.751,399.443c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054c0-8.284,6.716-15,15-15h66.054
+			c8.284,0,15,6.716,15,15V399.443z M418.751,263.028c0,8.284-6.716,15-15,15h-66.054c-8.284,0-15-6.716-15-15v-66.054
+			c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V263.028z M418.751,126.612c0,8.284-6.716,15-15,15h-66.054
+			c-8.284,0-15-6.716-15-15V60.559c0-8.284,6.716-15,15-15h66.054c8.284,0,15,6.716,15,15V126.612z"/>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/information_icon.svg b/metavis/Resources/information_icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..febc28da980f1ef056ca0d6dda3e60d379e02e00
--- /dev/null
+++ b/metavis/Resources/information_icon.svg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	viewBox="0 0 490.318 490.318" style="enable-background:new 0 0 490.318 490.318;"
+	 xml:space="preserve">
+<g>
+	<g>
+		<g>
+			<path d="M245.148,0C109.967,0,0.009,109.98,0.009,245.162c0,135.182,109.958,245.156,245.139,245.156
+				c135.186,0,245.162-109.978,245.162-245.156C490.31,109.98,380.333,0,245.148,0z M245.148,438.415
+				c-106.555,0-193.234-86.698-193.234-193.253c0-106.555,86.68-193.258,193.234-193.258c106.559,0,193.258,86.703,193.258,193.258
+				C438.406,351.717,351.706,438.415,245.148,438.415z"/>
+			<path d="M270.036,221.352h-49.771c-8.351,0-15.131,6.78-15.131,15.118v147.566c0,8.352,6.78,15.119,15.131,15.119h49.771
+				c8.351,0,15.131-6.77,15.131-15.119V236.471C285.167,228.133,278.387,221.352,270.036,221.352z"/>
+			<path d="M245.148,91.168c-24.48,0-44.336,19.855-44.336,44.336c0,24.484,19.855,44.34,44.336,44.34
+				c24.485,0,44.342-19.855,44.342-44.34C289.489,111.023,269.634,91.168,245.148,91.168z"/>
+		</g>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/information_icon_hovered.svg b/metavis/Resources/information_icon_hovered.svg
new file mode 100644
index 0000000000000000000000000000000000000000..54170bd12e3eb749eb080415afac264f8618abce
--- /dev/null
+++ b/metavis/Resources/information_icon_hovered.svg
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	viewBox="0 0 490.318 490.318" style="enable-background:new 0 0 490.318 490.318;"
+	 xml:space="preserve">
+<g>
+	<g>
+		<g>
+			<path d="M245.148,0C109.967,0,0.009,109.98,0.009,245.162c0,135.182,109.958,245.156,245.139,245.156
+				c135.186,0,245.162-109.978,245.162-245.156C490.31,109.98,380.333,0,245.148,0z M245.148,438.415
+				c-106.555,0-193.234-86.698-193.234-193.253c0-106.555,86.68-193.258,193.234-193.258c106.559,0,193.258,86.703,193.258,193.258
+				C438.406,351.717,351.706,438.415,245.148,438.415z"/>
+			<path fill="#ff9f00" d="M245.148,438.415
+				c-106.555,0-193.234-86.698-193.234-193.253c0-106.555,86.68-193.258,193.234-193.258c106.559,0,193.258,86.703,193.258,193.258
+				C438.406,351.717,351.706,438.415,245.148,438.415z"/>
+			<path d="M270.036,221.352h-49.771c-8.351,0-15.131,6.78-15.131,15.118v147.566c0,8.352,6.78,15.119,15.131,15.119h49.771
+				c8.351,0,15.131-6.77,15.131-15.119V236.471C285.167,228.133,278.387,221.352,270.036,221.352z"/>
+			<path d="M245.148,91.168c-24.48,0-44.336,19.855-44.336,44.336c0,24.484,19.855,44.34,44.336,44.34
+				c24.485,0,44.342-19.855,44.342-44.34C289.489,111.023,269.634,91.168,245.148,91.168z"/>
+			</g>
+	</g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/rubbish.svg b/metavis/Resources/rubbish.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8a847768242b67262d7a9fdf02a0c4e94f6ef591
--- /dev/null
+++ b/metavis/Resources/rubbish.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	  viewBox="0 0 372.693 372.693" style="enable-background:new 0 0 372.693 372.693;"
+	 xml:space="preserve">
+<g>
+	<path d="M322.248,51.317h-67.296v-18.09C254.952,14.904,240.047,0,221.727,0h-70.755c-18.323,0-33.233,14.904-33.233,33.228v18.084
+		H50.452c-18.324,0-33.237,14.906-33.237,33.218v35.38c0,9.535,7.755,17.285,17.297,17.285h23.476v202.274
+		c0,18.321,14.907,33.225,33.225,33.225h194.472c18.32,0,33.236-14.915,33.236-33.225V137.201h19.264
+		c9.535,0,17.294-7.75,17.294-17.285v-35.38C355.478,66.224,340.568,51.317,322.248,51.317z M152.308,34.576h68.067v16.741h-68.067
+		V34.576z M153.353,306.316c0,9.188-7.485,16.67-16.681,16.67c-9.206,0-16.696-7.482-16.696-16.67v-139.59
+		c0-9.196,7.491-16.693,16.696-16.693c9.196,0,16.681,7.497,16.681,16.693V306.316z M203.028,306.316
+		c0,9.188-7.481,16.67-16.681,16.67c-9.197,0-16.681-7.482-16.681-16.67v-139.59c0-9.196,7.484-16.693,16.681-16.693
+		c9.206,0,16.681,7.497,16.681,16.693V306.316z M252.723,306.316c0,9.188-7.493,16.67-16.692,16.67c-9.2,0-16.67-7.482-16.67-16.67
+		v-139.59c0-9.196,7.47-16.693,16.67-16.693c9.199,0,16.692,7.497,16.692,16.693V306.316z"/>
+	
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/rubbish_hovered.svg b/metavis/Resources/rubbish_hovered.svg
new file mode 100644
index 0000000000000000000000000000000000000000..fa7360a2c63db2dc486061d04fd44450504c568b
--- /dev/null
+++ b/metavis/Resources/rubbish_hovered.svg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	  viewBox="0 0 372.693 372.693" style="enable-background:new 0 0 372.693 372.693;"
+	 xml:space="preserve">
+<g>
+	<path d="M322.248,51.317h-67.296v-18.09C254.952,14.904,240.047,0,221.727,0h-70.755c-18.323,0-33.233,14.904-33.233,33.228v18.084
+		H50.452c-18.324,0-33.237,14.906-33.237,33.218v35.38c0,9.535,7.755,17.285,17.297,17.285h23.476v202.274
+		c0,18.321,14.907,33.225,33.225,33.225h194.472c18.32,0,33.236-14.915,33.236-33.225V137.201h19.264
+		c9.535,0,17.294-7.75,17.294-17.285v-35.38C355.478,66.224,340.568,51.317,322.248,51.317z M152.308,34.576h68.067v16.741h-68.067
+		V34.576z M153.353,306.316c0,9.188-7.485,16.67-16.681,16.67c-9.206,0-16.696-7.482-16.696-16.67v-139.59
+		c0-9.196,7.491-16.693,16.696-16.693c9.196,0,16.681,7.497,16.681,16.693V306.316z M203.028,306.316
+		c0,9.188-7.481,16.67-16.681,16.67c-9.197,0-16.681-7.482-16.681-16.67v-139.59c0-9.196,7.484-16.693,16.681-16.693
+		c9.206,0,16.681,7.497,16.681,16.693V306.316z M252.723,306.316c0,9.188-7.493,16.67-16.692,16.67c-9.2,0-16.67-7.482-16.67-16.67
+		v-139.59c0-9.196,7.47-16.693,16.67-16.693c9.199,0,16.692,7.497,16.692,16.693V306.316z"/>
+	<path fill="#ff9f00" d="M153.353,306.316c0,9.188-7.485,16.67-16.681,16.67c-9.206,0-16.696-7.482-16.696-16.67v-139.59
+		c0-9.196,7.491-16.693,16.696-16.693c9.196,0,16.681,7.497,16.681,16.693V306.316z M203.028,306.316
+		c0,9.188-7.481,16.67-16.681,16.67c-9.197,0-16.681-7.482-16.681-16.67v-139.59c0-9.196,7.484-16.693,16.681-16.693
+		c9.206,0,16.681,7.497,16.681,16.693V306.316z M252.723,306.316c0,9.188-7.493,16.67-16.692,16.67c-9.2,0-16.67-7.482-16.67-16.67
+		v-139.59c0-9.196,7.47-16.693,16.67-16.693c9.199,0,16.692,7.497,16.692,16.693V306.316z"/>
+	<path fill="#ff9f00" d="M152.308,34.576h68.067v16.741h-68.067 V34.576z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/settingIcon.svg b/metavis/Resources/settingIcon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4ca5176f474d1d76578ff99fa46b8b6aceb618ec
--- /dev/null
+++ b/metavis/Resources/settingIcon.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 174.248 174.248" style="enable-background:new 0 0 174.248 174.248;" xml:space="preserve">
+<g>
+	<path d="M173.145,73.91c-0.413-2.722-2.29-4.993-4.881-5.912l-13.727-4.881c-0.812-2.3-1.733-4.536-2.754-6.699l6.247-13.146
+		c1.179-2.479,0.899-5.411-0.729-7.628c-5.265-7.161-11.556-13.452-18.698-18.693c-2.219-1.629-5.141-1.906-7.625-0.724
+		l-13.138,6.242c-2.163-1.021-4.402-1.94-6.704-2.752l-4.883-13.729c-0.919-2.586-3.184-4.458-5.9-4.876
+		c-9.65-1.483-16.792-1.483-26.457,0c-2.713,0.418-4.981,2.29-5.9,4.876l-4.883,13.729c-2.302,0.812-4.541,1.731-6.702,2.752
+		l-13.143-6.242c-2.479-1.181-5.406-0.904-7.623,0.724c-7.142,5.241-13.433,11.532-18.698,18.693
+		c-1.629,2.217-1.908,5.148-0.729,7.628l6.247,13.146c-1.021,2.159-1.94,4.4-2.754,6.699L5.982,68.003
+		c-2.589,0.919-4.463,3.189-4.879,5.907c-0.749,4.92-1.099,9.115-1.099,13.219c0,4.098,0.35,8.299,1.099,13.219
+		c0.413,2.722,2.29,4.993,4.881,5.912l13.727,4.881c0.814,2.304,1.736,4.541,2.754,6.704l-6.247,13.141
+		c-1.179,2.479-0.899,5.411,0.727,7.623c5.258,7.156,11.549,13.447,18.7,18.698c2.217,1.629,5.144,1.911,7.625,0.724l13.138-6.242
+		c2.163,1.021,4.402,1.94,6.704,2.752l4.883,13.729c0.919,2.586,3.184,4.458,5.9,4.876c4.828,0.744,9.154,1.104,13.228,1.104
+		c4.074,0,8.401-0.36,13.228-1.104c2.715-0.418,4.981-2.29,5.9-4.876l4.883-13.729c2.302-0.812,4.541-1.731,6.704-2.752
+		l13.138,6.242c2.484,1.186,5.411,0.904,7.628-0.724c7.159-5.26,13.45-11.551,18.698-18.698c1.626-2.212,1.906-5.144,0.727-7.623
+		l-6.247-13.141c1.021-2.163,1.942-4.405,2.754-6.704l13.727-4.881c2.591-0.919,4.468-3.189,4.881-5.912
+		c0.749-4.92,1.099-9.12,1.099-13.219S173.894,78.829,173.145,73.91z M158.949,93.72l-12.878,4.58
+		c-2.251,0.797-3.982,2.625-4.66,4.92c-1.15,3.889-2.664,7.569-4.504,10.943c-1.142,2.1-1.213,4.619-0.187,6.777l5.841,12.285
+		c-2.822,3.389-5.943,6.515-9.337,9.334l-12.283-5.834c-2.161-1.036-4.672-0.953-6.775,0.185c-3.379,1.838-7.061,3.35-10.953,4.502
+		c-2.29,0.676-4.118,2.406-4.917,4.657l-4.582,12.883c-4.677,0.476-8.503,0.476-13.18,0l-4.582-12.883
+		c-0.8-2.246-2.628-3.982-4.917-4.657c-3.894-1.152-7.579-2.664-10.953-4.502c-2.103-1.147-4.619-1.22-6.775-0.185l-12.283,5.839
+		c-3.391-2.825-6.512-5.946-9.337-9.339l5.841-12.285c1.026-2.159,0.955-4.677-0.187-6.777c-1.835-3.364-3.35-7.049-4.504-10.948
+		c-0.678-2.29-2.411-4.118-4.66-4.915l-12.878-4.58c-0.243-2.343-0.36-4.502-0.36-6.592s0.117-4.244,0.36-6.587l12.881-4.584
+		c2.248-0.797,3.979-2.625,4.657-4.915c1.152-3.889,2.667-7.574,4.504-10.953c1.142-2.095,1.213-4.619,0.187-6.772l-5.841-12.285
+		c2.827-3.393,5.948-6.519,9.337-9.339l12.288,5.839c2.151,1.036,4.677,0.953,6.775-0.185c3.372-1.838,7.054-3.35,10.948-4.502
+		c2.29-0.676,4.118-2.411,4.917-4.657l4.582-12.883c4.633-0.481,8.466-0.481,13.18,0l4.582,12.883
+		c0.8,2.246,2.628,3.982,4.917,4.657c3.894,1.152,7.579,2.664,10.953,4.502c2.103,1.147,4.614,1.22,6.775,0.185l12.283-5.839
+		c3.389,2.82,6.51,5.946,9.337,9.339l-5.841,12.285c-1.026,2.154-0.955,4.677,0.187,6.772c1.843,3.389,3.357,7.069,4.504,10.948
+		c0.678,2.295,2.409,4.123,4.66,4.92l12.878,4.58c0.243,2.343,0.36,4.502,0.36,6.592S159.192,91.377,158.949,93.72z"/>
+	<path d="M87.124,50.802c-19.062,0-34.571,15.508-34.571,34.571s15.508,34.571,34.571,34.571s34.571-15.508,34.571-34.571
+		S106.186,50.802,87.124,50.802z M87.124,105.009c-10.827,0-19.636-8.809-19.636-19.636s8.809-19.636,19.636-19.636
+		s19.636,8.809,19.636,19.636S97.951,105.009,87.124,105.009z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/settingIcon_hovered.svg b/metavis/Resources/settingIcon_hovered.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c2613d674c44968114d27c2b38136af0a6a94bbf
--- /dev/null
+++ b/metavis/Resources/settingIcon_hovered.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 174.248 174.248" style="enable-background:new 0 0 174.248 174.248;" xml:space="preserve">
+<g>
+	<path d="M173.145,73.91c-0.413-2.722-2.29-4.993-4.881-5.912l-13.727-4.881c-0.812-2.3-1.733-4.536-2.754-6.699l6.247-13.146
+		c1.179-2.479,0.899-5.411-0.729-7.628c-5.265-7.161-11.556-13.452-18.698-18.693c-2.219-1.629-5.141-1.906-7.625-0.724
+		l-13.138,6.242c-2.163-1.021-4.402-1.94-6.704-2.752l-4.883-13.729c-0.919-2.586-3.184-4.458-5.9-4.876
+		c-9.65-1.483-16.792-1.483-26.457,0c-2.713,0.418-4.981,2.29-5.9,4.876l-4.883,13.729c-2.302,0.812-4.541,1.731-6.702,2.752
+		l-13.143-6.242c-2.479-1.181-5.406-0.904-7.623,0.724c-7.142,5.241-13.433,11.532-18.698,18.693
+		c-1.629,2.217-1.908,5.148-0.729,7.628l6.247,13.146c-1.021,2.159-1.94,4.4-2.754,6.699L5.982,68.003
+		c-2.589,0.919-4.463,3.189-4.879,5.907c-0.749,4.92-1.099,9.115-1.099,13.219c0,4.098,0.35,8.299,1.099,13.219
+		c0.413,2.722,2.29,4.993,4.881,5.912l13.727,4.881c0.814,2.304,1.736,4.541,2.754,6.704l-6.247,13.141
+		c-1.179,2.479-0.899,5.411,0.727,7.623c5.258,7.156,11.549,13.447,18.7,18.698c2.217,1.629,5.144,1.911,7.625,0.724l13.138-6.242
+		c2.163,1.021,4.402,1.94,6.704,2.752l4.883,13.729c0.919,2.586,3.184,4.458,5.9,4.876c4.828,0.744,9.154,1.104,13.228,1.104
+		c4.074,0,8.401-0.36,13.228-1.104c2.715-0.418,4.981-2.29,5.9-4.876l4.883-13.729c2.302-0.812,4.541-1.731,6.704-2.752
+		l13.138,6.242c2.484,1.186,5.411,0.904,7.628-0.724c7.159-5.26,13.45-11.551,18.698-18.698c1.626-2.212,1.906-5.144,0.727-7.623
+		l-6.247-13.141c1.021-2.163,1.942-4.405,2.754-6.704l13.727-4.881c2.591-0.919,4.468-3.189,4.881-5.912
+		c0.749-4.92,1.099-9.12,1.099-13.219S173.894,78.829,173.145,73.91z M158.949,93.72l-12.878,4.58
+		c-2.251,0.797-3.982,2.625-4.66,4.92c-1.15,3.889-2.664,7.569-4.504,10.943c-1.142,2.1-1.213,4.619-0.187,6.777l5.841,12.285
+		c-2.822,3.389-5.943,6.515-9.337,9.334l-12.283-5.834c-2.161-1.036-4.672-0.953-6.775,0.185c-3.379,1.838-7.061,3.35-10.953,4.502
+		c-2.29,0.676-4.118,2.406-4.917,4.657l-4.582,12.883c-4.677,0.476-8.503,0.476-13.18,0l-4.582-12.883
+		c-0.8-2.246-2.628-3.982-4.917-4.657c-3.894-1.152-7.579-2.664-10.953-4.502c-2.103-1.147-4.619-1.22-6.775-0.185l-12.283,5.839
+		c-3.391-2.825-6.512-5.946-9.337-9.339l5.841-12.285c1.026-2.159,0.955-4.677-0.187-6.777c-1.835-3.364-3.35-7.049-4.504-10.948
+		c-0.678-2.29-2.411-4.118-4.66-4.915l-12.878-4.58c-0.243-2.343-0.36-4.502-0.36-6.592s0.117-4.244,0.36-6.587l12.881-4.584
+		c2.248-0.797,3.979-2.625,4.657-4.915c1.152-3.889,2.667-7.574,4.504-10.953c1.142-2.095,1.213-4.619,0.187-6.772l-5.841-12.285
+		c2.827-3.393,5.948-6.519,9.337-9.339l12.288,5.839c2.151,1.036,4.677,0.953,6.775-0.185c3.372-1.838,7.054-3.35,10.948-4.502
+		c2.29-0.676,4.118-2.411,4.917-4.657l4.582-12.883c4.633-0.481,8.466-0.481,13.18,0l4.582,12.883
+		c0.8,2.246,2.628,3.982,4.917,4.657c3.894,1.152,7.579,2.664,10.953,4.502c2.103,1.147,4.614,1.22,6.775,0.185l12.283-5.839
+		c3.389,2.82,6.51,5.946,9.337,9.339l-5.841,12.285c-1.026,2.154-0.955,4.677,0.187,6.772c1.843,3.389,3.357,7.069,4.504,10.948
+		c0.678,2.295,2.409,4.123,4.66,4.92l12.878,4.58c0.243,2.343,0.36,4.502,0.36,6.592S159.192,91.377,158.949,93.72z"/>
+	<path fill="#ff9f00" d="M158.949,93.72l-12.878,4.58
+		c-2.251,0.797-3.982,2.625-4.66,4.92c-1.15,3.889-2.664,7.569-4.504,10.943c-1.142,2.1-1.213,4.619-0.187,6.777l5.841,12.285
+		c-2.822,3.389-5.943,6.515-9.337,9.334l-12.283-5.834c-2.161-1.036-4.672-0.953-6.775,0.185c-3.379,1.838-7.061,3.35-10.953,4.502
+		c-2.29,0.676-4.118,2.406-4.917,4.657l-4.582,12.883c-4.677,0.476-8.503,0.476-13.18,0l-4.582-12.883
+		c-0.8-2.246-2.628-3.982-4.917-4.657c-3.894-1.152-7.579-2.664-10.953-4.502c-2.103-1.147-4.619-1.22-6.775-0.185l-12.283,5.839
+		c-3.391-2.825-6.512-5.946-9.337-9.339l5.841-12.285c1.026-2.159,0.955-4.677-0.187-6.777c-1.835-3.364-3.35-7.049-4.504-10.948
+		c-0.678-2.29-2.411-4.118-4.66-4.915l-12.878-4.58c-0.243-2.343-0.36-4.502-0.36-6.592s0.117-4.244,0.36-6.587l12.881-4.584
+		c2.248-0.797,3.979-2.625,4.657-4.915c1.152-3.889,2.667-7.574,4.504-10.953c1.142-2.095,1.213-4.619,0.187-6.772l-5.841-12.285
+		c2.827-3.393,5.948-6.519,9.337-9.339l12.288,5.839c2.151,1.036,4.677,0.953,6.775-0.185c3.372-1.838,7.054-3.35,10.948-4.502
+		c2.29-0.676,4.118-2.411,4.917-4.657l4.582-12.883c4.633-0.481,8.466-0.481,13.18,0l4.582,12.883
+		c0.8,2.246,2.628,3.982,4.917,4.657c3.894,1.152,7.579,2.664,10.953,4.502c2.103,1.147,4.614,1.22,6.775,0.185l12.283-5.839
+		c3.389,2.82,6.51,5.946,9.337,9.339l-5.841,12.285c-1.026,2.154-0.955,4.677,0.187,6.772c1.843,3.389,3.357,7.069,4.504,10.948
+		c0.678,2.295,2.409,4.123,4.66,4.92l12.878,4.58c0.243,2.343,0.36,4.502,0.36,6.592S159.192,91.377,158.949,93.72z"/>
+	<path d="M87.124,50.802c-19.062,0-34.571,15.508-34.571,34.571s15.508,34.571,34.571,34.571s34.571-15.508,34.571-34.571
+		S106.186,50.802,87.124,50.802z M87.124,105.009c-10.827,0-19.636-8.809-19.636-19.636s8.809-19.636,19.636-19.636
+		s19.636,8.809,19.636,19.636S97.951,105.009,87.124,105.009z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/metavis/Resources/up-triangle.svg b/metavis/Resources/up-triangle.svg
new file mode 100644
index 0000000000000000000000000000000000000000..90ec064f7ca48ff28e38025b05edd803d47a1461
--- /dev/null
+++ b/metavis/Resources/up-triangle.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--U+25B3-->
+<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="-40 10 240 170">
+   <polygon points="20 153  90 38  160 153" fill="none" stroke="#000" stroke-width="20" />
+</svg>
\ No newline at end of file
diff --git a/metavis/RunData.cpp b/metavis/RunData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..08c591d63a7566d648ca0cee62146d8e533b8c68
--- /dev/null
+++ b/metavis/RunData.cpp
@@ -0,0 +1,463 @@
+#include "pch.h"
+#include "GraphView.h"
+#include "RunData.h"
+#include <QDebug>
+#include <QString>
+#include <regex>
+#include <algorithm>
+
+
+RunData::RunData()
+{
+}
+
+RunData::RunData(std::string filePath) : fileStream(filePath), filePath(filePath)
+{
+    
+    std::string file = filePath.substr(filePath.find_last_of("/\\") + 1);
+    name = file.substr(0, file.rfind("."));
+    if (!fileStream.is_open())
+    {
+        //Cant open file
+        badFileFlag = true;
+        return;
+    }
+    std::string buffer;
+    getLine(buffer);
+    qDebug() << QString::fromStdString(buffer);
+    /*bool retflag;
+    metalogFile(retflag);
+    if (retflag) return;*/
+    std::string integerRegexString = "([\\+\\-]?\\d+)";
+    std::string doubleRegexString = "([\\+\\-]?\\d+(?:\\.\\d+(?:E[\\+\\-]\\d+)?)?)";
+    std::string binaryRegexString = "([01]+)";
+    std::string seperator = ",";
+    std::regex regexLine(integerRegexString
+        + seperator + integerRegexString
+        + seperator + integerRegexString
+        + seperator + doubleRegexString
+        + seperator + binaryRegexString);
+    while (fileStream.peek() != EOF) {
+        std::string buffer;
+        getLine(buffer);
+        SolutionPointData sol;
+        std::smatch match;
+        if (!std::regex_search(buffer, match, regexLine)) {
+            qDebug() << "Bad formatatted Line[" << actualLine << "].";
+            qDebug() << "Failed to matched:";
+            qDebug() << QString::fromStdString(buffer);
+            return;
+        }
+        sol.round = std::stoi(match[1]);
+        sol.iteration = std::stoi(match[2]);
+        sol.particleNumber = std::stoi(match[3]);
+        sol.objectiveFunction = std::stod(match[4]);
+        sol.bitVec.resize(match[5].length());
+        std::string binaryString = match[5];
+        for (std::string::size_type i = 0; i < binaryString.size(); ++i) {
+            sol.bitVec[i] = (binaryString[i] == '1');
+        }
+        solutionVec.push_back(sol);
+    }
+    fileStream.close();
+    qDebug() << "Import done";
+   
+
+
+    //Set Runs apart
+    int count = 0;
+    std::vector<SolutionPointData>::iterator begin = solutionVec.begin();
+    for (auto iter = solutionVec.begin(); iter != solutionVec.end(); iter++) {
+        if (iter->round != begin->round) {
+            std::string endString("[");
+            endString += std::to_string(count++);
+            endString += "]";
+            singleRunList.push_back(SingleRun(name, begin, iter, name +  endString));
+            begin = iter;
+        }
+    }
+    std::string endString("[");
+    endString += std::to_string(count);
+    endString += "]";
+    singleRunList.push_back(SingleRun(name, begin, solutionVec.end(), name + endString));
+
+
+
+    //Generate PascalTriangle
+    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+
+    int amountOfBits = begin->bitVec.size();
+    int lines = amountOfBits + 1;
+    std::vector<boost::multiprecision::cpp_int> pascalTriangleVec(((lines + 1) / 2 * (lines / 2 + 1)));
+    for (int line = 0; line < lines; line++) {
+        for (int number = 0; number < line + 1; number++) {
+            if (number > line / 2) break;
+            if (number == 0 || number == line) {
+                pascalTriangleVec[binominalIndex(line, number)] = 1;
+            }
+            else {
+                pascalTriangleVec[binominalIndex(line, number)] = pascalTriangleVec[binominalIndex(line - 1, number)] + pascalTriangleVec[binominalIndex(line - 1, number - 1)];
+            }
+
+        }
+    }
+    std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
+    std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
+    qDebug() << "PascalTriangle: " << time.count() << "ms";
+    //Calculate Additional Data
+    for (SingleRun& srun : singleRunList) {
+        srun.calculateAdditionalData(pascalTriangleVec, amountOfBits);
+    }
+    calculateAverageOverRuns();
+
+}
+
+void RunData::metalogFile(bool& retflag)
+{
+    retflag = true;
+    /* Start extracting */
+    while (fileStream.peek() != EOF) {
+        std::string buffer;
+        getLine(buffer);
+        SolutionPointData sol;
+
+        std::regex regexIter("i:([\\+\\-]?\\d+)");
+        std::regex regexObjectiveFunction("of:([\\+\\-]?\\d+\\.\\d+(?:E[\\+\\-]\\d+)?)");
+        std::smatch match;
+        if (!std::regex_search(buffer, match, regexIter)) {
+            qDebug() << "Bad formatatted Line[" << actualLine << "].";
+            qDebug() << "Failed to matched:";
+            qDebug() << QString::fromStdString(buffer);
+            return;
+        }
+        sol.iteration = std::stoi(match[1]);
+        if (!std::regex_search(buffer, match, regexObjectiveFunction)) {
+            qDebug() << "Bad formatatted Line[" << actualLine << "].";
+            qDebug() << "Failed to matched:";
+            qDebug() << QString::fromStdString(buffer);
+            return;
+        }
+        sol.objectiveFunction = std::stod(match[1]);
+        std::regex regexParticleNumber("pN:([\\+\\-]?\\d+)");
+        if (!std::regex_search(buffer, match, regexParticleNumber)) {
+            qDebug() << "Bad formatatted Line[" << actualLine << "].";
+            qDebug() << "Failed to matched:";
+            qDebug() << QString::fromStdString(buffer);
+            return;
+        }
+        sol.particleNumber = std::stoi(match[1]);
+        std::regex regexBitVec("b:([01]+)");
+        if (!std::regex_search(buffer, match, regexBitVec)) {
+            qDebug() << "Bad formatatted Line[" << actualLine << "].";
+            qDebug() << "Failed to matched:";
+            qDebug() << QString::fromStdString(buffer);
+            return;
+        }
+        sol.bitVec.resize(match[1].length());
+        int count = 0;
+        std::string str = match[1];
+        for (std::string::size_type i = 0; i < str.size(); ++i) {
+            sol.bitVec[i] = (str[i] == '1');
+        }
+        solutionVec.push_back(sol);
+    }
+    retflag = false;
+}
+
+void RunData::getLine(std::string& bufferString)
+{
+    std::getline(fileStream, bufferString);
+    actualLine++;
+}
+
+void RunData::calculateAverageOverRuns()
+{
+    qDebug() << "calculateAverageOverRuns";
+
+    {
+        std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+        int iter = singleRunList.begin()->bestMaxSolutionFoundPerIteration.size();
+        double n = singleRunList.size();
+        bestAverageMaxSolutionFoundPerIteration.resize(iter);
+        for (int i = 0; i < iter; i++) {
+            double average = std::accumulate(singleRunList.begin(), singleRunList.end(), 0.0, [i](double a, const SingleRun& b) -> double
+                {return a + b.bestMaxSolutionFoundPerIteration[i].y; }) / n;
+            bestAverageMaxSolutionFoundPerIteration[i] = GraphDataPoint((double)i, average);
+        }
+        std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
+        std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
+        qDebug() << "Time" << time.count() << "ms";
+    }
+
+}
+
+SingleRun::SingleRun(std::string uniqueName, const std::vector<SolutionPointData>::iterator begin, const std::vector<SolutionPointData>::iterator end, std::string name = "")
+    :begin(begin), end(end), name(name), runDataName(uniqueName)
+{
+
+}
+
+void SingleRun::calculateAdditionalData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits)
+{
+    calculateBestAndAverageIter();
+    calculateParticleSolution();
+    calculateDotsForDistribution();
+    calculateBitFieldData(pascalTriangleVec, amountOfBits);
+    calculateMeanHammingDistance();
+}
+
+void SingleRun::calculateBestAndAverageIter()
+{
+    if (begin == end) {
+        return;
+    }
+    double minObjectiveFunctionInIter = begin->objectiveFunction;
+    double maxObjectiveFunctionInIter = begin->objectiveFunction;
+    double bestMinObjectiveFunctionFound = begin->objectiveFunction;
+    double bestMaxObjectiveFunctionFound = begin->objectiveFunction;
+    double actualIterObjectiveFunctionAggregate = begin->objectiveFunction;
+    int actualIter = begin->iteration;
+    int foundSolutionInIteration = 1; 
+    for (auto iter = begin; iter != end; iter++) {
+        SolutionPointData& nextData = *iter;
+        if (nextData.iteration != actualIter) {
+            //save last
+            bestMinSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMinObjectiveFunctionFound));
+            bestMaxSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMaxObjectiveFunctionFound));
+            averageSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, actualIterObjectiveFunctionAggregate / (double)foundSolutionInIteration));
+            minSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, minObjectiveFunctionInIter));
+            maxSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, maxObjectiveFunctionInIter));
+            //init new iteration
+            actualIter = nextData.iteration;
+            foundSolutionInIteration = 1;
+            actualIterObjectiveFunctionAggregate = nextData.objectiveFunction;
+            minObjectiveFunctionInIter = nextData.objectiveFunction;
+            maxObjectiveFunctionInIter = nextData.objectiveFunction;
+        }
+        else {
+            //increae aggregate
+            foundSolutionInIteration++;
+            actualIterObjectiveFunctionAggregate += nextData.objectiveFunction;
+        }
+        //update best min and max if better
+        if (nextData.objectiveFunction < bestMinObjectiveFunctionFound) {
+            bestMinObjectiveFunctionFound = nextData.objectiveFunction;
+        }
+        if (nextData.objectiveFunction > bestMaxObjectiveFunctionFound) {
+            bestMaxObjectiveFunctionFound = nextData.objectiveFunction;
+        }
+        if (nextData.objectiveFunction < minObjectiveFunctionInIter) {
+            minObjectiveFunctionInIter = nextData.objectiveFunction;
+        }
+        if (nextData.objectiveFunction > maxObjectiveFunctionInIter) {
+            maxObjectiveFunctionInIter = nextData.objectiveFunction;
+        }
+    }
+    //save last iteration
+    bestMinSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMinObjectiveFunctionFound));
+    bestMaxSolutionFoundPerIteration.push_back(GraphDataPoint((double)actualIter, bestMaxObjectiveFunctionFound));
+    averageSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, actualIterObjectiveFunctionAggregate / (double)foundSolutionInIteration));
+    minSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, minObjectiveFunctionInIter));
+    maxSolutionPerItertion.push_back(GraphDataPoint((double)actualIter, maxObjectiveFunctionInIter));
+}
+
+void SingleRun::calculateParticleSolution()
+{
+    for (auto iter = begin; iter != end; iter++) {
+        GraphDataPoint point(iter->iteration, iter->objectiveFunction, &*iter);
+        auto treeIter = particleMap.find(iter->particleNumber);
+        if (treeIter == particleMap.end()) {
+            //create new Entry
+            std::vector<GraphDataPoint> vec;
+            vec.push_back(point);
+            particleMap.insert({ iter->particleNumber, vec});
+        }
+        else {
+            //append to vector in Entry
+            treeIter->second.push_back(point);
+        }
+    }
+}
+
+void SingleRun::calculateDotsForDistribution()
+{
+    for (std::vector<SolutionPointData>::iterator it = begin; it != end; ++it) {
+        dotsForDistribution.push_back(GraphDataPoint((double)it->iteration, it->objectiveFunction, &*it));
+    }
+}
+
+boost::multiprecision::cpp_int positionInPermutation2(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfUnsetBits)
+{
+    //recursion base
+    if (amountOfUnsetBits == 0) return 1;
+    int amountOfBits = end - begin;
+    std::vector<bool>::iterator indexIter = std::find(begin, end, false);
+    int index = indexIter - begin;
+    int amountOfBitsAfterIndex = (amountOfBits - 1) - index;
+    //recursion base
+    if (amountOfUnsetBits == 1) return (amountOfBits - 1) - index;
+    //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex 
+    boost::multiprecision::cpp_int before = (amountOfUnsetBits <= amountOfBitsAfterIndex) ? pascalTriangleVec[RunData::binominalIndex(amountOfBitsAfterIndex, amountOfUnsetBits)] : 0;
+    //Step 2 the actual position of the rest
+    boost::multiprecision::cpp_int after = positionInPermutation2(pascalTriangleVec, ++indexIter, end, amountOfUnsetBits - 1);
+    //Step 3 add Step 1 and Step 2
+    return before + after;
+}
+
+void SingleRun::calculateBitFieldData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits)
+{
+    
+    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+
+    for (std::vector<SolutionPointData>::iterator it = begin; it != end; ++it) {
+            int amountOfSetBits = std::count(it->bitVec.begin(), it->bitVec.end(), true);
+            int amountOfUnsetBits = it->bitVec.size() - amountOfSetBits;
+            boost::multiprecision::cpp_dec_float_100 position(positionInPermutation2(pascalTriangleVec, it->bitVec.begin(), it->bitVec.end(), amountOfUnsetBits));
+            boost::multiprecision::cpp_dec_float_100 maxAmountOfPermutaions (pascalTriangleVec[RunData::binominalIndex(amountOfBits, amountOfSetBits)] - 1);
+
+            dotsForBitField.push_back(GraphDataPoint((position / maxAmountOfPermutaions).convert_to<double>(), amountOfSetBits, &*it));
+    }
+   std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
+   std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
+   qDebug() << "BitFieldBerechnung: " << time.count() << "ms";
+}
+
+void SingleRun::calculateMeanHammingDistance()
+{
+    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
+    std::vector<SolutionPointData>::iterator iterBegin = begin;
+    for (std::vector<SolutionPointData>::iterator iter = begin; iter != end; iter++) {
+        if (iter->iteration != iterBegin->iteration) {
+            double mean = RunData::meanHammingDistance(iterBegin, iter);
+            meanHammingDistancePerIteration.push_back(GraphDataPoint(iterBegin->iteration, mean));
+            iterBegin = iter;
+        }
+    }
+    std::chrono::high_resolution_clock::time_point endPoint = std::chrono::high_resolution_clock::now();
+    std::chrono::milliseconds time = std::chrono::duration_cast<std::chrono::milliseconds>(endPoint - start);
+    qDebug() << "Mean: " << time.count() << "ms";
+}
+
+
+int RunData::binominalIndex(const int n, int k)
+{
+    if (k > n / 2) k = n - k;
+    return ((n + 1) / 2) * (n / 2 + 1) + k;
+}
+
+int RunData::hammingdistance(std::vector<bool>& bitVecA, std::vector<bool>& bitVecB)
+{
+    //assert((bitVecA.size() == bitVecB.size()));
+    int count = 0;
+    auto iterB = bitVecB.begin();
+    for (auto iterA = bitVecA.begin(); iterA != bitVecA.end(); iterA++) {
+        if (*iterA != *iterB) {
+            count++;
+        }
+        iterB++;
+    }
+    return count;
+}
+
+double RunData::meanHammingDistance(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end)
+{
+    if (std::distance(begin, end)  <= 1) {
+        return 0.0;
+    }
+    std::vector<SolutionPointData>::iterator startParticle(begin);
+    double hammingValuesAccumulated = 0.0;
+    int count = 0;
+    for (std::vector<SolutionPointData>::iterator iter = begin; iter != end; iter++) {
+        for (std::vector<SolutionPointData>::iterator iterParticle = iter + 1; iterParticle != end; iterParticle++) {
+            hammingValuesAccumulated += hammingdistance(iter->bitVec, iterParticle->bitVec);
+            count++;
+        }
+    }
+    return hammingValuesAccumulated / (double) count;
+}
+
+boost::multiprecision::cpp_int RunData::binominal(const int n,int k)
+{
+    boost::multiprecision::cpp_int value(1);
+    if (k > n / 2) k = n - k;
+    for (int i = 0; i < k; i++) {
+        value *= boost::multiprecision::cpp_int(n - i);
+        value /= boost::multiprecision::cpp_int(i + 1);
+    }
+    return value;
+}
+
+boost::multiprecision::cpp_int RunData::positionInPermutation(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int setBits)
+{
+    int amountOfBits = end - begin;
+    //recursion base
+    if (setBits == 0) return 1;
+    std::vector<bool>::iterator indexIter = std::find(begin, end, true);//TODO:false k�nnte andersrum sortieren!
+    int index = indexIter - begin;
+    int bitsAfterIndex = (amountOfBits - 1) - index;
+    //recursion base
+    if (setBits == 1) return (amountOfBits - 1) - index;
+    //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex 
+    boost::multiprecision::cpp_int before = binominal(bitsAfterIndex, setBits);
+    //Step 2 teh actual position of the rest
+    boost::multiprecision::cpp_int after = positionInPermutation(++indexIter, end, setBits - 1);
+    //setp 3 add Step 1 and Step 2
+    return before + after;
+}
+
+boost::multiprecision::cpp_int RunData::positionInPermutation_reversed(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfUnsetBits)
+{
+    qDebug() << "Method()";
+    int amountOfBits = end - begin;
+    //recursion base
+    if (amountOfUnsetBits == 0) return 1;
+    std::vector<bool>::iterator indexIter = std::find(begin, end, false);
+    int index = indexIter - begin;
+    qDebug() << "index: " << index;
+    int bitsAfterIndex = (amountOfBits - 1) - index;
+    //recursion base
+    if (amountOfUnsetBits == 1) return (amountOfBits - 1) - index;
+    //Step 1 the amount of permutations with the rest amountOfBitsAfterIndex 
+    boost::multiprecision::cpp_int before = (amountOfUnsetBits <= bitsAfterIndex)? binominal(bitsAfterIndex, amountOfUnsetBits):0;
+    qDebug() << "before: " << "binominal("<< bitsAfterIndex << "," << amountOfUnsetBits  << ")" << before.convert_to<int>();
+    //Step 2 teh actual position of the rest
+    boost::multiprecision::cpp_int after = positionInPermutation_reversed(++indexIter, end, amountOfUnsetBits - 1);
+    qDebug() << "after: " << after.convert_to<int>();
+    qDebug() << "return:" << before.convert_to<int>() << "+" << after.convert_to<int>();
+    //setp 3 add Step 1 and Step 2
+    return before + after;
+}
+
+
+GraphDataPoint::GraphDataPoint(double x, double y, SolutionPointData* orginalPoint) : x(x), y(y), orginalPoint(orginalPoint)
+{
+
+}
+
+GraphDataPoint::GraphDataPoint(double x, double y, QColor color, SolutionPointData* orginalPoint)
+    : x(x), y(y), orginalPoint(orginalPoint), color(color)
+{
+}
+
+bool GraphDataPoint::existLink() const
+{
+    return orginalPoint != nullptr;
+}
+
+QPointF GraphDataPoint::toQPointF() const
+{
+    return QPointF(x, y);
+}
+
+double GraphDataPoint::squaredDistance(QPointF& graphPoint) const
+{
+    return std::pow(graphPoint.x() - x, 2) + std::pow(graphPoint.y() - y, 2);
+}
+
+std::string SolutionPointData::bitstringToStdString()
+{
+    std::string str(bitVec.size(), 0);
+    std::transform(bitVec.begin(), bitVec.end(), str.begin(),
+        [](bool b) -> char { return b ? '1' : '0'; });
+    return str;
+}
diff --git a/metavis/RunData.h b/metavis/RunData.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b8d3340ea89d72caa5d2f4b8d2b8fa8eb8714ed
--- /dev/null
+++ b/metavis/RunData.h
@@ -0,0 +1,93 @@
+#pragma once
+#include <string>
+#include <vector>
+#include <fstream>
+#include <QPoint>
+#include <map>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/cpp_dec_float.hpp>
+
+class RunData;
+
+struct SolutionPointData {
+	int round;
+	int iteration;
+	double objectiveFunction;
+	int particleNumber;
+	std::vector<bool> bitVec;
+	std::string bitstringToStdString();
+};
+struct GraphDataPoint {
+	double x;
+	double y;
+	SolutionPointData* orginalPoint;
+	QColor color;
+	GraphDataPoint() :x(0), y(0), orginalPoint(nullptr) {}
+	GraphDataPoint(double x, double y, SolutionPointData* orginalPoint = nullptr);
+	GraphDataPoint(double x, double y, QColor color, SolutionPointData* orginalPoint = nullptr);
+	bool existLink() const;
+	QPointF toQPointF() const;
+	double squaredDistance(QPointF& graphPoint) const;
+};
+
+class SingleRun {
+public:
+	std::string name;
+	std::string runDataName;
+	const std::vector<SolutionPointData>::iterator begin;
+	const std::vector<SolutionPointData>::iterator end;
+	SingleRun(std::string uniqueName, const std::vector<SolutionPointData>::iterator begin, const std::vector<SolutionPointData>::iterator end, std::string name);
+	std::vector<GraphDataPoint> bestMinSolutionFoundPerIteration;
+	std::vector<GraphDataPoint> bestMaxSolutionFoundPerIteration;
+	std::vector<GraphDataPoint> averageSolutionPerItertion;
+	std::vector<GraphDataPoint> minSolutionPerItertion;
+	std::vector<GraphDataPoint> maxSolutionPerItertion;
+	std::vector<GraphDataPoint> dotsForDistribution;
+	std::vector<GraphDataPoint> dotsForBitField;
+	std::vector<GraphDataPoint> meanHammingDistancePerIteration;
+	std::map<int, std::vector<GraphDataPoint>> particleMap;
+
+	void calculateAdditionalData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits);
+private:
+	void calculateBestAndAverageIter();
+	void calculateParticleSolution();
+	void calculateDotsForDistribution();
+	void calculateBitFieldData(std::vector<boost::multiprecision::cpp_int>& pascalTriangleVec, int amountOfBits);
+	void calculateMeanHammingDistance();
+};
+
+
+
+class RunData
+{
+public:
+	std::string name;
+	std::string information;
+	std::string filePath;
+	std::vector<SolutionPointData> solutionVec;
+	std::list<SingleRun> singleRunList;
+	std::vector<GraphDataPoint> bestAverageMaxSolutionFoundPerIteration;
+
+
+
+	RunData();
+	RunData(std::string filePath);
+
+	void metalogFile(bool& retflag);
+
+private:
+	bool badFileFlag = false;
+	std::fstream fileStream;
+	int actualLine = 0;
+	void getLine(std::string& bufferString);
+	void calculateAverageOverRuns();
+	
+public:
+	static int binominalIndex(const int n, int k);
+	int static hammingdistance(std::vector<bool>& bitVecA, std::vector<bool>& bitVecB);
+	double static meanHammingDistance(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end);
+	static boost::multiprecision::cpp_int binominal(const int n, const int k);
+	static boost::multiprecision::cpp_int positionInPermutation(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfSetBits);
+	static boost::multiprecision::cpp_int positionInPermutation_reversed(std::vector<bool>::iterator begin, std::vector<bool>::iterator end, int amountOfUnsetBits);
+};
+
diff --git a/metavis/Scratchpad.cpp b/metavis/Scratchpad.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6182668fc0368338bbad02a203b5c6cb1c0485ad
--- /dev/null
+++ b/metavis/Scratchpad.cpp
@@ -0,0 +1,48 @@
+#include "pch.h"
+#include "Scratchpad.h"
+#include "HoverButton.h"
+#include <QAction>
+
+Scratchpad::Scratchpad(QWidget *parent)
+	: BitInspectorPanel(parent)
+{
+	HoverButton* rubbishButton = new HoverButton();
+	rubbishButton->setMinimumSize(20, 20);
+	rubbishButton->setMaximumSize(20, 20);
+	rubbishButton->setIcon(QIcon(":/metavis/Resources/rubbish.svg"));
+	rubbishButton->setHoveredIcon(QIcon(":/metavis/Resources/rubbish_hovered.svg"));
+	rubbishButton->setAttribute(Qt::WA_TranslucentBackground);
+	rubbishButton->setStyleSheet(rubbishButton->styleSheet() + "border: none;");
+	rubbishButton->setToolTip("Clear scratchpad");
+	qDebug() << topPanel->count();
+	topPanel->insertWidget(topPanel->count()-1, rubbishButton);
+	connect(rubbishButton, &QPushButton::released, this, &Scratchpad::clear);
+	
+	QAction* clearAction = new QAction("Clear");
+	this->contextMenu->addAction(clearAction);
+	connect(clearAction, &QAction::triggered, this, &Scratchpad::clear);
+
+	popupWidget->setInformation("<h3><u>Scratchpad</u></h3> Shows selected solution from search space visualizations or metrics. Each solution gets displayed in a row. To add solutions go in a other visualization and press & drag the RMB(Right-Mouse-Button) to select the points to add to this scratchpad.<br><b>Clear button</b> removes all solutions from this pad.<br> Alternative is press RMB and \"Clear\" in the scratchpad. <br><b>Iteration:</b> Show the iteration the solution is generated.<br><b>Number:</b> Show which individual in the popullation is represent.<br><b>Objective Function:</b> Describes how well the solution is, it depends on the problem if a low or high value is desired.<br><b>Binary:</b> Shows the bitstring of the solution. White rectangle represents the bit is <i>false<i> and black <i>true<i>.");
+}
+
+Scratchpad::~Scratchpad()
+{
+}
+
+void Scratchpad::addPoint(const SolutionPointData& point)
+{
+	inspector->clear();
+	points.push_back(point);
+	inspector->updateData(points.begin(), points.end());
+}
+
+void Scratchpad::clear()
+{
+	inspector->clear();
+	points.clear();
+}
+
+void Scratchpad::contextMenuEvent(QContextMenuEvent* event)
+{
+	contextMenu->exec(event->globalPos());
+}
diff --git a/metavis/Scratchpad.h b/metavis/Scratchpad.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b666ebcb6fbc710a2414a2fd00278b54fe19b8f
--- /dev/null
+++ b/metavis/Scratchpad.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "BitInspectorPanel.h"
+#include "RunData.h"
+#include <QMenu>
+
+class Scratchpad : public BitInspectorPanel
+{
+	Q_OBJECT
+
+public:
+	Scratchpad(QWidget *parent);
+	~Scratchpad();
+	void addPoint(const SolutionPointData& point);
+	void clear();
+protected:
+	QMenu* contextMenu = new QMenu(this);
+	void contextMenuEvent(QContextMenuEvent* event) override;
+private:
+	//Points to display
+	std::vector<SolutionPointData> points;
+};
diff --git a/metavis/SearchSpacePlott.cpp b/metavis/SearchSpacePlott.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85c9b9f9235bf6687d05ebaa12fc5d40cf456693
--- /dev/null
+++ b/metavis/SearchSpacePlott.cpp
@@ -0,0 +1,51 @@
+#include "pch.h"
+#include "SearchSpacePlott.h"
+
+SearchSpacePlott::SearchSpacePlott(QWidget *parent)
+	: GraphPlott(parent, false, true, false)
+{
+	QSlider* circleSizeSlider = new QSlider(Qt::Horizontal);
+	circleSizeSlider->setMinimum(1);
+	circleSizeSlider->setMaximum(15);
+	circleSizeSlider->setValue(circleSize);
+	circleSizeSlider->setMaximumWidth(80);
+	circleSizeSlider->setMaximumHeight(16);
+	this->buttonPanel->insertSpacing(1, 5);
+	this->buttonPanel->insertWidget(1, circleSizeSlider);
+	this->buttonPanel->insertSpacing(1, 5);
+	this->buttonPanel->insertWidget(1, new QLabel("Size:"));
+	connect(circleSizeSlider, &QSlider::valueChanged, this, [this, circleSizeSlider]() {this->circleSize = circleSizeSlider->value(); this->update(); });
+	QSlider* transparentSlider = new QSlider(Qt::Horizontal);
+	transparentSlider->setMinimum(5);
+	transparentSlider->setMaximum(50);
+	transparentSlider->setValue(50);
+	transparentSlider->setMaximumWidth(80);
+	transparentSlider->setMaximumHeight(16);
+	this->buttonPanel->insertSpacing(1, 5);
+	this->buttonPanel->insertWidget(1, transparentSlider);
+	this->buttonPanel->insertSpacing(1, 5);
+	this->buttonPanel->insertWidget(1, new QLabel("Transparency:"));
+	connect(transparentSlider, &QSlider::valueChanged, this, [this, transparentSlider]() {this->transparentAlphaValue = ((double)transparentSlider->value()) / 50.0; this->update(); });
+	this->setMinimumSize(200, 50);
+}
+
+SearchSpacePlott::~SearchSpacePlott()
+{
+}
+
+void SearchSpacePlott::mouseMoveEvent(QMouseEvent* event)
+{
+	GraphPlott::mouseMoveEvent(event);
+}
+
+void SearchSpacePlott::setMinimumIterationToDispaly(int min)
+{
+	minIter = min;
+	update();
+}
+
+void SearchSpacePlott::setMaximumIterationToDispaly(int max)
+{
+	maxIter = max;
+	update();
+}
diff --git a/metavis/SearchSpacePlott.h b/metavis/SearchSpacePlott.h
new file mode 100644
index 0000000000000000000000000000000000000000..14ed71fd61f16bf15c694206f4b1e7a78fb9c7cd
--- /dev/null
+++ b/metavis/SearchSpacePlott.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <QWidget>
+#include <QMouseEvent>
+#include "GraphPlott.h"
+
+
+class SearchSpacePlott : public GraphPlott
+{
+	Q_OBJECT
+
+public:
+	SearchSpacePlott(QWidget *parent);
+	~SearchSpacePlott();
+protected:
+	int minIter = 0;
+	int maxIter = 100;
+
+	int circleSize = 2;
+	double transparentAlphaValue = 1;
+	virtual void mouseMoveEvent(QMouseEvent* event) override;
+public slots:
+	void setMinimumIterationToDispaly(int min);
+	void setMaximumIterationToDispaly(int max);
+};
diff --git a/metavis/SettingDialog.cpp b/metavis/SettingDialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c818ca11a0bf94cf6f528a1876088fa6272a7db2
--- /dev/null
+++ b/metavis/SettingDialog.cpp
@@ -0,0 +1,49 @@
+#include "pch.h"
+#include "SettingDialog.h"
+#include <QDebug>
+SettingDialog::SettingDialog(QSettings* settings, QWidget* parent)
+	: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint), settings(settings)
+{
+	ui.setupUi(this);
+	//manuel connect all button with buttonHandler
+	connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(dialogButtonHandler(QAbstractButton*)));
+}
+
+SettingDialog::~SettingDialog()
+{
+}
+
+
+
+void SettingDialog::acceptButtonClicked()
+{
+	qDebug() << "Accept";
+	apply();
+	accept();
+}
+
+void SettingDialog::apply()
+{
+	qDebug() << "Apply";
+}
+
+
+void SettingDialog::dialogButtonHandler(QAbstractButton* button)
+{
+	switch (ui.buttonBox->buttonRole(button)) {
+		case QDialogButtonBox::ButtonRole::AcceptRole:
+			acceptButtonClicked();
+			break;
+		case QDialogButtonBox::ButtonRole::ApplyRole:
+			apply();
+			break;
+		case QDialogButtonBox::ButtonRole::RejectRole:
+		default:
+			/* close the window and dont apply changes*/
+			reject();
+			break;
+	}
+}
+
+
+
diff --git a/metavis/SettingDialog.h b/metavis/SettingDialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec1313c98c9c59f3ca5ca698f9474785ff6f3482
--- /dev/null
+++ b/metavis/SettingDialog.h
@@ -0,0 +1,38 @@
+#pragma once
+#include <QDialog>
+#include <QSettings>
+#include "ui_SettingDialog.h"
+#include <QAbstractButton>
+
+/**
+ * A dialog to change the Setting for the main program.
+ */
+class SettingDialog : public QDialog
+{
+	Q_OBJECT
+
+public:
+	SettingDialog(QSettings* settings, QWidget *parent = Q_NULLPTR);
+	~SettingDialog();
+
+private:
+	Ui::SettingDialog ui;
+	QSettings* settings;
+	/**
+	 *  Apply the settings and close the SettingDialog afterwords.
+	 */
+	void acceptButtonClicked();
+	/**
+	 *  Save the changes from the dialog to the actual settings.
+	 */
+	void apply();
+	
+
+
+public slots:
+	/**
+	 * Handle the button clicked in the SettingDialog.
+	 * @param button the Button returned from the Signal.
+	 */
+	void dialogButtonHandler(QAbstractButton* button);
+};
diff --git a/metavis/SettingDialog.ui b/metavis/SettingDialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..33de0f14e78c0042197f23c2a4aa836d4954e435
--- /dev/null
+++ b/metavis/SettingDialog.ui
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SettingDialog</class>
+ <widget class="QDialog" name="SettingDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>295</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>SettingDialog</string>
+  </property>
+  <property name="locale">
+   <locale language="English" country="UnitedKingdom"/>
+  </property>
+  <widget class="QDialogButtonBox" name="buttonBox">
+   <property name="geometry">
+    <rect>
+     <x>165</x>
+     <y>260</y>
+     <width>221</width>
+     <height>23</height>
+    </rect>
+   </property>
+   <property name="locale">
+    <locale language="English" country="UnitedKingdom"/>
+   </property>
+   <property name="standardButtons">
+    <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+   </property>
+  </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/metavis/TsneControlPanel.cpp b/metavis/TsneControlPanel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c8ece7fe73694341b0055baa2f04e0da7e3250ca
--- /dev/null
+++ b/metavis/TsneControlPanel.cpp
@@ -0,0 +1,144 @@
+#include "pch.h"
+#include "TsneControlPanel.h"
+#include <QPushButton>
+#include <QProgressBar>
+#include <QGridLayout>
+#include <QSpacerItem>
+#include <QLineEdit>
+#include <QSlider>
+
+TsneControlPanel::TsneControlPanel(QWidget *parent)
+	: QWidget(parent)
+{
+	plott->setVisibleWindow(-20, 20, -20, 20);
+
+
+	QVBoxLayout* layout = new QVBoxLayout(this);
+	layout->setContentsMargins(0, 0, 0, 0);
+	QHBoxLayout* buttonLayout = new QHBoxLayout();
+	buttonLayout->setContentsMargins(0, 0, 0, 0);
+	layout->addWidget(plott);
+	layout->addLayout(buttonLayout);
+
+	//ButtonPanel
+	showOptionsButton = new QPushButton("Hide Options");
+	connect(showOptionsButton, &QPushButton::pressed, this, &TsneControlPanel::toggleOptions);
+	QPushButton* startButton = new QPushButton("Start");
+	connect(startButton, &QPushButton::pressed, this, &TsneControlPanel::start);
+	QPushButton* pauseButton = new QPushButton("Pause");
+	connect(pauseButton, &QPushButton::pressed, this, &TsneControlPanel::pause);
+	iterationLabel->setText("Iteration: 0");
+	progressBar->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Preferred); 
+	progressBar->setAlignment(Qt::AlignCenter);
+	progressBar->setValue(0);
+	progressBar->setMaximum(tsneSettings->maxIter - 1);
+	buttonLayout->addWidget(startButton);
+	buttonLayout->addWidget(pauseButton);
+	buttonLayout->addWidget(iterationLabel);
+	buttonLayout->addWidget(progressBar);
+	buttonLayout->addWidget(showOptionsButton);
+	
+	
+	layout->addWidget(tsneSettings);
+	
+	layout->addWidget(slider);
+
+	//Slider
+	slider->setTitle("Iteration:");
+	connect(slider, &RangeSlider::maxChanged, plott, &TsnePlott::setMaximumIterationToDispaly);
+	connect(slider, &RangeSlider::minChanged, plott, &TsnePlott::setMinimumIterationToDispaly);
+	
+	
+	//Gradient
+	layout->addWidget(gradient);
+	connect(gradient, &ColorGradient::gradientChanged, this, [this]() {this->plott->updateColors(*gradient); });
+
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("Tsne");
+	if (settings.value("hideOptions", true).toBool()) {
+		toggleOptions();
+	}
+	settings.endGroup();
+}
+
+TsneControlPanel::~TsneControlPanel()
+{
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("Tsne");
+	settings.setValue("hideOptions", this->isOptionHidden);
+	settings.endGroup();
+}
+
+void TsneControlPanel::assignData(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end, QString runName)
+{
+	this->begin = begin;
+	this->end = end;
+	runName = runName;
+	plott->setDisplayLabel(runName);
+	resetPanel();
+	plott->clear();
+}
+
+void TsneControlPanel::clear()
+{
+	begin = std::vector<SolutionPointData>::iterator();
+	end = std::vector<SolutionPointData>::iterator();
+	runName = "";
+	resetPanel();
+	plott->clear();
+}
+
+
+void TsneControlPanel::toggleOptions()
+{
+	this->isOptionHidden = !this->isOptionHidden;
+	showOptionsButton->setText(this->isOptionHidden ? "More Options" : "Hide Options");
+	this->slider->setHidden(this->isOptionHidden);
+	this->gradient->setHidden(this->isOptionHidden);
+	this->tsneSettings->setHidden(this->isOptionHidden);
+}
+
+void TsneControlPanel::resetPanel()
+{
+	if (algo != nullptr) {
+		delete algo;
+		algo = nullptr;
+	}
+	iterationChanged(0);
+}
+
+
+void TsneControlPanel::pause()
+{
+	if (algo != nullptr) {
+		algo->pause();
+	}
+}
+
+void TsneControlPanel::iterationChanged(int iter)
+{
+	iterationLabel->setText("Iteration: " + QString::number(iter));
+	plott->update();
+	progressBar->setValue(iter);
+}
+
+void TsneControlPanel::start()
+{
+	qDebug() << "start";
+	if (begin == end) {
+		qDebug() << "NoData";
+		return;
+	}
+	double* matrixY = nullptr;
+	double** matrixYPtr = &matrixY;
+	resetPanel();
+	algo = new tSneAlgo(begin, end, matrixYPtr, tsneSettings->perplexity, tsneSettings->learnrate, tsneSettings->maxIter);
+	connect(algo, &tSneAlgo::changedIter, this, &TsneControlPanel::iterationChanged);
+	connect(algo, &tSneAlgo::algoDone, this, &TsneControlPanel::finished);
+	emit started();
+	algo->start();
+	qDebug() << "Y:" << matrixY;
+	plott->assignMatrix(begin, end, matrixY, std::distance(begin, end), *gradient);
+}
diff --git a/metavis/TsneControlPanel.h b/metavis/TsneControlPanel.h
new file mode 100644
index 0000000000000000000000000000000000000000..abfb47d2a9bf834b51e59e6b50887e57f68a7e22
--- /dev/null
+++ b/metavis/TsneControlPanel.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <QWidget>
+#include "TsnePlott.h"
+#include "RangeSlider.h"
+#include "ColorGradient.h"
+#include <QProgressBar>
+#include "TsneSettings.h"
+#include "tSneAlgo.h"
+#include <string>
+#include <vector>
+#include "RunData.h"
+
+class TsneControlPanel : public QWidget
+{
+	Q_OBJECT
+
+public:
+	TsneControlPanel(QWidget *parent);
+	~TsneControlPanel();
+	TsnePlott* plott = new TsnePlott(this);
+	void assignData(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end, QString runName);
+	void clear();
+
+
+protected:
+	RangeSlider* slider = new RangeSlider(this);
+	ColorGradient* gradient = new ColorGradient(this);
+	QProgressBar* progressBar = new QProgressBar();
+	TsneSettings* tsneSettings = new TsneSettings(this);
+	QLabel* iterationLabel = new QLabel();
+	bool isOptionHidden = false;
+	void toggleOptions();
+	void resetPanel();
+
+private:
+	QString runName;
+	std::vector<SolutionPointData>::iterator begin, end;
+	tSneAlgo* algo = nullptr;
+	QPushButton* showOptionsButton;
+public slots:
+	void start();
+	void pause();
+	void iterationChanged(int iter);
+signals:
+	void started();
+	void finished();
+};
diff --git a/metavis/TsnePlott.cpp b/metavis/TsnePlott.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9250cd77d49ac345ac16f4f4c680015cef60c5d
--- /dev/null
+++ b/metavis/TsnePlott.cpp
@@ -0,0 +1,172 @@
+#include "pch.h"
+#include "TsnePlott.h"
+#include <limits>
+TsnePlott::TsnePlott(QWidget *parent)
+	: SearchSpacePlott(parent)
+{
+	setAxisLegend("X Axis", "Y Axis");
+}
+
+TsnePlott::~TsnePlott()
+{
+}
+
+void TsnePlott::assignMatrix(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end, double* yMatrixFromTsneAlgo, int n, ColorGradient& gradient)
+{
+	this->begin = begin;
+	this->end = end;
+	this->yMatrixFromTsneAlgo = yMatrixFromTsneAlgo;
+	this->N = n;
+	updateColors(gradient);
+	
+}
+
+void TsnePlott::clear()
+{
+	begin = end = std::vector<SolutionPointData>::iterator();
+	yMatrixFromTsneAlgo = nullptr;
+	N = 0;
+	colorPointDataVec.clear();
+	update();
+}
+
+void TsnePlott::updateColors(ColorGradient& gradient)
+{
+	colorPointDataVec.clear();
+	for (auto iterator = begin; iterator != end; iterator++) {
+		colorPointDataVec.push_back(gradient.getColorFromValue(iterator->objectiveFunction));
+	}
+	update();
+}
+
+void TsnePlott::frameGraphInView()
+{
+	if (begin == end || !yMatrixFromTsneAlgo) {
+		return;
+	}
+	VisibleWindow nextWindow(0,0,0,0);
+	QPointF first(yMatrixFromTsneAlgo[0], yMatrixFromTsneAlgo[1]);
+	nextWindow.xMin = nextWindow.xMax = first.x();
+	nextWindow.yMin = nextWindow.yMax = first.y();
+
+
+	for (int i = 1; i < this->N; i++) {
+		QPointF point(yMatrixFromTsneAlgo[2 * i], yMatrixFromTsneAlgo[2 * i + 1]);
+		if (point.x() < nextWindow.xMin) {
+			nextWindow.xMin = point.x();
+		}
+		else if (point.x() > nextWindow.xMax) {
+			nextWindow.xMax = point.x();
+		}
+		if (point.y() < nextWindow.yMin) {
+			nextWindow.yMin = point.y();
+		}
+		else if (point.y() > nextWindow.yMax) {
+			nextWindow.yMax = point.y();
+		}
+	}
+	nextWindow.ZoomOut(0.05);
+	if (std::abs(nextWindow.xMax - nextWindow.xMin) > std::numeric_limits<double>::min()) {
+		window.xMin = nextWindow.xMin;
+		window.xMax = nextWindow.xMax;
+	}
+	if (std::abs(nextWindow.yMax - nextWindow.yMin) > std::numeric_limits<double>::min()) {
+		window.yMin = nextWindow.yMin;
+		window.yMax = nextWindow.yMax;
+	}
+	update();
+}
+
+void TsnePlott::searchForPointUnderCursor()
+{
+	//check if mouse stayed still
+	QPoint globalPosition = QCursor::pos();
+	QPointF pos = this->mapFromGlobal(globalPosition);
+
+	if (pos != lastPosition) {
+		return;
+	}
+	if (begin == end || !yMatrixFromTsneAlgo) {
+		return;
+	}
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+	
+	QPointF minPoint = transformGraphToView(QPointF(yMatrixFromTsneAlgo[0], yMatrixFromTsneAlgo[1]));
+	std::vector<SolutionPointData>::iterator minData = begin;
+	double minSqaredDistance = sqaredDistance(transformGraphToView(minPoint, stregth_factorX, stregth_factorY, translation), pos);
+	auto iter = begin;
+	for (int i = 1; i < this->N; i++, iter++) {
+		if (iter->iteration < minIter) {
+			continue;
+		}
+		if (iter->iteration > maxIter) {
+			break;
+		}
+		QPointF point(yMatrixFromTsneAlgo[2 * i], yMatrixFromTsneAlgo[2 * i + 1]);
+		double distance = sqaredDistance(transformGraphToView(point, stregth_factorX, stregth_factorY, translation), pos);
+		if (distance < minSqaredDistance) {
+			minSqaredDistance = distance;
+			minPoint = point;
+			minData = iter;
+		}
+	}
+
+	//if curser is radius + 3pixel away
+	if (minSqaredDistance <= circleSize * circleSize + 9) {
+		QPointF pointInWidget = transformGraphToView(minPoint, stregth_factorX, stregth_factorY, translation);
+		QToolTip::showText(this->mapToGlobal(QPoint(pointInWidget.x(), pointInWidget.y())) - QPoint(0, 35), QString::fromStdString(minData->bitstringToStdString()));
+	}
+}
+
+void TsnePlott::addPointsInWindowToScratchPad(VisibleWindow& window)
+{
+	if (!pad) {
+		qDebug() << "NoPad";
+		return;
+	}
+	if (begin == end || !yMatrixFromTsneAlgo) {
+		return;
+	}
+	auto iter = begin;
+	for (int i = 1; i < this->N; i++, iter++) {
+		if (iter->iteration < minIter) {
+			continue;
+		}
+		if (iter->iteration > maxIter) {
+			break;
+		}
+		QPointF point(yMatrixFromTsneAlgo[2 * i], yMatrixFromTsneAlgo[2 * i + 1]);
+		if (window.inBound(point)) {
+			pad->addPoint(*iter);
+		}
+	}
+}
+
+void TsnePlott::drawData(QPainter& painter)
+{
+	if (begin == end || !yMatrixFromTsneAlgo) {
+		return;
+	}
+	QRect graphDisplayRect = getDisplayRect();
+	QPointF translation(graphDisplayRect.left(), graphDisplayRect.top());
+	double stregth_factorX = graphDisplayRect.width() / std::abs(window.xMax - window.xMin);
+	double stregth_factorY = graphDisplayRect.height() / std::abs(window.yMax - window.yMin);
+	auto iter = begin;
+	painter.setPen(Qt::transparent);
+	for (int i = 0; i < this->N; i++, iter++) {
+		if (iter->iteration < minIter) {
+			continue;
+		}
+		if (iter->iteration > maxIter) {
+			break;
+		}
+		QColor color = colorPointDataVec[i];
+		color.setAlphaF(this->transparentAlphaValue);
+		painter.setBrush(color);
+		painter.drawEllipse(transformGraphToView(QPointF(yMatrixFromTsneAlgo[2 * i], yMatrixFromTsneAlgo[2 * i + 1]), stregth_factorX, stregth_factorY, translation), circleSize, circleSize);
+	}
+	painter.setBrush(Qt::BrushStyle::NoBrush);
+}
diff --git a/metavis/TsnePlott.h b/metavis/TsnePlott.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f5a9a18471266b9ec32514a76973eb4d72b89cb
--- /dev/null
+++ b/metavis/TsnePlott.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <QWidget>
+#include <SearchSpacePlott.h>
+#include <vector>
+#include "RunData.h"
+#include "ColorGradient.h"
+
+
+class TsnePlott : public SearchSpacePlott
+{
+	Q_OBJECT
+
+
+
+public:
+	TsnePlott(QWidget *parent);
+	~TsnePlott();
+	void assignMatrix(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end,  double* yMatrixFromTsneAlgo, int n, ColorGradient& gradient);
+	void clear();
+	void updateColors(ColorGradient& gradient);
+	void virtual frameGraphInView();
+protected:
+	virtual void drawData(QPainter& painter) override;
+	virtual void searchForPointUnderCursor() override;
+	virtual void addPointsInWindowToScratchPad(VisibleWindow& window) override;
+private:
+	std::vector<SolutionPointData>::iterator begin, end;
+	std::vector<QColor> colorPointDataVec;
+	double* yMatrixFromTsneAlgo = nullptr;
+	int N;
+
+};
diff --git a/metavis/TsneSettings.cpp b/metavis/TsneSettings.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17f37f8758597023e91ff10925863ffbef4fb713
--- /dev/null
+++ b/metavis/TsneSettings.cpp
@@ -0,0 +1,125 @@
+#include "pch.h"
+#include "TsneSettings.h"
+#include <QLineEdit>
+#include <QSlider>
+#include <QRegExp>
+
+
+TsneSettings::TsneSettings(QWidget *parent)
+	: QWidget(parent)
+{
+	readSettigns();
+	//Layout 
+	tsneSettings->setContentsMargins(0, 0, 0, 0);
+	tsneSettings->addWidget(new QLabel("T-SNE Settings:"), 0, 0);
+	tsneSettings->addWidget(new QLabel("   Perplexity"), 1, 0);
+	tsneSettings->addWidget(new QLabel("   Lernrate"), 2, 0);
+	
+	perplexityEdit->setMinimumWidth(80);
+	perplexityEdit->setMaximumWidth(80);
+	perplexityEdit->setText(QString::number(perplexity));
+	tsneSettings->addWidget(perplexityEdit, 1, 1);
+	
+	perplexitySlider->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Preferred);
+	perplexitySlider->setValue(perplexity);
+	perplexitySlider->setMinimum(perplexityMin);
+	perplexitySlider->setMaximum(perplexityMax);
+	perplexitySlider->setTickInterval((perplexityMax - perplexityMin + 1) / 10);
+	perplexitySlider->setTickPosition(QSlider::TickPosition::TicksBelow);
+	tsneSettings->addWidget(perplexitySlider, 1, 2);
+	
+	learnrateEdit->setMinimumWidth(80);
+	learnrateEdit->setMaximumWidth(80);
+	learnrateEdit->setText(QString::number(learnrate));
+	tsneSettings->addWidget(learnrateEdit, 2, 1);
+	
+	learnrateSlider->setValue(learnrate);
+	learnrateSlider->setMinimum(learnrateMin);
+	learnrateSlider->setMaximum(learnrateMax);
+	learnrateSlider->setTickInterval((learnrateMax - learnrateMin + 1) / 10);
+	learnrateSlider->setTickPosition(QSlider::TickPosition::TicksBelow);
+	learnrateSlider->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Preferred);
+	tsneSettings->addWidget(learnrateSlider, 2, 2);
+	
+
+	QRegExp rxMinMax("[0-9]+");
+	QRegExpValidator* validatorMinMax = new QRegExpValidator(rxMinMax, 0);
+	learnrateEdit->setValidator(validatorMinMax);
+	perplexityEdit->setValidator(validatorMinMax);
+
+	connect(perplexitySlider, &QSlider::valueChanged, this, &TsneSettings::setPerplexity);
+	connect(learnrateSlider, &QSlider::valueChanged, this, &TsneSettings::setLearnrate);
+	connect(learnrateEdit, &QLineEdit::editingFinished, this, &TsneSettings::learnrateEditChangeEvent);
+	connect(perplexityEdit, &QLineEdit::editingFinished, this, &TsneSettings::perplexityEditChangeEvent);
+}
+
+TsneSettings::~TsneSettings()
+{
+	writeSettings();
+}
+
+void TsneSettings::setPerplexity(int value)
+{
+	if (perplexity == value) return;
+	perplexity = std::clamp(value, perplexityMin, perplexityMax);
+	perplexitySlider->setValue(perplexity);
+	perplexityEdit->setText(QString::number(perplexity));
+	emit perplexityChanged(perplexity);
+}
+
+void TsneSettings::setLearnrate(int value)
+{
+	if (learnrate == value) return;
+	learnrate = std::clamp(value, learnrateMin, learnrateMax);
+	learnrateSlider->setValue(learnrate);
+	learnrateEdit->setText(QString::number(learnrate));
+	emit learnrateChanged(learnrate);
+}
+
+void TsneSettings::readSettigns()
+{
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("Tsne");
+	maxIter = settings.value("maxIter", 750).toInt();
+	perplexity = settings.value("perplexity", 10).toInt();
+	perplexityMin = settings.value("perplexity_MIN", 1).toInt();
+	perplexityMax = settings.value("perplexity_MAX", 50).toInt();
+	learnrate = settings.value("learnrate", 200).toInt();
+	learnrateMin = settings.value("learnrate_MIN", 1).toInt();
+	learnrateMax = settings.value("learnrate_MAX", 1000).toInt();
+	settings.endGroup();
+}
+
+void TsneSettings::writeSettings()
+{
+	//Settings
+	QSettings settings("settings.ini", QSettings::IniFormat, this);
+	settings.beginGroup("Tsne");
+	settings.setValue("maxIter", maxIter);
+	settings.setValue("perplexity", perplexity);
+	settings.setValue("perplexity_MIN", perplexityMin);
+	settings.setValue("perplexity_MAX", perplexityMax);
+	settings.setValue("learnrate", learnrate);
+	settings.setValue("learnrate_MIN", learnrateMin);
+	settings.setValue("learnrate_MAX", learnrateMax);
+	settings.endGroup();
+}
+
+void TsneSettings::learnrateEditChangeEvent()
+{
+	bool success = false;
+	int value = learnrateEdit->text().toInt(&success);
+	if (success) {
+		setLearnrate(value);
+	}
+}
+
+void TsneSettings::perplexityEditChangeEvent()
+{
+	bool success = false;
+	int value = perplexityEdit->text().toInt(&success);
+	if (success) {
+		setPerplexity(value);
+	}
+}
diff --git a/metavis/TsneSettings.h b/metavis/TsneSettings.h
new file mode 100644
index 0000000000000000000000000000000000000000..2720b8dfb768266d391b8f191738928a6f88c0bc
--- /dev/null
+++ b/metavis/TsneSettings.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <QWidget>
+#include <QLineEdit>
+#include <QSlider>
+#include <QGridLayout>
+
+class TsneSettings : public QWidget
+{
+	Q_OBJECT
+
+public:
+	TsneSettings(QWidget *parent);
+	~TsneSettings();
+	int maxIter;
+	int perplexity, perplexityMax, perplexityMin;
+	int learnrate, learnrateMax, learnrateMin;
+	void setPerplexity(int value);
+	void setLearnrate(int value);
+protected:
+	QGridLayout* tsneSettings = new QGridLayout(this);
+	QSlider* perplexitySlider = new QSlider(Qt::Orientation::Horizontal);
+	QSlider* learnrateSlider = new QSlider(Qt::Orientation::Horizontal);
+	QLineEdit* perplexityEdit = new QLineEdit();
+	QLineEdit* learnrateEdit = new QLineEdit();
+private:
+	void readSettigns();
+	void writeSettings();
+	void learnrateEditChangeEvent();
+	void perplexityEditChangeEvent();
+signals:
+	void perplexityChanged(int perplexity);
+	void learnrateChanged(int learnrate);
+};
diff --git a/metavis/Worker.cpp b/metavis/Worker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..83bc909517edb0161ed8b84c6ce30c8ab7255408
--- /dev/null
+++ b/metavis/Worker.cpp
@@ -0,0 +1,11 @@
+#include "pch.h"
+#include "Worker.h"
+
+Worker::Worker(std::thread t) : t(std::move(t))
+{
+}
+
+Worker::~Worker()
+{
+	t.join();
+}
diff --git a/metavis/Worker.h b/metavis/Worker.h
new file mode 100644
index 0000000000000000000000000000000000000000..516bf2ac3a93043000085e9a8e4564a1aca80e9e
--- /dev/null
+++ b/metavis/Worker.h
@@ -0,0 +1,10 @@
+#pragma once
+#include <thread>
+class Worker
+{
+	std::thread t;
+public:
+	Worker(std::thread t);
+	~Worker();
+};
+
diff --git a/metavis/main.cpp b/metavis/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..770c974e9b1d6ebc22a93173c60552263caf7891
--- /dev/null
+++ b/metavis/main.cpp
@@ -0,0 +1,16 @@
+#include "pch.h"
+#include "metavis.h"
+#include <QtWidgets/QApplication>
+#include <QtGui>
+#include <QDebug>
+#include <Vector>
+#include <boost/multiprecision/cpp_int.hpp>
+#include "RunData.h"
+/* entrance of the program */
+int main(int argc, char *argv[])
+{ 
+	QApplication a(argc, argv);
+	metavis w;
+	w.show();
+	return a.exec();
+}
diff --git a/metavis/metavis.cpp b/metavis/metavis.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d7e9384b245c6baae35d406cc94de48ff21c6641
--- /dev/null
+++ b/metavis/metavis.cpp
@@ -0,0 +1,406 @@
+#include "pch.h"
+#include "metavis.h"
+#include "SettingDialog.h"
+#include <QStandardPaths>
+#include <QDockwidget>
+#include <QLabel>
+#include <QLayout>
+#include <QDebug>
+#include <QStyleFactory>
+#include <QFileDialog>
+#include <QDir>
+#include <map>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <QDesktopWidget>
+#include <QSlider>
+#include <QSizePolicy>
+#include <QScrollArea>
+#include <QMainWindow>
+#include "DockableGraphView.h"
+#include <QShortcut>
+#include "RangeSlider.h"
+#include "tsneIteractive.h"
+#include "util.h"
+
+
+metavis::metavis(QWidget* parent)
+	: QMainWindow(parent)
+{
+	ui.setupUi(this);
+	/* create settings object*/
+	//settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "TK", "metavis", this);
+	settings = new QSettings("settings.ini", QSettings::IniFormat, this);
+	//settings = new QSettings(QCoreApplication::applicationDirPath()+ "hatschi.ini", QSettings::IniFormat);
+	setStyleSheet(styleSheet() + "QMainWindow::separator {background: rgb(200, 200, 200);width: 1px;height: 1px;}");
+	setStyleSheet(styleSheet() + "QTabBar::tab:selected {color: rgb(0, 122, 204);}");
+	setStyleSheet(styleSheet() + "QTabWidget::pane {border-top: 0px solid #C2C7CB;margin: -9px -9px -13px -9px;}");
+	this->setDockNestingEnabled(true);
+	option = dockOption::right;
+	createBitInSpector();
+	QDockWidget* saveForTabPad = lastDocked;
+	option = dockOption::splitTop;
+	createProjectManager();
+	option = dockOption::splitLeft;
+	createBitFieldV2();
+	QDockWidget* saveForTabTsne = lastDocked;
+	initPlotter();
+	createScratchpad(saveForTabPad);
+	createTSNE(saveForTabTsne);
+
+
+	readMainWindowSettings();
+	ui.actionOpen->setShortcut(QKeySequence(Qt::CTRL + Qt::Key::Key_O));
+	QMenu* viewMenu = createPopupMenu();
+	viewMenu->setTitle("View");
+	ui.menuBar->insertMenu(manager->projectMenu->menuAction(), viewMenu);
+	this->setCentralWidget(nullptr);
+} 
+
+
+
+
+void metavis::openSetting() {
+	SettingDialog settingDialog(settings, this);
+	/* Blocking operation */
+	settingDialog.exec();
+}
+
+metavis::~metavis()
+{
+	writeActualMainWindowSettings();
+}
+
+void metavis::selectRunData(RunData* data)
+{
+	selectedBestGraph->removeAll();
+	selectedBestGraph->setDisplayLabel(QString::fromStdString(data->name));
+	for (SingleRun& run : data->singleRunList) {
+		selectedBestGraph->addSeries(&run.bestMaxSolutionFoundPerIteration, data->name, QString::fromStdString(run.name), QColor(12, 116, 137, 200), GraphPlottSeries::SeriesType::Line);
+	}
+	selectedBestGraph->addSeries(&data->bestAverageMaxSolutionFoundPerIteration, data->name, "average best from " + QString::fromStdString(data->name), QColor(255, 0, 0), GraphPlottSeries::SeriesType::Line);
+	selectedBestGraph->getSeriesVector().back().lineWidth = 3;
+	selectedBestGraph->frameGraphInView();
+}
+
+void metavis::selectSingleRun(SingleRun* run)
+{
+	selectedBestAverageGraph->removeAll();
+	selectedBestAverageGraph->setDisplayLabel(QString::fromStdString(run->name));
+	selectedBestAverageGraph->addSeries(&run->bestMaxSolutionFoundPerIteration, run->runDataName, "best", QColor(255, 0, 0), GraphPlottSeries::SeriesType::Line);
+	selectedBestAverageGraph->addSeries(&run->averageSolutionPerItertion, run->runDataName, "average", QColor(0, 0, 255), GraphPlottSeries::SeriesType::Line);
+	selectedBestAverageGraph->frameGraphInView();
+
+	selectedMinMaxGraph->removeAll();
+	selectedMinMaxGraph->setDisplayLabel(QString::fromStdString(run->name));
+	selectedMinMaxGraph->addSeries(&run->dotsForDistribution, run->runDataName,"distribution", QColor(255, 165, 0, 100), GraphPlottSeries::SeriesType::Dot);
+	selectedMinMaxGraph->addSeries(&run->minSolutionPerItertion, run->runDataName,"min", QColor(255, 0, 0), GraphPlottSeries::SeriesType::Line);
+	selectedMinMaxGraph->addSeries(&run->maxSolutionPerItertion, run->runDataName,"max" , QColor(0, 0, 255), GraphPlottSeries::SeriesType::Line);
+	selectedMinMaxGraph->frameGraphInView();
+
+	selectedMeanHammingDistanceGraph->removeAll();
+	selectedMeanHammingDistanceGraph->setDisplayLabel(QString::fromStdString(run->name));
+	selectedMeanHammingDistanceGraph->addSeries(&run->meanHammingDistancePerIteration, run->runDataName, "mean Hamming Distance", QColor(255, 0, 0), GraphPlottSeries::SeriesType::Line);
+	selectedMeanHammingDistanceGraph->frameGraphInView();
+
+	bitfieldPanel->field->setDisplayLabel(QString::fromStdString(run->name));
+	bitfieldPanel->displaySingleRun(run);
+	bitfieldPanel->update();
+
+	inspectorPanel->inspector->updateData(run->begin, run->end);
+	inspectorPanel->setRunName(run->name);
+
+	tsnePanel->assignData(run->begin, run->end, QString::fromStdString(run->name));
+}
+
+
+
+
+void metavis::removeRunDataFromAllViews(RunData* data)
+{
+	selectedBestAverageGraph->removeRunData(data);
+	selectedBestAverageGraph->update();
+
+	selectedMinMaxGraph->removeRunData(data);
+	selectedMinMaxGraph->update();
+
+	selectedMeanHammingDistanceGraph->removeRunData(data);
+	selectedMeanHammingDistanceGraph->update();
+
+	selectedBestGraph->removeRunData(data);
+	selectedBestGraph->update();
+
+	bitfieldPanel->clearRun();
+	bitfieldPanel->update();
+
+	inspectorPanel->removeRun();
+	tsnePanel->clear();
+}
+
+
+
+void metavis::dockWidget(QDockWidget* dock)
+{
+	switch (option) {
+	case left:
+		addDockWidget(Qt::LeftDockWidgetArea, dock);
+		break;
+	case right:
+		addDockWidget(Qt::RightDockWidgetArea, dock);
+		break;
+	case top:
+		addDockWidget(Qt::TopDockWidgetArea, dock);
+		break;
+	case bottom:
+		addDockWidget(Qt::BottomDockWidgetArea, dock);
+		break;
+	case splitLeft:
+		this->splitDockWidget(lastDocked, dock, Qt::Orientation::Horizontal);
+		this->splitDockWidget(dock, lastDocked, Qt::Orientation::Horizontal);
+		break;
+	case splitRight:
+		this->splitDockWidget(lastDocked, dock, Qt::Orientation::Horizontal);
+		break;
+	case splitBottom:
+		this->splitDockWidget(lastDocked, dock, Qt::Orientation::Vertical);
+		break;
+	case splitTop:
+		this->splitDockWidget(lastDocked, dock, Qt::Orientation::Vertical);
+		this->splitDockWidget(dock, lastDocked, Qt::Orientation::Vertical);
+		break;
+	case tab:
+		tabifyDockWidget(lastDocked, dock);
+		break;
+	default:
+		addDockWidget(Qt::LeftDockWidgetArea, dock);
+		break;
+	}
+	lastDocked = dock;
+}
+
+GraphView* metavis::createCustomWidget(QString titleString, bool tabToLast)
+{
+	DockableGraphView* dock = new DockableGraphView(this, titleString);
+	qDebug() << titleString;
+	dockWidget(dock);
+	return dock->view;
+}
+
+
+void metavis::createBitFieldV2()
+{
+	QDockWidget* dock = new QDockWidget(this);
+	bitfieldPanel = new BitfieldControlPanel(this);
+	bitfieldPanel->field->setScratchpad(pad);
+	bitfieldPanel->field->setInformation("<h3><u>Bitfield</u></h3>This search space visualization display all found solution of a single run.<br>Hover over a dot two see its bitstring.<br>The color represents the objective function.<br><b><font color=\"gray\">Gray</font> patternd area:</b> represents the area where no solution can be generated.<br><b>Y Axis:</b> Represents the amount of set bits of a sollution.<br><b>X Axis:</b> Represents a position when all sollutions with this ammount of set bits are side by side<br> ordered with their corresponding value is decreasing.<br>Example with a four long bitstring and two set bits the possible solutions are:<br>1100 1010 1001 0110 0101 0011<br>The solution 0101 is the 5th possible sollution and gets the position value \'0.8\'.<br><br><b>Tipp</b> select a interesting area and add the points to the scratchpad for fast comparison.<h3><u>Options</u></h3>Transparency slider handles the transparency of the dots.<br>Size slider handles the radius of the dots.<br><b>Tipp</b> make the dots big and the transparency low the see clustering.<br>Under \'More Options\' the color for the objective function and the displayed itertion can be controlled.");
+	dock->setWindowTitle("Bitfield");
+	dock->setObjectName("Bitfield");
+	dock->setWidget(bitfieldPanel);
+	dockWidget(dock);
+}
+
+void metavis::createProjectManager()
+{
+	QDockWidget* dock= new QDockWidget(this);
+	manager = new ProjectManager(this);
+	dock->setWindowTitle("Project Manager");
+	dock->setObjectName("Project Manager");
+	dock->setWidget(manager);
+	connect(ui.actionOpen, &QAction::triggered, manager, &ProjectManager::openFileDialog);
+	dockWidget(dock);
+	manager->projectMenu->setTitle("Project");
+	ui.menuBar->addMenu(manager->projectMenu);
+}
+
+void metavis::createTSNE(QDockWidget* dockto)
+{
+
+
+	QDockWidget* dock = new QDockWidget(this);
+	tsnePanel = new TsneControlPanel(this);
+	connect(tsnePanel, &TsneControlPanel::started, this, [this]() {this->showStatusBarMessage("T-SNE calculating...");});
+	connect(tsnePanel, &TsneControlPanel::finished, this, &metavis::clearStatusBar);
+	tsnePanel->plott->setScratchpad(pad);
+	tsnePanel->plott->setInformation("<h3><u>T-SNE</u></h3>This search space evaluation uses a gradient descent method and have to be calculated first via the \"Start\" button.<br>This search space visualization display all found solution of a single run.<br>Hover over a dot two see its bitstring.<br>The color represents the objective function.<br> The axis have no special meaning beside to indicating the distance between solutions.<br><b>Start Button:</b> starts the tsne methods this may take a while.<br><b>Pause Button:</b> pause the tsne methods.<br><br><br><b>Tipp</b> select a interesting area and add the points to the scratchpad for fast comparison.<h3><u>Options</u></h3>Transparency slider handles the transparency of the dots.<br>Size slider handles the radius of the dots.<br><b>Tipp</b> make the dots big and the transparency low the see clustering.<br>Under \'More Options\' the color for the objective function and the displayed itertion can be controlled.<br> Also two important parameter for T-SNE can be controlled via slider or textfield.<br><b>Perplexity</b> is a parameter that should indicate how many neighbors a solution have.<br><b>Learnrate:</b> is a parameter that determine how fast the gradient descent methods make updates.");
+	dock->setWindowTitle("T-SNE");
+	dock->setObjectName("T-SNE");
+	dock->setWidget(tsnePanel);
+	this->tabifyDockWidget(dockto, dock);
+	dockto->raise();
+}
+
+GraphPlott* metavis::initGraphPlott(QString title, QString YAxisLegend, QString XAxisLegend)
+{
+	QDockWidget* dock = new QDockWidget(this);
+	GraphPlott* graphplott = new GraphPlott(this);
+	graphplott->setDefaultVisibleWindow(0, 100, 30, 110);
+	dock->setWidget(graphplott);
+	dock->setWindowTitle(title);
+	dock->setObjectName(title);
+	graphplott->setAxisLegend(XAxisLegend, YAxisLegend);
+	dockWidget(dock);
+	return graphplott;
+}
+
+void metavis::initPlotter()
+{
+	option = splitLeft;
+	selectedBestGraph = initGraphPlott("Best Overview");
+	selectedBestGraph->setScratchpad(pad);
+	selectedBestGraph->setInformation("<h3><u>Best Overview</u></h3>Shows all rounds best graph in <font color=\"gray\">gray</font> for comparison.<br>The <font color=\"red\">red</font> line shows the average best over all rounds.<br>By hovering over a line the round name is shown.<br><br><b>Objective Function:</b> Describes how well the solution is, it depends on the problem if a low or high value is desired.");
+	option = splitTop;
+	selectedBestAverageGraph = initGraphPlott("Best Average");
+	selectedBestAverageGraph->setScratchpad(pad);
+	selectedBestAverageGraph->setInformation("<h3><u>Best Average</u></h3>The <font color=\"red\">red</font> line shows the best graph that presents the best objective function value found for each iteration of a single round.<br>The <font color=\"blue\">blue</font> line shows the average graph that presents the average objective function value in the popullation for each iteration of a single round.<br><br><b>Objective Function:</b> Describes how well the solution is, it depends on the problem if a low or high value is desired.");
+	//GraphPlott* selectedParticleGraph = initGraphPlott("Best Vs Average");
+	option = tab;
+	selectedMinMaxGraph = initGraphPlott("Min Max Distribution");
+	selectedMinMaxGraph->setInformation("<h3><u>Min Max Distribution</u></h3>The <font color=\"blue\">blue</font> line shows the max graph that presents the maximum objective function value in the popullation for each iteration of a single round.<br>The <font color=\"red\">red</font> line shows the minimum objective function value in the popullation for each iteration of a single round.<br>The <font color=\"orange\">orange</font> dots shows the all objective function values in the popullation for each iteration of a single round.<br><br><b>Objective Function:</b> Describes how well the solution is, it depends on the problem if the a or high value is desired.");
+	selectedMinMaxGraph->setScratchpad(pad);
+	option = tab;
+	selectedMeanHammingDistanceGraph = initGraphPlott("Mean Hamming Distance", "Mean Hamming Distance");
+	selectedMeanHammingDistanceGraph->setInformation("<h3><u>Mean Hamming Distance</u></h3>The <font color=\"red\">red</font> line shows the mean hamming distance for each solution to each solution from the popullation for each iteration of a single round.<br><br><b>Hamming Distance:</b> Describes the distance between two bitstrings by calculating the amount of different bits, e.g. 00110 and 11100 have a hamming distance of 3.");
+	multiBestGraph;
+	multiAvgGraph;
+	multiMinGraph;
+	multiMaxGraph;
+	multiMeanHammingDistanceGraph;
+}
+
+
+void metavis::createBitInSpector()
+{
+	QDockWidget* dock = new QDockWidget(this);
+	inspectorPanel = new BitInspectorPanel(this);
+	dock->setWidget(inspectorPanel);
+	dock->setWindowTitle("Inspector");
+	dock->setObjectName("Inspector");
+	dockWidget(dock);
+}
+
+void metavis::createScratchpad(QDockWidget* dockto)
+{
+	QDockWidget* dock = new QDockWidget(this);
+	dock->setWidget(pad);
+	dock->setWindowTitle("Scratchpad");
+	dock->setObjectName("Scratchpad");
+	this->tabifyDockWidget(dockto, dock);
+	dockto->raise();
+}
+
+void metavis::writeActualMainWindowSettings()
+{
+	settings->beginGroup("MainWindow");
+	settings->setValue("maximized", isMaximized());
+	if (!isMaximized()) {
+		/* position and size of the window if not maximized */
+		settings->setValue("pos", pos());
+		settings->setValue("size", size());
+		settings->setValue("screenCount", QApplication::desktop()->screenCount());
+	}
+	settings->setValue("geometry", saveGeometry());
+	settings->setValue("windowState", saveState());
+	settings->endGroup();
+}
+
+void metavis::readMainWindowSettings()
+{
+	settings->beginGroup("MainWindow");
+	if (QApplication::desktop()->screenCount() == settings->value("screenCount", 1)) {
+		//Only when same screeenCount move the window;
+		move(settings->value("pos", QPoint(360, 200)).toPoint());
+	}
+	resize(settings->value("size", QSize(1200, 675)).toSize());
+	if (settings->value("maximized", false).toBool()) {
+		showMaximized();
+	}
+	this->restoreGeometry(settings->value("geometry").toByteArray());
+	this->restoreState(settings->value("windowState").toByteArray());
+	settings->endGroup();
+}
+
+
+
+
+
+
+
+void metavis::openFile()
+{
+	
+	//int oldIndex = runVec.size();
+	/*int size = runList.size();
+	for (int i = 0; i < pathList.size(); i++) {
+		qDebug() << "file:" << pathList[i];
+		runList.push_back(RunData(pathList[i].toStdString()));
+	}*/
+	/*for (std::list<RunData>::iterator iter = std::next(runList.begin(), size); iter != runList.end(); iter++) {
+		QColor runColor = multiBestGraph->generateNextColorForGraph();
+		multiBestGraph->addLine(&iter->bestMinSolutionFoundPerIteration, &*iter, runColor);
+		multiAvgGraph->addLine(&iter->averageSolutionPerItertion, &*iter, runColor);
+		multiMaxGraph->addLine(&iter->maxSolutionPerItertion, &*iter, runColor);
+		multiMinGraph->addLine(&iter->minSolutionPerItertion, &*iter, runColor);
+		multiMeanHammingDistanceGraph->addLine(&iter->meanHammingDistancePerIteration, &*iter, runColor);
+	}*/
+
+
+	/*
+	for (int i = 0; i < runList.size(); i++) {
+		QColor runColor = multiBestGraph->generateNextColorForGraph();
+		multiBestGraph->addLine(&runList[i].bestSolutionPerIteration, &runList[i], runColor);
+		multiAvgGraph->addLine(&runList[i].averageSolutionPerItertion, &runList[i], runColor);
+		multiMaxGraph->addLine(&runList[i].maxSolutionPerItertion, &runList[i], runColor);
+		multiMinGraph->addLine(&runList[i].minSolutionPerItertion, &runList[i], runColor);
+		//multiMeanHammingDistanceGraph->addLine(&runVec[i].meanHammingDistancePerIteration, &runVec[i], runColor);
+	}*/
+	/*std::vector<RunData>::iterator end = runVec.end();
+	for (int i = 0; i < pathList.size(); i++) {
+		qDebug() << "file:" << pathList[i];
+		runVec.push_back(RunData(pathList[i].toStdString()));
+	}
+	for (std::vector<RunData>::iterator iter = end; iter != runVec.end(); iter++) {
+		QColor runColor = multiBestGraph->generateNextColorForGraph();
+		multiBestGraph->addLine(&iter->bestSolutionPerIteration, &*iter, runColor);
+		multiAvgGraph->addLine(&iter->averageSolutionPerItertion, &*iter, runColor);
+		multiMaxGraph->addLine(&iter->maxSolutionPerItertion, &*iter, runColor);
+		multiMinGraph->addLine(&iter->minSolutionPerItertion, &*iter, runColor);
+		multiMeanHammingDistanceGraph->addLine(&iter->meanHammingDistancePerIteration, &*iter, runColor);
+	}*/
+	//actualBestAverageGraph->addLine(runVec[0].bestSolutionPerIteration, QColor(255, 0, 0));
+	//actualBestAverageGraph->addLine(runVec[0].averageSolutionPerItertion, QColor(0, 0, 255));
+	//actualMinMaxGraph->addLine(runVec[0].minSolutionPerItertion, QColor(255, 0, 0));
+	//actualMinMaxGraph->addLine(runVec[0].maxSolutionPerItertion, QColor(0, 0, 255));
+	//actualMinMaxGraph->addDots(runVec[0].dotsForDistribution, QColor(255, 165, 0, 100));
+	//for (auto iter = runVec[0].particleMap.begin(); iter != runVec[0].particleMap.end(); iter++) {
+	//	actualParticleGraph->addLine(iter->second);
+	//}
+	////Test
+	/*RunData* rundata = &runList.back();
+
+	bitField->addDots(&rundata->dotsForBitField, rundata, QColor(255, 165, 0, 100));
+	updateBitFieldColors();
+	bitField->graphSeriesVec.back().useDataPointColor = true;
+	tsneWidget->assignRunData(&runList.back());
+	inspector->addData(&runList.back().solutionVec);
+	plottTest->addSeries(&rundata->bestMaxSolutionFoundPerIteration, rundata, QColor(255, 165, 0, 100), GraphPlottSeries::SeriesType::Line);*/
+	//actualMeanHmmingDistanceGraph->addLine(runVec[0].meanHammingDistancePerIteration, QColor(255, 0, 0));
+
+
+}
+
+void metavis::showStatusBarLoading()
+{
+	ui.statusBar->showMessage("Loading...");
+	ui.statusBar->setStyleSheet("background-color: rgb(247, 197, 72);");
+}
+
+void metavis::showStatusBarMessage(QString message)
+{
+	ui.statusBar->showMessage(message);
+	ui.statusBar->setStyleSheet("background-color: rgb(247, 197, 72);");
+}
+
+void metavis::clearStatusBar()
+{
+	ui.statusBar->clearMessage();
+	ui.statusBar->setStyleSheet("background-color: rgb(240, 240, 240);");
+}
diff --git a/metavis/metavis.h b/metavis/metavis.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b9952c0929a64493fbdf74bd17443e454ac1c0e
--- /dev/null
+++ b/metavis/metavis.h
@@ -0,0 +1,102 @@
+#pragma once
+#include <QtWidgets/QMainWindow>
+#include <QSettings>
+#include <vector>
+#include "ui_metavis.h"
+#include "RunData.h"
+#include "GraphView.h"
+
+#include "BitfieldControlPanel.h"
+#include "TsneControlPanel.h"
+
+#include "GraphPlott.h"
+#include "BitInspectorPanel.h"
+#include "Scratchpad.h"
+#include "tsneIteractive.h"
+#include "ProjectManager.h"
+class ProjectManager;
+
+
+/**
+ * Main class of the GUI.
+ */
+class metavis : public QMainWindow
+{
+	Q_OBJECT
+
+public:
+	metavis(QWidget *parent = Q_NULLPTR);
+	~metavis();
+	GraphPlott* selectedBestAverageGraph;
+	GraphPlott* selectedParticleGraph;
+	GraphPlott* selectedMinMaxGraph;
+	GraphPlott* selectedMeanHammingDistanceGraph;
+	GraphPlott* selectedBestGraph;
+
+
+
+	GraphPlott* multiBestGraph;
+	GraphPlott* multiAvgGraph;
+	GraphPlott* multiMinGraph;
+	GraphPlott* multiMaxGraph;
+	GraphPlott* multiMeanHammingDistanceGraph;
+	
+	GraphPlott* plottTest;
+	
+	BitfieldControlPanel* bitfieldPanel;
+	BitInspectorPanel* inspectorPanel;
+	Scratchpad* pad = new Scratchpad(this);
+	tsneIteractive* tsneWidget;
+	TsneControlPanel* tsnePanel;
+	GraphView* bitField;
+
+	enum dockOption{left, right, bottom, top, splitLeft, splitRight, splitBottom, splitTop, tab};
+
+	void selectRunData(RunData* data);
+	void selectSingleRun(SingleRun* run);
+	void removeRunDataFromAllViews(RunData* data);
+
+
+
+
+
+private:
+	Ui::metavisClass ui;
+	QSettings* settings;
+	ProjectManager* manager;
+
+	//To Tab all 
+	QDockWidget* lastDocked;
+	dockOption option;
+	void dockWidget(QDockWidget* dock);
+
+private:
+	/* Widget functions */
+	GraphView* createCustomWidget(QString titleString, bool tabToLast = false);
+	void createBitFieldV2();
+	void createProjectManager();
+	void createTSNE(QDockWidget* dockto);
+	GraphPlott* initGraphPlott(QString title, QString YAxisLegend = "ObjectiveFunction", QString XAxisLegend = "Iteration");
+	void initPlotter();
+	void createBitInSpector();
+	void createScratchpad(QDockWidget* dockto);
+	/* Setting functions*/
+	void writeActualMainWindowSettings();
+	void readMainWindowSettings();
+
+
+
+
+public slots:
+	/**
+	 * Opens the settingWindows Dialog.
+	 */
+	void openSetting();
+	/**
+	 * Open a logFile.	
+	 */
+	void openFile();
+	void showStatusBarLoading();
+	void showStatusBarMessage(QString message);
+	void clearStatusBar();
+};
diff --git a/metavis/metavis.ico b/metavis/metavis.ico
new file mode 100644
index 0000000000000000000000000000000000000000..6396b1c0ca3d24c3ed0e9fea8cbc648b116fb373
Binary files /dev/null and b/metavis/metavis.ico differ
diff --git a/metavis/metavis.qrc b/metavis/metavis.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..65fbfad7decc2d18f682e8cd12141f4d3576279c
--- /dev/null
+++ b/metavis/metavis.qrc
@@ -0,0 +1,21 @@
+<RCC>
+    <qresource prefix="/metavis">
+        <file>Resources/close_big_red.svg</file>
+        <file>Resources/settingIcon_hovered.svg</file>
+        <file>Resources/close.svg</file>
+        <file>Resources/settingIcon.svg</file>
+        <file>Resources/assignButton.svg</file>
+        <file>Resources/information_icon.svg</file>
+        <file>Resources/information_icon_hovered.svg</file>
+        <file>Resources/gridIcon.svg</file>
+        <file>Resources/gridIcon_hovered.svg</file>
+        <file>Resources/up-triangle.svg</file>
+        <file>Resources/frame.svg</file>
+        <file>Resources/frame_hovered.svg</file>
+        <file>Resources/binaryIcon.svg</file>
+        <file>Resources/rubbish.svg</file>
+        <file>Resources/rubbish_hovered.svg</file>
+        <file>Resources/arrow_right.svg</file>
+        <file>Resources/file.svg</file>
+    </qresource>
+</RCC>
diff --git a/metavis/metavis.rc b/metavis/metavis.rc
new file mode 100644
index 0000000000000000000000000000000000000000..d9089ef151a0c1ea54bc41d2faab4cbfa02be966
--- /dev/null
+++ b/metavis/metavis.rc
@@ -0,0 +1,2 @@
+IDI_ICON1		ICON		DISCARDABLE	"metavis.ico"
+
diff --git a/metavis/metavis.ui b/metavis/metavis.ui
new file mode 100644
index 0000000000000000000000000000000000000000..88595b8fc44d57baf30aef8aab27ec0f2c8645f6
--- /dev/null
+++ b/metavis/metavis.ui
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>metavisClass</class>
+ <widget class="QMainWindow" name="metavisClass">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1200</width>
+    <height>675</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>metavis</string>
+  </property>
+  <widget class="QWidget" name="centralWidget">
+   <layout class="QHBoxLayout" name="horizontalLayout">
+    <property name="spacing">
+     <number>0</number>
+    </property>
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menuBar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1200</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <property name="nativeMenuBar">
+    <bool>true</bool>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="actionOpen"/>
+   </widget>
+   <addaction name="menuFile"/>
+  </widget>
+  <widget class="QStatusBar" name="statusBar"/>
+  <action name="actionOpen">
+   <property name="text">
+    <string>Open..</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSettings">
+   <property name="text">
+    <string>Settings</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+P</string>
+   </property>
+  </action>
+  <action name="ActionAddMetalogFile">
+   <property name="text">
+    <string>Add .csv-File..</string>
+   </property>
+  </action>
+  <action name="ActionRemoveFiles">
+   <property name="text">
+    <string>Remove all files.</string>
+   </property>
+  </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+  <include location="metavis.qrc"/>
+ </resources>
+ <connections/>
+ <slots>
+  <slot>openSetting()</slot>
+  <slot>openFile()</slot>
+ </slots>
+</ui>
diff --git a/metavis/metavis.vcxproj b/metavis/metavis.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..28d3eb5ce25fd09416576a692a9b133ab7cbde32
--- /dev/null
+++ b/metavis/metavis.vcxproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{B12702AD-ABFB-343A-A199-8E24837244A3}</ProjectGuid>
+    <Keyword>QtVS_v301</Keyword>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <PropertyGroup Condition="'$(QtMsBuild)'=='' or !Exists('$(QtMsBuild)\qt.targets')">
+    <QtMsBuild>$(MSBuildProjectDirectory)\QtMsBuild</QtMsBuild>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)Intermediate\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <OutDir>$(SolutionDir)Build\$(Platform)\$(Configuration)\</OutDir>
+    <IntDir>$(SolutionDir)Intermediate\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+  </PropertyGroup>
+  <Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
+    <Message Importance="High" Text="QtMsBuild: could not locate qt.targets, qt.props; project may not build correctly." />
+  </Target>
+  <ImportGroup Label="ExtensionSettings" />
+  <ImportGroup Label="Shared" />
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ImportGroup Condition="Exists('$(QtMsBuild)\qt_defaults.props')">
+    <Import Project="$(QtMsBuild)\qt_defaults.props" />
+  </ImportGroup>
+  <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <QtInstall>msvc2017_64</QtInstall>
+    <QtModules>charts;core;gui;widgets;;concurrent</QtModules>
+  </PropertyGroup>
+  <PropertyGroup Label="QtSettings" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <QtInstall>msvc2017_64</QtInstall>
+    <QtModules>charts;core;gui;widgets;;concurrent</QtModules>
+  </PropertyGroup>
+  <ImportGroup Condition="Exists('$(QtMsBuild)\qt.props')">
+    <Import Project="$(QtMsBuild)\qt.props" />
+  </ImportGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <Optimization>Disabled</Optimization>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+      <AdditionalIncludeDirectories>$(SolutionDir)\metaviscon\;C:\Program Files (x86)\boost\boost_1_72_0;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <LanguageStandard>stdcpp17</LanguageStandard>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(Qt_LIBS_);%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <DebugInformationFormat />
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+      <AdditionalIncludeDirectories>$(SolutionDir)\metaviscon\;C:\Program Files (x86)\boost\boost_1_72_0;.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <LanguageStandard>stdcpp17</LanguageStandard>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <OutputFile>$(OutDir)\$(ProjectName).exe</OutputFile>
+      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(Qt_LIBS_);%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\metaviscon\src\t_sne\sptree.cpp" />
+    <ClCompile Include="..\metaviscon\src\t_sne\tsne.cpp" />
+    <ClCompile Include="Bitfield.cpp" />
+    <ClCompile Include="BitfieldControlPanel.cpp" />
+    <ClCompile Include="BitInspector.cpp" />
+    <ClCompile Include="BitInspectorPanel.cpp" />
+    <ClCompile Include="ColorButton.cpp" />
+    <ClCompile Include="ColorGradient.cpp" />
+    <ClCompile Include="Concurrent.cpp" />
+    <ClCompile Include="DockableGraphView.cpp" />
+    <ClCompile Include="GraphPlott.cpp" />
+    <ClCompile Include="GraphView.cpp" />
+    <ClCompile Include="GraphViewSettingDialog.cpp" />
+    <ClCompile Include="GraphViewSettingItem.cpp" />
+    <ClCompile Include="HoverButton.cpp" />
+    <ClCompile Include="InformationPopUp.cpp" />
+    <ClCompile Include="main.cpp" />
+    <ClCompile Include="MetalogManagerItem.cpp" />
+    <ClCompile Include="metavis.cpp" />
+    <ClCompile Include="pch.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="Plott.cpp" />
+    <ClCompile Include="Project.cpp" />
+    <ClCompile Include="ProjectManager.cpp" />
+    <ClCompile Include="RangeSlider.cpp" />
+    <ClCompile Include="RunData.cpp" />
+    <ClCompile Include="Scratchpad.cpp" />
+    <ClCompile Include="SearchSpacePlott.cpp" />
+    <ClCompile Include="SettingDialog.cpp" />
+    <ClCompile Include="tSneAlgo.cpp" />
+    <ClCompile Include="TsneControlPanel.cpp" />
+    <ClCompile Include="tsneIteractive.cpp" />
+    <ClCompile Include="TsnePlott.cpp" />
+    <ClCompile Include="TsneSettings.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <QtMoc Include="metavis.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <QtUic Include="GraphViewSettingDialog.ui" />
+    <QtUic Include="GraphViewSettingItem.ui" />
+    <QtUic Include="MetalogManagerItem.ui" />
+    <QtUic Include="metavis.ui" />
+    <QtUic Include="SettingDialog.ui" />
+    <QtUic Include="tsneIteractive.ui" />
+  </ItemGroup>
+  <ItemGroup>
+    <QtRcc Include="metavis.qrc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="metavis.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <QtMoc Include="SettingDialog.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\metaviscon\src\t_sne\sptree.h" />
+    <ClInclude Include="..\metaviscon\src\t_sne\tsne.h" />
+    <ClInclude Include="..\metaviscon\src\t_sne\vptree.h" />
+    <QtMoc Include="ColorGradient.h" />
+    <QtMoc Include="ColorButton.h" />
+    <QtMoc Include="BitInspector.h" />
+    <QtMoc Include="Bitfield.h" />
+    <QtMoc Include="BitfieldControlPanel.h" />
+    <QtMoc Include="BitInspectorPanel.h" />
+    <ClInclude Include="Concurrent.h" />
+    <QtMoc Include="Plott.h" />
+    <QtMoc Include="GraphPlott.h" />
+    <QtMoc Include="HoverButton.h" />
+    <QtMoc Include="InformationPopUp.h" />
+    <ClInclude Include="Project.h" />
+    <QtMoc Include="tSneAlgo.h" />
+    <QtMoc Include="RangeSlider.h" />
+    <QtMoc Include="tsneIteractive.h" />
+    <QtMoc Include="Scratchpad.h" />
+    <QtMoc Include="SearchSpacePlott.h" />
+    <QtMoc Include="TsneControlPanel.h" />
+    <QtMoc Include="TsnePlott.h" />
+    <QtMoc Include="TsneSettings.h" />
+    <ClInclude Include="util.h" />
+    <QtMoc Include="DockableGraphView.h" />
+    <QtMoc Include="GraphViewSettingDialog.h" />
+    <QtMoc Include="GraphViewSettingItem.h" />
+    <QtMoc Include="MetalogManagerItem.h" />
+    <ClInclude Include="pch.h" />
+    <QtMoc Include="ProjectManager.h" />
+    <ClInclude Include="RunData.h" />
+    <QtMoc Include="GraphView.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
+    <Import Project="$(QtMsBuild)\qt.targets" />
+  </ImportGroup>
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/metavis/metavis.vcxproj.filters b/metavis/metavis.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..0fabe9aeb9dfecfa0621a95ffb55534cd2c968d0
--- /dev/null
+++ b/metavis/metavis.vcxproj.filters
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
+      <Extensions>qrc;*</Extensions>
+      <ParseFiles>false</ParseFiles>
+    </Filter>
+    <Filter Include="Form Files">
+      <UniqueIdentifier>{99349809-55BA-4b9d-BF79-8FDBB0286EB3}</UniqueIdentifier>
+      <Extensions>ui</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}</UniqueIdentifier>
+      <Extensions>qrc;*</Extensions>
+      <ParseFiles>false</ParseFiles>
+    </Filter>
+    <Filter Include="Source Files\Data">
+      <UniqueIdentifier>{53513f5d-6839-4eae-849d-e19c5c42de66}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\UserInterface">
+      <UniqueIdentifier>{9ee1379c-2518-4abe-ba18-3acca2489089}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\UserInterface\GraphView">
+      <UniqueIdentifier>{690b435e-6eee-460a-b8b0-3b7041e1cd72}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\UserInterface\ProjectManager">
+      <UniqueIdentifier>{d1f02e10-3301-4d1d-95ff-8ce35a9eba2d}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\UserInterface\MainMenu">
+      <UniqueIdentifier>{6720c6d8-7b65-4f16-abd1-aade3b8799f8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Data">
+      <UniqueIdentifier>{538f690b-294c-49b3-95d1-92948c60f6f8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\UserInterface">
+      <UniqueIdentifier>{349cc4e0-be79-4c7a-8412-89a28d0ae77c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\UserInterface\ProjectManager">
+      <UniqueIdentifier>{e95bcea7-9a19-4b96-bb3c-8311955305d9}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\UserInterface\GraphView">
+      <UniqueIdentifier>{db20d7fd-184e-4d06-a522-5140379fd6d6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\UserInterface\MainMenu">
+      <UniqueIdentifier>{85af9a93-1361-42e0-85cf-79b1d962850c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\UserInterface\Widget">
+      <UniqueIdentifier>{c2f8a3bf-19b7-4cb4-9f0e-134dc4aaee70}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\UserInterface\Widget">
+      <UniqueIdentifier>{52a467e5-efc6-44c1-a9f6-ff9005d2b7dc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Algorithm">
+      <UniqueIdentifier>{08564a5b-8aa0-4f33-bf76-2f50ff559168}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Algorithm\tSNE">
+      <UniqueIdentifier>{94e95fb3-1251-48f0-9e2f-ef92e78f6777}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Data\algorithm">
+      <UniqueIdentifier>{c236e5d9-90d7-4b48-beb3-ed38213acbbc}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Data\algorithm\tSNE">
+      <UniqueIdentifier>{492da30c-1983-45f2-a819-091e43e6d706}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\MultiThreading">
+      <UniqueIdentifier>{c80d6242-cd8a-4453-92f3-102a7a2a8474}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="GraphView.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="GraphViewSettingDialog.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="GraphViewSettingItem.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="DockableGraphView.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="metavis.cpp">
+      <Filter>Source Files\UserInterface\MainMenu</Filter>
+    </ClCompile>
+    <ClCompile Include="RunData.cpp">
+      <Filter>Source Files\Data</Filter>
+    </ClCompile>
+    <ClCompile Include="MetalogManagerItem.cpp">
+      <Filter>Source Files\UserInterface\ProjectManager</Filter>
+    </ClCompile>
+    <ClCompile Include="ProjectManager.cpp">
+      <Filter>Source Files\UserInterface\ProjectManager</Filter>
+    </ClCompile>
+    <ClCompile Include="SettingDialog.cpp">
+      <Filter>Source Files\UserInterface\MainMenu</Filter>
+    </ClCompile>
+    <ClCompile Include="pch.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Project.cpp">
+      <Filter>Source Files\Data</Filter>
+    </ClCompile>
+    <ClCompile Include="RangeSlider.cpp">
+      <Filter>Source Files\UserInterface\Widget</Filter>
+    </ClCompile>
+    <ClCompile Include="tsneIteractive.cpp">
+      <Filter>Source Files\UserInterface\MainMenu</Filter>
+    </ClCompile>
+    <ClCompile Include="..\metaviscon\src\t_sne\tsne.cpp">
+      <Filter>Source Files\Algorithm\tSNE</Filter>
+    </ClCompile>
+    <ClCompile Include="..\metaviscon\src\t_sne\sptree.cpp">
+      <Filter>Source Files\Algorithm\tSNE</Filter>
+    </ClCompile>
+    <ClCompile Include="ColorGradient.cpp">
+      <Filter>Source Files\UserInterface\Widget</Filter>
+    </ClCompile>
+    <ClCompile Include="ColorButton.cpp">
+      <Filter>Source Files\UserInterface\Widget</Filter>
+    </ClCompile>
+    <ClCompile Include="tSneAlgo.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Concurrent.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Plott.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="BitInspector.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="HoverButton.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="GraphPlott.cpp">
+      <Filter>Source Files\UserInterface\GraphView</Filter>
+    </ClCompile>
+    <ClCompile Include="Bitfield.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="BitfieldControlPanel.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="BitInspectorPanel.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Scratchpad.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="SearchSpacePlott.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="TsneControlPanel.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="TsnePlott.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="TsneSettings.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="InformationPopUp.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <QtMoc Include="DockableGraphView.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="GraphView.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="GraphViewSettingDialog.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="GraphViewSettingItem.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="MetalogManagerItem.h">
+      <Filter>Header Files\UserInterface\ProjectManager</Filter>
+    </QtMoc>
+    <QtMoc Include="metavis.h">
+      <Filter>Header Files\UserInterface\MainMenu</Filter>
+    </QtMoc>
+    <QtMoc Include="ProjectManager.h">
+      <Filter>Header Files\UserInterface\ProjectManager</Filter>
+    </QtMoc>
+    <QtMoc Include="SettingDialog.h">
+      <Filter>Header Files\UserInterface\MainMenu</Filter>
+    </QtMoc>
+    <QtMoc Include="RangeSlider.h">
+      <Filter>Header Files\UserInterface\Widget</Filter>
+    </QtMoc>
+    <QtMoc Include="ColorGradient.h">
+      <Filter>Header Files\UserInterface\Widget</Filter>
+    </QtMoc>
+    <QtMoc Include="tsneIteractive.h">
+      <Filter>Header Files\UserInterface\MainMenu</Filter>
+    </QtMoc>
+    <QtMoc Include="ColorButton.h">
+      <Filter>Header Files\UserInterface\Widget</Filter>
+    </QtMoc>
+    <QtMoc Include="tSneAlgo.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="Plott.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="BitInspector.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="Bitfield.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="BitfieldControlPanel.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="GraphPlott.h">
+      <Filter>Header Files\UserInterface\GraphView</Filter>
+    </QtMoc>
+    <QtMoc Include="HoverButton.h">
+      <Filter>Header Files\UserInterface\Widget</Filter>
+    </QtMoc>
+    <QtMoc Include="BitInspectorPanel.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="Scratchpad.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="SearchSpacePlott.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="TsneControlPanel.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="TsnePlott.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="TsneSettings.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+    <QtMoc Include="InformationPopUp.h">
+      <Filter>Header Files</Filter>
+    </QtMoc>
+  </ItemGroup>
+  <ItemGroup>
+    <QtUic Include="metavis.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+    <QtUic Include="SettingDialog.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+    <QtUic Include="GraphViewSettingDialog.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+    <QtUic Include="GraphViewSettingItem.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+    <QtUic Include="MetalogManagerItem.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+    <QtUic Include="tsneIteractive.ui">
+      <Filter>Form Files</Filter>
+    </QtUic>
+  </ItemGroup>
+  <ItemGroup>
+    <QtRcc Include="metavis.qrc">
+      <Filter>Resource Files</Filter>
+    </QtRcc>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="metavis.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="pch.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="util.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="RunData.h">
+      <Filter>Header Files\Data</Filter>
+    </ClInclude>
+    <ClInclude Include="Project.h">
+      <Filter>Header Files\Data</Filter>
+    </ClInclude>
+    <ClInclude Include="..\metaviscon\src\t_sne\vptree.h">
+      <Filter>Header Files\Data\algorithm\tSNE</Filter>
+    </ClInclude>
+    <ClInclude Include="..\metaviscon\src\t_sne\sptree.h">
+      <Filter>Header Files\Data\algorithm\tSNE</Filter>
+    </ClInclude>
+    <ClInclude Include="..\metaviscon\src\t_sne\tsne.h">
+      <Filter>Header Files\Data\algorithm\tSNE</Filter>
+    </ClInclude>
+    <ClInclude Include="Concurrent.h">
+      <Filter>Header Files\MultiThreading</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/metavis/pch.cpp b/metavis/pch.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17305716aacd2a39a54423c3fb2000dc2266794a
--- /dev/null
+++ b/metavis/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
\ No newline at end of file
diff --git a/metavis/pch.h b/metavis/pch.h
new file mode 100644
index 0000000000000000000000000000000000000000..26791a56c157942a232d190b7fd3696c1b6730d7
--- /dev/null
+++ b/metavis/pch.h
@@ -0,0 +1,36 @@
+#pragma once
+//QT
+#include <QWidget>
+#include <QPaintEvent>
+#include <QPen>
+#include <QPainter>
+#include <QSettings>
+#include <QPoint>
+#include <QDialog>
+#include <QAbstractButton>
+#include <QDebug>
+#include <QBrush>
+#include <QtWidgets/QApplication>
+#include <QtGui>
+#include <QStandardPaths>
+#include <QDockwidget>
+#include <QLabel>
+#include <QLayout>
+#include <QStyleFactory>
+#include <QFileDialog>
+#include <QDir>
+#include <QString>
+#include <QToolTip>
+#include <QTimer>
+#include <QSlider>
+
+//Std
+#include <list>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <map>
+#include <random>
+#include <algorithm>
+#include <sstream>
+#include <regex>
\ No newline at end of file
diff --git a/metavis/tSneAlgo.cpp b/metavis/tSneAlgo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5b87f7e1efc3806c74f0920135e54934e0ff4feb
--- /dev/null
+++ b/metavis/tSneAlgo.cpp
@@ -0,0 +1,691 @@
+#include "pch.h"
+#include "tSneAlgo.h"
+#include <cfloat>
+#include <cmath>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <ctime>
+
+
+//This product includes software developed by the Delft University of Technology.
+
+
+#include "src/t_sne/tsne.h"
+#include "src/t_sne/vptree.h"
+#include "src/t_sne/sptree.h"
+
+#pragma warning(disable:4996)
+
+
+static double sign(double inputArrayX) { return (inputArrayX == .0 ? .0 : (inputArrayX < .0 ? -1.0 : 1.0)); }
+
+static void zeroMean(double* inputArrayX, int N, int D);
+static void computeGaussianPerplexity(double* inputArrayX, int N, int D, double* P, double perplexity);
+static void computeGaussianPerplexity(double* inputArrayX, int N, int D, unsigned int** _row_P, unsigned int** _col_P, double** _val_P, double perplexity, int K);
+static double randn();
+static void computeExactGradient(double* P, double* Y, int N, int D, double* dC);
+static void computeGradient(unsigned int* inp_row_P, unsigned int* inp_col_P, double* inp_val_P, double* Y, int N, int D, double* dC, double theta);
+static double evaluateError(double* P, double* Y, int N, int D);
+static double evaluateError(unsigned int* row_P, unsigned int* col_P, double* val_P, double* Y, int N, int D, double theta);
+static void computeSquaredEuclideanDistance(double* inputArrayX, int N, int D, double* DD);
+static void symmetrizeMatrix(unsigned int** row_P, unsigned int** col_P, double** val_P, int N);
+
+tSneAlgo::tSneAlgo(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end, double** YnotInitialized, double perplexity, double learningRate, int maxIter)
+	:perplexity(perplexity), learningRate(learningRate), N(std::distance(begin, end)), D(begin->bitVec.size()), maxIter(maxIter)
+{
+	//N -> amount of dataPoints 
+	//D -> Dimension of DataPoints
+	qDebug() << "N:" << N << " D:" << D;
+    
+    //Create Input Matrix
+	inputArrayX = new double[N * D];
+	for (int n = 0; n < N; n++) {
+		const SolutionPointData& sol = *std::next(begin, n);
+		for (int d = 0; d < D; d++) {
+			inputArrayX[n * D + d] = sol.bitVec[d] ? 1.0 : 0.0;
+		}
+	}
+
+    //Create Output Matrix
+    *YnotInitialized = outputArrayY = (double*)calloc(N * outputDimesion, sizeof(double));
+}
+
+tSneAlgo::~tSneAlgo()
+{
+    reset();
+	delete inputArrayX;
+	delete outputArrayY;
+}
+
+void tSneAlgo::run()
+{
+    //TSNE::run
+    //Init
+     // Set random seed
+ 
+    if (useRandomSeed != true) {
+        if (randomSeet >= 0) {
+            printf("Using random seed: %d\n", randomSeet);
+            srand((unsigned int)randomSeet);
+        }
+        else {
+            printf("Using current time as random seed...\n");
+            srand(time(NULL));
+        }
+    }
+
+    // Determine whether we are using an exact algorithm
+    if (N - 1 < 3 * perplexity) { printf("Perplexity too large for the number of data points!\n"); exit(1); }
+    printf("Using no_dims = %d, perplexity = %f, and theta = %f\n", outputDimesion, perplexity, theta);
+    bool exact = (theta == .0) ? true : false;
+
+    // Set learning parameters
+    float total_time = .0;
+    clock_t start, end;
+    double momentum = .5, final_momentum = .8;
+
+    // Allocate some memory
+    double* dY = (double*)malloc(N * outputDimesion * sizeof(double));
+    double* uY = (double*)malloc(N * outputDimesion * sizeof(double));
+    double* gains = (double*)malloc(N * outputDimesion * sizeof(double));
+    if (dY == NULL || uY == NULL || gains == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    for (int i = 0; i < N * outputDimesion; i++)    uY[i] = .0;
+    for (int i = 0; i < N * outputDimesion; i++) gains[i] = 1.0;
+
+    // Normalize input data (to prevent numerical problems)
+    printf("Computing input similarities...\n");
+    start = clock();
+    zeroMean(inputArrayX, N, D);
+    double max_X = 0.0;
+    for (int i = 0; i < N * D; i++) {
+        if (fabs(inputArrayX[i]) > max_X) max_X = fabs(inputArrayX[i]);
+    }
+    for (int i = 0; i < N * D; i++) inputArrayX[i] /= max_X;
+    // Compute input similarities for exact t-SNE
+    double* P = nullptr; unsigned int* row_P = nullptr; unsigned int* col_P = nullptr; double* val_P = nullptr;
+    if (exact) {
+
+        // Compute similarities
+        printf("Exact?");
+        P = (double*)malloc(N * N * sizeof(double));
+        if (P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+        computeGaussianPerplexity(inputArrayX, N, D, P, perplexity);
+
+        // Symmetrize input similarities
+        printf("Symmetrizing...\n");
+        int nN = 0;
+        for (int n = 0; n < N; n++) {
+            int mN = (n + 1) * N;
+            for (int m = n + 1; m < N; m++) {
+                P[nN + m] += P[mN + n];
+                P[mN + n] = P[nN + m];
+                mN += N;
+            }
+            nN += N;
+        }
+        double sum_P = .0;
+        for (int i = 0; i < N * N; i++) sum_P += P[i];
+        for (int i = 0; i < N * N; i++) P[i] /= sum_P;
+    }
+
+    // Compute input similarities for approximate t-SNE
+    else {
+        // Compute asymmetric pairwise input similarities
+        computeGaussianPerplexity(inputArrayX, N, D, &row_P, &col_P, &val_P, perplexity, (int)(3 * perplexity));
+
+        // Symmetrize input similarities
+        symmetrizeMatrix(&row_P, &col_P, &val_P, N);
+        double sum_P = .0;
+        for (int i = 0; i < row_P[N]; i++) sum_P += val_P[i];
+        for (int i = 0; i < row_P[N]; i++) val_P[i] /= sum_P;
+    }
+    end = clock();
+    // Lie about the P-values
+    if (exact) { for (int i = 0; i < N * N; i++)        P[i] *= 12.0; }
+    else { for (int i = 0; i < row_P[N]; i++) val_P[i] *= 12.0; }
+
+    // Initialize solution (randomly)
+    if (skipRandomInit != true) {
+        for (int i = 0; i < N * outputDimesion; i++) outputArrayY[i] = randn() * .0001;
+    }
+
+    // Perform main training loop
+    if (exact) printf("Input similarities computed in %4.2f seconds!\nLearning embedding...\n", (float)(end - start) / CLOCKS_PER_SEC);
+    else printf("Input similarities computed in %4.2f seconds (sparsity = %f)!\nLearning embedding...\n", (float)(end - start) / CLOCKS_PER_SEC, (double)row_P[N] / ((double)N * (double)N));
+    start = clock();
+    double last_C = -1;
+    for (actualIteration = 0; actualIteration < maxIter; actualIteration++) {
+        checkPaused();
+        if (checkCancel()) break;
+        emit changedIter(actualIteration);
+        // Compute (approximate) gradient
+        if (exact) computeExactGradient(P, outputArrayY, N, outputDimesion, dY);
+        else computeGradient(row_P, col_P, val_P, outputArrayY, N, outputDimesion, dY, theta);
+
+        // Update gains
+        for (int i = 0; i < N * outputDimesion; i++) gains[i] = (sign(dY[i]) != sign(uY[i])) ? (gains[i] + .2) : (gains[i] * .8);
+        for (int i = 0; i < N * outputDimesion; i++) if (gains[i] < .01) gains[i] = .01;
+
+        // Perform gradient update (with momentum and gains)
+        for (int i = 0; i < N * outputDimesion; i++) uY[i] = momentum * uY[i] - learningRate * gains[i] * dY[i];
+        for (int i = 0; i < N * outputDimesion; i++)  outputArrayY[i] +=  uY[i];
+
+        // Make solution zero-mean
+        zeroMean(outputArrayY, N, outputDimesion);
+
+        // Stop lying about the P-values after a while, and switch momentum
+        if (actualIteration == stopLyingIter) {
+            if (exact) { for (int i = 0; i < N * N; i++)        P[i] /= 12.0; }
+            else { for (int i = 0; i < row_P[N]; i++) val_P[i] /= 12.0; }
+        }
+        if (actualIteration == momentumSwitchIter) momentum = final_momentum;
+
+        // Print out progress
+        if (actualIteration > 0 && (actualIteration % 50 == 0 || actualIteration == maxIter - 1)) {
+            end = clock();
+            double C = .0;
+            if (exact) C = evaluateError(P, outputArrayY, N, outputDimesion);
+            else      C = evaluateError(row_P, col_P, val_P, outputArrayY, N, outputDimesion, theta);  // doing approximate computation here!
+
+            if (actualIteration == 0)
+                printf("Iteration %d: error is %f\n", actualIteration + 1, C);
+            else {
+                total_time += (float)(end - start) / CLOCKS_PER_SEC;
+                printf("Iteration %d: error is %f (50 iterations in %4.2f seconds)\n", actualIteration, C, (float)(end - start) / CLOCKS_PER_SEC);
+            }
+            start = clock();
+            last_C = C;
+        }
+    }
+    end = clock(); total_time += (float)(end - start) / CLOCKS_PER_SEC;
+
+    // Clean up memory
+    free(dY);
+    free(uY);
+    free(gains);
+    if (exact) free(P);
+    else {
+        free(row_P); row_P = NULL;
+        free(col_P); col_P = NULL;
+        free(val_P); val_P = NULL;
+    }
+    printf("Fitting performed in %4.2f seconds.\n", total_time);
+    emit algoDone();
+}
+
+
+void tSneAlgo::setLearningRate(double epsillon)
+{
+    learningRate = epsillon;
+
+}
+
+void tSneAlgo::setPerplexity(double perplexity)
+{
+    this->perplexity = perplexity;
+}
+
+
+
+// Compute gradient of the t-SNE cost function (using Barnes-Hut algorithm)
+static void computeGradient(unsigned int* inp_row_P, unsigned int* inp_col_P, double* inp_val_P, double* Y, int N, int D, double* dC, double theta)
+{
+
+    // Construct space-partitioning tree on current map
+    SPTree* tree = new SPTree(D, Y, N);
+
+    // Compute all terms required for t-SNE gradient
+    double sum_Q = .0;
+    double* pos_f = (double*)calloc(N * D, sizeof(double));
+    double* neg_f = (double*)calloc(N * D, sizeof(double));
+    if (pos_f == NULL || neg_f == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    tree->computeEdgeForces(inp_row_P, inp_col_P, inp_val_P, N, pos_f);
+    for (int n = 0; n < N; n++) tree->computeNonEdgeForces(n, theta, neg_f + n * D, &sum_Q);
+
+    // Compute final t-SNE gradient
+    for (int i = 0; i < N * D; i++) {
+        dC[i] = pos_f[i] - (neg_f[i] / sum_Q);
+    }
+    free(pos_f);
+    free(neg_f);
+    delete tree;
+}
+
+// Compute gradient of the t-SNE cost function (exact)
+static void computeExactGradient(double* P, double* Y, int N, int D, double* dC) {
+
+    // Make sure the current gradient contains zeros
+    for (int i = 0; i < N * D; i++) dC[i] = 0.0;
+
+    // Compute the squared Euclidean distance matrix
+    double* DD = (double*)malloc(N * N * sizeof(double));
+    if (DD == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    computeSquaredEuclideanDistance(Y, N, D, DD);
+
+    // Compute Q-matrix and normalization sum
+    double* Q = (double*)malloc(N * N * sizeof(double));
+    if (Q == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    double sum_Q = .0;
+    int nN = 0;
+    for (int n = 0; n < N; n++) {
+        for (int m = 0; m < N; m++) {
+            if (n != m) {
+                Q[nN + m] = 1 / (1 + DD[nN + m]);
+                sum_Q += Q[nN + m];
+            }
+        }
+        nN += N;
+    }
+
+    // Perform the computation of the gradient
+    nN = 0;
+    int nD = 0;
+    for (int n = 0; n < N; n++) {
+        int mD = 0;
+        for (int m = 0; m < N; m++) {
+            if (n != m) {
+                double mult = (P[nN + m] - (Q[nN + m] / sum_Q)) * Q[nN + m];
+                for (int d = 0; d < D; d++) {
+                    dC[nD + d] += (Y[nD + d] - Y[mD + d]) * mult;
+                }
+            }
+            mD += D;
+        }
+        nN += N;
+        nD += D;
+    }
+
+    // Free memory
+    free(DD); DD = NULL;
+    free(Q);  Q = NULL;
+}
+
+
+// Evaluate t-SNE cost function (exactly)
+static double evaluateError(double* P, double* Y, int N, int D) {
+
+    // Compute the squared Euclidean distance matrix
+    double* DD = (double*)malloc(N * N * sizeof(double));
+    double* Q = (double*)malloc(N * N * sizeof(double));
+    if (DD == NULL || Q == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    computeSquaredEuclideanDistance(Y, N, D, DD);
+
+    // Compute Q-matrix and normalization sum
+    int nN = 0;
+    double sum_Q = DBL_MIN;
+    for (int n = 0; n < N; n++) {
+        for (int m = 0; m < N; m++) {
+            if (n != m) {
+                Q[nN + m] = 1 / (1 + DD[nN + m]);
+                sum_Q += Q[nN + m];
+            }
+            else Q[nN + m] = DBL_MIN;
+        }
+        nN += N;
+    }
+    for (int i = 0; i < N * N; i++) Q[i] /= sum_Q;
+
+    // Sum t-SNE error
+    double C = .0;
+    for (int n = 0; n < N * N; n++) {
+        C += P[n] * log((P[n] + FLT_MIN) / (Q[n] + FLT_MIN));
+    }
+
+    // Clean up memory
+    free(DD);
+    free(Q);
+    return C;
+}
+
+// Evaluate t-SNE cost function (approximately)
+static double evaluateError(unsigned int* row_P, unsigned int* col_P, double* val_P, double* Y, int N, int D, double theta)
+{
+
+    // Get estimate of normalization term
+    SPTree* tree = new SPTree(D, Y, N);
+    double* buff = (double*)calloc(D, sizeof(double));
+    double sum_Q = .0;
+    for (int n = 0; n < N; n++) tree->computeNonEdgeForces(n, theta, buff, &sum_Q);
+
+    // Loop over all edges to compute t-SNE error
+    int ind1, ind2;
+    double C = .0, Q;
+    for (int n = 0; n < N; n++) {
+        ind1 = n * D;
+        for (int i = row_P[n]; i < row_P[n + 1]; i++) {
+            Q = .0;
+            ind2 = col_P[i] * D;
+            for (int d = 0; d < D; d++) buff[d] = Y[ind1 + d];
+            for (int d = 0; d < D; d++) buff[d] -= Y[ind2 + d];
+            for (int d = 0; d < D; d++) Q += buff[d] * buff[d];
+            Q = (1.0 / (1.0 + Q)) / sum_Q;
+            C += val_P[i] * log((val_P[i] + FLT_MIN) / (Q + FLT_MIN));
+        }
+    }
+
+    // Clean up memory
+    free(buff);
+    delete tree;
+    return C;
+}
+
+
+// Compute input similarities with a fixed perplexity
+static void computeGaussianPerplexity(double* inputArrayX, int N, int D, double* P, double perplexity) {
+
+    // Compute the squared Euclidean distance matrix
+    double* DD = (double*)malloc(N * N * sizeof(double));
+    if (DD == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    computeSquaredEuclideanDistance(inputArrayX, N, D, DD);
+
+    // Compute the Gaussian kernel row by row
+    int nN = 0;
+    for (int n = 0; n < N; n++) {
+
+        // Initialize some variables
+        bool found = false;
+        double beta = 1.0;
+        double min_beta = -DBL_MAX;
+        double max_beta = DBL_MAX;
+        double tol = 1e-5;
+        double sum_P;
+
+        // Iterate until we found a good perplexity
+        int iter = 0;
+        while (!found && iter < 200) {
+
+            // Compute Gaussian kernel row
+            for (int m = 0; m < N; m++) P[nN + m] = exp(-beta * DD[nN + m]);
+            P[nN + n] = DBL_MIN;
+
+            // Compute entropy of current row
+            sum_P = DBL_MIN;
+            for (int m = 0; m < N; m++) sum_P += P[nN + m];
+            double H = 0.0;
+            for (int m = 0; m < N; m++) H += beta * (DD[nN + m] * P[nN + m]);
+            H = (H / sum_P) + log(sum_P);
+
+            // Evaluate whether the entropy is within the tolerance level
+            double Hdiff = H - log(perplexity);
+            if (Hdiff < tol && -Hdiff < tol) {
+                found = true;
+            }
+            else {
+                if (Hdiff > 0) {
+                    min_beta = beta;
+                    if (max_beta == DBL_MAX || max_beta == -DBL_MAX)
+                        beta *= 2.0;
+                    else
+                        beta = (beta + max_beta) / 2.0;
+                }
+                else {
+                    max_beta = beta;
+                    if (min_beta == -DBL_MAX || min_beta == DBL_MAX)
+                        beta /= 2.0;
+                    else
+                        beta = (beta + min_beta) / 2.0;
+                }
+            }
+
+            // Update iteration counter
+            iter++;
+        }
+
+        // Row normalize P
+        for (int m = 0; m < N; m++) P[nN + m] /= sum_P;
+        nN += N;
+    }
+
+    // Clean up memory
+    free(DD); DD = NULL;
+}
+
+
+// Compute input similarities with a fixed perplexity using ball trees (this function allocates memory another function should free)
+static void computeGaussianPerplexity(double* inputArrayX, int N, int D, unsigned int** _row_P, unsigned int** _col_P, double** _val_P, double perplexity, int K) {
+
+    if (perplexity > K) printf("Perplexity should be lower than K!\n");
+
+    // Allocate the memory we need
+    *_row_P = (unsigned int*)malloc((N + 1) * sizeof(unsigned int));
+    *_col_P = (unsigned int*)calloc(N * K, sizeof(unsigned int));
+    *_val_P = (double*)calloc(N * K, sizeof(double));
+    if (*_row_P == NULL || *_col_P == NULL || *_val_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    unsigned int* row_P = *_row_P;
+    unsigned int* col_P = *_col_P;
+    double* val_P = *_val_P;
+    double* cur_P = (double*)malloc((N - 1) * sizeof(double));
+    if (cur_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    row_P[0] = 0;
+    for (int n = 0; n < N; n++) row_P[n + 1] = row_P[n] + (unsigned int)K;
+
+    // Build ball tree on data set
+    VpTree<DataPoint, euclidean_distance>* tree = new VpTree<DataPoint, euclidean_distance>();
+    vector<DataPoint> obj_X(N, DataPoint(D, -1, inputArrayX));
+    for (int n = 0; n < N; n++) obj_X[n] = DataPoint(D, n, inputArrayX + n * D);
+    tree->create(obj_X);
+
+    // Loop over all points to find nearest neighbors
+    printf("Building tree...\n");
+    vector<DataPoint> indices;
+    vector<double> distances;
+    for (int n = 0; n < N; n++) {
+
+        if (n % 10000 == 0) printf(" - point %d of %d\n", n, N);
+
+        // Find nearest neighbors
+        indices.clear();
+        distances.clear();
+        tree->search(obj_X[n], K + 1, &indices, &distances);
+
+        // Initialize some variables for binary search
+        bool found = false;
+        double beta = 1.0;
+        double min_beta = -DBL_MAX;
+        double max_beta = DBL_MAX;
+        double tol = 1e-5;
+
+        // Iterate until we found a good perplexity
+        int iter = 0; double sum_P;
+        while (!found && iter < 200) {
+
+            // Compute Gaussian kernel row
+            for (int m = 0; m < K; m++) cur_P[m] = exp(-beta * distances[m + 1] * distances[m + 1]);
+
+            // Compute entropy of current row
+            sum_P = DBL_MIN;
+            for (int m = 0; m < K; m++) sum_P += cur_P[m];
+            double H = .0;
+            for (int m = 0; m < K; m++) H += beta * (distances[m + 1] * distances[m + 1] * cur_P[m]);
+            H = (H / sum_P) + log(sum_P);
+
+            // Evaluate whether the entropy is within the tolerance level
+            double Hdiff = H - log(perplexity);
+            if (Hdiff < tol && -Hdiff < tol) {
+                found = true;
+            }
+            else {
+                if (Hdiff > 0) {
+                    min_beta = beta;
+                    if (max_beta == DBL_MAX || max_beta == -DBL_MAX)
+                        beta *= 2.0;
+                    else
+                        beta = (beta + max_beta) / 2.0;
+                }
+                else {
+                    max_beta = beta;
+                    if (min_beta == -DBL_MAX || min_beta == DBL_MAX)
+                        beta /= 2.0;
+                    else
+                        beta = (beta + min_beta) / 2.0;
+                }
+            }
+
+            // Update iteration counter
+            iter++;
+        }
+
+        // Row-normalize current row of P and store in matrix
+        for (unsigned int m = 0; m < K; m++) cur_P[m] /= sum_P;
+        for (unsigned int m = 0; m < K; m++) {
+            col_P[row_P[n] + m] = (unsigned int)indices[m + 1].index();
+            val_P[row_P[n] + m] = cur_P[m];
+        }
+    }
+
+    // Clean up memory
+    obj_X.clear();
+    free(cur_P);
+    delete tree;
+}
+
+
+// Symmetrizes a sparse matrix
+static void symmetrizeMatrix(unsigned int** _row_P, unsigned int** _col_P, double** _val_P, int N) {
+
+    // Get sparse matrix
+    unsigned int* row_P = *_row_P;
+    unsigned int* col_P = *_col_P;
+    double* val_P = *_val_P;
+
+    // Count number of elements and row counts of symmetric matrix
+    int* row_counts = (int*)calloc(N, sizeof(int));
+    if (row_counts == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    for (int n = 0; n < N; n++) {
+        for (int i = row_P[n]; i < row_P[n + 1]; i++) {
+
+            // Check whether element (col_P[i], n) is present
+            bool present = false;
+            for (int m = row_P[col_P[i]]; m < row_P[col_P[i] + 1]; m++) {
+                if (col_P[m] == n) present = true;
+            }
+            if (present) row_counts[n]++;
+            else {
+                row_counts[n]++;
+                row_counts[col_P[i]]++;
+            }
+        }
+    }
+    int no_elem = 0;
+    for (int n = 0; n < N; n++) no_elem += row_counts[n];
+
+    // Allocate memory for symmetrized matrix
+    unsigned int* sym_row_P = (unsigned int*)malloc((N + 1) * sizeof(unsigned int));
+    unsigned int* sym_col_P = (unsigned int*)malloc(no_elem * sizeof(unsigned int));
+    double* sym_val_P = (double*)malloc(no_elem * sizeof(double));
+    if (sym_row_P == NULL || sym_col_P == NULL || sym_val_P == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+
+    // Construct new row indices for symmetric matrix
+    sym_row_P[0] = 0;
+    for (int n = 0; n < N; n++) sym_row_P[n + 1] = sym_row_P[n] + (unsigned int)row_counts[n];
+
+    // Fill the result matrix
+    int* offset = (int*)calloc(N, sizeof(int));
+    if (offset == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    for (int n = 0; n < N; n++) {
+        for (unsigned int i = row_P[n]; i < row_P[n + 1]; i++) {                                  // considering element(n, col_P[i])
+
+            // Check whether element (col_P[i], n) is present
+            bool present = false;
+            for (unsigned int m = row_P[col_P[i]]; m < row_P[col_P[i] + 1]; m++) {
+                if (col_P[m] == n) {
+                    present = true;
+                    if (n <= col_P[i]) {                                                 // make sure we do not add elements twice
+                        sym_col_P[sym_row_P[n] + offset[n]] = col_P[i];
+                        sym_col_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = n;
+                        sym_val_P[sym_row_P[n] + offset[n]] = val_P[i] + val_P[m];
+                        sym_val_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = val_P[i] + val_P[m];
+                    }
+                }
+            }
+
+            // If (col_P[i], n) is not present, there is no addition involved
+            if (!present) {
+                sym_col_P[sym_row_P[n] + offset[n]] = col_P[i];
+                sym_col_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = n;
+                sym_val_P[sym_row_P[n] + offset[n]] = val_P[i];
+                sym_val_P[sym_row_P[col_P[i]] + offset[col_P[i]]] = val_P[i];
+            }
+
+            // Update offsets
+            if (!present || (present && n <= col_P[i])) {
+                offset[n]++;
+                if (col_P[i] != n) offset[col_P[i]]++;
+            }
+        }
+    }
+
+    // Divide the result by two
+    for (int i = 0; i < no_elem; i++) sym_val_P[i] /= 2.0;
+
+    // Return symmetrized matrices
+    free(*_row_P); *_row_P = sym_row_P;
+    free(*_col_P); *_col_P = sym_col_P;
+    free(*_val_P); *_val_P = sym_val_P;
+
+    // Free up some memery
+    free(offset); offset = NULL;
+    free(row_counts); row_counts = NULL;
+}
+
+// Compute squared Euclidean distance matrix
+static void computeSquaredEuclideanDistance(double* inputArrayX, int N, int D, double* DD) {
+    const double* XnD = inputArrayX;
+    for (int n = 0; n < N; ++n, XnD += D) {
+        const double* XmD = XnD + D;
+        double* curr_elem = &DD[n * N + n];
+        *curr_elem = 0.0;
+        double* curr_elem_sym = curr_elem + N;
+        for (int m = n + 1; m < N; ++m, XmD += D, curr_elem_sym += N) {
+            *(++curr_elem) = 0.0;
+            for (int d = 0; d < D; ++d) {
+                *curr_elem += (XnD[d] - XmD[d]) * (XnD[d] - XmD[d]);
+            }
+            *curr_elem_sym = *curr_elem;
+        }
+    }
+}
+
+
+// Makes data zero-mean
+static void zeroMean(double* inputArrayX, int N, int D) {
+
+    // Compute data mean
+    double* mean = (double*)calloc(D, sizeof(double));
+    if (mean == NULL) { printf("Memory allocation failed!\n"); exit(1); }
+    int nD = 0;
+    for (int n = 0; n < N; n++) {
+        for (int d = 0; d < D; d++) {
+            mean[d] += inputArrayX[nD + d];
+        }
+        nD += D;
+    }
+    for (int d = 0; d < D; d++) {
+        mean[d] /= (double)N;
+    }
+    // Subtract data mean
+    nD = 0;
+    for (int n = 0; n < N; n++) {
+        for (int d = 0; d < D; d++) {
+            inputArrayX[nD + d] -= mean[d];
+        }
+        nD += D;
+    }
+    free(mean); mean = NULL;
+}
+
+
+// Generates a Gaussian random number
+static double randn() {
+    double inputArrayX, y, radius;
+    do {
+        inputArrayX = 2 * (rand() / ((double)RAND_MAX + 1)) - 1;
+        y = 2 * (rand() / ((double)RAND_MAX + 1)) - 1;
+        radius = (inputArrayX * inputArrayX) + (y * y);
+    } while ((radius >= 1.0) || (radius == 0.0));
+    radius = sqrt(-2 * log(radius) / radius);
+    inputArrayX *= radius;
+    y *= radius;
+    return inputArrayX;
+}
\ No newline at end of file
diff --git a/metavis/tSneAlgo.h b/metavis/tSneAlgo.h
new file mode 100644
index 0000000000000000000000000000000000000000..1756ebb8ae6478615b3a86297168b413f487f21a
--- /dev/null
+++ b/metavis/tSneAlgo.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <QObject>
+#include "RunData.h"
+#include "Concurrent.h"
+#include <vector>
+
+
+class tSneAlgo : public QObject, public Concurrent
+{
+	Q_OBJECT
+public:
+	tSneAlgo(std::vector<SolutionPointData>::iterator begin, std::vector<SolutionPointData>::iterator end, double** YnotInitialized, double perplexity, double learningRate, int maxIter);
+	~tSneAlgo();
+	int actualIteration = 0;
+	double perplexity, learningRate;
+	// in between 0.0 and 1.0
+	double theta = 0;
+	int maxIter = 750, stopLyingIter = 120, momentumSwitchIter = 20;
+private:
+	int N, D, outputDimesion = 2;
+	bool useRandomSeed = true;
+	bool skipRandomInit = false;
+	int randomSeet = 182437123;
+
+	//intermediate
+	double* inputArrayX;
+	double* outputArrayY;
+	void run() override;
+
+public:
+	void setLearningRate(double epsillon);
+	void setPerplexity(double perplexity);
+signals:
+	void changedIter(int iter);
+	void algoDone();
+};
+
diff --git a/metavis/tsneIteractive.cpp b/metavis/tsneIteractive.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4d7ad836f6adae843dbf57ed62a5440592849305
--- /dev/null
+++ b/metavis/tsneIteractive.cpp
@@ -0,0 +1,120 @@
+#include "pch.h"
+#include "tsneIteractive.h"
+#include <QDebug>
+#include <thread>
+#include <future>
+#include <chrono>
+
+#include "src/t_sne/tsne.h"
+#include "tSneAlgo.h"
+
+tsneIteractive::tsneIteractive(QWidget *parent)
+	: QWidget(parent), view(new GraphView(this, Bound(-50,50,-50,50))), gradient(new ColorGradient(this))
+{
+	ui.setupUi(this);
+	ui.verticalLayout->insertWidget(0, view);
+	view->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding);
+	ui.verticalLayout->addWidget(gradient);
+	//ui.gridLayout->addWidget(gradient, 4, 0);
+	//ui.gridLayout->addWidget(gradient, 4, 0, 1, 4);
+	view->setUseFixedBound(true);
+	connect(timer, &QTimer::timeout, this, static_cast<void (tsneIteractive::*)()>(&tsneIteractive::updateCanvasIfAlgoRuns));
+	connect(ui.startButton, &QPushButton::pressed,
+		this, &tsneIteractive::startRun);
+	connect(ui.pauseButton, &QPushButton::pressed,
+		this, &tsneIteractive::pauseRun);
+	connect(gradient, &ColorGradient::gradientChanged, this, &tsneIteractive::updateViewGradient);
+	ui.perplexitySlider->setMinimum(1);
+	ui.perplexitySlider->setMaximum(50);
+	ui.perplexitySlider->setValue(20);
+	ui.perplexityLineEdit->setText(QString::number(20));
+	ui.learnrateSlider->setMinimum(1);
+	ui.learnrateSlider->setMaximum(1000);
+	ui.learnrateSlider->setValue(200);
+	ui.learnrateLineEdit->setText(QString::number(200));
+	connect(ui.learnrateSlider, &QSlider::valueChanged, this, [this](int value){
+		ui.learnrateSlider->setToolTip(QString::number(value));
+		ui.learnrateLineEdit->setText(QString::number(value));
+		if (tsneConcurrent != nullptr) {
+			this->tsneConcurrent->setLearningRate(value);
+		}
+		});
+	connect(ui.perplexitySlider, &QSlider::valueChanged, this, [this](int value) {
+		ui.perplexitySlider->setToolTip(QString::number(value));
+		ui.perplexityLineEdit->setText(QString::number(value));
+		if (tsneConcurrent != nullptr) {
+			this->tsneConcurrent->setPerplexity(value);
+		}
+		});
+	ui.progressBar->setMinimum(0);
+	ui.progressBar->setMaximum(750);
+	ui.progressBar->setValue(0);
+	
+}
+
+tsneIteractive::~tsneIteractive()
+{
+	if (tsneConcurrent != nullptr) {
+		delete tsneConcurrent;
+	}
+}
+
+void tsneIteractive::assignRunData(RunData* data)
+{
+	this->data = data;
+}
+
+tSneAlgo* tsneIteractive::getTsneConcurrent()
+{
+	return tsneConcurrent;
+}
+
+void tsneIteractive::updateCanvasIfAlgoRuns()
+{
+	if (tsneConcurrent->actualIteration >= 750) {
+		timer->stop();
+	}
+	ui.progressBar->setValue(tsneConcurrent->actualIteration);
+	//view->autoZoomOut();
+	view->update();
+	ui.iterLabel->setText(QString("Iteration: ") + QString::number(tsneConcurrent->actualIteration));
+}
+
+void tsneIteractive::updateViewGradient()
+{
+	view->updateGraphColors(*gradient);
+	update();
+}
+
+void tsneIteractive::pauseRun()
+{
+	qDebug() << "Pause";
+	tsneConcurrent->pause();
+	if (timer->isActive()) {
+		timer->stop();
+	}
+	else {
+		timer->start();
+	}
+}
+
+void tsneIteractive::startRun()
+{
+	if (data == nullptr) {
+		qDebug() << "NoData!";
+		return;
+	}
+	double* Y = nullptr;
+	double** X = &Y;
+	if (tsneConcurrent != nullptr) {
+		delete tsneConcurrent;
+	}
+	tsneConcurrent = new tSneAlgo(data->solutionVec.begin(), data->solutionVec.end(), X, 20, 200, 750);
+	tsneConcurrent->start();
+	qDebug() << "Y:" << Y;
+	view->addYMatrix(Y, data->solutionVec);
+	view->updateGraphColors(*gradient);
+	view->update();
+	timer->start(34);
+
+}
diff --git a/metavis/tsneIteractive.h b/metavis/tsneIteractive.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4fc4c8315eab5c1efebae09edc283f8b44dd501
--- /dev/null
+++ b/metavis/tsneIteractive.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <QWidget>
+#include "ui_tsneIteractive.h"
+#include "GraphView.h"
+#include "RunData.h"
+#include "ColorGradient.h"
+#include "tSneAlgo.h"
+
+class tsneIteractive : public QWidget
+{
+	Q_OBJECT
+public:
+	tsneIteractive(QWidget *parent = Q_NULLPTR);
+	~tsneIteractive();
+
+	GraphView* view;
+	ColorGradient* gradient;
+	RunData* data = nullptr;
+	void assignRunData(RunData* data);
+	tSneAlgo* tsneConcurrent = nullptr;
+	tSneAlgo* getTsneConcurrent();
+private:
+	Ui::tsneIteractive ui;
+	
+	//Concurrent
+	QTimer* timer = new QTimer(this);
+	void updateCanvasIfAlgoRuns();
+	void updateViewGradient();
+
+
+public slots:
+	void startRun();
+	void pauseRun();
+};
diff --git a/metavis/tsneIteractive.ui b/metavis/tsneIteractive.ui
new file mode 100644
index 0000000000000000000000000000000000000000..3b527f5fe62da3324d901b8569c948ed33a33181
--- /dev/null
+++ b/metavis/tsneIteractive.ui
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>tsneIteractive</class>
+ <widget class="QWidget" name="tsneIteractive">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>664</width>
+    <height>459</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>tsneIteractive</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QGridLayout" name="gridLayout">
+     <property name="sizeConstraint">
+      <enum>QLayout::SetFixedSize</enum>
+     </property>
+     <item row="1" column="1">
+      <widget class="QLabel" name="perplexityLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>20</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Perplexity</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QPushButton" name="pauseButton">
+       <property name="minimumSize">
+        <size>
+         <width>35</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Pause</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="0">
+      <widget class="QPushButton" name="startButton">
+       <property name="minimumSize">
+        <size>
+         <width>35</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Start</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QLabel" name="learnrateLabel">
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>20</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Learnrate</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="2">
+      <widget class="QLineEdit" name="perplexityLineEdit">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>70</width>
+         <height>16777215</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="2">
+      <widget class="QLabel" name="iterLabel">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>20</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Iteration: 0</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="3">
+      <widget class="QSlider" name="perplexitySlider">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="tickPosition">
+        <enum>QSlider::TicksBelow</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="3">
+      <widget class="QProgressBar" name="progressBar">
+       <property name="value">
+        <number>24</number>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+       <property name="format">
+        <string>%p%</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="2">
+      <widget class="QLineEdit" name="learnrateLineEdit">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>70</width>
+         <height>16777215</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="3" colspan="2">
+      <widget class="QSlider" name="learnrateSlider">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="tickPosition">
+        <enum>QSlider::TicksBelow</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/metavis/util.h b/metavis/util.h
new file mode 100644
index 0000000000000000000000000000000000000000..7de822e6e70ca528f6d938bad56a9dd36c3cf865
--- /dev/null
+++ b/metavis/util.h
@@ -0,0 +1,36 @@
+#pragma once
+#include <QColor>
+namespace util {
+	inline double linearInterpolate(double first, double second, double alpha) {
+		return first * (1.0 - alpha) + second * alpha;
+	}
+	inline double inverseLinearInterpolation(double min, double max, double value) {
+		if (max - min == 0) return max;
+		else return (value - min) / (max - min);
+	}
+	inline QColor interpolateHSL(QColor& first, QColor& second, double alpha)
+	{
+		double firstH, firstS, firstL;
+		double secondH, secondS, secondL;
+
+		first.getHslF(&firstH, &firstS, &firstL);
+		second.getHslF(&secondH, &secondS, &secondL);
+		if (firstH == -1) {
+			firstH = (secondH != -1) ? secondH : 0;
+		}
+		if (secondH == -1) {
+			secondH = (firstH != -1) ? firstH : 0;
+		}
+		const double h = util::linearInterpolate(firstH, secondH, alpha);
+		const double s = util::linearInterpolate(firstS, secondS, alpha);
+		const double l = util::linearInterpolate(firstL, secondL, alpha);
+		return QColor::fromHslF(h, s, l);
+	}
+	inline QColor interpolateRGB(QColor& first, QColor& second, double alpha)
+	{
+		const double r = util::linearInterpolate(first.redF(), second.redF(), alpha);
+		const double g = util::linearInterpolate(first.greenF(), second.greenF(), alpha);
+		const double b = util::linearInterpolate(first.blueF(), second.blueF(), alpha);
+		return QColor::fromRgbF(r, g, b);
+	}
+}