Working with Data Sets
The FlexPro data sets are largely determined by these four properties: DataStructure, DataType, NumberOfRows and NumberOfColumns. The DataStructure property determines the data structure of the data set. FlexPro offers support for nine data structures, six of which are composed of up to three components: The DataType property determines the data type of the data set or, if the data set has an aggregate data structure, the data types of the individual components it contains. FlexPro also supports several data types for numbers, text, Boolean values, times and duration. Not all data types are allowed for all components of a data set. Strings, for example, cannot be used as a data type for data sets that have an aggregate data structure. The two properties NumberOfRows and NumberOfColumns determine the size of a data set. NumberOfRows can be used with all data structures except scalar values and determines the number of data rows. NumberOfColumns is only relevant for the two-dimensional data structures data matrix and signal series, and determines the number of columns. For all other data structures, this property has the value One and cannot be changed. A change in the NumberOfRows or NumberOfColumns may effect several components of a data set. If, for example, you increase the number of rows in a signal, its X and Y components will increase.
Creating a Data Set
The best practice is to use FlexPro to generate the right code for the creation of a data set by activating the macro recorder and then creating a data set using the wizard. For example, for a signal series with three columns containing 100 values each, the code should look something like this:
With ActiveDatabase.RootFolder.Add("SignalSeries", fpObjectTypeDataSet)
.DataStructure = fpDataStructureSignalSeries
.DataType(fpDataComponentY) = fpDataTypeFloat64
.DataType(fpDataComponentX) = fpDataTypeFloat64
.NumberOfColumns = 3
.NumberOfRows = 100
.FillColumns "(NumberOfRows(i), FloatingPoint64 0, FloatingPoint64 0)", _
fpDataComponentY
.FillColumns "(NumberOfRows(i), FloatingPoint64 0, FloatingPoint64 1)", _
fpDataComponentX
.Update
End With
An important aspect in creating the data set efficiently is to apply the properties DataStructure, DataType, NumberOfRows and NumberOfColumns in the correct sequence. Since the data set is restructured with every instance of write access to one of these properties, this data set should only reach its full size when it is last accessed. The wizard uses the correct sequence. First, the data structure of the data set is determined. Now the components of the data set are available, and their data types can be determined. Finally, the number of columns is specified. The data set only consists of one row containing three columns, i.e. three values. Once the number of rows is specified, the data set grows to include 300 values. Finally, the contents of the columns are initialized. This step can be omitted if the data set is to be filled with data at a later time.
Reading and Writing the Data of a Data Set
If you use the Value method of the DataSet object without specifying arguments you can access the complete content of the data set. This approach is recommended for smaller data sets only, since the complete contents have to be transferred into a variant array, i.e. the main memory. If the data set has an aggregate data structure, Value passes all components as the signal object. If you want to assign a variable in Visual Basic, you have to use the Set statement. The following example reads a signal and then calculates the Delta-t from the X component.
Dim S As Signal
Set S = SignalDataSet.Value
Dim Delta As Double
Delta = S.X(1) - S.X(0)
Please note that the first X value in S.X has the index zero. During write-access to the Value property, you also have to consider that the value with the index zero is contained in the array.
Dim V(2) As Double
V(0) = 1
V(1) = 2
V(2) = 3
DataSet.Value = V
Thus, an array that is dimensioned with (n) in Basic has n + 1 values!
FlexPro can effectively process data sets of several gigabytes in size. This is possible because data sets that are a certain customizable size or larger are managed as files on the hard disk and therefore do not have to be loaded completely into main memory. When accessing the data of a data set via the Automation Object Model, the data to be transferred are always moved as a variant array and therefore copied completely into main memory. With very large data sets, you should therefore only access parts of the data. By using the optional arguments Row and Column of the Value property, you can directly access individual values, rows or columns in a data set.
The following example accesses the values in a rectangular area in the Y component of a signal series and sets these to zero.
Dim Row, Col As Long
For Row = 1 To 4
For Col = 1 To 2
SignalSeriesDataSet.Value(fpDataComponentY, Col, Row) = 0
Next
Next
You can also transfer data block by block. To do this, you can use the ValueObjectRange object, which you can access using the Range property of the data set. This enables read/write access to a section of the data in the data set.
The following example copies the first five values in the Y component of a signal to the positions 6 to 10.
SignalDataSet.Value(fpDataComponentY, , 6, , 10).Value = _
SignalDataSet.Range(fpDataComponentY, , 1, , 5).Value
Please note the following:
•Read and write access to the ValueObjectRange object are passed on directly to the data set. The ValueObjectRange object does not keep a copy of the data in the section.
•The ValueObjectRange object can also be used for formulas, data link objects and analysis objects. In this case, however, only read-access is allowed.
•By using the Value property of the ValueObjectRange object, not only can you access the complete range, but also columns, rows or individual values as well.
•The sequential indices of the ValueObjectRange object always start with One, even if the range in the data set starts with a higher index.
Dim Range As ValueObjectRange
Set Range = SignalSeriesDataSet.Range(fpDataComponentY, 1, 2, 2, 5)
Dim Data As Variant
Data = Range.Value 'Data is now of type variant/double(0 to 1, 0 to 3)
Transferring Large Data Sets Section by Section
Saving data that is generated continually as a data set, e.g. during a measuring process, is very common. The obvious solution for this problem is to create the data set with the correct data structure and data type and to initialize the number of rows with zero. Upon receiving the data, the number of rows is then increased; a ValueObjectRange object is used to enter the most recent value into the data set. For a data series, the code for this procedure looks as follows:
With DataSeries
.NumberOfRows = .NumberOfRows + 1
.Value( , , .NumberOfRows) = NewValue
End With
The disadvantage of this procedure is, however, that the processing speed is comparatively low. With every increase of the data set, FlexPro has to copy the values internally, which is very expensive, particularly with larger data sets. Furthermore, the data volume transferred per each access to the Automation interface of FlexPro is very low. You can avoid these problems by first gathering the generated data in an array and then transferring the content of the array as a whole.
Dim Data(1000000 - 1) As Double
For i = 0 to 100000 - 1
Data(i) = NewValue
Next
With DataSeries
.NumberOfRows = .NumberOfRows + 1000000
.Range(fpDataComponentY, , .NumberOfRows - 1000000 + 1, _
, .NumberOfRows).Value = Data
End With