From 2d7586f5d27941c690ba4d7a5c0ae5abb7bedbb4 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Thu, 21 Jul 2016 16:09:08 +0200
Subject: [PATCH] separate reading input data into independent classes

---
 .../ComponentData/AccelerationCurveReader.cs  |  95 ++++++++++++++
 .../CrossWindCorrectionCurveReader.cs         |   0
 .../ComponentData/RetarderLossMapReader.cs    |  94 +++++++++++++
 .../TorqueConverterDataReader.cs              |  76 +++++++++++
 .../TransmissionLossMapReader.cs              | 124 ++++++++++++++++++
 .../Data/AccelerationCurve.cs                 |  85 +-----------
 .../Data/Gearbox/TorqueConverterData.cs       |  35 ++++-
 .../Data/Gearbox/TransmissionLossMap.cs       | 120 ++---------------
 .../Data/RetarderLossMap.cs                   |  89 +------------
 9 files changed, 442 insertions(+), 276 deletions(-)
 create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs
 rename VectoCore/VectoCore/{Models/SimulationComponent/Data => InputData/Reader/ComponentData}/CrossWindCorrectionCurveReader.cs (100%)
 create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs
 create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs
 create mode 100644 VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs

diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs
new file mode 100644
index 0000000000..1319d7c684
--- /dev/null
+++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/AccelerationCurveReader.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data
+{
+	public class AccelerationCurveReader
+	{
+		public static AccelerationCurveData ReadFromStream(Stream stream)
+		{
+			var data = VectoCSVFile.ReadStream(stream);
+			return Create(data);
+		}
+
+		public static AccelerationCurveData ReadFromFile(string fileName)
+		{
+			try {
+				var data = VectoCSVFile.Read(fileName);
+				return Create(data);
+			} catch (Exception ex) {
+				throw new VectoException("ERROR while reading AccelerationCurve File: " + ex.Message);
+			}
+		}
+
+		internal static AccelerationCurveData Create(DataTable data)
+		{
+			if (data.Columns.Count != 3) {
+				throw new VectoException("Acceleration Limiting File must consist of 3 columns.");
+			}
+
+			if (data.Rows.Count < 2) {
+				throw new VectoException("Acceleration Limiting File must consist of at least two entries.");
+			}
+
+			if (HeaderIsValid(data.Columns)) {
+				return CreateFromColumnNames(data);
+			}
+			LoggingObject.Logger<AccelerationCurveData>()
+				.Warn("Acceleration Curve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: {3}",
+					Fields.Velocity, AccelerationCurveReader.Fields.Acceleration,
+					Fields.Deceleration,
+					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
+			return CreateFromColumnIndizes(data);
+		}
+
+		private static AccelerationCurveData CreateFromColumnIndizes(DataTable data)
+		{
+			return new AccelerationCurveData(data.Rows.Cast<DataRow>()
+				.Select(r => new KeyValuePair<MeterPerSecond, AccelerationCurveData.AccelerationEntry>(
+					r.ParseDouble(0).KMPHtoMeterPerSecond(),
+					new AccelerationCurveData.AccelerationEntry {
+						Acceleration = r.ParseDouble(1).SI<MeterPerSquareSecond>(),
+						Deceleration = r.ParseDouble(2).SI<MeterPerSquareSecond>()
+					}))
+				.OrderBy(x => x.Key)
+				.ToList());
+		}
+
+		private static AccelerationCurveData CreateFromColumnNames(DataTable data)
+		{
+			return new AccelerationCurveData(
+				data.Rows.Cast<DataRow>()
+					.Select(r => new KeyValuePair<MeterPerSecond, AccelerationCurveData.AccelerationEntry>(
+						r.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(),
+						new AccelerationCurveData.AccelerationEntry {
+							Acceleration = r.ParseDouble(Fields.Acceleration).SI<MeterPerSquareSecond>(),
+							Deceleration = r.ParseDouble(Fields.Deceleration).SI<MeterPerSquareSecond>()
+						}))
+					.OrderBy(x => x.Key)
+					.ToList());
+		}
+
+		private static bool HeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(Fields.Velocity) &&
+					columns.Contains(Fields.Acceleration) &&
+					columns.Contains(Fields.Deceleration);
+		}
+
+		public static class Fields
+		{
+			public const string Velocity = "v";
+
+			public const string Acceleration = "acc";
+
+			public const string Deceleration = "dec";
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/CrossWindCorrectionCurveReader.cs
similarity index 100%
rename from VectoCore/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurveReader.cs
rename to VectoCore/VectoCore/InputData/Reader/ComponentData/CrossWindCorrectionCurveReader.cs
diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs
new file mode 100644
index 0000000000..9cd7522be1
--- /dev/null
+++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/RetarderLossMapReader.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data
+{
+	public class RetarderLossMapReader
+	{
+		/// <summary>
+		/// Read the retarder loss map from a file.
+		/// </summary>
+		/// <param name="fileName"></param>
+		/// <returns></returns>
+		public static RetarderLossMap ReadFromFile(string fileName)
+		{
+			try {
+				return Create(VectoCSVFile.Read(fileName));
+			} catch (Exception ex) {
+				throw new VectoException("ERROR while loading RetarderLossMap: " + ex.Message);
+			}
+		}
+
+		/// <summary>
+		/// Create the retarder loss map from an appropriate datatable. (2 columns: Retarder Speed, Torque Loss)
+		/// </summary>
+		/// <param name="data"></param>
+		/// <returns></returns>
+		public static RetarderLossMap Create(DataTable data)
+		{
+			if (data.Columns.Count != 2) {
+				throw new VectoException("RetarderLossMap Data File must consist of 2 columns: Retarder Speed, Torque Loss");
+			}
+
+			if (data.Rows.Count < 2) {
+				throw new VectoException("RetarderLossMap must contain at least 2 entries.");
+			}
+
+			List<RetarderLossMap.RetarderLossEntry> entries;
+			if (HeaderIsValid(data.Columns)) {
+				entries = CreateFromColumnNames(data);
+			} else {
+				LoggingObject.Logger<RetarderLossMap>().Warn(
+					"RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.",
+					Fields.RetarderSpeed, Fields.TorqueLoss,
+					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()));
+				entries = CreateFromColumnIndizes(data);
+			}
+
+			entries.Sort((entry1, entry2) => entry1.RetarderSpeed.Value().CompareTo(entry2.RetarderSpeed.Value()));
+			return new RetarderLossMap(entries);
+		}
+
+		private static List<RetarderLossMap.RetarderLossEntry> CreateFromColumnNames(DataTable data)
+		{
+			return data.Rows.Cast<DataRow>()
+				.Select(row => new RetarderLossMap.RetarderLossEntry {
+					RetarderSpeed = DataTableExtensionMethods.ParseDouble(row, (string)Fields.RetarderSpeed).RPMtoRad(),
+					TorqueLoss = DataTableExtensionMethods.ParseDouble(row, (string)Fields.TorqueLoss).SI<NewtonMeter>()
+				}).ToList();
+		}
+
+		private static bool HeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss);
+		}
+
+		private static List<RetarderLossMap.RetarderLossEntry> CreateFromColumnIndizes(DataTable data)
+		{
+			return data.Rows.Cast<DataRow>()
+				.Select(row => new RetarderLossMap.RetarderLossEntry {
+					RetarderSpeed = row.ParseDouble(0).RPMtoRad(),
+					TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>()
+				}).ToList();
+		}
+
+		private static class Fields
+		{
+			/// <summary>
+			///     [rpm]
+			/// </summary>
+			public const string RetarderSpeed = "Retarder Speed";
+
+			/// <summary>
+			///     [Nm]
+			/// </summary>
+			public const string TorqueLoss = "Torque Loss";
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs
new file mode 100644
index 0000000000..f6deb29f19
--- /dev/null
+++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TorqueConverterDataReader.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
+{
+	public class TorqueConverterDataReader {
+		public static TorqueConverterData ReadFromFile(string filename)
+		{
+			return Create(VectoCSVFile.Read(filename));
+		}
+
+		public static TorqueConverterData ReadFromStream(Stream stream)
+		{
+			return Create(VectoCSVFile.ReadStream(stream));
+		}
+
+		public static TorqueConverterData Create(DataTable data)
+		{
+			if (data.Columns.Count != 3) {
+				throw new VectoException("TorqueConverter Characteristics data must consist of 3 columns");
+			}
+			if (data.Rows.Count < 2) {
+				throw new VectoException("TorqueConverter Characteristics data must contain at least 2 lines with numeric values");
+			}
+
+			List<TorqueRatioCurveEntry> torqueRatio;
+			List<CharacteristicTorqueEntry> characteristicTorque;
+			if (HeaderIsValid(data.Columns)) {
+				torqueRatio = (from DataRow row in data.Rows
+					select
+						new TorqueRatioCurveEntry() {
+							SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio),
+							TorqueRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.TorqueRatio)
+						}).ToList();
+				characteristicTorque = (from DataRow row in data.Rows
+					select
+						new CharacteristicTorqueEntry() {
+							SpeedRatio = DataTableExtensionMethods.ParseDouble(row, (string)Fields.SpeedRatio),
+							Torque = DataTableExtensionMethods.ParseDouble(row, (string)Fields.CharacteristicTorque).SI<NewtonMeter>()
+						}).ToList();
+			} else {
+				torqueRatio = (from DataRow row in data.Rows
+					select
+						new TorqueRatioCurveEntry() {
+							SpeedRatio = row.ParseDouble(0),
+							TorqueRatio = row.ParseDouble(1)
+						}).ToList();
+				characteristicTorque = (from DataRow row in data.Rows
+					select
+						new CharacteristicTorqueEntry() {
+							SpeedRatio = row.ParseDouble(0),
+							Torque = row.ParseDouble(2).SI<NewtonMeter>()
+						}).ToList();
+			}
+			return new TorqueConverterData(torqueRatio, characteristicTorque);
+		}
+
+		private static bool HeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(Fields.SpeedRatio) && columns.Contains(Fields.TorqueRatio) &&
+					columns.Contains(Fields.CharacteristicTorque);
+		}
+
+		public static class Fields
+		{
+			public const string SpeedRatio = "Speed Ratio";
+			public const string TorqueRatio = "Torque Ratio";
+			public const string CharacteristicTorque = "MP1000";
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs
new file mode 100644
index 0000000000..ca761e29df
--- /dev/null
+++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
+{
+	public sealed class TransmissionLossMapReader
+	{
+		public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName)
+		{
+			try {
+				var data = VectoCSVFile.Read(fileName, true);
+				return Create(data, gearRatio, gearName);
+			} catch (Exception ex) {
+				throw new VectoException("ERROR while reading TransmissionLossMap: " + ex.Message);
+			}
+		}
+
+		/// <summary>
+		/// Create a TransmissionLoss Map from a DataTable.
+		/// </summary>
+		/// <param name="data"></param>
+		/// <param name="gearRatio"></param>
+		/// <param name="gearName"></param>
+		/// <returns></returns>
+		public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName)
+		{
+			if (data.Columns.Count < 3) {
+				throw new VectoException("TransmissionLossMap Data File for {0} must consist of at least 3 columns.", gearName);
+			}
+
+			if (data.Rows.Count < 4) {
+				throw new VectoException(
+					"TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName);
+			}
+
+			List<TransmissionLossMap.GearLossMapEntry> entries;
+			if (HeaderIsValid(data.Columns)) {
+				entries = CreateFromColumnNames(data);
+			} else {
+				LoggingObject.Logger<TransmissionLossMap>().Warn(
+					"TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}, <{3}>'. Got: '{4}'. Falling back to column index.",
+					TransmissionLossMapReader.Fields.InputSpeed, TransmissionLossMapReader.Fields.InputTorque,
+					TransmissionLossMapReader.Fields.TorqeLoss, TransmissionLossMapReader.Fields.Efficiency,
+					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName);
+
+				entries = CreateFromColumIndizes(data);
+			}
+
+			return new TransmissionLossMap(entries, gearRatio, gearName);
+		}
+
+		/// <summary>
+		/// Create a DataTable from an efficiency value.
+		/// </summary>
+		/// <param name="efficiency"></param>
+		/// <param name="gearRatio"></param>
+		/// <param name="gearName"></param>
+		/// <returns></returns>
+		public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName)
+		{
+			var entries = new List<TransmissionLossMap.GearLossMapEntry> {
+				new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(),
+					(1 - efficiency) * 1e5.SI<NewtonMeter>()),
+				new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(),
+					(1 - efficiency) * 1e5.SI<NewtonMeter>()),
+				new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()),
+				new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()),
+				new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), -1e5.SI<NewtonMeter>(),
+					(1 - efficiency) * 1e5.SI<NewtonMeter>()),
+				new TransmissionLossMap.GearLossMapEntry(5000.RPMtoRad(), 1e5.SI<NewtonMeter>(),
+					(1 - efficiency) * 1e5.SI<NewtonMeter>()),
+			};
+			return new TransmissionLossMap(entries, gearRatio, gearName);
+		}
+
+		private static bool HeaderIsValid(DataColumnCollection columns)
+		{
+			return columns.Contains(TransmissionLossMapReader.Fields.InputSpeed) &&
+					columns.Contains(TransmissionLossMapReader.Fields.InputTorque) &&
+					columns.Contains(TransmissionLossMapReader.Fields.TorqeLoss);
+		}
+
+		private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumnNames(DataTable data)
+		{
+			return (from DataRow row in data.Rows
+				select new TransmissionLossMap.GearLossMapEntry(
+					inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(),
+					inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(),
+					torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>()))
+				.ToList();
+		}
+
+		private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumIndizes(DataTable data)
+		{
+			return (from DataRow row in data.Rows
+				select new TransmissionLossMap.GearLossMapEntry(
+					inputSpeed: row.ParseDouble(0).RPMtoRad(),
+					inputTorque: row.ParseDouble(1).SI<NewtonMeter>(),
+					torqueLoss: row.ParseDouble(2).SI<NewtonMeter>()))
+				.ToList();
+		}
+
+		public static class Fields
+		{
+			/// <summary>[rpm]</summary>
+			public const string InputSpeed = "Input Speed";
+
+			/// <summary>[Nm]</summary>
+			public const string InputTorque = "Input Torque";
+
+			/// <summary>[Nm]</summary>
+			public const string TorqeLoss = "Torque Loss";
+
+			/// <summary>[-]</summary>
+			public const string Efficiency = "Eff";
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs
index ca50bfcc17..e8053c20ea 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/AccelerationCurve.cs
@@ -43,86 +43,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 {
 	public class AccelerationCurveData : SimulationComponentData
 	{
-		private List<KeyValuePair<MeterPerSecond, AccelerationEntry>> _entries;
+		private readonly List<KeyValuePair<MeterPerSecond, AccelerationEntry>> _entries;
 
-		public static AccelerationCurveData ReadFromStream(Stream stream)
+		protected internal AccelerationCurveData(List<KeyValuePair<MeterPerSecond, AccelerationEntry>> entries)
 		{
-			var data = VectoCSVFile.ReadStream(stream);
-			return Create(data);
-		}
-
-		public static AccelerationCurveData ReadFromFile(string fileName)
-		{
-			try {
-				var data = VectoCSVFile.Read(fileName);
-				return Create(data);
-			} catch (Exception ex) {
-				throw new VectoException("ERROR while reading AccelerationCurve File: " + ex.Message);
-			}
-		}
-
-		internal static AccelerationCurveData Create(DataTable data)
-		{
-			if (data.Columns.Count != 3) {
-				throw new VectoException("Acceleration Limiting File must consist of 3 columns.");
-			}
-
-			if (data.Rows.Count < 2) {
-				throw new VectoException("Acceleration Limiting File must consist of at least two entries.");
-			}
-
-			if (HeaderIsValid(data.Columns)) {
-				return CreateFromColumnNames(data);
-			}
-			Logger<AccelerationCurveData>()
-				.Warn("Acceleration Curve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: {3}",
-					Fields.Velocity, Fields.Acceleration, Fields.Deceleration,
-					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
-			return CreateFromColumnIndizes(data);
-		}
-
-		private static AccelerationCurveData CreateFromColumnIndizes(DataTable data)
-		{
-			return new AccelerationCurveData {
-				_entries = data.Rows.Cast<DataRow>()
-					.Select(r => new KeyValuePair<MeterPerSecond, AccelerationEntry>(
-						r.ParseDouble(0).KMPHtoMeterPerSecond(),
-						new AccelerationEntry {
-							Acceleration = r.ParseDouble(1).SI<MeterPerSquareSecond>(),
-							Deceleration = r.ParseDouble(2).SI<MeterPerSquareSecond>()
-						}))
-					.OrderBy(x => x.Key)
-					.ToList()
-			};
-		}
-
-		private static AccelerationCurveData CreateFromColumnNames(DataTable data)
-		{
-			return new AccelerationCurveData {
-				_entries = data.Rows.Cast<DataRow>()
-					.Select(r => new KeyValuePair<MeterPerSecond, AccelerationEntry>(
-						r.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(),
-						new AccelerationEntry {
-							Acceleration = r.ParseDouble(Fields.Acceleration).SI<MeterPerSquareSecond>(),
-							Deceleration = r.ParseDouble(Fields.Deceleration).SI<MeterPerSquareSecond>()
-						}))
-					.OrderBy(x => x.Key)
-					.ToList()
-			};
-		}
-
-		private static bool HeaderIsValid(DataColumnCollection columns)
-		{
-			return columns.Contains(Fields.Velocity) &&
-					columns.Contains(Fields.Acceleration) &&
-					columns.Contains(Fields.Deceleration);
+			_entries = entries;
 		}
 
 		public AccelerationEntry Lookup(MeterPerSecond key)
 		{
 			var index = FindIndex(key);
 
-			return new AccelerationEntry {
+			return new AccelerationCurveData.AccelerationEntry {
 				Acceleration =
 					VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key,
 						_entries[index - 1].Value.Acceleration,
@@ -234,14 +166,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 			var t = Math.Log(((v2 * k + d) / (v1 * k + d)).Cast<Scalar>()) / k;
 			return m / k * Math.Exp((k * t).Value()) + b * t + c;
 		}
-
-		private static class Fields
-		{
-			public const string Velocity = "v";
-
-			public const string Acceleration = "acc";
-
-			public const string Deceleration = "dec";
-		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
index cd32910fff..237c80718c 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs
@@ -29,7 +29,40 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using iTextSharp.text.pdf.codec;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
 namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 {
-	public class TorqueConverterData {}
+	public class TorqueConverterData
+	{
+		public List<TorqueRatioCurveEntry> TorqueRatio;
+		public List<CharacteristicTorqueEntry> CharacteristicTorque;
+
+		protected internal TorqueConverterData(List<TorqueRatioCurveEntry> torqueRatio,
+			List<CharacteristicTorqueEntry> characteristicTorque)
+		{
+			TorqueRatio = torqueRatio;
+			CharacteristicTorque = characteristicTorque;
+		}
+	}
+
+
+	public class CharacteristicTorqueEntry
+	{
+		public double SpeedRatio;
+		public NewtonMeter Torque;
+	}
+
+	public class TorqueRatioCurveEntry
+	{
+		public double SpeedRatio;
+		public double TorqueRatio;
+	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
index 91c7fc84a5..90441ee4d8 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs
@@ -45,7 +45,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 {
 	public sealed class TransmissionLossMap : LoggingObject
 	{
-		[ValidateObject] private readonly List<GearLossMapEntry> _entries;
+		[ValidateObject] private readonly IReadOnlyList<GearLossMapEntry> _entries;
 
 		private readonly double _ratio;
 
@@ -59,103 +59,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 		/// </summary>
 		private readonly DelaunayMap _invertedLossMap;
 
-		public void DrawGraph()
-		{
-			_lossMap.DrawGraph();
-		}
-
 		public string GearName { get; private set; }
 
-		public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName)
-		{
-			try {
-				var data = VectoCSVFile.Read(fileName, true);
-				return Create(data, gearRatio, gearName);
-			} catch (Exception ex) {
-				throw new VectoException("ERROR while reading TransmissionLossMap: " + ex.Message);
-			}
-		}
-
-		/// <summary>
-		/// Create a TransmissionLoss Map from a DataTable.
-		/// </summary>
-		/// <param name="data"></param>
-		/// <param name="gearRatio"></param>
-		/// <param name="gearName"></param>
-		/// <returns></returns>
-		public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName)
-		{
-			if (data.Columns.Count < 3) {
-				throw new VectoException("TransmissionLossMap Data File for {0} must consist of at least 3 columns.", gearName);
-			}
-
-			if (data.Rows.Count < 4) {
-				throw new VectoException(
-					"TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName);
-			}
-
-			List<GearLossMapEntry> entries;
-			if (HeaderIsValid(data.Columns)) {
-				entries = CreateFromColumnNames(data);
-			} else {
-				Logger<TransmissionLossMap>().Warn(
-					"TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}, <{3}>'. Got: '{4}'. Falling back to column index.",
-					Fields.InputSpeed, Fields.InputTorque, Fields.TorqeLoss, Fields.Efficiency,
-					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName);
-
-				entries = CreateFromColumIndizes(data);
-			}
-
-			return new TransmissionLossMap(entries, gearRatio, gearName);
-		}
-
-		/// <summary>
-		/// Create a DataTable from an efficiency value.
-		/// </summary>
-		/// <param name="efficiency"></param>
-		/// <param name="gearRatio"></param>
-		/// <param name="gearName"></param>
-		/// <returns></returns>
-		public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName)
-		{
-			var entries = new List<GearLossMapEntry> {
-				new GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()),
-				new GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()),
-				new GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()),
-				new GearLossMapEntry(5000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()),
-				new GearLossMapEntry(5000.RPMtoRad(), -1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()),
-				new GearLossMapEntry(5000.RPMtoRad(), 1e5.SI<NewtonMeter>(), (1 - efficiency) * 1e5.SI<NewtonMeter>()),
-			};
-			return new TransmissionLossMap(entries, gearRatio, gearName);
-		}
-
-		private static bool HeaderIsValid(DataColumnCollection columns)
-		{
-			return columns.Contains(Fields.InputSpeed) && columns.Contains(Fields.InputTorque) &&
-					columns.Contains(Fields.TorqeLoss);
-		}
-
-		private static List<GearLossMapEntry> CreateFromColumnNames(DataTable data)
-		{
-			return (from DataRow row in data.Rows
-				select new GearLossMapEntry(
-					inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(),
-					inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(),
-					torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>()))
-				.ToList();
-		}
-
-		private static List<GearLossMapEntry> CreateFromColumIndizes(DataTable data)
-		{
-			return (from DataRow row in data.Rows
-				select new GearLossMapEntry(
-					inputSpeed: row.ParseDouble(0).RPMtoRad(),
-					inputTorque: row.ParseDouble(1).SI<NewtonMeter>(),
-					torqueLoss: row.ParseDouble(2).SI<NewtonMeter>()))
-				.ToList();
-		}
-
-		private TransmissionLossMap(List<GearLossMapEntry> entries, double gearRatio, string gearName)
+		public TransmissionLossMap(IReadOnlyList<GearLossMapEntry> entries, double gearRatio, string gearName)
 		{
 			GearName = gearName;
 			_ratio = gearRatio;
@@ -181,7 +87,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 		/// <returns>Torque loss as seen on input side (towards the engine).</returns>
 		public LossMapResult GetTorqueLoss(PerSecond outAngularVelocity, NewtonMeter outTorque)
 		{
-			var result = new LossMapResult();
+			var result = new TransmissionLossMap.LossMapResult();
 			var torqueLoss = _lossMap.Interpolate(outAngularVelocity.ConvertTo().Rounds.Per.Minute.Value() * _ratio,
 				outTorque.Value() / _ratio);
 
@@ -233,6 +139,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 			get { return _entries[i]; }
 		}
 
+		public void DrawGraph()
+		{
+			_lossMap.DrawGraph();
+		}
+
 		[DebuggerDisplay("GearLossMapEntry({InputSpeed}, {InputTorque}, {TorqueLoss})")]
 		public class GearLossMapEntry
 		{
@@ -252,20 +163,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
 				TorqueLoss = torqueLoss;
 			}
 		}
-
-		private static class Fields
-		{
-			/// <summary>[rpm]</summary>
-			public const string InputSpeed = "Input Speed";
-
-			/// <summary>[Nm]</summary>
-			public const string InputTorque = "Input Torque";
-
-			/// <summary>[Nm]</summary>
-			public const string TorqeLoss = "Torque Loss";
-
-			/// <summary>[-]</summary>
-			public const string Efficiency = "Eff";
-		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs
index 1b50887eb0..319f5b3e94 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs
@@ -45,10 +45,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 	/// </summary>
 	public class RetarderLossMap : SimulationComponentData
 	{
-		[ValidateObject] private List<RetarderLossEntry> _entries;
+		[ValidateObject] private readonly IReadOnlyList<RetarderLossEntry> _entries;
 		private PerSecond _minSpeed;
 		private PerSecond _maxSpeed;
 
+		protected internal RetarderLossMap(List<RetarderLossEntry> entries)
+		{
+			_entries = entries;
+		}
+
 		/// <summary>
 		/// Gets the minimal defined speed of the retarder loss map.
 		/// </summary>
@@ -65,50 +70,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 			get { return _maxSpeed ?? (_maxSpeed = _entries.Max(e => e.RetarderSpeed)); }
 		}
 
-		/// <summary>
-		/// Read the retarder loss map from a file.
-		/// </summary>
-		/// <param name="fileName"></param>
-		/// <returns></returns>
-		public static RetarderLossMap ReadFromFile(string fileName)
-		{
-			try {
-				return Create(VectoCSVFile.Read(fileName));
-			} catch (Exception ex) {
-				throw new VectoException("ERROR while loading RetarderLossMap: " + ex.Message);
-			}
-		}
-
-		/// <summary>
-		/// Create the retarder loss map from an appropriate datatable. (2 columns: Retarder Speed, Torque Loss)
-		/// </summary>
-		/// <param name="data"></param>
-		/// <returns></returns>
-		public static RetarderLossMap Create(DataTable data)
-		{
-			if (data.Columns.Count != 2) {
-				throw new VectoException("RetarderLossMap Data File must consist of 2 columns: Retarder Speed, Torque Loss");
-			}
-
-			if (data.Rows.Count < 2) {
-				throw new VectoException("RetarderLossMap must contain at least 2 entries.");
-			}
-
-			List<RetarderLossEntry> entries;
-			if (HeaderIsValid(data.Columns)) {
-				entries = CreateFromColumnNames(data);
-			} else {
-				Logger<RetarderLossMap>().Warn(
-					"RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.",
-					Fields.RetarderSpeed, Fields.TorqueLoss,
-					", ".Join(data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()));
-				entries = CreateFromColumnIndizes(data);
-			}
-
-			entries.Sort((entry1, entry2) => entry1.RetarderSpeed.Value().CompareTo(entry2.RetarderSpeed.Value()));
-			return new RetarderLossMap { _entries = entries };
-		}
-
 		/// <summary>
 		/// Calculates the retarder losses.
 		/// </summary>
@@ -121,30 +82,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 				angularVelocity);
 		}
 
-		private static List<RetarderLossEntry> CreateFromColumnNames(DataTable data)
-		{
-			return data.Rows.Cast<DataRow>()
-				.Select(row => new RetarderLossEntry {
-					RetarderSpeed = row.ParseDouble(Fields.RetarderSpeed).RPMtoRad(),
-					TorqueLoss = row.ParseDouble(Fields.TorqueLoss).SI<NewtonMeter>()
-				}).ToList();
-		}
-
-		private static bool HeaderIsValid(DataColumnCollection columns)
-		{
-			return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss);
-		}
-
-		private static List<RetarderLossEntry> CreateFromColumnIndizes(DataTable data)
-		{
-			return data.Rows.Cast<DataRow>()
-				.Select(row => new RetarderLossEntry {
-					RetarderSpeed = row.ParseDouble(0).RPMtoRad(),
-					TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>()
-				}).ToList();
-		}
-
-		private class RetarderLossEntry
+		public class RetarderLossEntry
 		{
 			[Required, SIRange(0, double.MaxValue)]
 			public PerSecond RetarderSpeed { get; set; }
@@ -152,18 +90,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 			[Required, SIRange(0, 500)]
 			public NewtonMeter TorqueLoss { get; set; }
 		}
-
-		private static class Fields
-		{
-			/// <summary>
-			///     [rpm]
-			/// </summary>
-			public const string RetarderSpeed = "Retarder Speed";
-
-			/// <summary>
-			///     [Nm]
-			/// </summary>
-			public const string TorqueLoss = "Torque Loss";
-		}
 	}
 }
\ No newline at end of file
-- 
GitLab