diff --git a/examples/assertresults/assertresults.py b/examples/assertresults/assertresults.py
new file mode 100644
index 0000000000000000000000000000000000000000..3810880cc81eaf12e1a399873c9a430fab4f161f
--- /dev/null
+++ b/examples/assertresults/assertresults.py
@@ -0,0 +1,25 @@
+import re
+import os
+import sys
+
+sys.path.append(os.path.normpath(os.getcwd() + "/data-processing/dataprocessing"))
+
+
+from validationtools import *
+from readtools import *
+#from ModelicaModel import ModelicaModel
+
+
+print("Test Start")
+# We need to extract all the result files from git now
+
+for files in os.listdir(
+        os.path.abspath("reference-results/Neplan/BasicGrids")):
+        #  Assert the result, model result path read from cmd line
+        validate_modelica_res(os.path.splitext(files)[0],
+                                      os.path.abspath("reference-results/Modelica/BasicGrids/" +
+                                                      os.path.splitext(files)[0] + ".mat"),
+                                      os.path.abspath("reference-results/Neplan/BasicGrids/" +
+                                                      os.path.splitext(files)[0] + ".rlf"))
+
+print("Test End")
diff --git a/examples/CompareResults/compare_modelica_distaix.py b/examples/compareresults/compare_modelica_distaix.py
similarity index 100%
rename from examples/CompareResults/compare_modelica_distaix.py
rename to examples/compareresults/compare_modelica_distaix.py
diff --git a/examples/CompareResults/compare_modelica_dpsim.py b/examples/compareresults/compare_modelica_dpsim.py
similarity index 98%
rename from examples/CompareResults/compare_modelica_dpsim.py
rename to examples/compareresults/compare_modelica_dpsim.py
index 28600a13b4a46e5ff8d66694e4a1d57f3edca587..e280c31c0e8fa2cf19c478f00484d546e83e8f39 100644
--- a/examples/CompareResults/compare_modelica_dpsim.py
+++ b/examples/compareresults/compare_modelica_dpsim.py
@@ -1,37 +1,37 @@
-from dataprocessing.readtools import *
-from dataprocessing.plottools import *
-import matplotlib.pyplot as plt
-from plottingtools.config import *
-
-current_emt_mod = read_timeseries_Modelica(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\EMT\UnitTest_Kundur_FullModel_Euler_1us.mat", ["synchronousGenerator_Park.i[1]"]) # Note: both results include only one damper winding in q axis
-current_emt_dpsim = read_timeseries_dpsim_real(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\EMT\DPsim\UnitTest_FullModel_Trap_1us\data_j.csv")[0]
-current_emt_dpsim.values = -current_emt_dpsim.values
-
-# Comparison EMT
-figure_id = 1
-plt.figure(figure_id, figsize=(12,8))
-set_timeseries_labels(current_emt_mod, ["EMT Modelica"])
-plot_timeseries(figure_id, current_emt_mod)
-set_timeseries_labels(current_emt_dpsim, "EMT DPsim") # TODO: modelica timeseries needs list element, dpsim timeseries needs string
-plot_timeseries(figure_id, current_emt_dpsim, plt_linestyle=':')
-plt.xlabel('Zeit [s]')
-plt.ylabel('Strom [A]')
-plt.show(block=False)
-
-# Comparison DP
-current_dp_mod = read_timeseries_Modelica(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\DP\UnitTest_Kundur_FullModel_Euler_1us.mat", ["synchronousGenerator_Park.I[1]"]) # Note: both results include only one damper winding in q axis
-current_dp_dpsim = read_timeseries_dpsim_cmpl(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\DP\DPsim\UnitTest_FullModel_Trap_1us\data_j.csv")[0]
-current_dp_dpsim.values = -current_dp_dpsim.values
-current_dpabs_dpsim = current_dp_dpsim.abs(current_dp_dpsim.name + ' abs')
-
-figure_id = 2
-plt.figure(figure_id, figsize=(12,8))
-set_timeseries_labels(current_dp_mod, ["DP Modelica"])
-plot_timeseries(figure_id, current_dp_mod)
-set_timeseries_labels(current_dpabs_dpsim, "DP DPsim") # TODO: modelica timeseries needs list element, dpsim timeseries needs string
-plot_timeseries(figure_id, current_dpabs_dpsim, plt_linestyle=':')
-plt.xlabel('Zeit [s]')
-plt.ylabel('Strom [A]')
-plt.show(block=True)
-
-
+from dataprocessing.readtools import *
+from dataprocessing.plottools import *
+import matplotlib.pyplot as plt
+from plottingtools.config import *
+
+current_emt_mod = read_timeseries_Modelica(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\EMT\UnitTest_Kundur_FullModel_Euler_1us.mat", ["synchronousGenerator_Park.i[1]"]) # Note: both results include only one damper winding in q axis
+current_emt_dpsim = read_timeseries_dpsim_real(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\EMT\DPsim\UnitTest_FullModel_Trap_1us\data_j.csv")[0]
+current_emt_dpsim.values = -current_emt_dpsim.values
+
+# Comparison EMT
+figure_id = 1
+plt.figure(figure_id, figsize=(12,8))
+set_timeseries_labels(current_emt_mod, ["EMT Modelica"])
+plot_timeseries(figure_id, current_emt_mod)
+set_timeseries_labels(current_emt_dpsim, "EMT DPsim") # TODO: modelica timeseries needs list element, dpsim timeseries needs string
+plot_timeseries(figure_id, current_emt_dpsim, plt_linestyle=':')
+plt.xlabel('Zeit [s]')
+plt.ylabel('Strom [A]')
+plt.show(block=False)
+
+# Comparison DP
+current_dp_mod = read_timeseries_Modelica(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\DP\UnitTest_Kundur_FullModel_Euler_1us.mat", ["synchronousGenerator_Park.I[1]"]) # Note: both results include only one damper winding in q axis
+current_dp_dpsim = read_timeseries_dpsim_cmpl(r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\SynchronousGenerator\DP\DPsim\UnitTest_FullModel_Trap_1us\data_j.csv")[0]
+current_dp_dpsim.values = -current_dp_dpsim.values
+current_dpabs_dpsim = current_dp_dpsim.abs(current_dp_dpsim.name + ' abs')
+
+figure_id = 2
+plt.figure(figure_id, figsize=(12,8))
+set_timeseries_labels(current_dp_mod, ["DP Modelica"])
+plot_timeseries(figure_id, current_dp_mod)
+set_timeseries_labels(current_dpabs_dpsim, "DP DPsim") # TODO: modelica timeseries needs list element, dpsim timeseries needs string
+plot_timeseries(figure_id, current_dpabs_dpsim, plt_linestyle=':')
+plt.xlabel('Zeit [s]')
+plt.ylabel('Strom [A]')
+plt.show(block=True)
+
+
diff --git a/examples/CompareResults/compare_modelica_plecs.py b/examples/compareresults/compare_modelica_plecs.py
similarity index 98%
rename from examples/CompareResults/compare_modelica_plecs.py
rename to examples/compareresults/compare_modelica_plecs.py
index 369325e132754b16baa57df8dafe0a362bcd9b70..da72501c86fa76df98a96ca47c603e3f26b3bd6c 100644
--- a/examples/CompareResults/compare_modelica_plecs.py
+++ b/examples/compareresults/compare_modelica_plecs.py
@@ -1,55 +1,55 @@
-from dataprocessing.readtools import *
-from dataprocessing.plottools import *
-import matplotlib.pyplot as plt
-import numpy as np
-
-results_path = r'\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\InductionMachine\results'
-
-### --- Read in section --- ###
-# Stator currents
-stator_currents_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.i[1]', 'inductionMachineSquirrelCage.i[2]', 'inductionMachineSquirrelCage.i[3]'])
-stator_currents_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineStatorCurrents.csv')
-
-# Rotor currents
-rotor_currents_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.i_qd0r[1]', 'inductionMachineSquirrelCage.i_qd0r[2]'])
-rotor_currents_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineRotorCurrentsDqRRFs.csv')
-rotor_currents_pls[1].values = -rotor_currents_pls[1].values # transformation DQ0->QD0
-
-# Torque and speed
-torque_speed_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.T_e', 'inductionMachineSquirrelCage.omega_rm'])
-torque_speed_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineTorqueSpeed.csv')
-torque_speed_mo[1].values = torque_speed_mo[1].values/2/np.pi*60 # transformation to r/min
-
-### --- Plot section --- ###
-# Stator currents
-figure_id = 1
-plt.figure(figure_id)
-plt.title("Stator currents")
-set_time_series_labels(stator_currents_mo, ['Modelica: Ias [A]', 'Modelica: Ibs [A]', 'Modelica: Ics [A]'])
-plot_in_subplots(figure_id, stator_currents_mo)
-set_time_series_labels(stator_currents_pls, ['PLECS: Ias [A]', 'PLECS: Ibs [A]', 'PLECS: Ics [A]'])
-plot_in_subplots(figure_id, stator_currents_pls, plt_linestyle='--')
-plt.xlabel('Time [s]')
-plt.show(block=False)
-
-# Rotor currents
-figure_id = 2
-plt.figure(figure_id)
-plt.title("Rotor currents (in synchronously rotating reference frame)")
-set_time_series_labels(rotor_currents_mo, ['Modelica: Iqr\' [A]', 'Modelica: Idr\' [A]'])
-plot_in_subplots(figure_id, rotor_currents_mo)
-set_time_series_labels(rotor_currents_pls, ['PLECS: Iqr\' [A]', 'PLECS: Idr\' [A]'])
-plot_in_subplots(figure_id, rotor_currents_pls, plt_linestyle='--')
-plt.xlabel('Time [s]')
-plt.show(block=False)
-
-# Torque and speed
-figure_id = 3
-plt.figure(figure_id)
-plt.title("Rotor currents (in synchronously rotating reference frame)")
-set_time_series_labels(torque_speed_mo, ['Modelica: Torque [Nm]', 'Modelica: Speed [r/min]'])
-plot_in_subplots(figure_id, torque_speed_mo)
-set_time_series_labels(torque_speed_pls, ['PLECS: Torque [Nm]', 'PLECS: Speed [r/min]'])
-plot_in_subplots(figure_id, torque_speed_pls, plt_linestyle='--')
-plt.xlabel('Time [s]')
+from dataprocessing.readtools import *
+from dataprocessing.plottools import *
+import matplotlib.pyplot as plt
+import numpy as np
+
+results_path = r'\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\InductionMachine\results'
+
+### --- Read in section --- ###
+# Stator currents
+stator_currents_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.i[1]', 'inductionMachineSquirrelCage.i[2]', 'inductionMachineSquirrelCage.i[3]'])
+stator_currents_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineStatorCurrents.csv')
+
+# Rotor currents
+rotor_currents_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.i_qd0r[1]', 'inductionMachineSquirrelCage.i_qd0r[2]'])
+rotor_currents_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineRotorCurrentsDqRRFs.csv')
+rotor_currents_pls[1].values = -rotor_currents_pls[1].values # transformation DQ0->QD0
+
+# Torque and speed
+torque_speed_mo = read_time_series_Modelica(results_path + r'\Modelica3hpMachineRRFs.mat', ['inductionMachineSquirrelCage.T_e', 'inductionMachineSquirrelCage.omega_rm'])
+torque_speed_pls = read_time_series_PLECS(results_path + r'\PLECS3hpMachineTorqueSpeed.csv')
+torque_speed_mo[1].values = torque_speed_mo[1].values/2/np.pi*60 # transformation to r/min
+
+### --- Plot section --- ###
+# Stator currents
+figure_id = 1
+plt.figure(figure_id)
+plt.title("Stator currents")
+set_time_series_labels(stator_currents_mo, ['Modelica: Ias [A]', 'Modelica: Ibs [A]', 'Modelica: Ics [A]'])
+plot_in_subplots(figure_id, stator_currents_mo)
+set_time_series_labels(stator_currents_pls, ['PLECS: Ias [A]', 'PLECS: Ibs [A]', 'PLECS: Ics [A]'])
+plot_in_subplots(figure_id, stator_currents_pls, plt_linestyle='--')
+plt.xlabel('Time [s]')
+plt.show(block=False)
+
+# Rotor currents
+figure_id = 2
+plt.figure(figure_id)
+plt.title("Rotor currents (in synchronously rotating reference frame)")
+set_time_series_labels(rotor_currents_mo, ['Modelica: Iqr\' [A]', 'Modelica: Idr\' [A]'])
+plot_in_subplots(figure_id, rotor_currents_mo)
+set_time_series_labels(rotor_currents_pls, ['PLECS: Iqr\' [A]', 'PLECS: Idr\' [A]'])
+plot_in_subplots(figure_id, rotor_currents_pls, plt_linestyle='--')
+plt.xlabel('Time [s]')
+plt.show(block=False)
+
+# Torque and speed
+figure_id = 3
+plt.figure(figure_id)
+plt.title("Rotor currents (in synchronously rotating reference frame)")
+set_time_series_labels(torque_speed_mo, ['Modelica: Torque [Nm]', 'Modelica: Speed [r/min]'])
+plot_in_subplots(figure_id, torque_speed_mo)
+set_time_series_labels(torque_speed_pls, ['PLECS: Torque [Nm]', 'PLECS: Speed [r/min]'])
+plot_in_subplots(figure_id, torque_speed_pls, plt_linestyle='--')
+plt.xlabel('Time [s]')
 plt.show()
\ No newline at end of file
diff --git a/examples/DPsim/cim_ieee_9_bus.py b/examples/readinresults/DPsim/cim_ieee_9_bus.py
similarity index 97%
rename from examples/DPsim/cim_ieee_9_bus.py
rename to examples/readinresults/DPsim/cim_ieee_9_bus.py
index 55a51defda0466ecbaa70e811ab7b13f10b9bed9..d1f1ff60610e429b9d5e1f218163f4ee3686d85f 100644
--- a/examples/DPsim/cim_ieee_9_bus.py
+++ b/examples/readinresults/DPsim/cim_ieee_9_bus.py
@@ -1,13 +1,13 @@
-from dataprocessing.readtools import *
-from dataprocessing.timeseries import *
-
-path = 'C:\\Users\\mmi\\git\\PowerSystemSimulation\\DPsim\\VisualStudio\\DPsimVS2017\\'
-logName = 'lvector-cim';
-dataType = '.csv';
-logFilename = path + logName + dataType;
-ts_dpsim = read_timeseries_dpsim_cmpl(logFilename)
-for ts in ts_dpsim:
-    ts_abs = ts.abs(ts.name + ' abs')
-    ts_phase = ts.phase(ts.name + ' phase')
-    print(ts.name + ': ' + str(ts_abs.values[0]) + '<' + str(ts_phase.values[0] * 180/np.pi))
-
+from dataprocessing.readtools import *
+from dataprocessing.timeseries import *
+
+path = 'C:\\Users\\mmi\\git\\PowerSystemSimulation\\DPsim\\VisualStudio\\DPsimVS2017\\'
+logName = 'lvector-cim';
+dataType = '.csv';
+logFilename = path + logName + dataType;
+ts_dpsim = read_timeseries_dpsim_cmpl(logFilename)
+for ts in ts_dpsim:
+    ts_abs = ts.abs(ts.name + ' abs')
+    ts_phase = ts.phase(ts.name + ' phase')
+    print(ts.name + ': ' + str(ts_abs.values[0]) + '<' + str(ts_phase.values[0] * 180/np.pi))
+
diff --git a/examples/DPsim/examples_plot.py b/examples/readinresults/DPsim/examples_plot.py
similarity index 97%
rename from examples/DPsim/examples_plot.py
rename to examples/readinresults/DPsim/examples_plot.py
index 20da45bfbb4f34eef596bdcb07a214e9126db717..eed141c15d9371231368a69a60d21d3094d74dca 100644
--- a/examples/DPsim/examples_plot.py
+++ b/examples/readinresults/DPsim/examples_plot.py
@@ -1,27 +1,27 @@
-from dataprocessing.dpsim import *
-from dataprocessing.plottools import *
-
-path = 'D:\\path\\to\\logs\\'
-logName = 'simulation_name_LeftVector'
-logFilename = path + logName + '.csv'
-
-ts_dpsim = read_timeseries_dpsim_cmpl(logFilename)
-
-phasors = get_node_voltage_phasors(ts_dpsim)
-print('Print phasors for all nodes at first time step:')
-for node, phasor in phasors.items():
-    print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))
-print('Print phasors for all nodes at last time step:')
-for node, phasor in phasors.items():
-    print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))
-
-emt_voltages = get_node_emt_voltages(ts_dpsim, 50)
-print('Print EMT voltages for all nodes at last time step:')
-for node, voltage in emt_voltages.items():
-    print(node + ': ' + str(voltage.values[-1]))
-
-# Change node number to fit example
-#plot_timeseries(1, phasors['n2']['abs'])
-plot_timeseries(2, emt_voltages['n2'])
-plt.show()
-
+from dataprocessing.dpsim import *
+from dataprocessing.plottools import *
+
+path = 'D:\\path\\to\\logs\\'
+logName = 'simulation_name_LeftVector'
+logFilename = path + logName + '.csv'
+
+ts_dpsim = read_timeseries_dpsim_cmpl(logFilename)
+
+phasors = get_node_voltage_phasors(ts_dpsim)
+print('Print phasors for all nodes at first time step:')
+for node, phasor in phasors.items():
+    print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))
+print('Print phasors for all nodes at last time step:')
+for node, phasor in phasors.items():
+    print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))
+
+emt_voltages = get_node_emt_voltages(ts_dpsim, 50)
+print('Print EMT voltages for all nodes at last time step:')
+for node, voltage in emt_voltages.items():
+    print(node + ': ' + str(voltage.values[-1]))
+
+# Change node number to fit example
+#plot_timeseries(1, phasors['n2']['abs'])
+plot_timeseries(2, emt_voltages['n2'])
+plt.show()
+
diff --git a/examples/Modelica/read_modelica_examples.py b/examples/readinresults/Modelica/read_modelica_examples.py
similarity index 98%
rename from examples/Modelica/read_modelica_examples.py
rename to examples/readinresults/Modelica/read_modelica_examples.py
index eab9a32d6f3292e9a4b1c96362c87a97c5cd1636..5e2115571a35337e7cdcf6e719fe65da4df8b6a8 100644
--- a/examples/Modelica/read_modelica_examples.py
+++ b/examples/readinresults/Modelica/read_modelica_examples.py
@@ -1,45 +1,45 @@
-from dataprocessing.readtools import *
-from dataprocessing.plottools import *
-import matplotlib.pyplot as plt
-
-
-# Example 1: read in single variable included in the Modelica results file
-voltage_node126 = read_timeseries_Modelica(
-    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
-    timeseries_names="N126.Vrel")
-plt.figure(1, figsize=(12,8))
-set_timeseries_labels(voltage_node126, "voltage N126")
-plt.plot(voltage_node126.time/3600, voltage_node126.values, label=voltage_node126.label)
-plt.legend()
-plt.show(block=True)
-
-# Example 2: read in multiple variables defined in a list
-voltage_two_nodes = read_timeseries_Modelica(
-    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
-    timeseries_names=["N127.Vrel", "N128.Vrel"])
-plt.figure(2, figsize=(12,8))
-plt.plot(voltage_two_nodes[0].time/3600, voltage_two_nodes[0].values, label=voltage_two_nodes[0].label)
-plt.plot(voltage_two_nodes[1].time/3600, voltage_two_nodes[1].values, label=voltage_two_nodes[1].label)
-plt.legend()
-plt.show(block=True)
-
-# Example 3: read in all voltages using regular expressions
-voltages_all_nodes = read_timeseries_Modelica(
-    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
-    timeseries_names='^[^.]*.Vrel$', is_regex=True)
-plt.figure(3, figsize=(12, 8))
-for i in range(len(voltages_all_nodes)):
-    plt.plot(voltages_all_nodes[i].time / 3600, voltages_all_nodes[i].values, label=voltages_all_nodes[i].label)
-plt.legend()
-plt.show(block=True)
-
-# Example 4: read in all variables
-variables_all = read_timeseries_Modelica(
-    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat")
-dict_variables_all = {}
-for ts in variables_all:
-    dict_variables_all[ts.name] = ts
-plt.figure(4, figsize=(12, 8))
-plt.plot(dict_variables_all["L12.Irel"].time/3600, dict_variables_all["L12.Irel"].values, label=dict_variables_all["L12.Irel"].label)
-plt.legend()
+from dataprocessing.readtools import *
+from dataprocessing.plottools import *
+import matplotlib.pyplot as plt
+
+
+# Example 1: read in single variable included in the Modelica results file
+voltage_node126 = read_timeseries_Modelica(
+    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
+    timeseries_names="N126.Vrel")
+plt.figure(1, figsize=(12,8))
+set_timeseries_labels(voltage_node126, "voltage N126")
+plt.plot(voltage_node126.time/3600, voltage_node126.values, label=voltage_node126.label)
+plt.legend()
+plt.show(block=True)
+
+# Example 2: read in multiple variables defined in a list
+voltage_two_nodes = read_timeseries_Modelica(
+    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
+    timeseries_names=["N127.Vrel", "N128.Vrel"])
+plt.figure(2, figsize=(12,8))
+plt.plot(voltage_two_nodes[0].time/3600, voltage_two_nodes[0].values, label=voltage_two_nodes[0].label)
+plt.plot(voltage_two_nodes[1].time/3600, voltage_two_nodes[1].values, label=voltage_two_nodes[1].label)
+plt.legend()
+plt.show(block=True)
+
+# Example 3: read in all voltages using regular expressions
+voltages_all_nodes = read_timeseries_Modelica(
+    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat",
+    timeseries_names='^[^.]*.Vrel$', is_regex=True)
+plt.figure(3, figsize=(12, 8))
+for i in range(len(voltages_all_nodes)):
+    plt.plot(voltages_all_nodes[i].time / 3600, voltages_all_nodes[i].values, label=voltages_all_nodes[i].label)
+plt.legend()
+plt.show(block=True)
+
+# Example 4: read in all variables
+variables_all = read_timeseries_Modelica(
+    r"\\tsclient\N\Research\German Public\ACS0049_SINERGIEN_bsc\Data\WorkData\SimulationResults\IEEE European\Single_scenario_fixed_PV\IEEEEuropean_60.mat")
+dict_variables_all = {}
+for ts in variables_all:
+    dict_variables_all[ts.name] = ts
+plt.figure(4, figsize=(12, 8))
+plt.plot(dict_variables_all["L12.Irel"].time/3600, dict_variables_all["L12.Irel"].values, label=dict_variables_all["L12.Irel"].label)
+plt.legend()
 plt.show(block=True)
\ No newline at end of file
diff --git a/examples/readinresults/NEPLAN/read_NEPLAN_example.py b/examples/readinresults/NEPLAN/read_NEPLAN_example.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d7e19771a33536bb7d2b54e2416a6a462289954
--- /dev/null
+++ b/examples/readinresults/NEPLAN/read_NEPLAN_example.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+import re
+from dataprocessing.readtools import *
+
+
+file = r"C:\Users\admin\Desktop\Load_read\Load_flow_WCSS.rlf"
+
+
+# Example 1: Read in all variable
+print('************************ Test for read in all variable start ****************')
+result_ALL = read_timeseries_NEPLAN_loadflow(file)
+for i in range(len(result_ALL)):
+    print('%s is %s' % (result_ALL[i].name, result_ALL[i].values)) # result as list of TimeSeries
+print('************************ Test for read in all variable end ****************')
+print('\n')
+
+
+# Example 2: Read in specific variable
+print('************************ Test for read in specific variable start ****************')
+
+print('************************ Read in specific Voltage ****************')
+result_U = read_timeseries_NEPLAN_loadflow(file, 'FOUR.U')
+for i in range(len(result_U)):
+    print('%s is %s' % (result_U[i].name, result_U[i].values))
+
+print('************************ Read in specific Voltage Angel ****************')
+result_ANGELU = read_timeseries_NEPLAN_loadflow(file, 'FOUR.ANGELU')
+for i in range(len(result_ANGELU)):
+    print('%s is %s' % (result_ANGELU[i].name, result_ANGELU[i].values))
+
+print('************************ Read in specific Current ****************')
+result_I = read_timeseries_NEPLAN_loadflow(file, 'LINE89.I')
+for i in range(len(result_I)):
+    print('%s is %s' % (result_I[i].name, result_I[i].values))
+
+print('************************ Read in specific Current Angel ****************')
+result_ANGELI = read_timeseries_NEPLAN_loadflow(file, 'LINE89.ANGELI')
+for i in range(len(result_ANGELI)):
+    print('%s is %s' % (result_ANGELI[i].name, result_ANGELI[i].values))
+print('************************ Test for read in specific variable end ****************')
+print('\n')
+
+
+# Example 3: Read in using regular expression
+print('************************ Test for read in using Regular Expression start ****************')
+print('************************ Read in Current using Regular Expression ****************')
+result_I_REG = read_timeseries_NEPLAN_loadflow(file, '^.*\.I$', True)
+for i in range(len(result_I_REG)):
+    print('%s is %s' % (result_I_REG[i].name, result_I_REG[i].values))
+
+print('************************ Read in Current Angel using Regular Expression ****************')
+result_ANGERLI_REG = read_timeseries_NEPLAN_loadflow(file, '^.*\.ANGELI$', True)
+for i in range(len(result_ANGERLI_REG)):
+    print('%s is %s' % (result_ANGERLI_REG[i].name, result_ANGERLI_REG[i].values))
+
+print('************************ Read in Voltage using Regular Expression ****************')
+result_U_REG = read_timeseries_NEPLAN_loadflow(file, '^.*\.U$', True)
+for i in range(len(result_U_REG)):
+    print('%s is %s' % (result_U_REG[i].name, result_U_REG[i].values))
+
+print('************************ Read in Voltage Angel using Regular Expression ****************')
+result_ANGELU_REG = read_timeseries_NEPLAN_loadflow(file, '^.*\.ANGELU$', True)
+for i in range(len(result_ANGELU_REG)):
+    print('%s is %s' % (result_ANGELU_REG[i].name, result_ANGELU_REG[i].values))
+print('************************ Test for read in using Regular Expression end ****************')
\ No newline at end of file
diff --git a/villas/dataprocessing/readtools.py b/villas/dataprocessing/readtools.py
index 19f1d29f38b1d762868e257131d8092ccb5466c0..cc385f56171f017456c9ed0ff6184c6247cf36a4 100644
--- a/villas/dataprocessing/readtools.py
+++ b/villas/dataprocessing/readtools.py
@@ -12,6 +12,7 @@ def read_timeseries_Modelica(filename, timeseries_names=None, is_regex=False):
         timeseries = []
         for name in sim.names():
             timeseries.append(TimeSeries(name, sim(name).times(), sim(name).values()))
+        timeseries_names = sim.names()
     elif is_regex is True:
         # Read in variables which match with regex
         timeseries = []
@@ -136,3 +137,181 @@ def read_dpsim_log(log_path):
         log_sections[section].append(line_pos)
 
     return log_lines, log_sections
+
+def read_timeseries_PLECS(filename, timeseries_names=None):
+    pd_df = pd.read_csv(filename)
+    timeseries_list = []
+    if timeseries_names is None:
+        # No trajectory names specified, thus read in all
+        timeseries_names = list(pd_df.columns.values)
+        timeseries_names.remove('Time')
+        for name in timeseries_names:
+            timeseries_list.append(TimeSeries(name, pd_df['Time'].values, pd_df[name].values))
+    else:
+        # Read in specified time series
+        for name in timeseries_names:
+            timeseries_list.append(TimeSeries(name, pd_df['Time'].values, pd_df[name].values))
+
+    print('PLECS results column names: ' + str(timeseries_names))
+    print('PLECS results number: ' + str(len(timeseries_list)))
+
+    return timeseries_list
+
+def read_timeseries_NEPLAN_loadflow(file_name, timeseries_names=None, is_regex=False):
+    """
+    Read in NEPLAN loadflow result from result file, the result is in angle notation, amplitude and angle are stored
+    separately
+    To keep consistent with the names of voltage in most cases, the name of voltage variables are changed into '.V*'
+    instead of '.U*' as in the result file
+
+    :param file_name: name of the mat file for the loadflow result from neplan
+    :param timeseries_names: column name to be read
+    :param is_regex: flag for using regular expression
+    :return: list of Timeseries objects
+    """
+    str_tmp = open(file_name, "r")  # Read in files
+    low = 0  # flag for the start of a new data in str_cmp
+    high = 0  # flag for the end of this new data in str_cmp
+    flag = True  # To judge if this is the first line of the file, which will be the names for the data type
+
+    # Read in data from result file of neplan
+    seq = []  # list for data type names
+    value = []  # list for data
+
+
+    namelist = ['U', 'ANGLEU', 'P', 'Q', 'I', 'ANGLEI']  # Suffix of the data name
+    timeseries = []
+    line_del = []  # a list for the value to be deleted
+    isfloat = re.compile(r'^[-+]?[0-9]+\.[0-9]+$')  # regular expression to find float values
+
+    # Transfer ',' in the floats in result file to '.'
+    for line in str_tmp.readlines():  # Check the data to find out floats with ','
+        line = line.replace(",", ".")
+        high -= high
+        low -= low
+        del value[:]
+        # read in different data and start processing
+        for letter in line:
+            if letter == "	" or letter == "\n":  # different data(separated by '	') or end(/n)
+                if low is not high:  # if low is equal to high, no data read in
+                    if flag:  # first line of the file, list for data-type name
+                        seq.append(line[low:high])
+                    else:  # not first line of the file,list for data
+                        if isfloat.match(line[low:high]):
+                            value.append(float(line[low:high]))
+                        else:
+                            value.append(line[low:high])
+                else:  # no data for this datatype
+                    value.append(r'#')  # No value, set as #
+                low = high + 1  # refresh low flag
+            high += 1
+
+        """
+        A typical line current in neplan has two parts from both end, but we doesn't have to calculate them 
+        with the assumption that the topology of the gird should be correct with which we can validate the 
+        current by comparing the voltage of the nodes connected to the ends of the line 
+        """
+        if flag is not True:  # flag is true when it's the first line
+            if value[3] is not '#':
+                for m in range(6):
+                    timeseries.append(TimeSeries(value[3] + '.' + namelist[m],
+                                                 np.array([0., 1.]), np.array([value[m + 6], value[m + 6]])))
+            else:
+                for m in range(2):
+                    timeseries.append(TimeSeries(value[1] + '.' + namelist[m],
+                                                 np.array([0., 1.]), np.array([value[m + 6], value[m + 6]])))
+        flag = False
+    str_tmp.close()
+
+    # Read in variables which match with regex
+    if is_regex is True:
+        p = re.compile(timeseries_names)
+        length = len(timeseries)
+        for rule_check in range(length):
+            if p.search(timeseries[rule_check].name):
+                pass
+            else:
+                line_del.append(rule_check)
+
+    # Read in specified time series
+    elif timeseries_names is not None:
+        length = len(timeseries)
+        for rule_check in range(length):
+            if timeseries_names == timeseries[rule_check].name:
+                pass
+            else:
+                line_del.append(rule_check)
+
+    # delete those values that are not needed.
+    line_del = set(line_del)
+    line_del = sorted(line_del)
+    for num_to_del in range(len(line_del)):
+        del timeseries[line_del[len(line_del) - num_to_del - 1]]
+
+    return timeseries
+
+
+def read_timeseries_simulink_loadflow(file_name, timeseries_names=None, is_regex=False):
+    """
+    Read in simulink load-flow result from result file(.rep), the result is in angle notation, amplitude and angle are stored
+    separately.
+    A suffix is used to tag different data for a component:
+        .Arms/.IDegree for current/current angle,
+        .Vrms/.VDegree for voltage/voltage angle.
+
+    :param file_name:path of the .rep file for the loadflow result from simulink
+    :param timeseries_names: specific values to be read
+    :param is_regex: flag for using regular expression
+    :return: list of Timeseries objects
+    """
+    str_tmp = open(file_name, 'r', encoding='latin-1')  # Read in files, using latin-1 to decode /xb0
+
+    # Read in data from result file of neplan
+    name = []  # list for data type names
+    value = []  # list for data
+    timeseries = []
+    line_del = []  # a list for the value to be deleted
+
+    for line in str_tmp.readlines():
+        line = line.replace("°", "")
+        del value[:]
+        del name[:]
+        # read in different data and start processing
+        if len(line) > 37:
+            if line[31:35] == '--->':
+                if line[13:17] == 'Arms':
+                    name = [line[37:len(line)].rstrip() + '.Arms', line[37:len(line)].rstrip() + '.IDegree']
+                elif line[13:17] == 'Vrms':
+                    name = [line[37:len(line)].rstrip() + '.Vrms', line[37:len(line)].rstrip() + '.VDegree']
+                value = [float(line[0:13]), float(line[18:31])]
+                timeseries.append(TimeSeries(name[0],
+                                             np.array([0., 1.]), np.array([value[0], value[0]])))
+                timeseries.append(TimeSeries(name[1],
+                                             np.array([0., 1.]), np.array([value[1], value[1]])))
+
+    # Read in variables which match with regex
+    if is_regex is True:
+        p = re.compile(timeseries_names)
+        length = len(timeseries)
+        for rule_check in range(length):
+            if p.search(timeseries[rule_check].name):
+                pass
+            else:
+                line_del.append(rule_check)
+
+    # Read in specified time series
+    elif timeseries_names is not None:
+        length = len(timeseries)
+        for rule_check in range(length):
+            if timeseries_names == timeseries[rule_check].name:
+                pass
+            else:
+                line_del.append(rule_check)
+
+    # delete those values that are not needed.
+    line_del = set(line_del)
+    line_del = sorted(line_del)
+    for num_to_del in range(len(line_del)):
+        del timeseries[line_del[len(line_del) - num_to_del - 1]]
+    return timeseries
+
diff --git a/villas/dataprocessing/validationtools.py b/villas/dataprocessing/validationtools.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8a5b27e7663465d50d45bcdb6b637e1bef2ab45
--- /dev/null
+++ b/villas/dataprocessing/validationtools.py
@@ -0,0 +1,169 @@
+#!/usr/bin/python
+# -*- coding: UTF-8 -*-
+
+import os
+
+from readtools import *
+
+"""
+The validationtools are used to validate the simulate results from the model.
+A typical process to validate a model contains four parts
+ - Building & Running the module to get results
+ - Reading in the results
+ - Mapping the results with the reference results
+ - Asserting the module
+The first step is done by Py4Mod package, the second by readtool.
+
+The validationtool focuses on the last two steps: the conversion function converts the reference-results 
+timeseries into the modelica timeseries (mapping the names and units), the comparision function compares two 
+timeseries, and the assert function gives an assertion to the result comparison. 
+
+At last, a top level validation function is introduced to organize the whole job.   
+"""
+
+def convert_neplan_to_modelica_timeseries(neplan_timeseries):
+    """
+    Mapping the variable names between modelica and neplan
+        - Voltage: change *.U and *.ANGLEU to *.V and *.Vangle
+        - Current: remove unnecessary current variables
+    :param neplan_timeseries: result of neplan in timeseries
+    :return: a mapped neplan_timeseries
+    """
+    line_del = []
+    # remove all the line current
+
+    # Find current of the same component, which means the current don't need to be validated
+    for check in range(len(neplan_timeseries)):
+        if neplan_timeseries[check].values[0] == '#':
+            line_del.append(check)
+        if '.P' in neplan_timeseries[check].name:
+            line_del.append(check)
+        if '.Q' in neplan_timeseries[check].name:
+            line_del.append(check)
+        for i in range(check + 1, len(neplan_timeseries)):
+            if neplan_timeseries[check].name == neplan_timeseries[i].name:
+                line_del.append(check)  # delete list of the unnecessary data
+                line_del.append(i)
+    line_del = sorted(set(line_del))
+    for num_to_del in range(len(line_del)):
+        del neplan_timeseries[line_del[len(line_del) - num_to_del - 1]]
+
+    # Change the unit of variables to keep consistent with those in modelica
+    for i in range(len(neplan_timeseries)):
+        if 'ANGLE' in neplan_timeseries[i].name:
+            neplan_timeseries[i].values = neplan_timeseries[i].values / 180 * cmath.pi  # unification of the unit
+        elif '.U' in neplan_timeseries[i].name or '.I' in neplan_timeseries[i].name:
+            neplan_timeseries[i].values = neplan_timeseries[i].values * 1000
+
+    # Change the name of variables to keep consistent with those in modelica
+    for i in range(len(neplan_timeseries)):
+        neplan_timeseries[i].name = neplan_timeseries[i].name.replace(' ', '')
+        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.ANGLEU', '.Vangle')
+        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.U', '.Vpp')
+        neplan_timeseries[i].name = neplan_timeseries[i].name.replace('.ANGLEI', '.Iangle')
+
+    return neplan_timeseries
+
+def convert_simulink_to_modelica_timeseries(simseri):
+    """
+    Convert the steady-state results timeseries from simulink to modelica timeseries
+    :param simseri: simulate timeseries, generated by the result file from simulink
+    :return: a result timeseries
+    """
+    res = []
+    for check in range(len(simseri)):
+        if 'U AB:' in simseri[check].name:
+            simseri[check].name = simseri[check].name.replace('U AB:', '')
+            simseri[check].name = simseri[check].name.replace('Vrms', 'Vpp')
+            simseri[check].name = simseri[check].name.replace('VDegree', 'Vangle')
+            simseri[check].name = simseri[check].name.replace(' ', '')
+            simseri[check].name = simseri[check].name.replace('_', '')
+            if 'Vangle' in simseri[check].name:
+                simseri[check].values = (simseri[check].values - 30)/180 * cmath.pi
+            res.append(simseri[check])
+    return res
+
+
+def compare_timeseries(ts1, ts2):
+    """
+    Compare the result from two timeseries.
+    :param ts1: timeseries
+    :param ts2: timeseries
+    :return: an error dic
+    """
+    if len(ts1) > len(ts2):
+        tmp = ts2
+        ts2 = ts1
+        ts1 = tmp
+    for i in range(len(ts1)):
+        ts1[i].name = ts1[i].name.upper()
+    for i in range(len(ts2)):
+        ts2[i].name = ts2[i].name.upper()
+
+    timeseries_names = []  # list for names of components
+    timeseries_error = []  # list for error
+    len_ts1 = len(ts1)
+    len_limit = len(ts2)
+
+    # Match the components in result files, and compare them
+    for i in range(len_ts1):
+        flag_not_found = False
+        for j in range(len_limit):
+            if ts1[i].name == ts2[j].name:  # Find the same variable
+                timeseries_names.append(ts1[i].name)
+                if ts1[i].values[0] == 0:
+                    timeseries_error.append(TimeSeries.rmse(ts2[j], ts1[i]))  # is it good to do so?
+                else:
+                    timeseries_error.append(TimeSeries.rmse(ts2[j], ts1[i])/ts1[i].values[0])
+
+                print(ts1[i].name)
+                print(timeseries_error[len(timeseries_error) - 1])
+                flag_not_found = True
+        if flag_not_found is False:
+            # No such variable in Modelica model, set the error to -1
+            timeseries_names.append(ts1[i].name)
+            timeseries_error.append(-1)
+    return dict(zip(timeseries_names, timeseries_error))
+
+
+def assert_modelia_results(net_name, error, threshold):
+    """
+    assert the result data of a net.
+    :param net_name: name of the network
+    :param modelica_res: timeseries of modelica result
+    :param simulink_res: timeseries of reference result
+    :return: outputs to command line which are the results of the assert
+    """
+    fail_list = []  # List for all the failed test
+    #  the limitations are set to 0.5
+    for name in error.keys():
+        if abs(error[name]) > threshold:
+            fail_list.append(name)
+        else:
+            print("Test on %s Passed" % name)
+
+    #  fail_list is 0, which means all the tests are passed
+    if len(fail_list) is 0:
+        print("\033[1;36;40mModel %s Passed\033[0m" % net_name)
+    else:
+        for name in fail_list:
+            print("\033[1;31;40mTest on %s of %s Failed\033[0m" % (name, net_name))
+        raise ValueError('Test on %s is not passed!' % net_name)
+
+
+def validate_modelica_res(net_name, modelica_res_path, reference_res_path, threshold=0.5):
+    """
+    Top level function for the validation of modelica, calls all the function needed to execute the validation.
+    :param modelica_res_path: the path of the modelica result file, whose suffix should be .mat
+    :param reference_res_path: the path of the reference result file, whose suffix should be .rep(simulink)/.rlf(neplan)
+    :param threshold: the threshold of the assertion, a default value of 0.5 is introduced.
+    :return: outputs to command line which are the results of the validation.
+    """
+    res_mod = read_timeseries_Modelica (modelica_res_path)
+    if os.path.splitext(reference_res_path)[1] == '.rep':
+        res_ref = convert_simulink_to_modelica_timeseries(read_timeseries_simulink_loadflow(reference_res_path))
+    elif os.path.splitext(reference_res_path)[1] == '.rlf':
+        res_ref = convert_neplan_to_modelica_timeseries(read_timeseries_NEPLAN_loadflow(reference_res_path))
+    
+    res_err = compare_timeseries(res_ref, res_mod)
+    assert_modelia_results(net_name, res_err, threshold)