This is an automated email from the ASF dual-hosted git repository.

rkk pushed a commit to branch tmp-stv
in repository https://gitbox.apache.org/repos/asf/sdap-nexus.git

commit 39815bd32fc72948666fbccc7a233025234b8efc
Author: rileykk <[email protected]>
AuthorDate: Tue Sep 26 17:18:04 2023 -0700

    Initial subsetting
    
    Still need to org and plot the data
---
 analysis/webservice/algorithms/Tomogram.py | 158 +++++++++++++++++++++++++++--
 1 file changed, 152 insertions(+), 6 deletions(-)

diff --git a/analysis/webservice/algorithms/Tomogram.py 
b/analysis/webservice/algorithms/Tomogram.py
index 14d3883..d43a3a8 100644
--- a/analysis/webservice/algorithms/Tomogram.py
+++ b/analysis/webservice/algorithms/Tomogram.py
@@ -14,35 +14,181 @@
 # limitations under the License.
 
 import logging
-from typing import Dict, Literal
+from typing import Dict, Literal, Union
+from numbers import Number
 import numpy as np
 import xarray as xr
 import matplotlib.pyplot as plt
 from webservice.NexusHandler import nexus_handler
 from webservice.algorithms.NexusCalcHandler import NexusCalcHandler
+from webservice.algorithms.DataInBoundsSearch import 
DataInBoundsSearchCalcHandlerImpl as Subset
+from webservice.webmodel import NexusResults, NexusProcessingException
+
 
 logger = logging.getLogger(__name__)
 
 
 class TomogramBaseClass(NexusCalcHandler):
-    def __int__(self, tile_service_factory, slice_bounds: Dict[Literal['lat', 
'lon', 'elevation'], slice], **kwargs):
+    def __init__(
+            self,
+            tile_service_factory,
+            slice_bounds: Dict[Literal['lat', 'lon', 'elevation'], 
Union[slice, Number]],
+            **kwargs
+    ):
         NexusCalcHandler.__init__(self, tile_service_factory)
         self.__slice_bounds = slice_bounds
+        self.__margin = kwargs.get('margin', 0.001)
 
         # slice bounds: dict relating dimension names to desired slicing
-        # When dealing with multi-var tiles, optional parameter to pick 
variable to plot, otherwise issue warning and pick the first one
+        # When dealing with multi-var tiles, optional parameter to pick 
variable to plot,
+        # otherwise issue warning and pick the first one
 
+    def parse_args(self, compute_options):
+        try:
+            ds = compute_options.get_dataset()[0]
+        except:
+            raise NexusProcessingException(reason="'ds' argument is required", 
code=400)
 
-@nexus_handler
+        parameter_s = compute_options.get_argument('parameter', None)
+
+        return ds, parameter_s
+
+    def do_subset(self, compute_options):
+        tile_service = self._get_tile_service()
+
+        ds, parameter = self.parse_args(compute_options)
+
+        bounds = self.__slice_bounds
+        sel = {}
+
+        if isinstance(bounds['lat'], slice):
+            min_lat = bounds['lat'].start
+            max_lat = bounds['lat'].stop
+        else:
+            min_lat = bounds['lat'] - self.__margin
+            max_lat = bounds['lat'] + self.__margin
+
+            sel = dict(lat=bounds['lat'])
+
+        if isinstance(bounds['lon'], slice):
+            min_lon = bounds['lon'].start
+            max_lon = bounds['lon'].stop
+        else:
+            min_lon = bounds['lon'] - self.__margin
+            max_lon = bounds['lon'] + self.__margin
+
+            sel = dict(lon=bounds['lon'])
+
+        if isinstance(bounds['elevation'], slice):
+            min_elevation = bounds['elevation'].start
+            max_elevation = bounds['elevation'].stop
+        else:
+            min_elevation = bounds['elevation'] - self.__margin
+            max_elevation = bounds['elevation'] + self.__margin
+
+            sel = dict(elevation=bounds['elevation'])
+
+        tiles = tile_service.find_tiles_in_box(
+            min_lat, max_lat, min_lon, max_lon,
+            ds=ds,
+            min_elevation=min_elevation,
+            max_elevation=max_elevation,
+            fetch_data=False
+        )
+
+        logger.info(f'Fetched {len(tiles):,}')
+
+        data = []
+
+        for i in range(len(tiles)-1, -1, -1): # tile in tiles:
+            tile = tiles.pop(i)
+
+            tile_id = tile.tile_id
+
+            logger.info(f'Processing tile {tile_id} | {i=}')
+
+            tile = tile_service.fetch_data_for_tiles(tile)[0]
+            tile = tile_service.mask_tiles_to_bbox(min_lat, max_lat, min_lon, 
max_lon, [tile])
+            # tile = tile_service.mask_tiles_to_time_range(start_time, 
end_time, tile)
+
+            if min_elevation and max_elevation:
+                tile = tile_service.mask_tiles_to_elevation(min_elevation, 
max_elevation, tile)
+
+            if len(tile) == 0:
+                logger.info(f'Skipping empty tile {tile_id}')
+                continue
+
+            tile = tile[0]
+
+            for nexus_point in tile.nexus_point_generator():
+                data_vals = nexus_point.data_vals if tile.is_multi else 
[nexus_point.data_vals]
+                data_val = None
+
+                for value, variable in zip(data_vals, tile.variables):
+                    if parameter is None or variable == parameter:
+                        data_val = value
+                        break
+
+                if data_val is None:
+                    logger.warning(f'No variable {parameter} found at point 
{nexus_point.index} for tile {tile.tile_id}')
+                    data_val = np.nan
+
+                data.append({
+                    'latitude': nexus_point.latitude,
+                    'longitude': nexus_point.longitude,
+                    'data': data_val
+                })
+
+        logger.info('Fetched data, organizing it for plotting')
+
+        return data
+
+
+# @nexus_handler
 class LatitudeTomogramImpl(TomogramBaseClass):
     pass
 
 
-@nexus_handler
+# @nexus_handler
 class LongitudeTomogramImpl(TomogramBaseClass):
     pass
 
 
 @nexus_handler
 class ElevationTomogramImpl(TomogramBaseClass):
-    pass
+    name = "Elevation-sliced Tomogram"
+    path = "/tomogram/elevation"
+    description = "Fetches point values for a given dataset and geographical 
area"
+    params = {
+        "ds": {
+            "name": "Dataset",
+            "type": "string",
+            "description": "The Dataset shortname to use in calculation. 
Required"
+        },
+        "parameter": {
+            "name": "Parameter",
+            "type": "string",
+            "description": "The parameter of interest."
+        },
+        "b": {
+            "name": "Bounding box",
+            "type": "comma-delimited float",
+            "description": "Minimum (Western) Longitude, Minimum (Southern) 
Latitude, "
+                           "Maximum (Eastern) Longitude, Maximum (Northern) 
Latitude. Required if 'metadataFilter' not provided"
+        },
+        "elevation": {
+            "name": "Slice elevation",
+            "type": "float",
+            "description": "The "
+        }
+    }
+    singleton = True
+
+    def __init__(self, tile_service_factory, **kwargs):
+        TomogramBaseClass.__init__(self, tile_service_factory, **kwargs)
+
+    def parse_args(self, compute_options):
+        pass
+
+    def calc(self, computeOptions, **args):
+        pass

Reply via email to