556 lines · 19.2 KB · C#
RawDownload
//******************************************************************************************************//  PQDSFile.cs - Gbtc////  Copyright © 2020, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/eclipse-1.0.php////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  03/06/2020 - Christoph Lackner//       Generated original version of source code.////******************************************************************************************************  using System;using System.Collections.Generic;using System.Globalization;using System.IO;using System.Linq;using System.Threading.Tasks; namespace GSF.PQDS{    /// <summary>    /// Class that represents a PQDS file.    /// </summary>    public class PQDSFile    {        #region[Properties]         private List<MetaDataTag> m_metaData;        private List<DataSeries> m_Data;        private DateTime m_initialTS;         #endregion[Properties]         #region[Constructors]        /// <summary>        /// Creates a new PQDS file.        /// </summary>        /// <param name="dataSeries"> Measurment data to be included as <see cref="DataSeries"/></param>        /// <param name="initialTimeStamp"> Timestamp used as the beginning of the PQDS file </param>        /// <param name="metaData"> List of MetaData to be included in the PQDS file as <see cref="MetaDataTag{DataType}"/> </param>        public PQDSFile(List<MetaDataTag> metaData, List<DataSeries> dataSeries, DateTime initialTimeStamp)        {            if (metaData is null) { this.m_metaData = new List<MetaDataTag>(); }            else { this.m_metaData = metaData; }             this.m_initialTS = initialTimeStamp;            this.m_Data = dataSeries;        }         /// <summary>        /// Creates a new PQDS file.        /// </summary>        public PQDSFile()        {            this.m_metaData = new List<MetaDataTag>();            this.m_Data = new List<DataSeries>();        }         #endregion[Constructors]         #region[Methods]         private void GetStartTime()        {            DateTime result;            int? day = null;            int? month = null;            int? year = null;             if (this.m_metaData.Select(item => item.Key).Contains("eventdate"))            {                string val = ((MetaDataTag<String>)this.m_metaData.Find(item => item.Key == "eventdate")).Value;                if (DateTime.TryParseExact(val, "MM/dd/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result))                {                    day = result.Day;                    month = result.Month;                    year = result.Year;                }            }            if (day is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventday"))                {                    day = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventday")).Value;                }                else                {                    day = DateTime.Now.Day;                }            }            if (month is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventmonth"))                {                    month = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventmonth")).Value;                }                else                {                    month = DateTime.Now.Month;                }            }            if (year is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventyear"))                {                    year = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventyear")).Value;                }                else                {                    year = DateTime.Now.Year;                }            }             int? hour = null;            int? minute = null;            int? second = null;             if (this.m_metaData.Select(item => item.Key).Contains("eventtime"))            {                string val = ((MetaDataTag<String>)this.m_metaData.Find(item => item.Key == "eventtime")).Value;                if (DateTime.TryParseExact(val, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out result))                {                    hour = result.Hour;                    minute = result.Minute;                    second = result.Second;                }            }            if (hour is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventhour"))                {                    hour = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventhour")).Value;                }                else                {                    hour = DateTime.Now.Hour;                }            }            if (minute is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventminute"))                {                    minute = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventminute")).Value;                }                else                {                    minute = DateTime.Now.Minute;                }            }            if (second is null)            {                if (this.m_metaData.Select(item => item.Key).Contains("eventsecond"))                {                    second = ((MetaDataTag<int>)this.m_metaData.Find(item => item.Key == "eventsecond")).Value;                }                else                {                    second = DateTime.Now.Second;                }            }              result = new DateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, (int)second);             this.m_initialTS = result;        }         private MetaDataTag CreateMetaData(string[] flds)        {             string dataTypeString = flds[3].Trim().ToUpper();            PQDSMetaDataType dataType;             switch (dataTypeString)            {                case "N":                    {                        dataType = PQDSMetaDataType.Numeric;                        break;                    }                case "E":                    {                        dataType = PQDSMetaDataType.Enumeration;                        break;                    }                case "B":                    {                        dataType = PQDSMetaDataType.Binary;                        break;                    }                case "A":                    {                        dataType = PQDSMetaDataType.AlphaNumeric;                        break;                    }                default:                    {                        dataType = PQDSMetaDataType.Text;                        break;                    }            }             string key = flds[0].Trim().ToLower();            string note = flds[4].Trim('"');            string unit = flds[2].Trim('"');             switch (dataType)            {                case (PQDSMetaDataType.AlphaNumeric):                    {                        string value = flds[1].Trim('"');                        return new MetaDataTag<String>(key, value, dataType, unit, note);                    }                case (PQDSMetaDataType.Text):                    {                        string value = flds[1].Trim('"');                        return new MetaDataTag<String>(key, value, dataType, unit, note);                    }                case (PQDSMetaDataType.Enumeration):                    {                        int value = Convert.ToInt32(flds[1].Trim('"'));                        return new MetaDataTag<int>(key, value, dataType, unit, note);                    }                case (PQDSMetaDataType.Numeric):                    {                        double value = Convert.ToDouble(flds[1].Trim('"'));                        return new MetaDataTag<double>(key, value, dataType, unit, note);                    }                case (PQDSMetaDataType.Binary):                    {                        Boolean value = Convert.ToBoolean(flds[1].Trim('"'));                        return new MetaDataTag<Boolean>(key, value, dataType, unit, note);                    }                default:                    {                        string value = flds[1].Trim('"');                        return new MetaDataTag<String>(key, value, dataType, unit, note);                    }            }          }         private Boolean IsDataHeader(string line)        {            if (!line.Contains(","))                return false;            String[] flds = line.Split(',');             if (flds[0].ToLower().Trim() == "waveform-data")                return true;             return false;        }         /// <summary>        /// List of included Metadata tags.        /// </summary>        public List<MetaDataTag> MetaData        {            get { return this.m_metaData; }        }         /// <summary>        /// List of data included in PQDS file as <see cref="DataSeries"/>.        /// </summary>        public List<DataSeries> Data        {            get { return this.m_Data; }        }         /// <summary>        /// Writes the content to a .csv file.        /// </summary>        /// <param name="stream"> The <see cref="StreamWriter"/> to write the data to. </param>        /// <param name="progress"> <see cref="IProgress{Double}"/> Progress Token</param>        public void WriteToStream(StreamWriter stream, IProgress<double> progress)        {            int n_data = this.Data.Select((item) => item.Length).Max();            int n_total = n_data + n_data + this.m_metaData.Count() + 1;             //create the metadata header            List<string> lines = new List<string>();            lines = this.m_metaData.Select(item => item.Write()).ToList();             lines.AddRange(DataLines(n_total, progress));             for (int i = 0; i < lines.Count(); i++)            {                stream.WriteLine(lines[i]);                progress.Report((double)(n_data + i) / n_total);            }                     }         /// <summary>        /// Writes the content to a .csv file.        /// </summary>        /// <param name="file"> file name </param>        /// <param name="progress"> <see cref="IProgress{Double}"/> Progress Token</param>        public void WriteToFile(string file, IProgress<double> progress)        {            // Open the file and write in each line            using (StreamWriter fileWriter = new StreamWriter(File.OpenWrite(file)))            {                WriteToStream(fileWriter, progress);            }         }        /// <summary>        /// Writes the content to a .csv file.        /// </summary>        /// <param name="file"> file name </param>        public void WriteToFile(string file)        {            Progress<double> prog = new Progress<double>();            WriteToFile(file, prog);        }         /// <summary>        /// Writes the content to an output Stream.        /// </summary>        /// <param name="stream"> The <see cref="StreamWriter"/> to write the data to. </param>        public void WriteToStream(StreamWriter stream)        {            Progress<double> prog = new Progress<double>();            WriteToStream(stream, prog);        }           /// <summary>        /// Reads the content from a PQDS File.        /// </summary>        /// <param name="filename"> file name</param>        public void ReadFromFile(string filename)        {            Progress<double> prog = new Progress<double>();            ReadFromFile(filename, prog);        }          /// <summary>        /// Reads the content from a PQDS File.        /// </summary>        /// <param name="filename"> file name</param>        /// <param name="progress"> <see cref="IProgress{Double}"/> Progress Token </param>        public void ReadFromFile(string filename, IProgress<double> progress)        {            List<string> lines = new List<string>();            // Open the file and read each line            using (StreamReader fileReader = new StreamReader(File.OpenRead(filename)))            {                while (!fileReader.EndOfStream)                {                    lines.Add(fileReader.ReadLine().Trim());                }            }             int index = 0;            String[] flds;            // Parse MetaData Section            this.m_metaData = new List<MetaDataTag>();             while (!(IsDataHeader(lines[index])))            {                if (!lines[index].Contains(","))                {                    index++;                    continue;                }                 flds = lines[index].Split(',');                 if (flds.Count() < 5)                {                    index++;                    continue;                }                this.m_metaData.Add(CreateMetaData(flds));                index++;                 if (index == lines.Count())                { throw new InvalidDataException("PQDS File not valid"); }                progress.Report((double)index / (double)lines.Count());            }             //Parse Data  Header            flds = lines[index].Split(',');             if (flds.Count() < 2)            {                throw new InvalidDataException("PQDS File has invalid data section or no data");            }             this.m_Data = new List<DataSeries>();            List<string> signals = new List<string>();            List<List<DataPoint>> data = new List<List<DataPoint>>();              for (int i = 1; i < flds.Count(); i++)            {                if (signals.Contains(flds[i].Trim().ToLower()))                {                    continue;                }                this.m_Data.Add(new DataSeries(flds[i].Trim().ToLower()));                signals.Add(flds[i].Trim().ToLower());                data.Add(new List<DataPoint>());            }             index++;            //Parse Data            GetStartTime();             while (index < lines.Count())            {                if (!lines[index].Contains(","))                {                    index++;                    continue;                }                 flds = lines[index].Split(',');                 if (flds.Count() != (this.m_Data.Count() + 1))                {                    index++;                    continue;                }                DateTime TS;                double milliseconds;                try                {                    milliseconds = Convert.ToDouble(flds[0].Trim());                    double ticks = milliseconds * 10000;                    TS = this.m_initialTS.AddTicks((int)ticks);                }                catch                {                    index++;                    continue;                }                 for (int i = 0; i < signals.Count(); i++)                {                    try                    {                        double value = Convert.ToDouble(flds[i + 1].Trim());                        data[i].Add(new DataPoint() { Time = TS, Value = value, Milliseconds = milliseconds });                    }                    catch                    {                        continue;                    }                }                 progress.Report((double)index / (double)lines.Count());                index++;            }             for (int i = 0; i < signals.Count(); i++)            {                int j = this.m_Data.FindIndex(item => item.Label == signals[i]);                this.m_Data[j].Series = data[j];            }        }         private List<String> DataLines(int n_total, IProgress<double> progress)        {            List<string> result = new List<string>();             //ensure they all start at the same Time            List<string> measurements = this.m_Data.Select(item => item.Label).ToList();            DateTime initalStart = this.m_Data.Select(item => item.Series[0].Time).Min();            List<TimeSpan> startTime = this.m_Data.Select(item => item.Series[0].Time - initalStart).ToList();             //1 ms difference is ok            if (startTime.Max().TotalMilliseconds > 1)            {                throw new Exception("The measurements start at different times");            }             //write the header            result.Add("waveform-data," + String.Join(",", measurements)); 

Lines 1–500 of 556.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t