Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • urbanite/open/traffic-simulation-dss
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (10)
# deployed in city # deployed in city
URBANITE_CITY="amsterdam" URBANITE_CITY="amsterdam"
# UI settings for default map position and zoom
CITY_COORDINATES="52.3676,4.9041" # Amsterdam
# CITY_COORDINATES="43.2630,-2.9350" # Bilbao
# CITY_COORDINATES="60.1566, 24.9118" # Helsinki
# CITY_COORDINATES="38.1937, 15.5542" # Messina
CITY_ZOOM_LEVEL="15"
# server settings # server settings
DSS_PORT=8083 DSS_PORT=8083
FLASK_SECRET_KEY="secret" FLASK_SECRET_KEY="secret"
......
This diff is collapsed.
...@@ -5,6 +5,7 @@ import os ...@@ -5,6 +5,7 @@ import os
import json import json
import threading import threading
import logging import logging
import time
from typing import Dict, List, Union from typing import Dict, List, Union
from pyproj import Transformer from pyproj import Transformer
...@@ -25,6 +26,29 @@ city = app.dotenv["URBANITE_CITY"] ...@@ -25,6 +26,29 @@ city = app.dotenv["URBANITE_CITY"]
data_dir = f"{app.dotenv['DATA_DIR']}/{app.dotenv['URBANITE_CITY']}" data_dir = f"{app.dotenv['DATA_DIR']}/{app.dotenv['URBANITE_CITY']}"
# DEBUG
@app.route("/dss/geojson/test/<sim_id>")
def geojsontest(sim_id):
app.logger.debug("starting test")
kpi_name = "pedestrianTravelTime"
app.logger.debug("starting load network and events")
network, events = utils.get_network_and_events(sim_id)
app.logger.debug("done")
app.logger.debug("starting calculate pedestrian travel time")
start_t = time.time()
pedestrianTravelTime = events.pedestrian_travel_time()["detailed_long_trips"]
delta_t = time.time() - start_t
app.logger.debug("done in %s s", delta_t)
app.logger.debug("starting write geojson pedestrian trips")
start_t = time.time()
pedestrianTravelTime = write_geojson_pedestrian_trips(
pedestrianTravelTime, network, sim_id
)
delta_t = time.time() - start_t
app.logger.info("written pedestrianTravelTime in %s s", delta_t)
return pedestrianTravelTime
@app.route("/dss/geojson/<int:sim_id>/<kpi_name>") @app.route("/dss/geojson/<int:sim_id>/<kpi_name>")
def get_kpi_geojson(sim_id, kpi_name): def get_kpi_geojson(sim_id, kpi_name):
sim_dir = utils.get_sim_dir_names([sim_id])[0] sim_dir = utils.get_sim_dir_names([sim_id])[0]
...@@ -59,6 +83,10 @@ def get_kpi_vis_info(): ...@@ -59,6 +83,10 @@ def get_kpi_vis_info():
"buttonLabel": "Pedestrian Travel Time", "buttonLabel": "Pedestrian Travel Time",
}, },
{"buttonValue": "dailyInternalTravels", "buttonLabel": "Internal Trips"}, {"buttonValue": "dailyInternalTravels", "buttonLabel": "Internal Trips"},
{
"buttonValue": "noisePollution",
"buttonLabel": "Noise Pollution",
},
] ]
elif city == "amsterdam": elif city == "amsterdam":
kpi_info = [ kpi_info = [
...@@ -71,10 +99,6 @@ def get_kpi_vis_info(): ...@@ -71,10 +99,6 @@ def get_kpi_vis_info():
elif city == "helsinki": elif city == "helsinki":
kpi_info = [ kpi_info = [
{"buttonValue": "pollution", "buttonLabel": "Pollution"}, {"buttonValue": "pollution", "buttonLabel": "Pollution"},
{
"buttonValue": "accousticPollution",
"buttonLabel": "Accoustic Pollution - WIP",
},
{ {
"buttonValue": "congestionsAndBottlenecks", "buttonValue": "congestionsAndBottlenecks",
"buttonLabel": "Congestions and Bottlenecks", "buttonLabel": "Congestions and Bottlenecks",
...@@ -95,7 +119,7 @@ def get_kpi_vis_info(): ...@@ -95,7 +119,7 @@ def get_kpi_vis_info():
"buttonValue": "averageSpeedOfPublicTransport", "buttonValue": "averageSpeedOfPublicTransport",
"buttonLabel": "Avg Public Transport Speed", "buttonLabel": "Avg Public Transport Speed",
}, },
{"buttonValue": "numberOfBikeTrips", "buttonLabel": "Number of Bike Trips"}, # {"buttonValue": "numberOfBikeTrips", "buttonLabel": "Number of Bike Trips"},
{ {
"buttonValue": "shareOfVehicles", "buttonValue": "shareOfVehicles",
"buttonLabel": "Share of Trips per Mode", "buttonLabel": "Share of Trips per Mode",
...@@ -114,33 +138,36 @@ def get_kpi_data_and_write(network, events, sim_id): ...@@ -114,33 +138,36 @@ def get_kpi_data_and_write(network, events, sim_id):
""" """
get_kpi_data_final_geojson is a list of links with kpis calculated get_kpi_data_final_geojson is a list of links with kpis calculated
""" """
app.logger.info("getting kpi data to write") app.logger.info(f"getting kpi data to write, city {city}")
results = {} results = {}
emisson_object = kpis_module.get_emissions(sim_id, network) emisson_object = kpis_module.get_emissions(sim_id, network)
rush_hour = utils.get_max_traffic_time(sim_id)
if network.city == "bilbao": if network.city == "bilbao":
if emisson_object is not None: if emisson_object is not None:
pollution = emisson_object.total_emissions_by_link() pollution = emisson_object.total_emissions_by_link()
app.logger.info("Emission by link") app.logger.info("Emission by link")
write_geojson(pollution, "pollution", network, sim_id) write_geojson_links(pollution, "pollution", network, sim_id)
app.logger.info("written emission") app.logger.info("written emission")
pedestrianTravelTime = events.pedestrian_travel_time()[0] pedestrianTravelTime = events.pedestrian_travel_time()["detailed_long_trips"]
app.logger.info("Pedestrian travel time") app.logger.info("Pedestrian travel time")
write_geojson(pedestrianTravelTime, "pedestrianTravelTime", network, sim_id) write_geojson_pedestrian_trips(pedestrianTravelTime, network, sim_id)
app.logger.info("written pedestrianTravelTime") app.logger.info("written pedestrianTravelTime")
dailyInternalTravels = events.vehicles_count_per_link() dailyInternalTravels = events.vehicles_count_per_link()
app.logger.info("Vehicles count per link") app.logger.info("Vehicles count per link")
write_geojson(dailyInternalTravels, "dailyInternalTravels", network, sim_id) write_geojson_links(
dailyInternalTravels, "dailyInternalTravels", network, sim_id
)
app.logger.info("written dailyInternalTravels") app.logger.info("written dailyInternalTravels")
elif network.city == "helsinki": elif network.city == "helsinki":
if emisson_object is not None: if emisson_object is not None:
pollution = emisson_object.total_emissions_by_link() pollution = emisson_object.total_emissions_by_link()
app.logger.info("total emissions by link") app.logger.info("total emissions by link")
write_geojson(pollution, "pollution", network, sim_id) write_geojson_links(pollution, "pollution", network, sim_id)
app.logger.info("written emission") app.logger.info("written emission")
# acousticPollution = None # TODO integrate with Inaki # acousticPollution = None # TODO integrate with Inaki
...@@ -148,9 +175,11 @@ def get_kpi_data_and_write(network, events, sim_id): ...@@ -148,9 +175,11 @@ def get_kpi_data_and_write(network, events, sim_id):
# write_geojson(pollution, "pollution", network, sim_id) # write_geojson(pollution, "pollution", network, sim_id)
# app.logger.info("written emission") # app.logger.info("written emission")
congestionsAndBottlenecks = events.get_congested_links() congestionsAndBottlenecks = events.get_congested_links(rush_hour)[
"congested_links"
]
app.logger.info("congestions and bottlenecks") app.logger.info("congestions and bottlenecks")
write_geojson( write_geojson_links(
congestionsAndBottlenecks, "congestionsAndBottlenecks", network, sim_id congestionsAndBottlenecks, "congestionsAndBottlenecks", network, sim_id
) )
app.logger.info("written congestionsAndBottlenecks") app.logger.info("written congestionsAndBottlenecks")
...@@ -159,20 +188,21 @@ def get_kpi_data_and_write(network, events, sim_id): ...@@ -159,20 +188,21 @@ def get_kpi_data_and_write(network, events, sim_id):
app.logger.info("harbour area traffic flow - TODO") app.logger.info("harbour area traffic flow - TODO")
elif network.city == "messina": elif network.city == "messina":
if emisson_object is not None: if emisson_object is not None:
pollution = emisson_object.total_emissions_by_link() pollution = emisson_object.total_emissions_by_link()
app.logger.info("Emission by link") app.logger.info("Emission by link")
write_geojson(pollution, "pollution", network, sim_id) write_geojson_links(pollution, "pollution", network, sim_id)
app.logger.info("written emission") app.logger.info("written emission")
publicTransportUse = events.public_transport_use_geojson() publicTransportUse = events.public_transport_use_geojson()
app.logger.info("public transport use") app.logger.info("public transport use")
write_geojson(publicTransportUse, "publicTransportUse", network, sim_id) write_geojson_links(publicTransportUse, "publicTransportUse", network, sim_id)
app.logger.info("written public transport use") app.logger.info("written public transport use")
averageSpeedOfPublicTransport = events.average_bus_speed_geojson() # TODO averageSpeedOfPublicTransport = events.average_bus_speed_geojson()
app.logger.info("average speed of public transport") app.logger.info("average speed of public transport")
write_geojson( write_geojson_links(
averageSpeedOfPublicTransport, averageSpeedOfPublicTransport,
"averageSpeedOfPublicTransport", "averageSpeedOfPublicTransport",
network, network,
...@@ -182,46 +212,48 @@ def get_kpi_data_and_write(network, events, sim_id): ...@@ -182,46 +212,48 @@ def get_kpi_data_and_write(network, events, sim_id):
numberOfBikeTrips = events.vehicles_count_per_link(only="bike") numberOfBikeTrips = events.vehicles_count_per_link(only="bike")
app.logger.info("number of bike trips") app.logger.info("number of bike trips")
write_geojson(numberOfBikeTrips, "numberOfBikeTrips", network, sim_id) write_geojson_links(numberOfBikeTrips, "numberOfBikeTrips", network, sim_id)
app.logger.info("written numberOfBikeTrips") app.logger.info("written numberOfBikeTrips")
shareOfVehicles = vehicleCountToShareGeojson(events.vehicles_count_per_link()) shareOfVehicles = vehicleCountToShareGeojson(events.vehicles_count_per_link())
# shareOfPublicTransport = events.share_public_transport()
app.logger.info("share of vehicles") app.logger.info("share of vehicles")
write_geojson(shareOfVehicles, "shareOfVehicles", network, sim_id) write_geojson_links(shareOfVehicles, "shareOfVehicles", network, sim_id)
app.logger.info("written shareOfVehicles") app.logger.info("written shareOfVehicles")
dailyInternalTravels = events.vehicles_count_per_link() dailyInternalTravels = events.vehicles_count_per_link()
app.logger.info("daily internal travels") app.logger.info("daily internal travels")
write_geojson(dailyInternalTravels, "dailyInternalTravels", network, sim_id) write_geojson_links(
dailyInternalTravels, "dailyInternalTravels", network, sim_id
)
app.logger.info("written dailyInternalTravels") app.logger.info("written dailyInternalTravels")
elif network.city == "amsterdam": elif network.city == "amsterdam":
if emisson_object is not None: if emisson_object is not None:
pollution = emisson_object.total_emissions_by_link() pollution = emisson_object.total_emissions_by_link()
app.logger.info("got emissions by link") app.logger.info("got emissions by link")
write_geojson(pollution, "pollution", network, sim_id) write_geojson_links(pollution, "pollution", network, sim_id)
app.logger.info("written pollution") app.logger.info("written pollution")
bikeability = events.bikeability_index() bikeability = events.bikeability_index()
app.logger.info("bikeability") app.logger.info("bikeability")
write_geojson(bikeability, "bikeability", network, sim_id) write_geojson_links(bikeability, "bikeability", network, sim_id)
app.logger.info("written bikeability") app.logger.info("written bikeability")
bike_safety = events.bike_safety_index() bike_safety = events.bike_safety_index()
app.logger.info("bike safety") app.logger.info("bike safety")
write_geojson(bike_safety, "bikeSafety", network, sim_id) write_geojson_links(bike_safety, "bikeSafety", network, sim_id)
app.logger.info("written bikeSafety") app.logger.info("written bikeSafety")
bike_intensity = events.vehicles_count_per_link() bike_intensity = events.vehicles_count_per_link()
app.logger.info("bikeIntensity") app.logger.info("bikeIntensity")
write_geojson(bike_intensity, "bikeIntensity", network, sim_id) write_geojson_links(bike_intensity, "bikeIntensity", network, sim_id)
app.logger.info("written bikeIntensity") app.logger.info("written bikeIntensity")
bike_congestion = events.get_congested_links(vehicle_mode="bicycle") bike_congestion = events.get_congested_links(rush_hour, vehicle_mode="bicycle")[
"congested_links"
]
app.logger.info("bikeCongestion") app.logger.info("bikeCongestion")
write_geojson(bike_congestion, "bikeCongestion", network, sim_id) write_geojson_links(bike_congestion, "bikeCongestion", network, sim_id)
app.logger.info("written bikeCongestion") app.logger.info("written bikeCongestion")
app.logger.info("done") app.logger.info("done")
...@@ -249,19 +281,62 @@ def vehicleCountToShareGeojson(data_per_link): ...@@ -249,19 +281,62 @@ def vehicleCountToShareGeojson(data_per_link):
return results return results
def write_geojson(kpi_data, kpi_name, network, sim_id): def write_geojson_pedestrian_trips(kpi_data, network, sim_id):
"""
Write a pedestrian kpi_data object to a file.
kpi_data should be a list [{"start_link": _, "end_link": _, "average_time": _ } ]
"""
data = {"type": "FeatureCollection", "features": []}
crs_transformer = Transformer.from_crs(network.crs_epsg, "epsg:4326")
# crs_transformer = Transformer.from_crs("epsg:2062", "epsg:4326")
for element in kpi_data:
if element["average_time"] < 3600.0:
continue
s_link = network.get_link(element["start_link"])
s_nodes = [network.get_node(s_link["from"]), network.get_node(s_link["to"])]
s_point = (
(float(s_nodes[0]["x"]) + float(s_nodes[1]["x"])) / 2.0,
(float(s_nodes[0]["y"]) + float(s_nodes[1]["y"])) / 2.0,
)
s_point = tuple(reversed(crs_transformer.transform(*s_point)))
e_link = network.get_link(element["end_link"])
e_nodes = [network.get_node(e_link["from"]), network.get_node(e_link["to"])]
e_point = (
(float(e_nodes[0]["x"]) + float(e_nodes[1]["x"])) / 2.0,
(float(e_nodes[0]["y"]) + float(e_nodes[1]["y"])) / 2.0,
)
e_point = tuple(reversed(crs_transformer.transform(*e_point)))
data["features"].append(
{
"type": "Feature",
"properties": {"long pedestrian trip": element["average_time"] / (60)},
"geometry": {"type": "LineString", "coordinates": [s_point, e_point]},
}
)
filename = get_filename(sim_id, "pedestrianTravelTime")
with open(filename, "w") as fp:
json.dump(data, fp, indent=2)
return data
def write_geojson_links(kpi_data, kpi_name, network, sim_id):
""" """
Write any kpi_data object to a file. Write a per link kpi_data object to a file.
kpi_data should be a dict { "link_id": {kpi1, kpi2, ...}, ...} kpi_data should be a dict { "link_id": {kpi1, kpi2, ...}, ...}
""" """
logger.debug("KPI DATA to be written: \n%s", kpi_data) # logger.debug("KPI DATA to be written: \n%s", kpi_data)
data = {"type": "FeatureCollection", "features": []} data = {"type": "FeatureCollection", "features": []}
crs_transformer = Transformer.from_crs(network.crs_epsg, "epsg:4326") crs_transformer = Transformer.from_crs(network.crs_epsg, "epsg:4326")
logger.warning("network city: %s, network epsg: %s", network.city, network.crs_epsg) logger.warning("network city: %s, network epsg: %s", network.city, network.crs_epsg)
for link_id, link_data in kpi_data.items(): for link_id, link_data in kpi_data.items():
if link_id.startswith("pt"): if link_id.startswith("pt"):
continue continue
if len(link_data) < 1: # if isinstance(link_data, float):
# link_data = {kpi_name: link_data}
elif len(link_data) < 1:
continue continue
link = network.get_link(link_id) link = network.get_link(link_id)
...@@ -289,7 +364,7 @@ def write_geojson(kpi_data, kpi_name, network, sim_id): ...@@ -289,7 +364,7 @@ def write_geojson(kpi_data, kpi_name, network, sim_id):
filename = get_filename(sim_id, kpi_name) filename = get_filename(sim_id, kpi_name)
with open(filename, "w") as fp: with open(filename, "w") as fp:
json.dump(data, fp) json.dump(data, fp, indent=2)
def get_filename(sim_id, kpi_name): def get_filename(sim_id, kpi_name):
......
...@@ -5,16 +5,10 @@ import time ...@@ -5,16 +5,10 @@ import time
import json import json
import os.path import os.path
import logging import logging
from typing import Union, List
import flask import flask
from jsonschema import validate from jsonschema import validate
import jsonpath_ng
from flask import Blueprint from flask import Blueprint
from flask import current_app as app from flask import current_app as app
from app.netedit.network import Network
from app.netedit.events import TimeSlot, VehicleEvents from app.netedit.events import TimeSlot, VehicleEvents
from app.netedit.events import EmissionEvents from app.netedit.events import EmissionEvents
from app import utils from app import utils
...@@ -30,15 +24,15 @@ assets_dir = app.dotenv["ASSETS_DIR"] ...@@ -30,15 +24,15 @@ assets_dir = app.dotenv["ASSETS_DIR"]
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# DEBUG # DEBUG
# @app.route("/dss/test/<int:simulation_id>", methods=["GET"]) @app.route("/dss/test/<int:simulation_id>", methods=["GET"])
# def test_kpi_congestions(simulation_id): def test_kpi_congestions(simulation_id):
# rush_hour = utils.get_max_traffic_time(simulation_id) app.logger.info("test called")
# network, events = utils.get_network_and_events(simulation_id) # rush_hour = utils.get_max_traffic_time(simulation_id)
# # result = events.get_congested_links(None, None, None, rush_hour) network, events = utils.get_network_and_events(simulation_id)
# ll = network.nearby_links_range("1364605710", 160) # ll = network.nearby_links_range("1691828242", 500)
# app.logger.debug(ll) result = events.bikeability_index()
# result = events.average_bus_speed(local_links=ll) # app.logger.info("result:\n%s", result)
# return {"avg_bus_speed": result} return {"res": result}
@app.route("/dss/kpis/<city_id>/<int:simulation_id>", methods=["GET"]) @app.route("/dss/kpis/<city_id>/<int:simulation_id>", methods=["GET"])
def get_kpis_for_city(city_id, simulation_id): def get_kpis_for_city(city_id, simulation_id):
...@@ -61,7 +55,6 @@ def get_kpis_for_city(city_id, simulation_id): ...@@ -61,7 +55,6 @@ def get_kpis_for_city(city_id, simulation_id):
if city_id == "bilbao": if city_id == "bilbao":
emission_object = get_emissions(simulation_id, network) emission_object = get_emissions(simulation_id, network)
rush_hour_time = utils.get_max_traffic_time(simulation_id) # rush hour time rush_hour_time = utils.get_max_traffic_time(simulation_id) # rush hour time
results = prepare_results_for_bilbao( results = prepare_results_for_bilbao(
simulation_id, network, events, emission_object, rush_hour_time simulation_id, network, events, emission_object, rush_hour_time
) )
...@@ -265,7 +258,7 @@ def prepare_results_for_bilbao( ...@@ -265,7 +258,7 @@ def prepare_results_for_bilbao(
""" """
Creates the kpis JSON object for Bilbao. Creates the kpis JSON object for Bilbao.
""" """
app.logger.info("Preparing results for bilbao %s", timeslot) app.logger.info("prepare_results_for_bilbao with timeslot %s", timeslot)
results = {"simulation_id": simulation_id} results = {"simulation_id": simulation_id}
results["bilbao"] = { results["bilbao"] = {
"cityWide": {"traffic": {}, "pollution": {}}, "cityWide": {"traffic": {}, "pollution": {}},
...@@ -279,17 +272,15 @@ def prepare_results_for_bilbao( ...@@ -279,17 +272,15 @@ def prepare_results_for_bilbao(
results["bilbao"]["cityWide"]["pollution"] = kpi results["bilbao"]["cityWide"]["pollution"] = kpi
results["bilbao"]["cityWide"]["traffic"] = {} results["bilbao"]["cityWide"]["traffic"] = {}
kpi = events.pedestrian_travel_time(timeslot) kpi = events.pedestrian_travel_time(timeslot=timeslot)
results["bilbao"]["cityWide"]["traffic"]["pedestrianTravelTime"] = kpi[0] results["bilbao"]["cityWide"]["traffic"]["pedestrianTravelTime"] = kpi["average_trip_duration"]
# app.logger.info(kpi[0]) # app.logger.info(kpi[0])
kpi = events.vehicles_count(timeslot) kpi = events.vehicles_count(timeslot)
results["bilbao"]["cityWide"]["traffic"]["dailyInternalBikeTravels"] = kpi[ results["bilbao"]["cityWide"]["traffic"]["dailyInternalBikeTravels"] = kpi["bike_count"]
"bike_count" #
] # # local
# # moyua center position in EPSG 32630
# local
# moyua center position in EPSG 32630
moyua_point = {"x": 505277.192210581, "y": 4790023.046986237} moyua_point = {"x": 505277.192210581, "y": 4790023.046986237}
local_links = network.nearby_links_range(moyua_point, delta=200) local_links = network.nearby_links_range(moyua_point, delta=200)
...@@ -298,43 +289,20 @@ def prepare_results_for_bilbao( ...@@ -298,43 +289,20 @@ def prepare_results_for_bilbao(
results["bilbao"]["local"]["pollution"] = kpi results["bilbao"]["local"]["pollution"] = kpi
results["bilbao"]["local"]["traffic"] = {} results["bilbao"]["local"]["traffic"] = {}
kpi = events.pedestrian_travel_time(local_links, timeslot) # kpi = events.pedestrian_travel_time(local_links, timeslot)
results["bilbao"]["local"]["traffic"]["pedestrianTravelTime"] = kpi[0] # makes no sense, can't have long trips in a small area
results["bilbao"]["local"]["traffic"]["pedestrianTravelTime"] = 0
kpi = events.vehicles_count(local_links, timeslot) kpi = events.vehicles_count(local_links, timeslot)
results["bilbao"]["local"]["traffic"]["dailyInternalBikeTravels"] = kpi[ results["bilbao"]["local"]["traffic"]["dailyInternalBikeTravels"] = kpi[
"bike_count" "bike_count"
] ]
# other
moyua_square_links = [
"22691",
"22692",
"51616",
"51617",
"52446",
"52447",
"45116",
"45117",
"45118",
"37953",
"45140",
"33748",
"33749",
"2484",
"2485",
"26087",
"47250",
"26024",
"43904",
"20252",
]
# If timeslot is not given, we are only interested in rush_hour_time # If timeslot is not given, we are only interested in rush_hour_time
if not timeslot: if not timeslot:
timeslot = TimeSlot(delta=3600, slot_index=rush_hour_time) timeslot = TimeSlot(delta=3600, slot_index=rush_hour_time)
_, total_capacity = events.capacity_to_moyua(moyua_square_links, timeslot) total_capacity = events.capacity_to_moyua(local_links, timeslot)
results["bilbao"]["entryCapacityToCenter"] = total_capacity results["bilbao"]["entryCapacityToCenter"] = total_capacity
return results return results
...@@ -360,19 +328,19 @@ def prepare_results_for_amsterdam(simulation_id, network, events, timeslot=None) ...@@ -360,19 +328,19 @@ def prepare_results_for_amsterdam(simulation_id, network, events, timeslot=None)
if kpi == 0: if kpi == 0:
kpi = 1 # TODO this needs to be fixes, as above kpi = 1 # TODO this needs to be fixes, as above
results["amsterdam"]["cityWide"]["traffic"]["bikeIntensity"] = kpi results["amsterdam"]["cityWide"]["traffic"]["bikeIntensity"] = kpi
app.logger.warn("bike intensity: %s", kpi) # app.logger.warn("bike intensity: %s", kpi)
kpi = events.get_congested_links(rush_hour, vehicle_mode="bicycle")["congestion_length"] kpi = events.get_congested_links(rush_hour, vehicle_mode="bicycle")["congestion_length"]
results["amsterdam"]["cityWide"]["traffic"]["bikeCongestion"] = kpi results["amsterdam"]["cityWide"]["traffic"]["bikeCongestion"] = kpi
app.logger.warn("bike congestion: %s", kpi) # app.logger.warn("bike congestion: %s", kpi)
kpi = events.bike_safety_aggregate(events.bike_safety_index(timeslot)) kpi = events.bike_safety_aggregate(events.bike_safety_index(timeslot))
results["amsterdam"]["cityWide"]["bikeInfrastructure"]["bikeSafety"] = kpi results["amsterdam"]["cityWide"]["bikeInfrastructure"]["bikeSafety"] = kpi
app.logger.warn("bike infrastructure: %s", kpi) # app.logger.warn("bike infrastructure: %s", kpi)
kpi = events.bikeability_aggregate(events.bikeability_index()) kpi = events.bikeability_aggregate(events.bikeability_index())
results["amsterdam"]["cityWide"]["bikeInfrastructure"]["bikeability"] = kpi results["amsterdam"]["cityWide"]["bikeInfrastructure"]["bikeability"] = kpi
app.logger.warn("bikeability: %s", kpi) # app.logger.warn("bikeability: %s", kpi)
# local # local
app.logger.info("local kpis...") app.logger.info("local kpis...")
...@@ -383,19 +351,19 @@ def prepare_results_for_amsterdam(simulation_id, network, events, timeslot=None) ...@@ -383,19 +351,19 @@ def prepare_results_for_amsterdam(simulation_id, network, events, timeslot=None)
kpi = events.vehicles_count(local_links=local_links, timeslot=timeslot)["bike_count"] kpi = events.vehicles_count(local_links=local_links, timeslot=timeslot)["bike_count"]
results["amsterdam"]["local"]["traffic"]["bikeIntensity"] = kpi results["amsterdam"]["local"]["traffic"]["bikeIntensity"] = kpi
app.logger.warn("bikeintensity: %s", kpi) # app.logger.warn("bikeintensity: %s", kpi)
kpi = events.get_congested_links(rush_hour, vehicle_mode="bicycle", local_links=local_links)["congestion_length"] kpi = events.get_congested_links(rush_hour, vehicle_mode="bicycle", local_links=local_links)["congestion_length"]
results["amsterdam"]["local"]["traffic"]["bikeCongestion"] = kpi results["amsterdam"]["local"]["traffic"]["bikeCongestion"] = kpi
app.logger.info("bike congestion: %s", kpi) # app.logger.info("bike congestion: %s", kpi)
kpi = events.bike_safety_aggregate(events.bike_safety_index(timeslot)) kpi = events.bike_safety_aggregate(events.bike_safety_index(timeslot))
results["amsterdam"]["local"]["bikeInfrastructure"]["bikeSafety"] = kpi results["amsterdam"]["local"]["bikeInfrastructure"]["bikeSafety"] = kpi
app.logger.info("bike safety: %s", kpi) # app.logger.info("bike safety: %s", kpi)
kpi = events.bikeability_aggregate(events.bikeability_index()) kpi = events.bikeability_aggregate(events.bikeability_index())
results["amsterdam"]["local"]["bikeInfrastructure"]["bikeability"] = kpi results["amsterdam"]["local"]["bikeInfrastructure"]["bikeability"] = kpi
app.logger.info("bikeability: %s", kpi) # app.logger.info("bikeability: %s", kpi)
return results return results
...@@ -410,11 +378,11 @@ def prepare_results_for_helsinki( ...@@ -410,11 +378,11 @@ def prepare_results_for_helsinki(
results["simulation_id"] = simulation_id results["simulation_id"] = simulation_id
results["helsinki"] = { results["helsinki"] = {
"cityWide": { "cityWide": {
"pollution": {"acousticPollution": -1}, "pollution": {"acousticPollution": 3},
"congestionsAndBottlenecks": -1, "congestionsAndBottlenecks": -1,
}, },
"local": { "local": {
"pollution": {"acousticPollution": -1}, "pollution": {"acousticPollution": 3},
"congestionsAndBottlenecks": -1, "congestionsAndBottlenecks": -1,
}, },
"harbourAreaTrafficFlow": -1, "harbourAreaTrafficFlow": -1,
...@@ -425,20 +393,16 @@ def prepare_results_for_helsinki( ...@@ -425,20 +393,16 @@ def prepare_results_for_helsinki(
kpi = emission_object.emissions_total(timeslot) kpi = emission_object.emissions_total(timeslot)
results["helsinki"]["cityWide"]["pollution"]["emissions"] = kpi results["helsinki"]["cityWide"]["pollution"]["emissions"] = kpi
# kpi = events.get_congested_links() # TODO: fix, this returns a big list of some links, instead should be a number?
results["helsinki"]["cityWide"][ results["helsinki"]["cityWide"][
"congestionsAndBottlenecks" "congestionsAndBottlenecks"
] = events.get_congested_links(rush_hour_time)["congestion_length"] ] = events.get_congested_links(rush_hour_time)["congestion_length"]
# local # local
# Jatkasaari center position in EPSG 32634 local_links = network.nearby_links_range("4449417566", delta=500)
jatkasaari_point = {"x": 717321.1395281242, "y": 6675402.725594756}
local_links = network.nearby_links_range(jatkasaari_point, delta=500)
network, events = utils.get_network_and_events(simulation_id, local=local_links)
if emission_object != None: if emission_object != None:
kpi = emission_object.emissions_total_links_sum(local_links, timeslot) kpi = emission_object.emissions_total_links_sum(local_links, timeslot)
app.logger.info(f"EMISSIONS: {kpi}") # app.logger.info(f"EMISSIONS: {kpi}")
results["helsinki"]["local"]["pollution"] = kpi results["helsinki"]["local"]["pollution"] = kpi
kpi = emission_object.total_emissions_by_link(local_links, timeslot) kpi = emission_object.total_emissions_by_link(local_links, timeslot)
...@@ -456,6 +420,7 @@ def prepare_results_for_messina(simulation_id, network, events, timeslot=None): ...@@ -456,6 +420,7 @@ def prepare_results_for_messina(simulation_id, network, events, timeslot=None):
""" """
Prepares the kpis JSON object for Messina. Prepares the kpis JSON object for Messina.
""" """
app.logger.info("prepare_results_for_messina with timeslot %s", timeslot)
results = {} results = {}
results["simulation_id"] = simulation_id results["simulation_id"] = simulation_id
results["messina"] = {"cityWide": {}, "local": {}} results["messina"] = {"cityWide": {}, "local": {}}
...@@ -486,10 +451,7 @@ def prepare_results_for_messina(simulation_id, network, events, timeslot=None): ...@@ -486,10 +451,7 @@ def prepare_results_for_messina(simulation_id, network, events, timeslot=None):
# Local # Local
results["messina"]["local"]["publicTransport"] = {} results["messina"]["local"]["publicTransport"] = {}
# TODO: Check again where these changes are in convert from/to appropriate EPSG local_links = network.nearby_links_range("1691828242", delta=1800)
point_near_changes = {"x": 547873.917444, "y": 4224853.800459}
local_links = network.nearby_links_range(point_near_changes, delta=500)
del vehicles_count
vehicles_count = events.vehicles_count(local_links=local_links, timeslot=timeslot) vehicles_count = events.vehicles_count(local_links=local_links, timeslot=timeslot)
kpi = events.average_bus_speed(local_links=local_links, timeslot=timeslot) kpi = events.average_bus_speed(local_links=local_links, timeslot=timeslot)
results["messina"]["local"]["publicTransport"][ results["messina"]["local"]["publicTransport"][
......
This diff is collapsed.
...@@ -26,13 +26,11 @@ class Network: ...@@ -26,13 +26,11 @@ class Network:
:param path: path to the network.xml file :param path: path to the network.xml file
:param type: string :param type: string
:param crs_epsg: the coordinate reference system used. :param crs_epsg: the coordinate reference system used.
Network files used by MATSim use CRS epsg 2062.
:param type: string :param type: string
""" """
self.city = city self.city = city
# used for importing counting locations, which use a different CRS
if city == "bilbao": if city == "bilbao":
self.crs_epsg = "32630" self.crs_epsg = "32630"
elif city == "amsterdam": elif city == "amsterdam":
...@@ -84,7 +82,16 @@ class Network: ...@@ -84,7 +82,16 @@ class Network:
elif child.tag == "links": elif child.tag == "links":
for link in child: for link in child:
links.append(link.attrib) link_attributes = link.attrib
# logger.debug("link %s", link.attrib)
for x in link:
# logger.debug("attributes %s", x.attrib)
for y in x:
# logger.debug("attribute %s", y.attrib)
if y.attrib["name"] == "osm:way:highway":
# logger.debug("text %s", y.text)
link_attributes["osm:way:highway"] = y.text
links.append(link_attributes)
self.nodes = nodes self.nodes = nodes
self.links = links self.links = links
...@@ -585,6 +592,7 @@ class Network: ...@@ -585,6 +592,7 @@ class Network:
"x": float(node["x"]), "x": float(node["x"]),
"y": float(node["y"]) "y": float(node["y"])
} }
logger.debug("point: %s", point)
candidates = self.search_kdtree_range( candidates = self.search_kdtree_range(
point, kdtree=self.link_kd_tree, delta=delta point, kdtree=self.link_kd_tree, delta=delta
) )
......
...@@ -2,6 +2,7 @@ import os ...@@ -2,6 +2,7 @@ import os
import json import json
import jsonschema import jsonschema
import logging import logging
import time
from typing import Union, List from typing import Union, List
from flask import current_app as app from flask import current_app as app
from app.netedit.network import Network from app.netedit.network import Network
...@@ -110,10 +111,12 @@ def getEventsFromKeywords(inputPath, outputPath, keywords: list): ...@@ -110,10 +111,12 @@ def getEventsFromKeywords(inputPath, outputPath, keywords: list):
output.close() output.close()
def get_network_and_events(simulation_id, local: Union[bool, List] = False): def get_network_and_events(simulation_id):
""" """
Returns the network and the events objects. Returns the network and the events objects.
""" """
start = time.time()
date = get_sim_dir_names([simulation_id])[0] date = get_sim_dir_names([simulation_id])[0]
network_path = f"{data_dir}/simulations/{simulation_id}/network.xml" network_path = f"{data_dir}/simulations/{simulation_id}/network.xml"
events_path = ( events_path = (
...@@ -126,9 +129,9 @@ def get_network_and_events(simulation_id, local: Union[bool, List] = False): ...@@ -126,9 +129,9 @@ def get_network_and_events(simulation_id, local: Union[bool, List] = False):
network = Network(city=city, path=network_path) network = Network(city=city, path=network_path)
import time
start = time.time()
events = VehicleEvents(path=events_path, network=network) events = VehicleEvents(path=events_path, network=network)
app.logger.warn( app.logger.warn(
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<DEXi> <DEXi>
<VERSION>5.05</VERSION> <VERSION>5.05</VERSION>
<CREATED>2022-12-06T14:27:02</CREATED> <CREATED>2023-04-03T09:52:25</CREATED>
<OPTION>a</OPTION> <OPTION>a</OPTION>
<OPTION>b</OPTION> <OPTION>b</OPTION>
<SETTINGS/> <SETTINGS/>
...@@ -22,10 +22,11 @@ ...@@ -22,10 +22,11 @@
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<FUNCTION> <FUNCTION>
<LOW>100001100022100110002111022211221002221122221</LOW> <LOW>110001100022111110002210022211111112211122211</LOW>
<CONSIST>False</CONSIST>
</FUNCTION> </FUNCTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local</NAME> <NAME>Local</NAME>
<SCALE> <SCALE>
...@@ -45,8 +46,8 @@ ...@@ -45,8 +46,8 @@
<FUNCTION> <FUNCTION>
<LOW>001012122</LOW> <LOW>001012122</LOW>
</FUNCTION> </FUNCTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local Pollution</NAME> <NAME>Local Pollution</NAME>
<SCALE> <SCALE>
...@@ -65,13 +66,13 @@ ...@@ -65,13 +66,13 @@
</SCALE> </SCALE>
<FUNCTION> <FUNCTION>
<LOW>2221122111211101110011000</LOW> <LOW>2221122111211101110011000</LOW>
<ENTERED>+-----------+-----------+</ENTERED> <ENTERED>+-----------------------+</ENTERED>
<WEIGHTS>50;50</WEIGHTS> <WEIGHTS>50;50</WEIGHTS>
<LOCWEIGHTS>50.00;50.00</LOCWEIGHTS> <LOCWEIGHTS>50.00;50.00</LOCWEIGHTS>
<NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local Emissions</NAME> <NAME>Local Emissions</NAME>
<SCALE> <SCALE>
...@@ -97,14 +98,14 @@ ...@@ -97,14 +98,14 @@
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<FUNCTION> <FUNCTION>
<LOW>00112011221122212223222330112211222122232223322334112221222322233223342334412223222332233423344334442223322334233443344434444</LOW> <LOW>00111011121112211222122230111211122112221222322233111221122212223222332233311222122232223322333233341222322233223332333433344</LOW>
<ENTERED>+------------------------------------------------------------------------------------------------+++-------------------------</ENTERED> <ENTERED>+---------------------------------------------------------------------------------------------------------------------------+</ENTERED>
<WEIGHTS>33.3333333333333;33.3333333333333;33.3333333333333</WEIGHTS> <WEIGHTS>33.3333333333333;33.3333333333333;33.3333333333333</WEIGHTS>
<LOCWEIGHTS>33.33;33.33;33.33</LOCWEIGHTS> <LOCWEIGHTS>33.33;33.33;33.33</LOCWEIGHTS>
<NORMLOCWEIGHTS>33.33;33.33;33.33</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>33.33;33.33;33.33</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<OPTION>4</OPTION> <OPTION>3</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local NOx</NAME> <NAME>Local NOx</NAME>
<SCALE> <SCALE>
...@@ -211,8 +212,8 @@ ...@@ -211,8 +212,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>3</OPTION> <OPTION>2</OPTION>
<OPTION>4</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
...@@ -238,7 +239,7 @@ ...@@ -238,7 +239,7 @@
<LOCWEIGHTS>50.00;50.00</LOCWEIGHTS> <LOCWEIGHTS>50.00;50.00</LOCWEIGHTS>
<NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local Pedestrian travel time</NAME> <NAME>Local Pedestrian travel time</NAME>
...@@ -264,8 +265,8 @@ ...@@ -264,8 +265,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>3</OPTION> <OPTION>2</OPTION>
<OPTION>3</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>Local Daily internal bike travels</NAME> <NAME>Local Daily internal bike travels</NAME>
...@@ -291,8 +292,8 @@ ...@@ -291,8 +292,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>3</OPTION> <OPTION>2</OPTION>
<OPTION>1</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
...@@ -313,10 +314,10 @@ ...@@ -313,10 +314,10 @@
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<FUNCTION> <FUNCTION>
<LOW>011012122</LOW> <LOW>001012122</LOW>
</FUNCTION> </FUNCTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<OPTION>2</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide Pollution</NAME> <NAME>City-wide Pollution</NAME>
<SCALE> <SCALE>
...@@ -340,8 +341,8 @@ ...@@ -340,8 +341,8 @@
<LOCWEIGHTS>50.00;50.00</LOCWEIGHTS> <LOCWEIGHTS>50.00;50.00</LOCWEIGHTS>
<NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>0</OPTION> <OPTION>1</OPTION>
<OPTION>2</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide Acoustic pollution</NAME> <NAME>City-wide Acoustic pollution</NAME>
<SCALE> <SCALE>
...@@ -366,8 +367,8 @@ ...@@ -366,8 +367,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>4</OPTION> <OPTION>2</OPTION>
<OPTION>0</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide Emissions</NAME> <NAME>City-wide Emissions</NAME>
...@@ -394,14 +395,14 @@ ...@@ -394,14 +395,14 @@
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<FUNCTION> <FUNCTION>
<LOW>00111011121112211223122330111211122112231223322333111221122312233223332333411223122332233323334333441223322333233343334433444</LOW> <LOW>00111011121112211222122230111211122112221222322233111221122212223222332233311222122232223322333233341222322233223332333433344</LOW>
<ENTERED>+-------------------------------------------------------------------------------------------------------------------------+++</ENTERED> <ENTERED>+---------------------------------------------------------------------------------------------------------------------------+</ENTERED>
<WEIGHTS>33.3333333333333;33.3333333333333;33.3333333333333</WEIGHTS> <WEIGHTS>33.3333333333333;33.3333333333333;33.3333333333333</WEIGHTS>
<LOCWEIGHTS>33.33;33.33;33.33</LOCWEIGHTS> <LOCWEIGHTS>33.33;33.33;33.33</LOCWEIGHTS>
<NORMLOCWEIGHTS>33.33;33.33;33.33</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>33.33;33.33;33.33</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>2</OPTION> <OPTION>2</OPTION>
<OPTION>1</OPTION> <OPTION>2</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide NOx</NAME> <NAME>City-wide NOx</NAME>
<SCALE> <SCALE>
...@@ -427,7 +428,7 @@ ...@@ -427,7 +428,7 @@
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>2</OPTION> <OPTION>2</OPTION>
<OPTION>0</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide PM10</NAME> <NAME>City-wide PM10</NAME>
...@@ -453,7 +454,7 @@ ...@@ -453,7 +454,7 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>3</OPTION> <OPTION>2</OPTION>
<OPTION>2</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
...@@ -480,8 +481,8 @@ ...@@ -480,8 +481,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>1</OPTION> <OPTION>2</OPTION>
<OPTION>0</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
...@@ -508,7 +509,7 @@ ...@@ -508,7 +509,7 @@
<LOCWEIGHTS>50.00;50.00</LOCWEIGHTS> <LOCWEIGHTS>50.00;50.00</LOCWEIGHTS>
<NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS> <NORMLOCWEIGHTS>50.00;50.00</NORMLOCWEIGHTS>
</FUNCTION> </FUNCTION>
<OPTION>2</OPTION> <OPTION>1</OPTION>
<OPTION>1</OPTION> <OPTION>1</OPTION>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide Pedestrian travel time</NAME> <NAME>City-wide Pedestrian travel time</NAME>
...@@ -534,18 +535,18 @@ ...@@ -534,18 +535,18 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>1</OPTION> <OPTION>2</OPTION>
<OPTION>3</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
<ATTRIBUTE> <ATTRIBUTE>
<NAME>City-wide Daily internal bike travels</NAME> <NAME>City-wide Daily internal bike travels</NAME>
<SCALE> <SCALE>
<SCALEVALUE> <SCALEVALUE>
<NAME>+15%</NAME> <NAME>-15%</NAME>
<GROUP>BAD</GROUP> <GROUP>BAD</GROUP>
</SCALEVALUE> </SCALEVALUE>
<SCALEVALUE> <SCALEVALUE>
<NAME>+5%</NAME> <NAME>- 5%</NAME>
<GROUP>BAD</GROUP> <GROUP>BAD</GROUP>
</SCALEVALUE> </SCALEVALUE>
<SCALEVALUE> <SCALEVALUE>
...@@ -553,16 +554,16 @@ ...@@ -553,16 +554,16 @@
<DESCRIPTION>No change</DESCRIPTION> <DESCRIPTION>No change</DESCRIPTION>
</SCALEVALUE> </SCALEVALUE>
<SCALEVALUE> <SCALEVALUE>
<NAME>- 5%</NAME> <NAME>+5%</NAME>
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
<SCALEVALUE> <SCALEVALUE>
<NAME>-15%</NAME> <NAME>+15%</NAME>
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>1</OPTION> <OPTION>2</OPTION>
<OPTION>1</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
...@@ -590,8 +591,8 @@ ...@@ -590,8 +591,8 @@
<GROUP>GOOD</GROUP> <GROUP>GOOD</GROUP>
</SCALEVALUE> </SCALEVALUE>
</SCALE> </SCALE>
<OPTION>1</OPTION> <OPTION>2</OPTION>
<OPTION>3</OPTION> <OPTION>2</OPTION>
</ATTRIBUTE> </ATTRIBUTE>
</ATTRIBUTE> </ATTRIBUTE>
</DEXi> </DEXi>