How to expose time series data in V1.4?

Help
LangXtest
2012-05-07
2013-04-25
  • LangXtest
    LangXtest
    2012-05-07

    Hi, All,
        Does anyone have any experience in exposing time series data from an OpenMI component?  Say I have two time series:
    TimeSeriesId    Time                          Value     Grade
    Stage@Site1    2010-01-20 13:00     2.2           10
    Stage@Site1    2010-01-20 13:15     2.3           10
    Stage@Site1    2010-01-20 13:30     2.4           10
    Discharge@Site1    2010-01-20 13:00     12.2           10
    Discharge@Site1    2010-01-20 13:15     12.3           10
    Discharge@Site1    2010-01-20 13:30     12.4           10

        I'd like to expose the data as OutputExchangeItems. But OpenMI GetValues  method (V1.4) only allows an array of doubles  or vectors.
        One way I can think of is to expose Timestamps, Values, Grades as 3 separate "Quantity" and then use TimeSeriesId as the ElementSet id in the element set.
       
        Thanks in advance for your help!

    LangX

     
  • Jesper Grooss
    Jesper Grooss
    2012-05-08

    You could try take a look at

    http://publicwiki.deltares.nl/display/OPENMI/HOW+TO+turn+an+Ascii+file+reader+into+a+Linkable+Component

    There an output item is created, containing 3 time series for 3 different locations (sites).

    For each time series (times and values) you can make an output exchange item. i.e. in your case you can make one output item for the Values and one for the Grades - for each site. And then you can distinguish between the sites by the ElementSetId.

    You can also make one exchange item for the Values at all sites and one for all Grades (assuming they all have values at the same times), and then make an ElementSet with two (or more, depending on the number of sites) elements. Then each output item is a vector item and not a scalar item. But most likely this is only going to make things more complicated, so I would stick with the first version.

     
  • LangXtest
    LangXtest
    2012-05-08

    Thanks, Jesper.
       I get it (I hope.:). I'll go with the first approach.
       I may need to add an output exchange item for "times" too, because in our use cases, the caller component may not know the times (can be discrete times) before making GetValues call. Even it knows the time stamps, it need to make one GetValues call for each point. In our case, two calls per point: one for Value, the other for Grade.By "point" I mean "time series point" which is a tuple of (time,value,grade,…).
       So my plan is to expose 3 "Quantities" whose values are arrays of double and the unique time series identifier is used as the element set id:
       Times
            - TimeSeries1
            - TimeSeries2
       Values
            - TimeSeries1
            - TimeSeries2
       Grades
            - TimeSeries1
            - TimeSeries2
       Where Time.Count == Values.Count == Grades.Count and ordered consistently.

       In GetValues call, ITime can be ITimeSpan (requesting the time series by a time range), or it can be ITimeStamp (requesting a specific time series data point ).

       I hope I've got it right. If you see any issues or have a better way of doing this, I'd appreciate your input.
       Thanks!

     
  • Jesper Grooss
    Jesper Grooss
    2012-05-09

    The idea with the exchange items is that you ask for a value using GetValues at a specified timestamp/span, and the exchange item will make sure that you get values at that time, i.e. it will do interpolation in time (for timestamps) or averaging over time (for timespans). So the consumer (the one calling GetValues) do not need to know the times of the provider (the exchange item (or the linkable component beneath the exchange item)).

    Related to the Times exchange item: When a consumer calls GetValues on that one, using a TimeStamp, it will get the same TimeStamp back. When a consumer does a GetValues call using a TimeSpan, it will get the mid point time back (average). Both you can calculate beforehand. If the consumer does not know the times of the exchange item beforehand, there is no (simple) way to get hold of those.

     
  • LangXtest
    LangXtest
    2012-05-09

    >The idea with the exchange items is that you ask for a value using GetValues
    > at a specified timestamp/span, and the exchange item will make sure
    >that you get values at that time, i.e. it will do interpolation
    >in time (for timestamps) or averaging over time (for timespans).

    But in one of our use cases, the consuming component need to get a list of points, not just a value. How can we do that?
    What I'm thinking is:
    If GetValues is by ITimeSpan, I give back an array (ScalarSet) of points that are within the time range.
    If time is ITimeStamp, then I give back a specific point for that time. No interpolation nor averaging nor aggregation on the provider side.

    If the consumer need to know the exact times for those values, a similar link can be made to the "Times" OutputExchangeItem.

    Now on the consumer side, it can assemble these arrays into time series points and use them in its calculation.

    Do you think that's the way how OpenMI components work?

     
  • Stef Hummel
    Stef Hummel
    2012-05-10

    OpenMI 1.4 offers an optional interface: IDiscreteTimes, that a linkable component may implement.  It was design for e.g. getting time series from data bases. If a component does implement IDiscreteTimes, one can query that component for output items (i.e. quantity/elementset combinations) that are actualle a time series:

    if (myComponent.HasDiscreteTimes(quant, elmset)) {
         int timesCount = myComponent.GetDiscreteTimesCount(quant, elmset);
         for (int i=0; i < timesCount; i++) {
              ITime stampOrSpan = myComponent.GetDiscreteTime(quant, elmset, i);
         }
    }

    The wrapping utilities in the SDK do not implement it, but one can extend a linkable component and let it implement the IDiscreteTimes interface.

    Best regards,
    Stef

     
  • Peter Schade
    Peter Schade
    2012-05-10

    … an example follows how to implement the methods for the IDiscreteTimes extension:

    public int GetDiscreteTimesCount(IQuantity quantity, IElementSet elementSet)
    {
    GEIExchangeItem exchangeItem = this.GetExchangeItem (elementSet, quantity);
    if ((exchangeItem == null) || !exchangeItem.HasDiscreteTimes)
    {
                             throw new Exception ("No corresponding exchange item found for elementSet " + elementSet.ID + " and quantity " + quantity.ID);
    }
    return exchangeItem.GetDiscreteTimesCount();
    }

    public bool HasDiscreteTimes(IQuantity quantity, IElementSet elementSet)
    {
    GEIExchangeItem exchangeItem = this.GetExchangeItem (elementSet, quantity);
    return ((exchangeItem != null) && (exchangeItem.HasDiscreteTimes));
    }

    public ITime GetDiscreteTime(IQuantity quantity, IElementSet elementSet, int discreteTimeIndex)
    {
    GEIExchangeItem exchangeItem = this.GetExchangeItem (elementSet, quantity);
    if ((exchangeItem == null) || !exchangeItem.HasDiscreteTimes)
    {
                          throw new Exception ("No corresponding exchange item found for elementSet " + elementSet.ID + " and quantity " + quantity.ID);
    }
    return exchangeItem.GetDiscreteTime(discreteTimeIndex);
    }

    Best regards
    Peter

     
  • LangXtest
    LangXtest
    2012-05-11

    Hi, Stef and Peter,
        Thanks a lot! That might be exactly what we want! So now I don't need to expose "Times" as a separate OutputExchangeItem. That's better.

    Best wishes,
    LangX