Harmonizer configuration
To configure Harmonizer properly, you need to know how Harmonizer works.
Please, see → Harmonizer methodology.
Harmonizer can be configured by setting some properties stored in the file:
/opt/ptv-optima-as/standalone/configuration/optima/optima-configuration.xml.
Important: For earlier releases than Optima v16.0.1604, the configuration file is: /opt/ptv-optima-as/standalone/configuration/harmonizer.xml.
The XML configuration file contains the following nodes:
Contains the general configuration parameters of Harmonizer .
Some parameters are directly mapped to the parameters of the standard Jakarta EE ScheduleExpression class.
| Parameter | Description |
|---|---|
|
schedule |
Harmonization schedule. |
|
schedule/second schedule/minute schedule/hour schedule/dayOfMonth schedule/month schedule/dayOfWeek schedule/year |
Parameters directly mapped to the parameters of the standard Jakarta EE ScheduleExpression class. Please, see the documentation: https://jakarta.ee/specifications/platform/10/apidocs/jakarta/ejb/scheduleexpression |
|
schedulePivot |
Pivoting schedule. The elements contained in this tag are managed exactly as the elements contained in schedule. |
|
processingDelay |
Integer value. Delay time in seconds, subtracted from the current time to start to cluster data requested by the field. |
|
clusterWindow |
Integer value. Width in seconds of the time window used to cluster data requested by the field. |
|
processingDelayResults |
Integer value. Delay time in seconds added to the current time to start managing the results. |
|
resultsValidity |
Integer value. Width in seconds of the time window in which the results based on data previously clustered in general.clusterWindow are valid. |
|
autostart |
Boolean value. It can be set to:
If the parameter is missing, the default value is false. Important: You can also start and stop the Harmonizer through the Optima Admin GUI (→ OptimaWSI administration dashboard). The autostart parameter is completely uncorrelated with the Optima Admin GUI. |
|
configurationVersion |
Integer value. This value is only printed in the log to check if the configuration file is reloaded. |
If timeNow is the current time, Harmonizer runs with the frequency set by the schedule elements.
It collects data from all sources that belong to the time window:
[(timeNow – processingDelay – clusterWindow), (timeNow – processingDelay)].
Harmonizer produces data fusion results that are valid in the temporal window:
[(timeNow + processingDelayResults), (timeNow + processingDelayResults + resultsValidity)].
The setup of the filtering procedure is controlled by the <filterRules> tag, containing one or more rules (<rule> tag) to be applied to filter each source.
Data is filtered according to different conditions ( <condition> tag).
Each rule can contain one or more conditions and a single <action> tag.
A condition represents the logical operation we would like to check in order to trigger the action.
A condition is composed by an attribute (see → Attributes), an operator (see → Operators), and a value.
Conditions are evaluated in the same order as they are specified and all conditions must be satisfied in order to apply the rule (logical AND mode).
Important: Rules are applied in the top-down order. This means that the order of rules is significant.
Example 1
In this example, six rules are listed and every rule has only one condition.
<configurations>
....
<harmonizer>
....
<filterRules>
<rule name="filterKO">
<condition attr="status" operator="maxequal" value="2" />
<action attr="reliabilitymultiplier" value="0.0" />
</rule>
<rule name="clocDisabledRule">
<condition attr="clocDisabled" operator="equal" value="1" />
<action attr="reliabilitymultiplier" value="0.0" />
</rule>
<rule name="speedzero">
<condition attr="speed" operator="min" value="0" />
<action attr="reliabilitymultiplier" value="0.0" />
</rule>
<rule name="flowzero">
<condition attr="flow" operator="min" value="0" />
<action attr="reliabilitymultiplier" value="0.0" />
</rule>
<rule name="speedmax">
<condition attr="speed" operator="maxequal" value="180" />
<action attr="reliabilitymultiplier" value="0.0" />
</rule>
<rule name="flowmax">
<condition attr="flow" operator="maxequal" value="2000" />
<action attr="reliabilitymultiplier" value="0.0" effectRelevance="0.8" />
</rule>
</filterRules>
....
</harmonizer>
....
</configurations>
As you can see, the <action> tag can have the attribute reliabilitymultiplier with the associated attribute value ∈[0,1], and the optional attribute effectRelevance.
The value is the number multiplied by the reliability of the measurements to set the reliability field in Harmonizer output:
HarmonizedReliability=value*reliability
The reliability of a measure is a value in the range [0-100] which the data provider expresses for each traffic state to define how reliable the given data is according to their own standards. Each traffic state has only one reliability value, which therefore equally affects all related measurements.
Important: It is possible that the reliability or the HarmonizedReliability of one or more traffic states is 0. In this case, when the Harmonizer examines a specific element (e.g., a single street), such traffic states are discarded, hence they don't contribute to the output at all. Should all traffic states of the same element be equal to 0, the system won't generate any relevant output for that element.
The attribute (effectRelevance) is used to sort the rules, in case of applyStrongestRuleOnly.
The complete list of attributes that can be used to build a rule is indicated in the table:
| Parameter | Description |
|---|---|
| reliabilitymultiplier |
Mandatory. It is associated to a value ∈[0,1]. |
| effectRelevance | If the effectRelevance is specified AND applyAllRules=false (→ Applying rules: applyAllRules parameter), the effectRelevance overwrites the value of reliabilitymultiplier. |
|
speed |
Real value (measured in Km/h).
|
|
flow |
Real value (measured in Veh/h).
|
|
area |
String value. Contains the name of the area defined in the model. The meta-data filed of the strt table must be filled with meta-data having as key "area" and as value the "area name". |
|
hierarchy |
Integer value. The filter condition works on the street hierarchy defined in the model in the field strt.hier. |
|
status |
Integer value. The filter condition works on the traffic states status. |
|
startTime endTime |
Timestamp value. The filter condition works on the traffic states time window start and end time. The format of the Timestamp can be in hh:mm. See also the standard ISO-8601. |
|
clocDisabled |
Boolean value. The filter condition affected the count location of a specific street.
|
You can use the following relational operators:
- greaterThanOrEqual (≥)
- greaterThan (>)
- equal (=)
- lessThan (<)
- lessThanOrEqual (≤)
- notEqual (<>)
- isNull
Important: These operators are equivalent to maxequal (≥), max (>), equal (=), min (<), and minequal (≤) used in Optima v15.5.1602 and earlier. For backward compatibility, you can still use these old operators.
It can be a numeric threshold value you can set or it can be some special predefined key.
In case of special needs (for example, to filter all data whose speed are lower than the free flow speed of the street), the value can be set to -1.
If there is more than one rule, you can set two different filtering modes based on the attribute applyAllRules of the <FilterRules> node.
applyAllRules=true
In this case all rules matching the specified conditions are applied in the specified top-down sequence.
All the values of the reliabilitymultiplier attribute, associated to the applied rules, must be multiplied to get a unique value (see Example 3 → Example: combination of two rules).
applyAllRules=false
Only the strongest rule is applied.
Each rule has in the <action> node the value for the reliability multiplier.
By default the relevance of a rule is given by (1-value): the rule having this number as the highest one is the strongest rule.
This number can be explicitly overwritten by setting "the relevance" of the rule through the attribute effectRelevance which is associated to the <action> node.
The effectRelevance is a number between 0 and 1.
If there are two or more rules with the same "strength" (the same relevance), ONLY the first rule is run (considering the top-down order).
You can apply the rules according to a specified source (see → <Sources> node node).
Important: The rules specified within the tag <filterRules> must be applied to the source defined by the tag <tableName>.
Example 2
<configurations>
....
<harmonizer>
....
<sources>
<source>
<filterRules>
<rule>clocDisabledRule</rule>
<rule>speedzero</rule>
<rule>flowzero</rule>
<rule>speedmax</rule>
</filterRules>
<pivoting>true</pivoting>
<tableName>trafficstate_here</tableName>
</source>
<source>
<filterRules>
<rule>filterRule1</rule>
<rule>filterRule2</rule>
</filterRules>
<pivoting>true</pivoting>
<tableName>trafficstate_here</tableName>
</source>
</sources>
....
</harmonizer>
....
</configurations>
A rule named filterRule1 with six conditions, combined with a rule filterRule2 with two conditions.
Example 3
<configurations>
....
<harmonizer>
....
<filterRules>
<rule name="filterRule1">
<condition attr="speed" operator="lessThanOrEqual" value="50" />
<condition attr="density" operator="greaterThanOrEqual" value="25" />
<condition attr="flow" operator="equal" value="street.capacity" />
<condition attr="area" operator="equal" value="center" />
<condition attr="hierarchy" operator="greaterThan" value="2" />
<condition attr="status" operator="equal" value="1" />
<action attr="reliabilitymultiplier" value="0.3" />
</rule>
<rule name=" filterRule2">
<condition attr="startTime" operator="greaterThan" value="10:00" />
<condition attr="endTime" operator="lessThan" value="12:00" />
<action attr="reliabilitymultiplier" value="0.9" />
</rule>
</filterRules>
....
</harmonizer>
....
</configurations>
In a specific scenario where:
- Speed is lower than or equal to 50
- Density is lower than or equal to 25
- Flow is equivalent to the reference values over the streets (strt table)
- The measurement is associated to a street with geographic location center
- The measurement is associated to a street with a hierarchy greater than 2
- The measurement is associated to a traffic state with its status equal to 1
- The given time window is 10:00 to 12:00.
The data reliability:
- Is multiplied by the factor 0.3 if the data matches only filterRule1
- Is multiplied by the factor 0.9 if the data matches only filterRule2
- Is multiplied by the factor 0.27 if the data matches both rules (0.27=0.9·0.3)
- Remains unchanged for data that does not match any of the rules.
A rule named filterRule3, based on count locations elements:
Example 4
<configurations>
....
<harmonizer>
....
<filterRules>
<rule name="filterRule3">
<condition attr="clocDisabled" operator="equal" value="true" />
<action attr="reliabilitymultiplier" value="0" />
</rule>
</filterRules>
....
</harmonizer>
....
</configurations>
If the count locations associated to a given traffic state are disabled (in the cloc table for the corresponding street disable = true), you can set the corresponding reliability to 0.
Important: Data with its reliability set to 0 is skipped by the clustering procedure.
Important: Setting the attribute clocDisabled to true or false is equivalent, on Optima v15.5.1602 and earlier, to set it to 1 or 0 (backward-compatibility).
You can build filtering rules with several special settings.
Important: The filtering based on geographic locations or streets hierarchy are implemented from Optima v16.0.1604.
Filtering with stored values
The settings:
- value="street.capacity"
- value="street.speed"
- value="street.density")
Mean that the incoming values for flow (or speed or density) are compared with the values stored in the strt table (→ Architecture and Data Model).
Important: This setting is equivalent to setting value=−1 on Optima v15.5.1602 and earlier versions, which are maintained for backward-compatibility.
Filtering for geographic location
You can filter with data based on the geographic location (attr="area").
To achieve this, the DB must be configured with a JSON name/value pair:
name=area, value=center
This JSON must be stored in the strt table.
Filtering for street hierarchy
You can filter with data based on the geographic location (attr="hierarchy").
To achieve this, the DB must be configured, setting the field strt.hier.
Filtering for time window
You can filter data according to the time window which starts at the startTime and ends at the endTime.
To achieve this you must use a query with the parameters tableName.fdat and tableName.ldat, as long as:
tableName.ldat > startTime and tableName.fdat < endTime.
For example:
trafficstate.ldat > startTime and trafficstate.fdat < endTime.
For further information, see:
-
→ Harmonizer
-
→ Real-time traffic data.
The <sources>/<source> node contains elements to configure each datasource.
The currently supported sources are DB tables in the Optima trafficstate format (→ Real-time traffic data).
Important: The rules specified within the tag <filterRules> must be applied to the source defined by the tag <tableName>.
| Parameter | Description |
|---|---|
| weight |
Real value. Relative source weight, used to harmonize different sources. If the weight <= 0, the source is ignored. |
| tableName |
String value. Contains the table name that identifies the source. The table must be named according to the format trafficstate_SourceName, where SourceName is the suffix that identifies the external source providing data to be harmonized. For example:
Moreover, the table must have the same column and data format for all the columns, as all the trafficstate_* tables. See Layout_RealtimeTrafficData for further details. |
| filterRules |
Contains the rules to be applied while filtering input measurements. |
| filterRules/rule |
String value. Identifier of the rule to be applied. |
| pivoting |
Boolean value.
|
| pivoting/maxElements |
Integer value. Maximum number of elements to take into account to calculate the average. |
| pivoting/momentum |
Integer value. Order of the momentum m. |
| recalculateEquivalents |
Boolean value.
If not present in the configuration, it is considered as disabled. |
Example 5
In this example you have tow different sources:
- <tableName>trafficstate_here</tableName>
- <tableName>trafficstate_scats</tableName>
Important: For every source that you want to connect to get data to be harmonized, you need a specific table named trafficstate_SourceName.
For the first source the pivoting is enabled, while it is disabled for the second source.
Only for the first source can you also get harmonized results for equivalent vehicles according to specific transport systems and ignoring input measures related to equivalent vehicles.
<configurations>
....
<harmonizer>
....
<sources>
<source>
<filterRules>
<rule>clocDisabledRule</rule>
<rule>speedzero</rule>
</filterRules>
<pivoting>true</pivoting>
<tableName>trafficstate_here</tableName>
</source>
<source>
<filterRules>
<rule>filterRule1</rule>
<rule>filterRule2</rule>
</filterRules>
<pivoting>false</pivoting>
<tableName>trafficstate_scats</tableName>
<recalculateEquivalents>true</recalculateEquivalents>
</source>
</sources>
....
</harmonizer>
....
</configurations>
The main goal of clustering is to group the better available data for the final harmonization process.
The grouping procedure considers all the measurements in a certain clustering window and chooses the center of the cluster as the best point of accumulation where most of the measurements are grouped.
Different parameters are used to specify the width of the clustering window, for each type of traffic parameter (speed, flow, and density):
| Parameter | Description |
|---|---|
|
speedClusterWindow |
Real value (measured in Km/h). Width of the clustering window for speed measurements. |
|
flowClusterWindow |
Real value (measured in Veh/h). Width of the clustering window for flow measurements. |
Clustering is performed for each source and each associated transport system, on each directional street and lane separately.
The parameters are valid globally for all sources, transport systems, directional streets and lanes; thus, you cannot set them for a specific source in a way and for another source in a different way.
Tip: Clustering cannot be disabled, but if you set all parameters to very high values, the process doesn't cut any data, thus the clustering is virtually disabled and all measured data is forwarded to the harmonization phase.
- The result of the aggregation process.
- Other parameters.
On Optima you can configure different destinations to write data produced by the Harmonizer.
A destination generally contains an output table of the DB where the following are stored:
These parameters control archiving and special processing during the aggregation process.
Important: A destination must contain a table created according to the tsta table schema of the Optima DB.
You can also configure a destination associated to Kafka when the Harmonizer must work with the MLF module (see → MLF-Harmonizer communication).
| Parameter | Description |
|---|---|
| tableName |
String value. Contains the results of the aggregation process. |
| keepOldData | Defines settings to manage old data in a destination table. If this tag is omitted, nothing is deleted. |
| keepOldData/timeWindow |
Integer value. Contains a value representing the duration of the time window after which data stored in tableName is deleted. Any positive value can be set, with two special values:
The unit of measurement is set in keepOldData/timeWindowIsIn. |
| keepOldData/timeWindowIsIn |
Sting value. Contains the unit of measurement for keepOldData.timeWindow. The default for PostgreSQL is minutes. |
| preQueries |
Contains an optional set of one or more queries that are specified in the nodes <query>...</query>. The set of queries is executed before writing data into tableName. |
| postQueries |
Contains an optional set of one or more queries, specified in the nodes <query>...</query>. The set of queries is executed after writing data into tableName. |
|
inmemorytransfer/lookupnames/lookupname |
String value (optional). Specify one or more JNDI lookup names for which other modules have registered an instance of the Java interface HarmonizerInMemorySink. The interface manages the list of Java Objects representing Harmonizer input and output objects. Important: For long processes, it is necessary to set a dedicated thread to reduce any possible interference regarding the data involved. You can also use the interface HarmonizerInMemorySinkWithExecutor to optimize the memory transfer action. |
| skipWriteToDb |
Boolean value (optional). It can be set:
This parameter does not influence the execution of preQueries, postQueries, and keepOldData |
Example 6
In the example:
- One source filtered with two rules and pivoting enabled.
- One source filtered with only one rule and pivoting disabled.
- No data is written in the DB table tsta_rtlm (destination), because skipWriteToDb is set at true.
- Nothing is deleted (keepOldData/timeWindow = -1)
- It is necessary to deploy a module by providing an implementation for the HarmonizerInMemorySink, and to register it by setting the tag lookupname with the name of the module.
- One block of preQueries with two queries.
- One block of postQueries with only one query.
- The last <destination> node contains info related to communication with Kafka.
<configurations>
....
<harmonizer>
....
<sources>
<source>
<filterRules>
<rule>filterRule1</rule>
<rule>filterRule2</rule>
</filterRules>
<pivoting>true</pivoting>
<tableName>trafficstate_here</tableName>
<recalculateEquivalents>false</recalculateEquivalents>
</source>
<source>
<filterRules>
<rule>filterRule3</rule>
</filterRules>
<pivoting>false</pivoting>
<tableName>trafficstate_scats</tableName>
<recalculateEquivalents>true</recalculateEquivalents>
</source>
</sources>
<destinations>
<destination>
<tableName>tsta_rltm</tableName>
<skipWriteToDb>true</skipWriteToDb>
<keepOldData><timeWindow>-1</timeWindow></keepOldData>
<inmemorytransfer>
<lookupnames>
<lookupname>theKeyUsedToRegisterInInitialContext</lookupname>
</lookupnames>
</inmemorytransfer>
<preQueries>
<query>update TABLE_NAME_A set COLUMN_NAME = val_1;</query>
<query>update TABLE_NAME_B set COLUMN_NAME = val_2;</query>
</preQueries>
<postQueries>
<query>update TABLE_NAME_C set COLUMN_NAME = val_3;</query>
</postQueries>
</destination>
<destination>
<type>KAFKA</type>
<bootstrapAddress>192.168.50.85:9092</bootstrapAddress>
<outputTopicName>sf-harmonizerdata_${env:ENVIRONMENTID}</outputTopicName>
<zoneId>Europe/Paris</zoneId>
</destination>
</destinations>
....
</harmonizer>
....
</configurations>