How to turn an Ascii file reader into a LinkableComponent
The input for a model is often contained in simple ASCII files. Wrapping these files in a Linkable Component allows you to make the data available to any OpenMI-compliant model.
You can also wrap the output file from one model so that it can serve as input for another component. Then you can run/test your model based on the output file, instead of actually having to link against to and run the model that made the file in parallel with you own model. Especially is this the only option, if the delivering model is not OpenMI-compliant.
Data in a Linkable Component is made available through the GetValues call of an Output item. Fig. 1 displays that exposing data from any Provider requires a GetValues call.
Figure 1: Data exchange using a GetValues call
What the Ascii file reader needs to do is to make an ILinkableComponent with an Output item that contains/have access to the data from the ascii file.
Implementation of an AsciiFileDataComponent
To be OpenMI-compliant, the AsciiFileDataComponent needs to implement the ILinkableComponent interface. The Oatc.OpenMI.Sdk.Backbone.LinkableComponent is an abstract class having basic implementation of parts of the ILinkableComponent interface. What remains to be implemented is:
- InputItems : List of IInputs, not relevant, hence return an empty list
- OutputItems: List of IOutputs, this is the list where to put the output item with the file data.
- AdaptedOutputFactories: List of factories that can create variations of the Output items. Can return an empty list.
- Initialise: This is where real work has to be done. We need to read the ascii file data and creates the corresponding Output items.
- Validate: Well, if everything is done correctly in Initialize, there is probably not much to validate. You may return null here.
- Prepare: Do nothing.
- Update: We can not update any further. This is for time progressing components. Throw an exception.
The Initialise function is the key point. It needs to read the ascii file and create corresponding Output items. To create an output item, the following information is required:
- IQuantity/IQuality/IValueDefinition: What does the output item contain
- ITimeSet: The times where values are available
- IElementSet: A spatial definition of where the values are situated.
- IValueSet: The actual values.
To ease implementation, you can use the Oatc.OpenMI.Sdk.Buffer.TimeBufferer which is an output item that implements interpolation and extrapolation in time. For every ascii file, you create such a TimeBufferer and put the data from the ascii file into it.
Below is an example of an ASCII file; there are a number of comments, followed by a line specifying the quantity and another containing the element set definition, followed by lines of data, each with an associated date.
We will let the component handle a number of ascii files, each filename given as one argument to Initialize. Prototype code for Initialize could look like:
You can find the entire example in
Difference to a numerical model
The difference between the wrapping of ASCII files and the approach used for numerical model components lies in the implementation of the OutputItems and the GetValues call.
In the case of a numerical model component, the ExchangeItems will usually be provided by a populated model. When wrapping an ASCII file, the information about possible ExchangeItems must be contained in the ASCII file itself.
Also, a numerical model will usually only provide instant values in its output items. The buffering is taken care of by putting an AdaptedOutput in front of the Output item that does the buffering. The ASCII file component provides directly the buffered data in an Output item