Skip to content

Fix issue #76: [C4GT Community]: Add Dynamic Color Scaling to GeoPlot… #79

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 43 additions & 19 deletions geoplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,28 @@
return result
}

function getColor(value, min, max) {
const factor = (value - min) / (max - min)
return interpolateColor(
Cesium.Color.BLUE,
Cesium.Color.RED,
factor
)
function getColor(value) {
// Use the injected min/max for dynamic color scaling.
// If min == max, factor will be NaN; handle this gracefully.
const min = parseFloat('$colorScaleMin');
const max = parseFloat('$colorScaleMax');
const factor = (value - min) / (max - min);
return interpolateColor(
Cesium.Color.BLUE,
Cesium.Color.RED,
Math.max(0, Math.min(1, factor))
);
}

function getPixelSize(value, min, max) {
const factor = (value - min) / (max - min)
return 100 * (1 + factor)
}
function getPixelSize(value) {
// Use the injected min/max for dynamic size scaling.
// If min == max, factor will be NaN; handle this gracefully.
const min = parseFloat('$colorScaleMin');
const max = parseFloat('$colorScaleMax');
const factor = (value - min) / (max - min);
return 100 * (1 + Math.max(0, Math.min(1, factor)));
}


function processTimeSeriesData(geoJsonData) {
const timeSeriesMap = new Map()
Expand Down Expand Up @@ -160,8 +169,8 @@
time,
getColor(
value,
timeSeriesData.minValue,
timeSeriesData.maxValue
getColor(value)

)
)

Expand All @@ -170,8 +179,7 @@
time,
getPixelSize(
value,
timeSeriesData.minValue,
timeSeriesData.maxValue
getPixelSize(value)
)
)
}
Expand Down Expand Up @@ -233,6 +241,12 @@ def __init__(self, config, options):
options["feature"],
options["visualization_type"],
)
# Optional: User can manually specify color scale bounds.
# If not provided, these will be computed dynamically from the data.
self.color_scale_min = options.get("color_scale_min", None)
self.color_scale_max = options.get("color_scale_max", None)



def render(self, state_trajectory):
coords, values = [], []
Expand All @@ -246,7 +260,14 @@ def render(self, state_trajectory):
values.append(
np.array(read_var(final_state, self.entity_property)).flatten().tolist()
)

# Flatten all property values for min/max calculation.
all_values = [v for value_list in values for v in value_list]
# Determine color scale bounds:
# Use user-specified min/max if provided, otherwise compute from data.
min_value = self.color_scale_min if self.color_scale_min is not None else min(all_values)

max_value = self.color_scale_max if self.color_scale_max is not None else max(all_values)
# Generate timestamps for each step in the simulation.
start_time = pd.Timestamp.utcnow()
timestamps = [
start_time + pd.Timedelta(seconds=i * self.step_time)
Expand All @@ -255,7 +276,7 @@ def render(self, state_trajectory):
* self.config["simulation_metadata"]["num_steps_per_episode"]
)
]

# Generate GeoJSON data for each coordinate and its corresponding values.
geojsons = []
for i, coord in enumerate(coords):
features = []
Expand All @@ -274,10 +295,11 @@ def render(self, state_trajectory):
}
)
geojsons.append({"type": "FeatureCollection", "features": features})

# Save GeoJSON data to file.
with open(geodata_path, "w", encoding="utf-8") as f:
json.dump(geojsons, f, ensure_ascii=False, indent=2)

# Generate HTML file for visualization.
# Use the template to create the HTML file.
tmpl = Template(geoplot_template)
with open(geoplot_path, "w", encoding="utf-8") as f:
f.write(
Expand All @@ -288,6 +310,8 @@ def render(self, state_trajectory):
"stopTime": timestamps[-1].isoformat(),
"data": json.dumps(geojsons),
"visualType": self.visualization_type,
"colorScaleMin": min_value,
"colorScaleMax": max_value,
}
)
)