(function (root) { 'use strict'; const CHANNELS = [ { channel: 'red', name: 'ts', label: 'Surface temperature', unit: 'K', factor: 1 }, { channel: 'green', name: 'pr', label: 'Precipitation', unit: 'mm/day', factor: 86400000 }, { channel: 'blue', name: 'sg', label: 'Elevation', unit: 'm', factor: null } ]; function create(index, gravity) { if (!index || !Array.isArray(index.fields) || !Number.isFinite(gravity) || gravity <= 0) return null; const fields = CHANNELS.map(channel => { const field = index.fields.find(item => item.name === channel.name); if (!field || !Array.isArray(field.shape) || field.shape.length !== 4 || field.shape[1] !== 1 || !field.shape[0] || field.shape[2] < 1 || field.shape[3] < 1 || !Number.isFinite(field.min) || !Number.isFinite(field.max)) return null; const expectedUnit = channel.name === 'ts' ? 'K' : channel.name === 'pr' ? 'm s-1' : 'm2 s-2'; if (field.unit !== expectedUnit) return null; return Object.assign({}, channel, { factor: channel.factor === null ? 1 / gravity : channel.factor, min: field.min * (channel.factor === null ? 1 / gravity : channel.factor), max: field.max * (channel.factor === null ? 1 / gravity : channel.factor), shape: field.shape.slice() }); }); if (fields.some(field => !field || !Number.isFinite(field.min) || !Number.isFinite(field.max) || field.max < field.min)) return null; const [reference] = fields; if (fields.some(field => field.shape[2] !== reference.shape[2] || field.shape[3] !== reference.shape[3])) return null; const timeCount = Math.max(...fields.map(field => field.shape[0])); if (fields.some(field => field.shape[0] !== 1 && field.shape[0] !== timeCount)) return null; return { channels: fields, timeCount }; } function normalise(value, channel) { if (!channel || !Number.isFinite(value)) return null; const converted = value * channel.factor; if (!Number.isFinite(converted)) return null; if (channel.max === channel.min) return converted === 0 ? 0 : 0.5; return Math.max(0, Math.min(1, (converted - channel.min) / (channel.max - channel.min))); } root.ExoComposite = { create, normalise }; })(window);