From 54b58a1d91e715eedee1c4b555e66a991d632a62 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Tue, 13 Dec 2016 13:42:21 +0100
Subject: [PATCH] refactoring: moving 1Hz Filter to separate file, movin modal
 result fields to separate file

---
 .../Models/Simulation/Data/ModalResult.cs     | 327 -----------------
 .../Simulation/Data/ModalResultField.cs       | 339 ++++++++++++++++++
 .../ModFilter/ModalData1HzFilter.cs           | 197 ++++++++++
 .../OutputData/ModalDataContainer.cs          | 188 ----------
 4 files changed, 536 insertions(+), 515 deletions(-)
 create mode 100644 VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
 create mode 100644 VectoCore/VectoCore/OutputData/ModFilter/ModalData1HzFilter.cs

diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
index 71cee71fec..f6c32af7b6 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
@@ -112,331 +112,4 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			VectoCSVFile.Write(fileName, this);
 		}
 	}
-
-	/// <summary>
-	///     Enum with field definitions of the Modal Results File (.vmod).
-	/// </summary>
-	public enum ModalResultField
-	{
-		/// <summary>
-		///     Time step [s].
-		///     Midpoint of the simulated interval.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "time [s]")] time,
-
-		/// <summary>
-		///     Simulation interval around the current time step. [s]
-		/// </summary>
-		[ModalResultField(typeof(SI), "simulation_interval", "dt [s]")] simulationInterval,
-
-		/// <summary>
-		///     Engine speed [1/min].
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "n_eng_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_eng_avg,
-
-		/// <summary>
-		///     [Nm]	Engine torque.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "T_eng_fcmap [Nm]")] T_eng_fcmap,
-
-		/// <summary>
-		///     [Nm]	Full load torque
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "Tq_full [Nm]")] Tq_full,
-
-		/// <summary>
-		///     [Nm]	Motoring torque
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "Tq_drag [Nm]")] Tq_drag,
-
-		/// <summary>
-		///     [kW]	Engine power.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_eng_out [kW]", outputFactor: 1e-3)] P_eng_out,
-
-		/// <summary>
-		///     [kW]	Engine full load power.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_eng_full [kW]", outputFactor: 1e-3)] P_eng_full,
-
-		/// <summary>
-		///     [kW]	Engine drag power.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_eng_drag [kW]", outputFactor: 1e-3)] P_eng_drag,
-
-		/// <summary>
-		///     [kW]	Engine power at clutch (equals Pe minus loss due to rotational inertia Pa Eng).
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_clutch_out [kW]", outputFactor: 1e-3)] P_clutch_out,
-
-		/// <summary>
-		///     [kW]	Rotational acceleration power: Engine.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "P_eng_inertia", caption: "P_eng_inertia [kW]", outputFactor: 1e-3)] P_eng_inertia,
-
-		/// <summary>
-		///     [kW]	Total auxiliary power demand .
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_aux [kW]", outputFactor: 1e-3)] P_aux,
-
-		/// <summary>
-		/// [g/h] Fuel consumption from FC map..
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "FC-Map", caption: "FC-Map [g/h]", outputFactor: 3600 * 1000)] FCMap,
-
-		/// <summary>
-		/// [g/h] Fuel consumption after Auxiliary-Start/Stop Correction. (Based on FC.)
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "FC-AUXc", caption: "FC-AUXc [g/h]", outputFactor: 3600 * 1000)] FCAUXc,
-
-		/// <summary>
-		/// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.)
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "FC-WHTCc", caption: "FC-WHTCc [g/h]", outputFactor: 3600 * 1000)] FCWHTCc,
-
-		/// <summary>
-		/// [g/h] Fuel consumption after smart auxiliary correction.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "FC-AAUX", caption: "FC-AAUX [g/h]", outputFactor: 3600 * 1000)] FCAAUX,
-
-		/// <summary>
-		/// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.)
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "FC-Final", caption: "FC-Final [g/h]", outputFactor: 3600 * 1000)] FCFinal,
-
-		/// <summary>
-		///     [km]	Travelled distance.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "dist [m]")] dist,
-
-		/// <summary>
-		///     [km/h]	Actual vehicle speed.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "v_act [km/h]", outputFactor: 3.6)] v_act,
-
-		/// <summary>
-		///     [km/h]	Target vehicle speed.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "v_targ [km/h]", outputFactor: 3.6)] v_targ,
-
-		/// <summary>
-		///     [m/s2]	Vehicle acceleration.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "acc [m/s^2]")] acc,
-
-		/// <summary>
-		///     [%]	    Road gradient.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "grad [%]")] grad,
-
-		/// <summary>
-		///     [-]	 GearData. "0" = clutch opened / neutral. "0.5" = lock-up clutch is open (AT with torque converter only, see
-		///     Gearbox)
-		/// </summary>
-		[ModalResultField(typeof(uint), caption: "Gear [-]")] Gear,
-
-		[ModalResultField(typeof(SI), caption: "n_gbx_out_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_gbx_out_avg,
-
-		[ModalResultField(typeof(SI), caption: "T_gbx_out [Nm]")] T_gbx_out,
-
-		/// <summary>
-		///     [kW]	Gearbox losses.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "P_gbx_loss", caption: "P_gbx_loss [kW]", outputFactor: 1e-3)] P_gbx_loss,
-
-		/// <summary>
-		///     [kW]	Losses in differential / axle transmission.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "Ploss Diff", caption: "P_axle_loss [kW]", outputFactor: 1e-3)] P_axle_loss,
-
-		/// <summary>
-		///     [kW]	Losses in angle transmission.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "Ploss Angle", caption: "P_angle_loss [kW]", outputFactor: 1e-3)] P_angle_loss,
-
-		/// <summary>
-		///     [kW]	Retarder losses.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "P_ret_loss", caption: "P_ret_loss [kW]", outputFactor: 1e-3)] P_ret_loss,
-
-		/// <summary>
-		///     [kW]	Rotational acceleration power: Gearbox.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "P_gbx_inertia", caption: "P_gbx_inertia [kW]", outputFactor: 1e-3)] P_gbx_inertia,
-
-		/// <summary>
-		///     [kW]	Vehicle acceleration power.
-		/// </summary>
-		[ModalResultField(typeof(SI), name: "P_veh_inertia", caption: "P_veh_inertia [kW]", outputFactor: 1e-3)] P_veh_inertia,
-
-		/// <summary>
-		///     [kW]	Rolling resistance power demand.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_roll [kW]", outputFactor: 1e-3)] P_roll,
-
-		/// <summary>
-		///     [kW]	Air resistance power demand.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_air [kW]", outputFactor: 1e-3)] P_air,
-
-		/// <summary>
-		///     [kW]	Power demand due to road gradient.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_slope [kW]", outputFactor: 1e-3)] P_slope,
-
-		/// <summary>
-		///     [kW]	Total power demand at wheel = sum of rolling, air, acceleration and road gradient resistance.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_wheel_in [kW]", outputFactor: 1e-3)] P_wheel_in,
-
-		/// <summary>
-		///     [kW]	Brake power. Drag power is included in Pe.
-		/// </summary>
-		[ModalResultField(typeof(SI), caption: "P_brake_loss [kW]", outputFactor: 1e-3)] P_brake_loss,
-
-		[ModalResultField(typeof(SI), caption: "P_wheel_inertia [kW]", outputFactor: 1e-3)] P_wheel_inertia,
-
-		[ModalResultField(typeof(SI), caption: "P_brake_in [kW]", outputFactor: 1e-3)] P_brake_in,
-
-		[ModalResultField(typeof(SI), caption: "P_axle_in [kW]", outputFactor: 1e-3)] P_axle_in,
-
-		[ModalResultField(typeof(SI), caption: "P_angle_in [kW]", outputFactor: 1e-3)] P_angle_in,
-
-		[ModalResultField(typeof(SI), caption: "P_ret_in [kW]", outputFactor: 1e-3)] P_retarder_in,
-
-		[ModalResultField(typeof(SI), caption: "P_gbx_in [kW]", outputFactor: 1e-3)] P_gbx_in,
-
-		[ModalResultField(typeof(SI), caption: "P_clutch_loss [kW]", outputFactor: 1e-3)] P_clutch_loss,
-
-		[ModalResultField(typeof(SI), caption: "P_trac [kW]", outputFactor: 1e-3)] P_trac,
-
-		[ModalResultField(typeof(SI), caption: "P_eng_fcmap [kW]", outputFactor: 1e-3)] P_eng_fcmap,
-
-		[ModalResultField(typeof(SI), caption: "P_eng_full_stat [kW]", outputFactor: 1e-3)] P_eng_full_stat,
-
-		/// <summary>
-		///     [kW]	Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle.
-		/// </summary>
-		[ModalResultField(typeof(SI), outputFactor: 1e-3)] P_aux_,
-
-		/// <summary>
-		///		[-]  true/false  indicate whether torque converter is locked or not (only applicable for gears with TC)
-		/// </summary>
-		[ModalResultField(typeof(int), caption: "TC locked")] TC_Locked,
-
-		/// <summary>
-		///     [-]	    Torque converter speed ratio
-		/// </summary>
-		[ModalResultField(typeof(double), name: "TCnu")] TorqueConverterSpeedRatio,
-
-		/// <summary>
-		///     [-]	    Torque converter torque ratio
-		/// </summary>
-		[ModalResultField(typeof(double), name: "TCmu")] TorqueConverterTorqueRatio,
-
-		[ModalResultField(typeof(SI), "P_TC_out [kW]", outputFactor: 1e-3)] P_TC_out,
-
-		/// <summary>
-		///     [kW]	Power loss at the torque converter.
-		/// </summary>
-		[ModalResultField(typeof(SI), "P_TC_loss [kW]", outputFactor: 1e-3)] P_TC_loss,
-
-		/// <summary>
-		///     [Nm]	Torque converter output torque
-		/// </summary>
-		[ModalResultField(typeof(SI), "T_TC_out")] TC_TorqueOut,
-
-		/// <summary>
-		///     [1/min]	Torque converter output speed
-		/// </summary>
-		[ModalResultField(typeof(SI), "n_TC_out", outputFactor: 60 / (2 * Math.PI))] TC_angularSpeedOut,
-
-		/// <summary>
-		///     [Nm]	Torque converter output torque
-		/// </summary>
-		[ModalResultField(typeof(SI), "T_TC_in")] TC_TorqueIn,
-
-		/// <summary>
-		///     [1/min]	Torque converter output speed
-		/// </summary>
-		[ModalResultField(typeof(SI), "n_TC_in", outputFactor: 60 / (2 * Math.PI))] TC_angularSpeedIn,
-
-		/// <summary>
-		///     [m]	Altitude
-		/// </summary>
-		[ModalResultField(typeof(SI))] altitude,
-
-		[ModalResultField(typeof(SI), name: "ds [m]")] simulationDistance,
-
-		[ModalResultField(typeof(double), caption: "AA_NonSmartAlternatorsEfficiency [%]")] AA_NonSmartAlternatorsEfficiency,
-		[ModalResultField(typeof(SI), caption: "AA_SmartIdleCurrent_Amps [A]")] AA_SmartIdleCurrent_Amps,
-		[ModalResultField(typeof(double), caption: "AA_SmartIdleAlternatorsEfficiency [%]")] AA_SmartIdleAlternatorsEfficiency,
-		[ModalResultField(typeof(SI), caption: "AA_SmartTractionCurrent_Amps [A]")] AA_SmartTractionCurrent_Amps,
-		[ModalResultField(typeof(double), caption: "AA_SmartTractionAlternatorEfficiency [%]")] AA_SmartTractionAlternatorEfficiency,
-		[ModalResultField(typeof(SI), caption: "AA_SmartOverrunCurrent_Amps [A]")] AA_SmartOverrunCurrent_Amps,
-		[ModalResultField(typeof(double), caption: "AA_SmartOverrunAlternatorEfficiency [%]")] AA_SmartOverrunAlternatorEfficiency,
-		[ModalResultField(typeof(SI), caption: "AA_CompressorFlowRate_LitrePerSec [Ni L/s]")] AA_CompressorFlowRate_LitrePerSec,
-		[ModalResultField(typeof(int), caption: "AA_OverrunFlag [bool]")] AA_OverrunFlag,
-		[ModalResultField(typeof(int), caption: "AA_EngineIdleFlag [bool]")] AA_EngineIdleFlag,
-		[ModalResultField(typeof(int), caption: "AA_CompressorFlag [bool]")] AA_CompressorFlag,
-		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFC_Grams [g]", outputFactor: 1000)] AA_TotalCycleFC_Grams,
-		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFC_Litres [l]")] AA_TotalCycleFC_Litres,
-		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankHVACMechanicals [W]")] AA_AveragePowerDemandCrankHVACMechanicals,
-		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankHVACElectricals [W]")] AA_AveragePowerDemandCrankHVACElectricals,
-		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankElectrics [W]")] AA_AveragePowerDemandCrankElectrics,
-		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankPneumatics [W]")] AA_AveragePowerDemandCrankPneumatics,
-		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFuelConsumptionCompressorOff [g]", outputFactor: 1000)] AA_TotalCycleFuelConsumptionCompressorOff,
-		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFuelConsumptionCompressorOn [g]", outputFactor: 1000)] AA_TotalCycleFuelConsumptionCompressorOn,
-	}
-
-	[AttributeUsage(AttributeTargets.Field)]
-	public class ModalResultFieldAttribute : Attribute
-	{
-		internal ModalResultFieldAttribute(Type dataType, string name = null, string caption = null, uint decimals = 4,
-			double outputFactor = 1, bool showUnit = false)
-		{
-			DataType = dataType;
-			Name = name;
-			Caption = caption;
-			Decimals = decimals;
-			OutputFactor = outputFactor;
-			ShowUnit = showUnit;
-		}
-
-		public bool ShowUnit { get; private set; }
-		public double OutputFactor { get; private set; }
-		public uint Decimals { get; private set; }
-		public Type DataType { get; private set; }
-		public string Name { get; private set; }
-		public string Caption { get; private set; }
-	}
-
-	public static class ModalResultFieldExtensionMethods
-	{
-		public static string GetName(this ModalResultField field)
-		{
-			return GetAttribute(field).Name ?? field.ToString();
-		}
-
-		public static string GetCaption(this ModalResultField field)
-		{
-			return GetAttribute(field).Caption ?? GetAttribute(field).Name ?? field.ToString();
-		}
-
-		public static string GetShortCaption(this ModalResultField field)
-		{
-			var caption = GetCaption(field);
-			return Regex.Replace(caption, @"\[.*?\]|\<|\>", "").Trim();
-		}
-
-		public static ModalResultFieldAttribute GetAttribute(this ModalResultField field)
-		{
-			return (ModalResultFieldAttribute)Attribute.GetCustomAttribute(ForValue(field), typeof(ModalResultFieldAttribute));
-		}
-
-		private static MemberInfo ForValue(ModalResultField field)
-		{
-			return typeof(ModalResultField).GetField(Enum.GetName(typeof(ModalResultField), field));
-		}
-	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
new file mode 100644
index 0000000000..bc408df103
--- /dev/null
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
@@ -0,0 +1,339 @@
+using System;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using TUGraz.VectoCommon.Utils;
+
+namespace TUGraz.VectoCore.Models.Simulation.Data
+{
+	/// <summary>
+	///     Enum with field definitions of the Modal Results File (.vmod).
+	/// </summary>
+	public enum ModalResultField
+	{
+		/// <summary>
+		///     Time step [s].
+		///     Midpoint of the simulated interval.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "time [s]")] time,
+
+		/// <summary>
+		///     Simulation interval around the current time step. [s]
+		/// </summary>
+		[ModalResultField(typeof(SI), "simulation_interval", "dt [s]")] simulationInterval,
+
+		/// <summary>
+		///     Engine speed [1/min].
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "n_eng_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_eng_avg,
+
+		/// <summary>
+		///     [Nm]	Engine torque.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "T_eng_fcmap [Nm]")] T_eng_fcmap,
+
+		/// <summary>
+		///     [Nm]	Full load torque
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "Tq_full [Nm]")] Tq_full,
+
+		/// <summary>
+		///     [Nm]	Motoring torque
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "Tq_drag [Nm]")] Tq_drag,
+
+		/// <summary>
+		///     [kW]	Engine power.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_eng_out [kW]", outputFactor: 1e-3)] P_eng_out,
+
+		/// <summary>
+		///     [kW]	Engine full load power.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_eng_full [kW]", outputFactor: 1e-3)] P_eng_full,
+
+		/// <summary>
+		///     [kW]	Engine drag power.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_eng_drag [kW]", outputFactor: 1e-3)] P_eng_drag,
+
+		/// <summary>
+		///     [kW]	Engine power at clutch (equals Pe minus loss due to rotational inertia Pa Eng).
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_clutch_out [kW]", outputFactor: 1e-3)] P_clutch_out,
+
+		/// <summary>
+		///     [kW]	Rotational acceleration power: Engine.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "P_eng_inertia", caption: "P_eng_inertia [kW]", outputFactor: 1e-3)] P_eng_inertia,
+
+		/// <summary>
+		///     [kW]	Total auxiliary power demand .
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_aux [kW]", outputFactor: 1e-3)] P_aux,
+
+		/// <summary>
+		/// [g/h] Fuel consumption from FC map..
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "FC-Map", caption: "FC-Map [g/h]", outputFactor: 3600 * 1000)] FCMap,
+
+		/// <summary>
+		/// [g/h] Fuel consumption after Auxiliary-Start/Stop Correction. (Based on FC.)
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "FC-AUXc", caption: "FC-AUXc [g/h]", outputFactor: 3600 * 1000)] FCAUXc,
+
+		/// <summary>
+		/// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.)
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "FC-WHTCc", caption: "FC-WHTCc [g/h]", outputFactor: 3600 * 1000)] FCWHTCc,
+
+		/// <summary>
+		/// [g/h] Fuel consumption after smart auxiliary correction.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "FC-AAUX", caption: "FC-AAUX [g/h]", outputFactor: 3600 * 1000)] FCAAUX,
+
+		/// <summary>
+		/// [g/h] Fuel consumption after WHTC Correction. (Based on FC-AUXc.)
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "FC-Final", caption: "FC-Final [g/h]", outputFactor: 3600 * 1000)] FCFinal,
+
+		/// <summary>
+		///     [km]	Travelled distance.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "dist [m]")] dist,
+
+		/// <summary>
+		///     [km/h]	Actual vehicle speed.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "v_act [km/h]", outputFactor: 3.6)] v_act,
+
+		/// <summary>
+		///     [km/h]	Target vehicle speed.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "v_targ [km/h]", outputFactor: 3.6)] v_targ,
+
+		/// <summary>
+		///     [m/s2]	Vehicle acceleration.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "acc [m/s^2]")] acc,
+
+		/// <summary>
+		///     [%]	    Road gradient.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "grad [%]")] grad,
+
+		/// <summary>
+		///     [-]	 GearData. "0" = clutch opened / neutral. "0.5" = lock-up clutch is open (AT with torque converter only, see
+		///     Gearbox)
+		/// </summary>
+		[ModalResultField(typeof(uint), caption: "Gear [-]")] Gear,
+
+		[ModalResultField(typeof(SI), caption: "n_gbx_out_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_gbx_out_avg,
+
+		[ModalResultField(typeof(SI), caption: "T_gbx_out [Nm]")] T_gbx_out,
+
+		/// <summary>
+		///     [kW]	Gearbox losses.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "P_gbx_loss", caption: "P_gbx_loss [kW]", outputFactor: 1e-3)] P_gbx_loss,
+
+		/// <summary>
+		///     [kW]	Losses in differential / axle transmission.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "Ploss Diff", caption: "P_axle_loss [kW]", outputFactor: 1e-3)] P_axle_loss,
+
+		/// <summary>
+		///     [kW]	Losses in angle transmission.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "Ploss Angle", caption: "P_angle_loss [kW]", outputFactor: 1e-3)] P_angle_loss,
+
+		/// <summary>
+		///     [kW]	Retarder losses.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "P_ret_loss", caption: "P_ret_loss [kW]", outputFactor: 1e-3)] P_ret_loss,
+
+		/// <summary>
+		///     [kW]	Rotational acceleration power: Gearbox.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "P_gbx_inertia", caption: "P_gbx_inertia [kW]", outputFactor: 1e-3)] P_gbx_inertia,
+
+		/// <summary>
+		///     [kW]	Vehicle acceleration power.
+		/// </summary>
+		[ModalResultField(typeof(SI), name: "P_veh_inertia", caption: "P_veh_inertia [kW]", outputFactor: 1e-3)] P_veh_inertia,
+
+		/// <summary>
+		///     [kW]	Rolling resistance power demand.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_roll [kW]", outputFactor: 1e-3)] P_roll,
+
+		/// <summary>
+		///     [kW]	Air resistance power demand.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_air [kW]", outputFactor: 1e-3)] P_air,
+
+		/// <summary>
+		///     [kW]	Power demand due to road gradient.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_slope [kW]", outputFactor: 1e-3)] P_slope,
+
+		/// <summary>
+		///     [kW]	Total power demand at wheel = sum of rolling, air, acceleration and road gradient resistance.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_wheel_in [kW]", outputFactor: 1e-3)] P_wheel_in,
+
+		/// <summary>
+		///     [kW]	Brake power. Drag power is included in Pe.
+		/// </summary>
+		[ModalResultField(typeof(SI), caption: "P_brake_loss [kW]", outputFactor: 1e-3)] P_brake_loss,
+
+		[ModalResultField(typeof(SI), caption: "P_wheel_inertia [kW]", outputFactor: 1e-3)] P_wheel_inertia,
+
+		[ModalResultField(typeof(SI), caption: "P_brake_in [kW]", outputFactor: 1e-3)] P_brake_in,
+
+		[ModalResultField(typeof(SI), caption: "P_axle_in [kW]", outputFactor: 1e-3)] P_axle_in,
+
+		[ModalResultField(typeof(SI), caption: "P_angle_in [kW]", outputFactor: 1e-3)] P_angle_in,
+
+		[ModalResultField(typeof(SI), caption: "P_ret_in [kW]", outputFactor: 1e-3)] P_retarder_in,
+
+		[ModalResultField(typeof(SI), caption: "P_gbx_in [kW]", outputFactor: 1e-3)] P_gbx_in,
+
+		[ModalResultField(typeof(SI), caption: "P_clutch_loss [kW]", outputFactor: 1e-3)] P_clutch_loss,
+
+		[ModalResultField(typeof(SI), caption: "P_trac [kW]", outputFactor: 1e-3)] P_trac,
+
+		[ModalResultField(typeof(SI), caption: "P_eng_fcmap [kW]", outputFactor: 1e-3)] P_eng_fcmap,
+
+		[ModalResultField(typeof(SI), caption: "P_eng_full_stat [kW]", outputFactor: 1e-3)] P_eng_full_stat,
+
+		/// <summary>
+		///     [kW]	Power demand of Auxiliary with ID xxx. See also Aux Dialog and Driving Cycle.
+		/// </summary>
+		[ModalResultField(typeof(SI), outputFactor: 1e-3)] P_aux_,
+
+		/// <summary>
+		///		[-]  true/false  indicate whether torque converter is locked or not (only applicable for gears with TC)
+		/// </summary>
+		[ModalResultField(typeof(int), caption: "TC locked")] TC_Locked,
+
+		/// <summary>
+		///     [-]	    Torque converter speed ratio
+		/// </summary>
+		[ModalResultField(typeof(double), name: "TCnu")] TorqueConverterSpeedRatio,
+
+		/// <summary>
+		///     [-]	    Torque converter torque ratio
+		/// </summary>
+		[ModalResultField(typeof(double), name: "TCmu")] TorqueConverterTorqueRatio,
+
+		[ModalResultField(typeof(SI), "P_TC_out [kW]", outputFactor: 1e-3)] P_TC_out,
+
+		/// <summary>
+		///     [kW]	Power loss at the torque converter.
+		/// </summary>
+		[ModalResultField(typeof(SI), "P_TC_loss [kW]", outputFactor: 1e-3)] P_TC_loss,
+
+		/// <summary>
+		///     [Nm]	Torque converter output torque
+		/// </summary>
+		[ModalResultField(typeof(SI), "T_TC_out")] TC_TorqueOut,
+
+		/// <summary>
+		///     [1/min]	Torque converter output speed
+		/// </summary>
+		[ModalResultField(typeof(SI), "n_TC_out", outputFactor: 60 / (2 * Math.PI))] TC_angularSpeedOut,
+
+		/// <summary>
+		///     [Nm]	Torque converter output torque
+		/// </summary>
+		[ModalResultField(typeof(SI), "T_TC_in")] TC_TorqueIn,
+
+		/// <summary>
+		///     [1/min]	Torque converter output speed
+		/// </summary>
+		[ModalResultField(typeof(SI), "n_TC_in", outputFactor: 60 / (2 * Math.PI))] TC_angularSpeedIn,
+
+		/// <summary>
+		///     [m]	Altitude
+		/// </summary>
+		[ModalResultField(typeof(SI))] altitude,
+
+		[ModalResultField(typeof(SI), name: "ds [m]")] simulationDistance,
+
+		[ModalResultField(typeof(double), caption: "AA_NonSmartAlternatorsEfficiency [%]")] AA_NonSmartAlternatorsEfficiency,
+		[ModalResultField(typeof(SI), caption: "AA_SmartIdleCurrent_Amps [A]")] AA_SmartIdleCurrent_Amps,
+		[ModalResultField(typeof(double), caption: "AA_SmartIdleAlternatorsEfficiency [%]")] AA_SmartIdleAlternatorsEfficiency,
+		[ModalResultField(typeof(SI), caption: "AA_SmartTractionCurrent_Amps [A]")] AA_SmartTractionCurrent_Amps,
+		[ModalResultField(typeof(double), caption: "AA_SmartTractionAlternatorEfficiency [%]")] AA_SmartTractionAlternatorEfficiency,
+		[ModalResultField(typeof(SI), caption: "AA_SmartOverrunCurrent_Amps [A]")] AA_SmartOverrunCurrent_Amps,
+		[ModalResultField(typeof(double), caption: "AA_SmartOverrunAlternatorEfficiency [%]")] AA_SmartOverrunAlternatorEfficiency,
+		[ModalResultField(typeof(SI), caption: "AA_CompressorFlowRate_LitrePerSec [Ni L/s]")] AA_CompressorFlowRate_LitrePerSec,
+		[ModalResultField(typeof(int), caption: "AA_OverrunFlag [bool]")] AA_OverrunFlag,
+		[ModalResultField(typeof(int), caption: "AA_EngineIdleFlag [bool]")] AA_EngineIdleFlag,
+		[ModalResultField(typeof(int), caption: "AA_CompressorFlag [bool]")] AA_CompressorFlag,
+		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFC_Grams [g]", outputFactor: 1000)] AA_TotalCycleFC_Grams,
+		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFC_Litres [l]")] AA_TotalCycleFC_Litres,
+		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankHVACMechanicals [W]")] AA_AveragePowerDemandCrankHVACMechanicals,
+		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankHVACElectricals [W]")] AA_AveragePowerDemandCrankHVACElectricals,
+		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankElectrics [W]")] AA_AveragePowerDemandCrankElectrics,
+		[ModalResultField(typeof(SI), caption: "AA_AveragePowerDemandCrankPneumatics [W]")] AA_AveragePowerDemandCrankPneumatics,
+		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFuelConsumptionCompressorOff [g]", outputFactor: 1000)] AA_TotalCycleFuelConsumptionCompressorOff,
+		[ModalResultField(typeof(SI), caption: "AA_TotalCycleFuelConsumptionCompressorOn [g]", outputFactor: 1000)] AA_TotalCycleFuelConsumptionCompressorOn,
+	}
+
+	[AttributeUsage(AttributeTargets.Field)]
+	public class ModalResultFieldAttribute : Attribute
+	{
+		internal ModalResultFieldAttribute(Type dataType, string name = null, string caption = null, uint decimals = 4,
+			double outputFactor = 1, bool showUnit = false)
+		{
+			DataType = dataType;
+			Name = name;
+			Caption = caption;
+			Decimals = decimals;
+			OutputFactor = outputFactor;
+			ShowUnit = showUnit;
+		}
+
+		public bool ShowUnit { get; private set; }
+		public double OutputFactor { get; private set; }
+		public uint Decimals { get; private set; }
+		public Type DataType { get; private set; }
+		public string Name { get; private set; }
+		public string Caption { get; private set; }
+	}
+
+	public static class ModalResultFieldExtensionMethods
+	{
+		public static string GetName(this ModalResultField field)
+		{
+			return GetAttribute(field).Name ?? field.ToString();
+		}
+
+		public static string GetCaption(this ModalResultField field)
+		{
+			return GetAttribute(field).Caption ?? GetAttribute(field).Name ?? field.ToString();
+		}
+
+		public static string GetShortCaption(this ModalResultField field)
+		{
+			var caption = GetCaption(field);
+			return Regex.Replace(caption, @"\[.*?\]|\<|\>", "").Trim();
+		}
+
+		public static Type GetDataType(this ModalResultField field)
+		{
+			return GetAttribute(field).DataType;
+		}
+
+		public static ModalResultFieldAttribute GetAttribute(this ModalResultField field)
+		{
+			return (ModalResultFieldAttribute)Attribute.GetCustomAttribute(ForValue(field), typeof(ModalResultFieldAttribute));
+		}
+
+		private static MemberInfo ForValue(ModalResultField field)
+		{
+			return typeof(ModalResultField).GetField(Enum.GetName(typeof(ModalResultField), field));
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/ModFilter/ModalData1HzFilter.cs b/VectoCore/VectoCore/OutputData/ModFilter/ModalData1HzFilter.cs
new file mode 100644
index 0000000000..73b5cde315
--- /dev/null
+++ b/VectoCore/VectoCore/OutputData/ModFilter/ModalData1HzFilter.cs
@@ -0,0 +1,197 @@
+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.Models.Simulation.Data;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.OutputData.ModFilter
+{
+	public class ModalData1HzFilter : IModalDataFilter
+	{
+		public ModalResults Filter(ModalResults data)
+		{
+			var results = (ModalResults)data.Clone();
+
+			object[] remainingRow = null;
+			var gearsList = new Dictionary<object, Second>(3);
+
+			var absTime = 0.SI<Second>();
+			var distance = 0.SI<Meter>();
+			var v = data.Rows[0].Field<MeterPerSecond>((int)ModalResultField.v_act);
+			var remainingDt = 0.SI<Second>();
+			var vPrevious = v;
+
+			for (var i = 0; i < data.Rows.Count; i++) {
+				var row = data.Rows[i];
+
+				var currentDt = row.Field<Second>((int)ModalResultField.simulationInterval);
+
+				if (row.Field<Meter>((int)ModalResultField.dist).IsSmaller(distance, 1e-3)) {
+					LogManager.GetLogger(typeof(ModalData1HzFilter).FullName).Error("1Hz-Filter: distance must always be increasing.");
+				}
+
+				// if a remainder and currentDt would exceed 1 second: take remainder and take current row to fill up to 1 second.
+				if (remainingDt > 0 && remainingDt + currentDt >= 1) {
+					// calculate values
+					var dt = 1.SI<Second>() - remainingDt;
+					var gear = row[(int)ModalResultField.Gear];
+					gearsList[gear] = gearsList.GetValueOrZero(gear) + dt;
+					var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
+					var ds = dt * v + a / 2 * dt * dt;
+					if (ds.IsSmaller(0)) {
+						throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
+					}
+					absTime += dt;
+					v += dt * a;
+					distance += ds;
+
+					// write a new row for the combined 1 second
+					var r = results.NewRow();
+					r.ItemArray = AddRow(remainingRow, MultiplyRow(row.ItemArray, dt));
+					r[(int)ModalResultField.time] = absTime;
+					r[(int)ModalResultField.simulationInterval] = 1.SI<Second>();
+					r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key;
+					r[(int)ModalResultField.dist] = distance;
+					r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
+					vPrevious = v;
+					results.Rows.Add(r);
+
+					// reset remainder
+					// reduce current dt by already taken diff
+					gearsList.Clear();
+					currentDt -= dt;
+					remainingDt = 0.SI<Second>();
+					remainingRow = null;
+				}
+
+				// if current row still longer than 1 second: split it to 1 second slices until it is < 1 second
+				while (currentDt >= 1) {
+					// calculate values
+					var dt = 1.SI<Second>();
+					currentDt = currentDt - 1.SI<Second>();
+					var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
+					var ds = v * dt + a / 2 * dt * dt;
+					if (ds.IsSmaller(0)) {
+						throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
+					}
+					absTime += dt;
+					v += a * dt;
+					distance += ds;
+
+					// write a new row for the sliced 1 second
+					var r = results.NewRow();
+					r.ItemArray = row.ItemArray;
+					r[(int)ModalResultField.time] = absTime;
+					r[(int)ModalResultField.simulationInterval] = dt;
+					r[(int)ModalResultField.dist] = distance;
+					r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
+					vPrevious = v;
+					results.Rows.Add(r);
+				}
+
+				// if there still is something left in current row: add to weighted values to remainder
+				if (currentDt > 0) {
+					// calculate values
+					var dt = currentDt;
+					var gear = row[(int)ModalResultField.Gear];
+					gearsList[gear] = gearsList.GetValueOrZero(gear) + dt;
+					var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
+					var ds = v * dt + a / 2 * dt * dt;
+					if (ds.IsSmaller(0)) {
+						throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
+					}
+					absTime += dt;
+					v += a * dt;
+					distance += ds;
+
+					// add to remainder
+					remainingRow = AddRow(remainingRow, MultiplyRow(row.ItemArray, dt));
+					remainingDt += dt;
+				} else {
+					// reset remainder (just to be sure!)
+					remainingRow = null;
+					remainingDt = 0.SI<Second>();
+					gearsList.Clear();
+				}
+			}
+
+			// if last row was not enough to full second: take last row as whole second
+			if (remainingDt > 0) {
+				// calculate values
+				var last = data.Rows.Cast<DataRow>().Last();
+				var dt = remainingDt;
+				var a = (MeterPerSquareSecond)last[(int)ModalResultField.acc];
+				var ds = v * dt + a / 2 * dt * dt;
+				if (ds.IsSmaller(0)) {
+					throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
+				}
+				v += a * dt;
+				distance += ds;
+
+				// write a new row for the last second
+				var r = results.NewRow();
+				r.ItemArray = MultiplyRow(remainingRow, 1 / dt).ToArray();
+				r[(int)ModalResultField.time] = VectoMath.Ceiling(absTime);
+				r[(int)ModalResultField.simulationInterval] = 1.SI<Second>();
+				r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key;
+				r[(int)ModalResultField.dist] = distance;
+				r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
+				results.Rows.Add(r);
+			}
+
+			return results;
+		}
+
+		private static IEnumerable<object> MultiplyRow(IEnumerable<object> row, SI dt)
+		{
+			return row.Select(val => {
+				if (val is SI) {
+					val = (SI)val * dt.Value();
+				} else {
+					val.Switch()
+						.Case<int>(i => val = i * dt.Value())
+						.Case<double>(d => val = d * dt.Value())
+						.Case<float>(f => val = f * dt.Value())
+						.Case<uint>(ui => val = ui * dt.Value());
+				}
+				return val;
+			});
+		}
+
+		private static object[] AddRow(IEnumerable<object> row, IEnumerable<object> addRow)
+		{
+			if (row == null) {
+				return addRow.ToArray();
+			}
+			if (addRow == null) {
+				return row.ToArray();
+			}
+
+			return row.ZipAll(addRow, (val, addVal) => {
+				if (val is SI || addVal is SI) {
+					if (DBNull.Value == val) {
+						val = addVal;
+					} else if (DBNull.Value != addVal) {
+						val = (SI)val + (SI)addVal;
+					}
+				} else {
+					val.Switch()
+						.Case<int>(i => val = i + (int)addVal)
+						.Case<double>(d => val = d + (double)addVal)
+						.Case<float>(f => val = f + (float)addVal)
+						.Case<uint>(ui => val = ui + (uint)addVal);
+				}
+				return val;
+			}).ToArray();
+		}
+
+		public string ID
+		{
+			get { return "1Hz"; }
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
index 3b37f42b16..bfcbf49898 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
@@ -35,12 +35,9 @@ using System.Data;
 using System.Globalization;
 using System.Linq;
 using System.Runtime.CompilerServices;
-using TUGraz.VectoCommon.Exceptions;
-using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
-using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.OutputData
 {
@@ -302,190 +299,5 @@ namespace TUGraz.VectoCore.OutputData
 				Auxiliaries[id] = col;
 			}
 		}
-
-		public class ModalData1HzFilter : IModalDataFilter
-		{
-			public ModalResults Filter(ModalResults data)
-			{
-				var results = (ModalResults)data.Clone();
-
-				object[] remainingRow = null;
-				var gearsList = new Dictionary<object, Second>(3);
-
-				var absTime = 0.SI<Second>();
-				var distance = 0.SI<Meter>();
-				var v = data.Rows[0].Field<MeterPerSecond>((int)ModalResultField.v_act);
-				var remainingDt = 0.SI<Second>();
-				var vPrevious = v;
-
-				for (var i = 0; i < data.Rows.Count; i++) {
-					var row = data.Rows[i];
-
-					var currentDt = row.Field<Second>((int)ModalResultField.simulationInterval);
-
-					if (row.Field<Meter>((int)ModalResultField.dist).IsSmaller(distance, 1e-3)) {
-						LogManager.GetLogger(typeof(ModalData1HzFilter).FullName).Error("1Hz-Filter: distance must always be increasing.");
-					}
-
-					// if a remainder and currentDt would exceed 1 second: take remainder and take current row to fill up to 1 second.
-					if (remainingDt > 0 && remainingDt + currentDt >= 1) {
-						// calculate values
-						var dt = 1.SI<Second>() - remainingDt;
-						var gear = row[(int)ModalResultField.Gear];
-						gearsList[gear] = gearsList.GetValueOrZero(gear) + dt;
-						var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
-						var ds = dt * v + a / 2 * dt * dt;
-						if (ds.IsSmaller(0)) {
-							throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
-						}
-						absTime += dt;
-						v += dt * a;
-						distance += ds;
-
-						// write a new row for the combined 1 second
-						var r = results.NewRow();
-						r.ItemArray = AddRow(remainingRow, MultiplyRow(row.ItemArray, dt));
-						r[(int)ModalResultField.time] = absTime;
-						r[(int)ModalResultField.simulationInterval] = 1.SI<Second>();
-						r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key;
-						r[(int)ModalResultField.dist] = distance;
-						r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
-						vPrevious = v;
-						results.Rows.Add(r);
-
-						// reset remainder
-						// reduce current dt by already taken diff
-						gearsList.Clear();
-						currentDt -= dt;
-						remainingDt = 0.SI<Second>();
-						remainingRow = null;
-					}
-
-					// if current row still longer than 1 second: split it to 1 second slices until it is < 1 second
-					while (currentDt >= 1) {
-						// calculate values
-						var dt = 1.SI<Second>();
-						currentDt = currentDt - 1.SI<Second>();
-						var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
-						var ds = v * dt + a / 2 * dt * dt;
-						if (ds.IsSmaller(0)) {
-							throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
-						}
-						absTime += dt;
-						v += a * dt;
-						distance += ds;
-
-						// write a new row for the sliced 1 second
-						var r = results.NewRow();
-						r.ItemArray = row.ItemArray;
-						r[(int)ModalResultField.time] = absTime;
-						r[(int)ModalResultField.simulationInterval] = dt;
-						r[(int)ModalResultField.dist] = distance;
-						r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
-						vPrevious = v;
-						results.Rows.Add(r);
-					}
-
-					// if there still is something left in current row: add to weighted values to remainder
-					if (currentDt > 0) {
-						// calculate values
-						var dt = currentDt;
-						var gear = row[(int)ModalResultField.Gear];
-						gearsList[gear] = gearsList.GetValueOrZero(gear) + dt;
-						var a = (MeterPerSquareSecond)row[(int)ModalResultField.acc];
-						var ds = v * dt + a / 2 * dt * dt;
-						if (ds.IsSmaller(0)) {
-							throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
-						}
-						absTime += dt;
-						v += a * dt;
-						distance += ds;
-
-						// add to remainder
-						remainingRow = AddRow(remainingRow, MultiplyRow(row.ItemArray, dt));
-						remainingDt += dt;
-					} else {
-						// reset remainder (just to be sure!)
-						remainingRow = null;
-						remainingDt = 0.SI<Second>();
-						gearsList.Clear();
-					}
-				}
-
-				// if last row was not enough to full second: take last row as whole second
-				if (remainingDt > 0) {
-					// calculate values
-					var last = data.Rows.Cast<DataRow>().Last();
-					var dt = remainingDt;
-					var a = (MeterPerSquareSecond)last[(int)ModalResultField.acc];
-					var ds = v * dt + a / 2 * dt * dt;
-					if (ds.IsSmaller(0)) {
-						throw new VectoSimulationException("1Hz-Filter: simulation distance must not be negative.");
-					}
-					v += a * dt;
-					distance += ds;
-
-					// write a new row for the last second
-					var r = results.NewRow();
-					r.ItemArray = MultiplyRow(remainingRow, 1 / dt).ToArray();
-					r[(int)ModalResultField.time] = VectoMath.Ceiling(absTime);
-					r[(int)ModalResultField.simulationInterval] = 1.SI<Second>();
-					r[(int)ModalResultField.Gear] = gearsList.MaxBy(kv => kv.Value).Key;
-					r[(int)ModalResultField.dist] = distance;
-					r[(int)ModalResultField.v_act] = (v + vPrevious) / 2;
-					results.Rows.Add(r);
-				}
-
-				return results;
-			}
-
-			private static IEnumerable<object> MultiplyRow(IEnumerable<object> row, SI dt)
-			{
-				return row.Select(val => {
-					if (val is SI) {
-						val = (SI)val * dt.Value();
-					} else {
-						val.Switch()
-							.Case<int>(i => val = i * dt.Value())
-							.Case<double>(d => val = d * dt.Value())
-							.Case<float>(f => val = f * dt.Value())
-							.Case<uint>(ui => val = ui * dt.Value());
-					}
-					return val;
-				});
-			}
-
-			private static object[] AddRow(IEnumerable<object> row, IEnumerable<object> addRow)
-			{
-				if (row == null) {
-					return addRow.ToArray();
-				}
-				if (addRow == null) {
-					return row.ToArray();
-				}
-
-				return row.ZipAll(addRow, (val, addVal) => {
-					if (val is SI || addVal is SI) {
-						if (DBNull.Value == val) {
-							val = addVal;
-						} else if (DBNull.Value != addVal) {
-							val = (SI)val + (SI)addVal;
-						}
-					} else {
-						val.Switch()
-							.Case<int>(i => val = i + (int)addVal)
-							.Case<double>(d => val = d + (double)addVal)
-							.Case<float>(f => val = f + (float)addVal)
-							.Case<uint>(ui => val = ui + (uint)addVal);
-					}
-					return val;
-				}).ToArray();
-			}
-
-			public string ID
-			{
-				get { return "1Hz"; }
-			}
-		}
 	}
 }
\ No newline at end of file
-- 
GitLab