using System; using System.Collections.Generic; using System.Linq; using Deltares.Standard.Application; namespace Deltares.Dam.Data { public abstract class TimeSeriesProcessor { internal readonly static LogHelper Logger = LogHelper.Create("Time Series Processor"); #region Constants /// /// Defines the default output file /// private const string DefaultOutputFileName = "output.xml"; /// e /// Defines the water level location id used in the FEWS time serie /// public const string WaterLevelInputLocationID = "outside"; /// /// Defines the parameter id of the water level defined in the FEWS time serie /// public const string WaterLevelInputParameterID = "Waterlevel"; /// /// Defines the parameter id for water pressure used in the FEWS time serie /// public const string WaterPressureParameterID = "Waterpressure"; /// /// Defines the sensor state missing value /// internal const double MissingValue = -999; #endregion public ICalculator Calculator { protected get; set; } /// /// Gets or sets the output parameter ID. /// /// This name or ID is used in the output (FEWS) time series /// /// The output parameter ID. /// public IEnumerable OutputParameters { get; set; } /// /// Sets the input time series, used in the calculations /// public TimeSerieCollection InputTimeSeriesCollection { protected get; set; } /// /// Gets or sets the output location ID colletion used for creating the output time series /// public virtual IEnumerable OutputLocations { get; set; } /// /// Gets or the output time series /// public TimeSerieCollection OutputTimeSeriesCollection { get; set; } /// /// Resets the monitoring point list /// public virtual void Initialize() { if (OutputTimeSeriesCollection == null) OutputTimeSeriesCollection = InputTimeSeriesCollection.GetShallowCopy(); else OutputTimeSeriesCollection.Clear(); } /// /// Loads the input time series. /// /// Name of the file. public void LoadInputTimeSeries(string fileName) { ThrowHelper.ThrowIfFileNameNullOrEmpty(fileName); try { // load the input time serie containing all water levels InputTimeSeriesCollection = TimeSerieCollection.LoadFromFile(fileName); } catch (Exception e) { throw new InvalidOperationException("There was an error loading the input time series", e); } } /// /// Saves the output time series to the specified file /// /// /// The output file that will contain the monitored and calculated results for each time entry public void SaveResultsToFile(string fileName) { if (OutputTimeSeriesCollection == null) throw new InvalidOperationException("No output time series collection to write"); if (string.IsNullOrWhiteSpace(fileName)) { fileName = DefaultOutputFileName; } // save the time serie to the output file OutputTimeSeriesCollection.Save(fileName); } /// /// Processes the FEWS input time series files to ouput /// time series /// public virtual void Process() { if (InputTimeSeriesCollection == null) return; if (OutputTimeSeriesCollection == null) throw new InvalidOperationException("No output time series set to write the results to"); if (OutputLocations == null) throw new InvalidOperationException("No output locations set. Set or override OutputLocations"); if (OutputParameters == null) throw new InvalidOperationException("No output parameters set. Set or override OutputParameters"); try { // Process the time series entries for each sensor and set the // value in the output time series CreateOutputSeries(); } catch (Exception e) { const string message = "There was an error processing the time series"; Logger.LogFatal(message, e); throw new InvalidOperationException(message, e); } } /// /// Processes the actual input to the output collection. This is a template method which will /// be called in the public ProcessSeries() method (if not overriden) /// protected virtual void CreateOutputSeries() { foreach (var timeSeries in InputTimeSeriesCollection.Series) { foreach (var location in OutputLocations) { foreach (var parameter in OutputParameters) { var copyOfSeries = timeSeries.GetShallowCopy(); foreach (var entry in timeSeries.Entries) { // get copy of the input entry var copyOfEntry = entry.GetShallowCopy(); // calculate its value copyOfEntry.Value = Calculator.Calculate(location, parameter) ?? MissingValue; // set parameter and location id's and add the projected entry to the output copyOfSeries.LocationId = location; copyOfSeries.ParameterId = parameter; copyOfSeries.Entries.Add(copyOfEntry); } // add the output series to the output collection OutputTimeSeriesCollection.Series.Add(copyOfSeries); } } } } } }