/// <summary>
 /// TimeSeriesLibrary is responsible for ensuring that a certain set of meta-parameters (which
 /// are saved as database fields) are coordinated with the BLOB of timeseries data. This method
 /// records all of the meta-parameters of an irregular timeseries into the fields of this 
 /// TSParameters object, using the input parameters given to the method.
 /// </summary>
 public void SetParametersIrregular(
             int timeStepCount, DateTime blobStartDate, DateTime blobEndDate, int compressionCode)
 {
     // Most of the parameters are straightforward
     TimeStepUnit = TSDateCalculator.TimeStepUnitCode.Irregular;
     TimeStepQuantity = 0;
     BlobStartDate = blobStartDate;
     CompressionCode = compressionCode;
 }
 /// <summary>
 /// TimeSeriesLibrary is responsible for ensuring that a certain set of meta-parameters (which
 /// are saved as database fields) are coordinated with the BLOB of timeseries data. This method
 /// records all of the meta-parameters of a regular timeseries into the fields of this TSParameters
 /// object, using the input parameters given to the method.
 /// </summary>
 public void SetParametersRegular(
             TSDateCalculator.TimeStepUnitCode timeStepUnit, short timeStepQuantity,
             int timeStepCount, DateTime blobStartDate, int compressionCode)
 {
     // Most of the parameters are straightforward
     TimeStepUnit = timeStepUnit;
     TimeStepQuantity = timeStepQuantity;
     BlobStartDate = blobStartDate;
     CompressionCode = compressionCode;
 }
Exemple #3
0
        /// <summary>
        /// This private method creates a List of TimeSeriesValue objects from the given BLOB (byte array)
        /// of time series values.  The method takes parameters for a maximum number of values,
        /// an earliest date, and a latest date, so that only a portion of the BLOB might be
        /// converted to the List.  This method is designed to do the operations that are common between
        /// the public methods ConvertBlobToListLimited() and ConvertBlobToListAll().
        /// </summary>
        /// <param name="timeStepUnit">TSDateCalculator.TimeStepUnitCode value for Minute,Hour,Day,Week,Month, Year, or Irregular</param>
        /// <param name="timeStepQuantity">The number of the given unit that defines the time step.
        /// For instance, if the time step is 6 hours long, then this value is 6.  If timeStepUnit is
        /// Irregular, then this value is ignored.</param>
        /// <param name="timeStepCount">the number of time steps that are stored in the blob</param>
        /// <param name="blobStartDate">The DateTime value of the first time step in the BLOB. If
        /// timeStepUnit is Irregular, then this value is ignored.</param>
        /// <param name="applyLimits">If value is true, then nReqValues, reqStartDate, and reqEndDate will be
        /// used to limit the portion of the BLOB that is converted to dateValueList.  If the value is false, then
        /// nReqValues, reqStartDate, and reqEndDate will be ignored.</param>
        /// <param name="nReqValues">The maximum number of time steps that should be added to dateValueList.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="reqStartDate">The earliest date that will be added to dateValueList.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="reqEndDate">The latest date that will be added to dateValueList.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="blobData">The BLOB (byte array) that this method will convert into a List</param>
        /// <param name="dateValueList">The List of TimeSeriesValues that this method will create from the BLOB.</param>
        /// <param name="compressionCode">a generation number that indicates what compression technique to use</param>
        /// <returns>The number of time steps added to dateValueList</returns>
        private unsafe int ConvertBlobToList(
            TSDateCalculator.TimeStepUnitCode timeStepUnit, short timeStepQuantity,
            int timeStepCount, DateTime blobStartDate, Boolean applyLimits,
            int nReqValues, DateTime reqStartDate, DateTime reqEndDate,
            Byte[] blobData, ref List <TimeSeriesValue> dateValueList, int compressionCode)
        {
            int nValuesRead = 0;

            if (timeStepUnit == TSDateCalculator.TimeStepUnitCode.Irregular)
            {
                // IRREGULAR TIME SERIES

                // If we're not limiting the output list (i.e., we're returning every time step from
                // the BLOB), then set the size of the intermediate array to match the size of the BLOB.
                if (applyLimits == false)
                {
                    nReqValues = timeStepCount;
                }
                // Allocate an array of date/value pairs that TSBlobCoder method will fill
                TSDateValueStruct[] dateValueArray = new TSDateValueStruct[nReqValues];
                // Method in the TSBlobCoder class does the real work
                nValuesRead = TSBlobCoder.ConvertBlobToArrayIrregular(timeStepCount, applyLimits,
                                                                      nReqValues, reqStartDate, reqEndDate,
                                                                      blobData, dateValueArray, compressionCode);
                // resize the array so that the List that we make from it will have exactly the right size
                if (nValuesRead != nReqValues)
                {
                    Array.Resize <TSDateValueStruct>(ref dateValueArray, nValuesRead);
                }
                // Convert the array of date/value pairs into the List that will be used by the caller
                dateValueList = dateValueArray
                                .Select(tsv => (TimeSeriesValue)tsv).ToList <TimeSeriesValue>();
            }
            else
            {
                // REGULAR TIME SERIES

                // If we're not limiting the output list (i.e., we're returning every time step from
                // the BLOB), then set the size of the intermediate array to match the size of the BLOB.
                if (applyLimits == false)
                {
                    nReqValues = timeStepCount;
                }
                // Allocate an array of values that TSBlobCoder method will fill
                double[] valueArray = new double[nReqValues];
                // Method in the TSBlobCoder class does the real work
                nValuesRead = TSBlobCoder.ConvertBlobToArrayRegular(timeStepUnit, timeStepQuantity,
                                                                    timeStepCount, blobStartDate, applyLimits,
                                                                    nReqValues, reqStartDate, reqEndDate,
                                                                    blobData, valueArray, compressionCode);
                // Allocate an array to hold the time series' date values
                DateTime[] dateArray = new DateTime[nValuesRead];
                // Fill the array with the date values corresponding to the time steps defined
                // for this time series in the database.
                TSDateCalculator.FillDateArray(timeStepUnit, timeStepQuantity, nValuesRead, dateArray, reqStartDate);
                // Allocate a List of date/value pairs that will be used by the caller
                dateValueList = new List <TimeSeriesValue>(nValuesRead);
                // Loop through all values, building the List of date/value pairs out of the
                // primitive array of dates and primitive array of values.
                int i;
                for (i = 0; i < nValuesRead; i++)
                {
                    dateValueList.Add(new TimeSeriesValue {
                        Date = dateArray[i], Value = valueArray[i]
                    });
                }
                nValuesRead = i;
            }
            return(nValuesRead);
        }
Exemple #4
0
        /// <summary>
        /// This method converts a BLOB (byte array) to an array of regular time step timeseries
        /// values (double precision floats).  The caller must give parameters of the
        /// time series, such as time step size and start date.  The method will convert
        /// only a portion of the BLOB if the applyLimits parameter is true, according to
        /// the parameter values nReqValues, reqStartDate, and reqEndDate.  If the
        /// applyLimits parameter is false, then the method converts the entire BLOB into
        /// the given array of values.  The array of values must have been allocated
        /// large enough prior to calling this method.
        /// </summary>
        /// <param name="timeStepUnit">TSDateCalculator.TimeStepUnitCode value for Minute,Hour,Day,Week,Month, Year, or Irregular</param>
        /// <param name="timeStepQuantity">The number of the given unit that defines the time step.
        /// For instance, if the time step is 6 hours long, then this value is 6.</param>
        /// <param name="timeStepCount">the number of time steps that are stored in the blob</param>
        /// <param name="blobStartDate">Date of the first time step in the BLOB</param>
        /// <param name="applyLimits">If true, then the method will convert only a portion of the BLOB,
        /// according to the parameter values nReqValues, reqStartDate, and reqEndDate.  If false, the method
        /// converts the entire BLOB into a value array.</param>
        /// <param name="nReqValues">The maximum number of elements that will be converted into the array of values.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="reqStartDate">The earliest date in the time series that will be written to the array of values.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="reqEndDate">The latest date in the time series that will be written to the array of values.
        /// If applyLimits==false, then this value is ignored.</param>
        /// <param name="blobData">the BLOB that will be converted</param>
        /// <param name="valueArray">the array of time series values that is produced from the BLOB</param>
        /// <param name="compressionCode">a generation number that indicates what compression technique to use</param>
        /// <returns>The number of time steps that were actually written to valueArray</returns>
        public static unsafe int ConvertBlobToArrayRegular(
            TSDateCalculator.TimeStepUnitCode timeStepUnit, short timeStepQuantity,
            int timeStepCount, DateTime blobStartDate, bool applyLimits,
            int nReqValues, DateTime reqStartDate, DateTime reqEndDate,
            Byte[] blobData, double[] valueArray, int compressionCode)
        {
            // The BLOB is kept in a compressed form, so our first step is to decompress it before
            // anything else can be done.
            Byte[] decompressedBlobData
                = DecompressBlob(blobData, timeStepCount * sizeof(double), compressionCode);

            // MemoryStream and BinaryReader objects enable bulk copying of data from the BLOB
            using (MemoryStream blobStream = new MemoryStream(decompressedBlobData))
                using (BinaryReader blobReader = new BinaryReader(blobStream))
                {
                    // How many elements of size 'double' are in the BLOB?
                    int numBlobBin    = (int)blobStream.Length;
                    int numBlobValues = numBlobBin / sizeof(double);

                    int numReadValues  = numBlobValues;
                    int numSkipValues  = 0;
                    int numTruncValues = 0;

                    // Values might be skipped from the front or truncated from the end of the array,
                    // but only if this flag is 'true'.
                    if (applyLimits)
                    {
                        // Do we skip any values at the front of the BLOB in order to fullfil the requested start date?
                        if (reqStartDate > blobStartDate)
                        {
                            numSkipValues = TSDateCalculator.CountSteps(blobStartDate, reqStartDate,
                                                                        timeStepUnit, timeStepQuantity);
                        }
                        // compute the last date in the BLOB
                        DateTime blobEndDate = TSDateCalculator.IncrementDate
                                                   (blobStartDate, timeStepUnit, timeStepQuantity, numBlobValues - 1);
                        // Do we truncate any values at the end of the BLOB in order to fulfill the requested end date?
                        if (reqEndDate < blobEndDate)
                        {
                            numTruncValues = TSDateCalculator.CountSteps(reqEndDate, blobEndDate,
                                                                         timeStepUnit, timeStepQuantity);
                        }
                        // the number of values that can actually be read from the BLOB
                        numReadValues = Math.Min(numBlobValues - numSkipValues - numTruncValues, nReqValues);
                    }

                    // the number of bytes that will actually be read
                    int numReadBin = numReadValues * sizeof(double);
                    // the number of bytes that will be skipped
                    int numSkipBin = numSkipValues * sizeof(double);

                    // If we've got zero values to read, then we're done early!
                    if (numReadValues <= 0)
                    {
                        return(0);
                    }

                    // Transfer the entire array of data as a block
                    Buffer.BlockCopy(blobReader.ReadBytes(numBlobBin), numSkipBin, valueArray, 0, numReadBin);

                    return(numReadValues);
                }
        }
 /// <summary>
 /// This method copies the parameters of a time series from a TSParameters object
 /// into this TSImport object.
 /// </summary>
 /// <param name="tsp">The TSParameters object that values will be copied from</param>
 public void RecordFromTSParameters(TSParameters tsp)
 {
     TimeStepUnit = tsp.TimeStepUnit;
     TimeStepQuantity = tsp.TimeStepQuantity;
     BlobStartDate = tsp.BlobStartDate;
     CompressionCode = tsp.CompressionCode;
 }
        // Note--this test class was created primarily b/c we wanted to individually test the different
        // compression methods.  Hence, we have created the test methods below.  The class TSBlobCoder
        // certainly deserves full test coverage, but that can be developed later.  In the meantime,
        // it is generally expected that TSBlobCoder has adequate test coverage via TSLibraryTest.

        #region Test Methods for ConvertBlobToListAll() and ConvertListToBlob()
        // The series of tests below is for ConvertBlobToListAll and ConvertListToBlob.
        // The tests take advantage of the fact that the methods are designed so that
        // the series that is put into the BLOB must be identical to the series that
        // comes out of the BLOB.

        // This method is re-used by the actual test methods that follow.
        public void ConvertBlobAll(List <TimeSeriesValue> inList,
                                   TSDateCalculator.TimeStepUnitCode timeStepUnit, short timeStepQuantity,
                                   DateTime blobStartDate, int compressionCode)
        {
            TSLibrary tsLib = new TSLibrary();

            var traceObject = new TSTrace
            {
                TraceNumber   = 1,
                TimeStepCount = inList.Count,
                EndDate       = inList.Last().Date
            };

            if (timeStepUnit == TSDateCalculator.TimeStepUnitCode.Irregular)
            {
                var    inArray  = inList.Select(v => (TSDateValueStruct)v).ToArray();
                var    outArray = new TSDateValueStruct[inList.Count];
                byte[] blobData = TSBlobCoder.ConvertArrayToBlobIrregular(inArray,
                                                                          compressionCode, traceObject);

                int ret = TSBlobCoder.ConvertBlobToArrayIrregular(inList.Count,
                                                                  false, 0, blobStartDate, blobStartDate,
                                                                  blobData, outArray, compressionCode);

                // The return value of the function must match the number of items in the original list
                Assert.AreEqual(ret, inList.Count);
                // the count in both lists must match
                Assert.AreEqual(inArray.Length, outArray.Length);
                // now check each item in the two lists
                Boolean AreEqual = true;
                for (int i = 0; i < ret; i++)
                {
                    if (outArray[i].Date != inArray[i].Date || outArray[i].Value != inArray[i].Value)
                    {
                        AreEqual = false;
                    }
                }
                Assert.IsTrue(AreEqual);
            }
            else
            {
                var    inArray  = inList.Select(v => v.Value).ToArray();
                var    outArray = new Double[inList.Count];
                byte[] blobData = TSBlobCoder.ConvertArrayToBlobRegular(inArray,
                                                                        compressionCode, traceObject);

                int ret = TSBlobCoder.ConvertBlobToArrayRegular(timeStepUnit, timeStepQuantity,
                                                                inList.Count, blobStartDate,
                                                                false, 0, blobStartDate, blobStartDate,
                                                                blobData, outArray, compressionCode);

                // The return value of the function must match the number of items in the original list
                Assert.AreEqual(ret, inList.Count);
                // the count in both lists must match
                Assert.AreEqual(inArray.Length, outArray.Length);
                // now check each item in the two lists
                Boolean AreEqual = true;
                for (int i = 0; i < ret; i++)
                {
                    if (outArray[i] != inArray[i])
                    {
                        AreEqual = false;
                    }
                }
                Assert.IsTrue(AreEqual);
            }
        }