function createCombinedMapWithHexBinsAndPoints(data, { width = 800, height = 600, mapType = 'Open-street map', logScale = [] } = {}) {
function median(values) {
const sorted = values.slice().sort((a, b) => a - b);
const middle = Math.floor(sorted.length / 2);
if (sorted.length % 2 === 0) {
return (sorted[middle - 1] + sorted[middle]) / 2;
}
return sorted[middle];
}
function renderMap(mapStyle, useLogScale) {
console.log('Rendering map with style:', mapStyle);
console.log('Using log scale:', useLogScale);
const colorscale = 'Viridis';
const z = useLogScale ? activities.map(a => a > 0 ? Math.log10(a) : 0) : activities;
Plotly.newPlot(mapDiv, [
{
type: 'densitymapbox',
lat: latitudes,
lon: longitudes,
z: z,
radius: 10,
colorscale: colorscale,
colorbar: {
title: useLogScale ? 'Activity (Log10 Scale)' : `Activity ${unit}`,
tickprefix: useLogScale ? 'log10(' : '',
tickvals: useLogScale ? [0, Math.log10(maxActivity)] : undefined,
ticktext: useLogScale ? ['10^0', `10^${Math.round(Math.log10(maxActivity))}`] : undefined
},
hoverinfo: 'skip',
},
{
type: 'scattermapbox',
mode: 'markers',
lat: latitudes,
lon: longitudes,
marker: {
size: 5,
color: z, // Color by activity
colorscale: colorscale,
},
text: activities.map(a => `Activity: ${a}`), // Tooltip text for points
hoverinfo: 'text'
}
], {
mapbox: {
style: mapStyle === 'Open-street map' ? 'open-street-map' : 'white-bg',
layers: mapStyle === 'US GS Imagery Background' ? [{
sourcetype: 'raster',
source: [
"https://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/{z}/{y}/{x}"
],
below: 'traces',
sourceattribution: 'United States Geological Survey'
}] : undefined,
center: {
lat: medianLat,
lon: medianLon
},
zoom: 3, // Initial zoom level
pitch: 0, // Default pitch angle
bearing: 0, // Default bearing angle
interactive: true // Ensure interactions like zoom and pan are enabled
},
margin: { r: 0, t: 0, l: 0, b: 0 },
width: width,
height: height,
scrollZoom: true // Enable mouse scroll zooming
});
}
// Create a container div to hold the elements
const containerDiv = document.createElement('div');
if (data.length === 0) {
// Create a message element for no data available
const noDataElement = document.createElement('h2');
noDataElement.innerText = "😢 No data, select an FAO Region.";
noDataElement.style.textAlign = "center";
noDataElement.style.margin = "20px";
// Append the no data message to the container
containerDiv.appendChild(noDataElement);
// Return the container div with the no data message
return containerDiv;
}
// Create a title element
const titleElement = document.createElement('h2');
const yearTitle = data[0].samplingYear; // Assuming all data is from the same year
const faoTitle = data[0].faoRegion; // Assuming all data is from the same FAO region
const unit = data[0].unit;
titleElement.innerText = `${nuclide_selected} Activity Concentrations for FAO Region ${faoTitle} in the Year ${yearTitle}.`;
titleElement.style.textAlign = "center";
titleElement.style.marginBottom = "20px"; // Add some margin below the title
// Append the title to the container
containerDiv.appendChild(titleElement);
// Create a div element to hold the map
const mapDiv = document.createElement('div');
mapDiv.style.width = `${width}px`;
mapDiv.style.height = `${height}px`;
// Append the map div to the container
containerDiv.appendChild(mapDiv);
// Extract data for plotting
const latitudes = data.map(d => d.latitude);
const longitudes = data.map(d => d.longitude);
const activities = data.map(d => d.activity);
// Calculate the median latitude and longitude
const medianLat = median(latitudes);
const medianLon = median(longitudes);
// Compute max activity value for log scale
const maxActivity = Math.max(...activities);
// Determine if log scale is enabled based on the checkbox input
const useLogScale = logScale.includes('Log10');
// Debugging output
console.log('Map Type:', mapType);
console.log('Log Scale:', useLogScale);
// Initial render of the map with the default style and scale
renderMap(mapType, useLogScale);
// Return the container div element containing the title and map
return containerDiv;
}