From c916ed2d87ed30db889170fc9df3c9645872df27 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Mon, 4 Jul 2022 07:56:03 +0200
Subject: [PATCH] refactoring sum-container to contain only availalbe component
 data

---
 .../Models/Simulation/Data/ModalResult.cs     |  22 +-
 .../OutputData/IModalDataContainer.cs         |   1 +
 .../OutputData/ModalDataContainer.cs          |   5 +
 .../VectoCore/OutputData/SumDataFields.cs     |   9 +-
 .../OutputData/SummaryDataContainer.cs        | 298 +++++++++++++++---
 .../Utils/MockModalDataContainer.cs           |   5 +
 6 files changed, 293 insertions(+), 47 deletions(-)

diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
index 6b984d0b34..94cb57ad78 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResult.cs
@@ -39,6 +39,7 @@ using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.Simulation.DataBus;
 using TUGraz.VectoCore.Models.SimulationComponent;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
 using TUGraz.VectoCore.Models.SimulationComponent.Impl;
@@ -287,6 +288,13 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			ModalResultField.MaxPropulsionTorqe
 		};
 
+		// ------------------------------------------------------------------------------------
+		public static readonly ModalResultField[] DCDCConverterSignals = {
+			ModalResultField.P_DCDC_In,
+			ModalResultField.P_DCDC_Out,
+			ModalResultField.P_DCDC_missing
+		};
+
 		protected internal readonly Dictionary<IFuelProperties, Dictionary<ModalResultField, DataColumn>> FuelColumns = new Dictionary<IFuelProperties, Dictionary<ModalResultField, DataColumn>>();
 
 		protected internal List<PowertrainPosition> ElectricMotors = new List<PowertrainPosition>();
@@ -304,8 +312,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 		protected void CreateColumns(ModalResultField[] columns, Func<ModalResultField, string> nameFunc = null, Func<ModalResultField, string> captionFunc = null)
 		{
 			foreach (var value in columns) {
-				var col = new DataColumn(nameFunc != null ? nameFunc(value) : value.GetName(),
-						value.GetAttribute().DataType)
+				var colName = nameFunc != null ? nameFunc(value) : value.GetName();
+				var col = new DataColumn(colName, value.GetAttribute().DataType)
 					{ Caption = captionFunc != null ? captionFunc(value) : value.GetCaption() };
 				col.ExtendedProperties[ExtendedPropertyNames.Decimals] = value.GetAttribute().Decimals;
 				col.ExtendedProperties[ExtendedPropertyNames.OutputFactor] = value.GetAttribute().OutputFactor;
@@ -317,7 +325,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 		public void RegisterComponent(VectoSimulationComponent component, VectoRunData runData)
 		{
 			switch (component) {
-				case ICombustionEngine c1: CreateCombustionEngineColumns(c1, runData); break;
+				case ICombustionEngine c1: CreateCombustionEngineColumns(runData); break;
 				case IClutch _:
 					CreateColumns(ClutchSignals);
 					break;
@@ -343,7 +351,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 				case IElectricMotor c4 when c4.Position != PowertrainPosition.IEPC:
 					CreateElectricMotorColumns(c4, runData, ElectricMotorSignals);
 					break;
-				case IElectricEnergyStorage c5 when c5 is BatterySystem: CreateBatteryColumns(c5, runData);
+				case IElectricEnergyStorage c5 when c5 is BatterySystem: CreateBatteryColumns(runData);
 					break;
 				case IElectricEnergyStorage _: CreateColumns(BatterySignals);
 					break;
@@ -351,10 +359,12 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 					break;
 				case IHybridController _: CreateColumns(HybridControllerSignals);
 					break;
+				case IDCDCConverter _: CreateColumns(DCDCConverterSignals);
+					break;
 			}
 		}
 
-		private void CreateBatteryColumns(IElectricEnergyStorage reess, VectoRunData vectoRunData)
+		private void CreateBatteryColumns(VectoRunData vectoRunData)
 		{
 			CreateColumns(BatterySignals);
 
@@ -390,7 +400,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			}
 		}
 
-		private void CreateCombustionEngineColumns(ICombustionEngine component, VectoRunData runData)
+		private void CreateCombustionEngineColumns(VectoRunData runData)
 		{
 			CreateColumns(CombustionEngineSignals);
 			if (runData.BusAuxiliaries != null) {
diff --git a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
index 16c627afea..bc603a90ab 100644
--- a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
@@ -149,6 +149,7 @@ namespace TUGraz.VectoCore.OutputData
 
 		ICorrectedModalData CorrectedModalData { get; }
 		void RegisterComponent(VectoSimulationComponent component);
+		bool ContainsColumn(string modalResultField);
 	}
 
 	public interface IModalDataPostProcessor
diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
index 87ba707ace..ed9bad665f 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
@@ -111,6 +111,11 @@ namespace TUGraz.VectoCore.OutputData
 			Data.RegisterComponent(component, _runData);
 		}
 
+		public bool ContainsColumn(string modalResultField)
+		{
+			return Data.Columns.Contains(modalResultField);
+		}
+
 		protected IModalDataPostProcessor GetModDataPostprocessor(VectoRunData runData)
 		{
 			switch (runData.JobType) {
diff --git a/VectoCore/VectoCore/OutputData/SumDataFields.cs b/VectoCore/VectoCore/OutputData/SumDataFields.cs
index 899402b3bf..30a6e31f38 100644
--- a/VectoCore/VectoCore/OutputData/SumDataFields.cs
+++ b/VectoCore/VectoCore/OutputData/SumDataFields.cs
@@ -1,4 +1,7 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using TUGraz.VectoCore.Models.Simulation.Data;
 
 namespace TUGraz.VectoCore.OutputData
 {
@@ -286,5 +289,9 @@ namespace TUGraz.VectoCore.OutputData
 		public const string E_IEPC_OFF_TIME_SHARE = "{0} off time share [%]";
 
 
+		public static readonly Dictionary<string, Tuple<ModalResultField[], Func<VectoRunData, IModalDataContainer, object>>> SumDataValue = new Dictionary<string, Tuple<ModalResultField[], Func<VectoRunData, IModalDataContainer, object>>>() {
+			{SumDataFields.ENGINE_MANUFACTURER, Tuple.Create<ModalResultField[], Func<VectoRunData, IModalDataContainer, object>>(null ,(r, m) => r.EngineData.Manufacturer)},
+			
+		};
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
index 244984a828..29b5e07fdb 100644
--- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs
@@ -43,6 +43,7 @@ using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.SimulationComponent;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Utils;
 
 // ReSharper disable MemberCanBePrivate.Global  -- used by API!
 
@@ -79,6 +80,33 @@ namespace TUGraz.VectoCore.OutputData
 			SumDataFields.SPECIFIC_FC, SumDataFields.K_VEHLINE, SumDataFields.K_ENGLINE
 		};
 
+		public static Tuple<string, Type>[] CommonColumns = {
+			Tuple.Create(SumDataFields.SORT, typeof(int)),
+			Tuple.Create(SumDataFields.JOB, typeof(string)),
+			Tuple.Create(SumDataFields.INPUTFILE, typeof(string)),
+			Tuple.Create(SumDataFields.CYCLE, typeof(string)),
+			Tuple.Create(SumDataFields.STATUS, typeof(string)),
+		};
+
+		public static Tuple<string, Type>[] CombustionEngineColumns = {
+			Tuple.Create(SumDataFields.ENGINE_MANUFACTURER, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_MODEL, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_FUEL_TYPE, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_RATED_POWER, typeof(ConvertedSI)),
+			Tuple.Create(SumDataFields.ENGINE_IDLING_SPEED, typeof(ConvertedSI)),
+			Tuple.Create(SumDataFields.ENGINE_RATED_SPEED, typeof(ConvertedSI)),
+			Tuple.Create(SumDataFields.ENGINE_DISPLACEMENT, typeof(ConvertedSI)),
+			Tuple.Create(SumDataFields.ENGINE_WHTC_URBAN, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_WHTC_RURAL, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_WHTC_MOTORWAY, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_BF_COLD_HOT, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_CF_REG_PER, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_ACTUAL_CORRECTION_FACTOR, typeof(string)),
+			Tuple.Create(SumDataFields.VEHICLE_FUEL_TYPE, typeof(string)),
+			Tuple.Create(SumDataFields.ENGINE_CERTIFICATION_NUMBER, typeof(string)),
+			Tuple.Create(SumDataFields.AVERAGE_ENGINE_EFFICIENCY, typeof(double)),
+		};
+
 		private object _tableLock = new object();
 		internal readonly DataTable Table;
 		private readonly ISummaryWriter _sumWriter;
@@ -93,12 +121,196 @@ namespace TUGraz.VectoCore.OutputData
 		{
 			_sumWriter = writer;
 			Table = new DataTable();
-			InitTableColumns();
+			//InitTableColumns();
+			CreateColumns(CommonColumns);
 		}
 
 		public void RegisterComponent(VectoSimulationComponent component)
 		{
+			switch (component) {
+				case ICombustionEngine _:
+					CreateColumns(CombustionEngineColumns);
+					break;
+			}
+		}
+
+		private void CreateColumns(Tuple<string, Type>[] cols)
+		{
+			lock (Table) {
+				Table.Columns.AddRange(cols.Where(x => !Table.Columns.Contains(x.Item1))
+					.Select(x => new DataColumn(x.Item1, x.Item2)).ToArray());
+			}
+		}
 
+		private IList<string> GetOutputColumnsOrdered()
+		{
+			var cols = new List<string>();
+			cols.AddRange(new[] {
+				SumDataFields.SORT,
+				SumDataFields.JOB,
+				SumDataFields.INPUTFILE,
+				SumDataFields.CYCLE,
+				SumDataFields.STATUS,
+				SumDataFields.VEHICLE_MANUFACTURER,
+				SumDataFields.VIN_NUMBER,
+				SumDataFields.VEHICLE_MODEL,
+				SumDataFields.HDV_CO2_VEHICLE_CLASS,
+				SumDataFields.CURB_MASS,
+				SumDataFields.LOADING,
+				SumDataFields.PassengerCount,
+				SumDataFields.TOTAL_VEHICLE_MASS,
+
+				SumDataFields.ENGINE_MANUFACTURER,
+				SumDataFields.ENGINE_MODEL,
+				SumDataFields.ENGINE_FUEL_TYPE,
+				SumDataFields.ENGINE_RATED_POWER,
+				SumDataFields.ENGINE_IDLING_SPEED,
+				SumDataFields.ENGINE_RATED_SPEED,
+				SumDataFields.ENGINE_DISPLACEMENT,
+				SumDataFields.ENGINE_WHTC_URBAN,
+				SumDataFields.ENGINE_WHTC_RURAL,
+				SumDataFields.ENGINE_WHTC_MOTORWAY,
+				SumDataFields.ENGINE_BF_COLD_HOT,
+				SumDataFields.ENGINE_CF_REG_PER,
+				SumDataFields.ENGINE_ACTUAL_CORRECTION_FACTOR,
+				SumDataFields.VEHICLE_FUEL_TYPE,
+
+				SumDataFields.AIRDRAG_MODEL,
+				SumDataFields.CD_x_A_DECLARED,
+				SumDataFields.CD_x_A,
+				SumDataFields.SLEEPER_CAB,
+				SumDataFields.DECLARED_RRC_AXLE1,
+				SumDataFields.DECLARED_FZISO_AXLE1,
+				SumDataFields.DECLARED_RRC_AXLE2,
+				SumDataFields.DECLARED_FZISO_AXLE2,
+				SumDataFields.DECLARED_RRC_AXLE3,
+				SumDataFields.DECLARED_FZISO_AXLE3,
+				SumDataFields.DECLARED_RRC_AXLE4,
+				SumDataFields.DECLARED_FZISO_AXLE4,
+				SumDataFields.ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER,
+				SumDataFields.ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER,
+				SumDataFields.R_DYN,
+				SumDataFields.NUM_AXLES_DRIVEN,
+				SumDataFields.NUM_AXLES_NON_DRIVEN,
+				SumDataFields.NUM_AXLES_TRAILER,
+				SumDataFields.GEARBOX_MANUFACTURER,
+				SumDataFields.GEARBOX_MODEL,
+				SumDataFields.GEARBOX_TYPE,
+				SumDataFields.GEAR_RATIO_FIRST_GEAR,
+				SumDataFields.GEAR_RATIO_LAST_GEAR,
+				SumDataFields.TORQUECONVERTER_MANUFACTURER,
+				SumDataFields.TORQUECONVERTER_MODEL,
+				SumDataFields.RETARDER_MANUFACTURER,
+				SumDataFields.RETARDER_MODEL,
+				SumDataFields.RETARDER_TYPE,
+				SumDataFields.ANGLEDRIVE_MANUFACTURER,
+				SumDataFields.ANGLEDRIVE_MODEL,
+				SumDataFields.ANGLEDRIVE_RATIO,
+				SumDataFields.AXLE_MANUFACTURER,
+				SumDataFields.AXLE_MODEL,
+				SumDataFields.AXLE_RATIO
+			});
+			cols.AddRange(new[] {
+				Constants.Auxiliaries.IDs.SteeringPump, Constants.Auxiliaries.IDs.Fan,
+				Constants.Auxiliaries.IDs.HeatingVentilationAirCondition,
+				Constants.Auxiliaries.IDs.PneumaticSystem, Constants.Auxiliaries.IDs.ElectricSystem
+			}.Select(x => string.Format(SumDataFields.AUX_TECH_FORMAT, x)));
+
+			cols.AddRange(new[] {
+				SumDataFields.TCU_MODEL, 
+				SumDataFields.ADAS_TECHNOLOGY_COMBINATION, 
+				SumDataFields.PTO_TECHNOLOGY, 
+				SumDataFields.REESS_CAPACITY,
+				SumDataFields.CARGO_VOLUME,
+				SumDataFields.TIME, 
+				SumDataFields.DISTANCE, 
+				SumDataFields.SPEED,
+				SumDataFields.ALTITUDE_DELTA,
+
+				SumDataFields.CO2_KM, 
+				SumDataFields.CO2_TKM, 
+				SumDataFields.CO2_M3KM, 
+				SumDataFields.CO2_PKM, 
+				SumDataFields.P_WHEEL,
+				SumDataFields.P_WHEEL_POS, 
+				SumDataFields.P_FCMAP, 
+				SumDataFields.P_FCMAP_POS,
+				SumDataFields.E_FCMAP_POS, 
+				SumDataFields.E_FCMAP_NEG, 
+				SumDataFields.E_POWERTRAIN_INERTIA, 
+				SumDataFields.E_AUX,
+				SumDataFields.E_AUX_EL_HV, 
+				SumDataFields.E_CLUTCH_LOSS,
+				SumDataFields.E_TC_LOSS, 
+				SumDataFields.E_SHIFT_LOSS, 
+				SumDataFields.E_GBX_LOSS, 
+				SumDataFields.E_RET_LOSS,
+				SumDataFields.E_ANGLE_LOSS,
+				SumDataFields.E_AXL_LOSS, 
+				SumDataFields.E_BRAKE, 
+				SumDataFields.E_VEHICLE_INERTIA, 
+				SumDataFields.E_WHEEL, 
+				SumDataFields.E_AIR,
+				SumDataFields.E_ROLL, 
+				SumDataFields.E_GRAD,
+				SumDataFields.AirConsumed, 
+				SumDataFields.AirGenerated, 
+				SumDataFields.E_PS_CompressorOff, 
+				SumDataFields.E_PS_CompressorOn,
+				SumDataFields.E_BusAux_ES_consumed, 
+				SumDataFields.E_BusAux_ES_generated, 
+				SumDataFields.Delta_E_BusAux_Battery,
+				SumDataFields.E_BusAux_PS_corr, 
+				SumDataFields.E_BusAux_ES_mech_corr,
+				SumDataFields.E_BusAux_HVAC_Mech, 
+				SumDataFields.E_BusAux_HVAC_El,
+				SumDataFields.E_BusAux_AuxHeater,
+				SumDataFields.E_WHR_EL, 
+				SumDataFields.E_WHR_MECH, 
+				SumDataFields.E_ICE_START, 
+				SumDataFields.E_AUX_ESS_missing,
+				SumDataFields.NUM_ICE_STARTS, 
+				SumDataFields.ACC,
+				SumDataFields.ACC_POS, 
+				SumDataFields.ACC_NEG, 
+				SumDataFields.ACC_TIMESHARE, 
+				SumDataFields.DEC_TIMESHARE,
+				SumDataFields.CRUISE_TIMESHARE,
+				SumDataFields.MAX_SPEED, 
+				SumDataFields.MAX_ACCELERATION, 
+				SumDataFields.MAX_DECELERATION, 
+				SumDataFields.AVG_ENGINE_SPEED,
+				SumDataFields.MAX_ENGINE_SPEED, 
+				SumDataFields.NUM_GEARSHIFTS, 
+				SumDataFields.STOP_TIMESHARE,
+				SumDataFields.ICE_FULL_LOAD_TIME_SHARE, 
+				SumDataFields.ICE_OFF_TIME_SHARE,
+				SumDataFields.COASTING_TIME_SHARE, 
+				SumDataFields.BRAKING_TIME_SHARE, 
+				SumDataFields.AVERAGE_POS_ACC,
+
+				SumDataFields.ENGINE_CERTIFICATION_NUMBER,
+				SumDataFields.AVERAGE_ENGINE_EFFICIENCY,
+				SumDataFields.TORQUE_CONVERTER_CERTIFICATION_METHOD, 
+				SumDataFields.TORQUE_CONVERTER_CERTIFICATION_NUMBER, 
+				SumDataFields.AVERAGE_TORQUE_CONVERTER_EFFICIENCY_WITHOUT_LOCKUP,
+				SumDataFields.AVERAGE_TORQUE_CONVERTER_EFFICIENCY_WITH_LOCKUP, 
+				SumDataFields.GEARBOX_CERTIFICATION_METHOD, 
+				SumDataFields.GEARBOX_CERTIFICATION_NUMBER, 
+				SumDataFields.AVERAGE_GEARBOX_EFFICIENCY, 
+				SumDataFields.RETARDER_CERTIFICATION_METHOD,
+				SumDataFields.RETARDER_CERTIFICATION_NUMBER, 
+				SumDataFields.ANGLEDRIVE_CERTIFICATION_METHOD, 
+				SumDataFields.ANGLEDRIVE_CERTIFICATION_NUMBER,
+				SumDataFields.AVERAGE_ANGLEDRIVE_EFFICIENCY,
+				SumDataFields.AXLEGEAR_CERTIFICATION_METHOD, 
+				SumDataFields.AXLEGEAR_CERTIFICATION_NUMBER, 
+				SumDataFields.AVERAGE_AXLEGEAR_EFFICIENCY, 
+				SumDataFields.AIRDRAG_CERTIFICATION_NUMBER,
+				SumDataFields.AIRDRAG_CERTIFICATION_METHOD, 
+			});
+
+			return cols.Where(x => Table.Columns.Contains(x)).ToArray();
 		}
 
 		private void InitTableColumns()
@@ -119,20 +331,7 @@ namespace TUGraz.VectoCore.OutputData
 						Tuple.Create(SumDataFields.LOADING, typeof(ConvertedSI)),
 						Tuple.Create(SumDataFields.PassengerCount, typeof(double)),
 						Tuple.Create(SumDataFields.TOTAL_VEHICLE_MASS, typeof(ConvertedSI)),
-						Tuple.Create(SumDataFields.ENGINE_MANUFACTURER, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_MODEL, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_FUEL_TYPE, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_RATED_POWER, typeof(ConvertedSI)),
-						Tuple.Create(SumDataFields.ENGINE_IDLING_SPEED, typeof(ConvertedSI)),
-						Tuple.Create(SumDataFields.ENGINE_RATED_SPEED, typeof(ConvertedSI)),
-						Tuple.Create(SumDataFields.ENGINE_DISPLACEMENT, typeof(ConvertedSI)),
-						Tuple.Create(SumDataFields.ENGINE_WHTC_URBAN, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_WHTC_RURAL, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_WHTC_MOTORWAY, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_BF_COLD_HOT, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_CF_REG_PER, typeof(string)),
-						Tuple.Create(SumDataFields.ENGINE_ACTUAL_CORRECTION_FACTOR, typeof(string)),
-						Tuple.Create(SumDataFields.VEHICLE_FUEL_TYPE, typeof(string)),
+						
 						Tuple.Create(SumDataFields.AIRDRAG_MODEL, typeof(string)),
 						Tuple.Create(SumDataFields.CD_x_A_DECLARED, typeof(ConvertedSI)),
 						Tuple.Create(SumDataFields.CD_x_A, typeof(ConvertedSI)),
@@ -249,29 +448,30 @@ namespace TUGraz.VectoCore.OutputData
 		{
 			if (_sumWriter != null) {
 				lock (Table) {
-					var view = new DataView(Table, "", SumDataFields.SORT, DataViewRowState.CurrentRows).ToTable();
-
-					var probablyEmptyCols = new[] { SumDataFields.E_WHEEL, SumDataFields.SPECIFIC_FC }.Select(x =>
-						x.Contains("{") ? x.Substring(0, x.IndexOf("{", StringComparison.Ordinal)) : x).ToArray();
-					var removeCandidates =
-						view.Columns.Cast<DataColumn>()
-							.Where(column => probablyEmptyCols.Any(x => column.ColumnName.StartsWith(x))).ToList();
-					var toRemove = new List<string>();
-					foreach (var column in removeCandidates) {
-						//var column = view.Columns[colName];
-						if (view.AsEnumerable().All(dr => dr.IsNull(column))) {
-							toRemove.Add(column.ColumnName);
-						}
-					}
-
-					toRemove = toRemove.Concat(
-						view.Columns.Cast<DataColumn>()
-							.Where(column => column.ColumnName.StartsWith(SumDataFields.INTERNAL_PREFIX))
-							.Select(x => x.ColumnName)).ToList();
-
-					foreach (var dataColumn in toRemove) {
-						view.Columns.Remove(dataColumn);
-					}
+					var outputColumns = GetOutputColumnsOrdered().ToArray();
+					var view = new DataView(Table, "", SumDataFields.SORT, DataViewRowState.CurrentRows).ToTable(false, outputColumns);
+
+					//var probablyEmptyCols = new[] { SumDataFields.E_WHEEL, SumDataFields.SPECIFIC_FC }.Select(x =>
+					//	x.Contains("{") ? x.Substring(0, x.IndexOf("{", StringComparison.Ordinal)) : x).ToArray();
+					//var removeCandidates =
+					//	view.Columns.Cast<DataColumn>()
+					//		.Where(column => probablyEmptyCols.Any(x => column.ColumnName.StartsWith(x))).ToList();
+					//var toRemove = new List<string>();
+					//foreach (var column in removeCandidates) {
+					//	//var column = view.Columns[colName];
+					//	if (view.AsEnumerable().All(dr => dr.IsNull(column))) {
+					//		toRemove.Add(column.ColumnName);
+					//	}
+					//}
+
+					//toRemove = toRemove.Concat(
+					//	view.Columns.Cast<DataColumn>()
+					//		.Where(column => column.ColumnName.StartsWith(SumDataFields.INTERNAL_PREFIX))
+					//		.Select(x => x.ColumnName)).ToList();
+
+					//foreach (var dataColumn in toRemove) {
+					//	view.Columns.Remove(dataColumn);
+					//}
 
 					try {
 						_sumWriter.WriteSumData(view);
@@ -350,10 +550,28 @@ namespace TUGraz.VectoCore.OutputData
 				Table.Rows.Add(tableRow);
 			}
 		}
-	
 
-	//[MethodImpl(MethodImplOptions.Synchronized)]
 		public virtual void Write(IModalDataContainer modData, VectoRunData runData)
+		{
+			var row = GetResultDictionary(modData, runData);
+
+			foreach (DataColumn col in Table.Columns) {
+				var func = SumDataFields.SumDataValue.GetVECTOValueOrDefault(col.ColumnName);
+				if (func == null) {
+					continue;
+				}
+
+				if (func.Item1 == null || func.Item1.All(x => modData.ContainsColumn(x.GetName()))) {
+					row[col.ColumnName] = func.Item2(runData, modData);
+				}
+			}
+
+			AddResultDictionary(row);
+		}
+
+
+		//[MethodImpl(MethodImplOptions.Synchronized)]
+		public virtual void WriteXXX(IModalDataContainer modData, VectoRunData runData)
 		{
 			//var row = GetResultRow(modData, runData); // Replace row with dictionary
 
diff --git a/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs b/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs
index 654024f341..27627d0721 100644
--- a/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs
+++ b/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs
@@ -350,6 +350,11 @@ namespace TUGraz.VectoCore.Tests.Utils
 			
 		}
 
+		public bool ContainsColumn(string modalResultField)
+		{
+			return true;
+		}
+
 		public WattSecond REESSEnergyEnd()
 		{
 			throw new NotImplementedException();
-- 
GitLab