analysis/webservice/algorithms/ColorBarHandler.py (109 lines of code) (raw):

# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json import math import time import numpy as np from . import colortables from webservice.algorithms.NexusCalcHandler import NexusCalcHandler as BaseHandler from webservice.NexusHandler import nexus_handler @nexus_handler class ColorBarCalcHandler(BaseHandler): name = "ColorBarHandler" path = "/colorbar" description = "Creates a CMC colorbar spec for a dataset" params = { "ds": { "name": "Dataset", "type": "string", "description": "A supported dataset shortname identifier" }, "t": { "name": "Time", "type": "int", "description": "Data observation date if not specifying a min/max" }, "min": { "name": "Minimum Value", "type": "float", "description": "Minimum value to use when computing color scales. Will be computed if not specified" }, "max": { "name": "Maximum Value", "type": "float", "description": "Maximum value to use when computing color scales. Will be computed if not specified" }, "ct": { "name": "Color Table", "type": "string", "description": "Identifier of a supported color table" } } singleton = True def __init__(self, tile_service_factory): BaseHandler.__init__(self, tile_service_factory) def __get_dataset_minmax(self, ds, dataTime): dataTimeStart = dataTime - 86400.0 # computeOptions.get_datetime_arg("t", None) dataTimeEnd = dataTime daysinrange = self._get_tile_service().find_days_in_range_asc(-90.0, 90.0, -180.0, 180.0, ds, dataTimeStart, dataTimeEnd) ds1_nexus_tiles = self._get_tile_service().get_tiles_bounded_by_box_at_time(-90.0, 90.0, -180.0, 180.0, ds, daysinrange[0]) data_min = 100000 data_max = -1000000 for tile in ds1_nexus_tiles: data_min = np.min((data_min, np.ma.min(tile.data))) data_max = np.max((data_max, np.ma.max(tile.data))) return data_min, data_max def __produce_color_list(self, colorbarDef, numColors, min, max, units): colors = [] labels = [] values = [] for i in range(0, numColors): index = float(i) / float(numColors) index = index * (len(colorbarDef) - 1) prev = int(math.floor(index)) next = int(math.ceil(index)) f = index - prev prevColor = colorbarDef[prev] nextColor = colorbarDef[next] color = [0, 0, 0, 255] color[0] = nextColor[0] * f + (prevColor[0] * (1.0 - f)) color[1] = nextColor[1] * f + (prevColor[1] * (1.0 - f)) color[2] = nextColor[2] * f + (prevColor[2] * (1.0 - f)) colors.append('%02x%02x%02xFF' % (color[0], color[1], color[2])) value = (float(i) / float(numColors - 1)) * (max - min) + min valueHigh = (float(i + 1) / float(numColors - 1)) * (max - min) + min labels.append("%3.2f %s" % (value, units)) values.append((value, valueHigh)) return colors, labels, values def calc(self, computeOptions, **args): ds = computeOptions.get_argument("ds", None) dataTime = computeOptions.get_datetime_arg("t", None) if dataTime is None: raise Exception("Missing 't' option for time") dataTime = time.mktime(dataTime.timetuple()) color_table_name = computeOptions.get_argument("ct", "smap") color_table = colortables.__dict__[color_table_name] min = computeOptions.get_float_arg("min", np.nan) max = computeOptions.get_float_arg("max", np.nan) num_colors = computeOptions.get_int_arg("num", 255) units = computeOptions.get_argument("units", "") if np.isnan(min) or np.isnan(max): data_min, data_max = self.__get_dataset_minmax(ds, dataTime) if np.isnan(min): min = data_min if np.isnan(max): max = data_max colors, labels, values = self.__produce_color_list(color_table, num_colors, min, max, units) obj = { "scale": { "colors": colors, "labels": labels, "values": values }, "id": ds } class SimpleResult(object): def toJson(self): return json.dumps(obj, indent=4) return SimpleResult()