From 47f9ed6de9db1ebe7a327e6fe5e7cb5f6c28f612 Mon Sep 17 00:00:00 2001 From: ReimarBauer Date: Mon, 2 Dec 2024 16:13:36 +0100 Subject: [PATCH] modules needed by wms should not use config_loader --- docs/samples/automation/retriever.py | 4 +- mslib/msui/editor.py | 3 +- mslib/msui/flighttrack.py | 3 +- mslib/msui/mpl_pathinteractor.py | 3 +- mslib/msui/topview.py | 2 +- mslib/mswms/mpl_hsec.py | 2 +- mslib/mswms/wms.py | 2 +- mslib/utils/coordinate.py | 142 ------------------------- mslib/utils/find_location.py | 47 +++++++++ mslib/utils/get_projection_params.py | 149 +++++++++++++++++++++++++++ mslib/utils/mssautoplot.py | 4 +- tests/_test_utils/test_coordinate.py | 14 +-- 12 files changed, 216 insertions(+), 159 deletions(-) create mode 100644 mslib/utils/find_location.py create mode 100644 mslib/utils/get_projection_params.py diff --git a/docs/samples/automation/retriever.py b/docs/samples/automation/retriever.py index 989faa95f..a5881169e 100644 --- a/docs/samples/automation/retriever.py +++ b/docs/samples/automation/retriever.py @@ -39,6 +39,7 @@ import mslib import mslib.utils +from mslib.utils.get_projection_params import get_projection_params from mslib.utils import thermolib from mslib.utils.config import config_loader, read_config_file from mslib.utils.units import units @@ -140,8 +141,7 @@ def main(): fig = plt.figure() for flight, section, vertical, filename, init_time, time in \ config["automated_plotting"]["flights"]: - params = mslib.utils.coordinate.get_projection_params( - config["predefined_map_sections"][section]["CRS"].lower()) + params = get_projection_params(config["predefined_map_sections"][section]["CRS"].lower()) params["basemap"].update(config["predefined_map_sections"][section]["map"]) wps = load_from_ftml(filename) wp_lats, wp_lons, wp_locs = [[x[i] for x in wps] for i in [0, 1, 3]] diff --git a/mslib/msui/editor.py b/mslib/msui/editor.py index a28b83208..c8140db7d 100644 --- a/mslib/msui/editor.py +++ b/mslib/msui/editor.py @@ -37,8 +37,7 @@ from mslib.msui.icons import icons from mslib.utils.config import MSUIDefaultConfig as mss_default from mslib.utils.config import config_loader, dict_raise_on_duplicates_empty, merge_dict -from mslib.utils.coordinate import get_projection_params - +from mslib.utils.get_projection_params import get_projection_params from mslib.support.qt_json_view import delegate from mslib.support.qt_json_view.view import JsonView diff --git a/mslib/msui/flighttrack.py b/mslib/msui/flighttrack.py index 3ca4760bc..dd575f2a7 100644 --- a/mslib/msui/flighttrack.py +++ b/mslib/msui/flighttrack.py @@ -46,7 +46,8 @@ from mslib import __version__ from mslib.utils.units import units -from mslib.utils.coordinate import find_location, path_points, get_distance +from mslib.utils.coordinate import path_points, get_distance +from mslib.utils.find_location import find_location from mslib.utils import thermolib from mslib.utils.verify_waypoint_data import verify_waypoint_data from mslib.utils.config import config_loader, save_settings_qsettings, load_settings_qsettings diff --git a/mslib/msui/mpl_pathinteractor.py b/mslib/msui/mpl_pathinteractor.py index 9b5a23364..fa542f64c 100644 --- a/mslib/msui/mpl_pathinteractor.py +++ b/mslib/msui/mpl_pathinteractor.py @@ -51,7 +51,8 @@ import matplotlib.patches as mpatches from PyQt5 import QtCore, QtWidgets -from mslib.utils.coordinate import get_distance, find_location, latlon_points, path_points +from mslib.utils.coordinate import get_distance, latlon_points, path_points +from mslib.utils.find_location import find_location from mslib.utils.units import units from mslib.utils.thermolib import pressure2flightlevel from mslib.msui import flighttrack as ft diff --git a/mslib/msui/topview.py b/mslib/msui/topview.py index d1db60818..5fdd3f4bd 100644 --- a/mslib/msui/topview.py +++ b/mslib/msui/topview.py @@ -32,7 +32,7 @@ import logging from mslib.utils.config import config_loader -from mslib.utils.coordinate import get_projection_params +from mslib.utils.get_projection_params import get_projection_params from PyQt5 import QtGui, QtWidgets, QtCore from mslib.msui.qt5 import ui_topview_window as ui from mslib.msui.qt5 import ui_topview_mapappearance as ui_ma diff --git a/mslib/mswms/mpl_hsec.py b/mslib/mswms/mpl_hsec.py index 3b6bd51e6..7db8690cf 100644 --- a/mslib/mswms/mpl_hsec.py +++ b/mslib/mswms/mpl_hsec.py @@ -42,7 +42,7 @@ import PIL.Image from mslib.mswms import mss_2D_sections -from mslib.utils.coordinate import get_projection_params +from mslib.utils.get_projection_params import get_projection_params from mslib.utils.units import convert_to from mslib.mswms.utils import make_cbar_labels_readable from mslib.utils.loggerdef import configure_mpl_logger diff --git a/mslib/mswms/wms.py b/mslib/mswms/wms.py index a95664e66..cbb8e4e18 100644 --- a/mslib/mswms/wms.py +++ b/mslib/mswms/wms.py @@ -143,7 +143,7 @@ def verify_pw(username, password): return authfunc(username, password) from mslib.mswms import mss_plot_driver -from mslib.utils.coordinate import get_projection_params +from mslib.utils.get_projection_params import get_projection_params # Logging the Standard Output, which will be added to the Apache Log Files logging.basicConfig(level=logging.DEBUG, diff --git a/mslib/utils/coordinate.py b/mslib/utils/coordinate.py index 63138d74a..26e217bb1 100644 --- a/mslib/utils/coordinate.py +++ b/mslib/utils/coordinate.py @@ -26,16 +26,12 @@ limitations under the License. """ -import logging import netCDF4 as nc import numpy as np from pyproj import Geod from scipy.interpolate import interp1d from scipy.ndimage import map_coordinates -from mslib.utils.config import config_loader - - __PR = Geod(ellps='WGS84') @@ -54,23 +50,6 @@ def get_distance(lat0, lon0, lat1, lon1): return __PR.inv(lon0, lat0, lon1, lat1)[-1] / 1000. -def find_location(lat, lon, tolerance=5): - """ - Checks if a location is present at given coordinates - :param lat: latitude - :param lon: longitude - :param tolerance: maximum distance between location and coordinates in km - :return: None or lat/lon, name - """ - locations = config_loader(dataset='locations') - distances = sorted([(get_distance(lat, lon, loc_lat, loc_lon), loc) - for loc, (loc_lat, loc_lon) in locations.items()]) - if len(distances) > 0 and distances[0][0] <= tolerance: - return locations[distances[0][1]], distances[0][1] - else: - return None - - def fix_angle(ang): """ Normalizes an angle between -180 and 180 degree. @@ -107,127 +86,6 @@ def rotate_point(point, angle, origin=(0, 0)): return temp_point -def get_projection_params(proj): - proj = proj.lower() - if proj.startswith("crs:"): - projid = proj[4:] - if projid == "84": - proj_params = { - "basemap": {"projection": "cyl"}, - "bbox": "degree"} - else: - raise ValueError("Only CRS code 84 is supported: '%s' given", proj) - - elif proj.startswith("auto:"): - raise ValueError("AUTO not supported") - - projid, unitsid, lon0, lat0 = proj[5:].split(",") - if projid == "42001": - proj_params = { - "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42002": - proj_params = { - "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42003": - proj_params = { - "basemap": {"projection": "ortho", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - else: - raise ValueError("unspecified AUTO code: '%s'", proj) - - elif proj.startswith("auto2:"): - raise ValueError("AUTO2 not supported") - - projid, factor, lon0, lat0 = proj[6:].split(",") - if projid == "42001": - proj_params = { - "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42002": - proj_params = { - "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42003": - proj_params = { - "basemap": {"projection": "ortho", "lon_0": lon0, "lat_0": lat0}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42004": - proj_params = { - "basemap": {"projection": "cyl"}, - "bbox": f"meter({lon0},{lat0})"} - elif projid == "42005": - proj_params = { - "basemap": {"projection": "moll", "lon_0": lon0, "lat_0": lat0}, - "bbox": "meter???"} - else: - raise ValueError("unspecified AUTO2 code: '%s'", proj) - - elif proj.startswith("epsg:"): - epsg = proj[5:] - if epsg.startswith("777") and len(epsg) == 8: # user defined MSS code. deprecated. - logging.warning("Using deprecated MSS-specific EPSG code. Switch to 'MSS:stere' instead.") - lat_0, lon_0 = int(epsg[3:5]), int(epsg[5:]) - proj_params = { - "basemap": {"projection": "stere", "lat_0": lat_0, "lon_0": lon_0}, - "bbox": "degree"} - elif epsg.startswith("778") and len(epsg) == 8: # user defined MSS code. deprecated. - logging.warning("Using deprecated MSS-specific EPSG code. Switch to 'MSS:stere' instead.") - lat_0, lon_0 = int(epsg[3:5]), int(epsg[5:]) - proj_params = { - "basemap": {"projection": "stere", "lat_0": -lat_0, "lon_0": lon_0}, - "bbox": "degree"} - elif epsg in ("4258", "4326"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "degree"} - elif epsg in ("3031", "3412"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,-90)"} - elif epsg in ("3411", "3413", "3575", "3995"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,90)"} - elif epsg in ("3395", "3857"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,0)"} - elif epsg in ("4839"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(10.5,51)"} - elif epsg in ("31467"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(-20.9631343,0.0037502)"} - elif epsg in ("31468"): - proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(-25.4097892,0.0037466)"} - else: - raise ValueError("EPSG code not supported by basemap module: '%s'", proj) - - elif proj.startswith("mss:"): - # some MSS-specific codes - params = proj[4:].split(",") - name = params[0] - if name == "stere": - lon0, lat0, lat_ts = params[1:] - proj_params = { - "basemap": {"projection": name, "lat_0": lat0, "lon_0": lon0, "lat_ts": lat_ts}, - "bbox": "degree"} - elif name == "cass": - lon0, lat0 = params[1:] - proj_params = { - "basemap": {"projection": name, "lon_0": lon0, "lat_0": lat0}, - "bbox": "degree"} - elif name == "lcc": - lon0, lat0, lat1, lat2 = params[1:] - proj_params = { - "basemap": {"projection": name, "lon_0": lon0, "lat_0": lat0, "lat_1": lat1, "lat_2": lat2}, - "bbox": "degree"} - elif name == "merc": - lat_ts = params[1] - proj_params = { - "basemap": {"projection": name, "lat_ts": lat_ts}, - "bbox": "degree"} - else: - raise ValueError("unknown MSS projection: '%s'", proj) - - else: - raise ValueError("unknown projection: '%s'", proj) - logging.debug("Identified CRS '%s' as '%s'", proj, proj_params) - return proj_params - - def interpolate_vertsec(data3D, data3D_lats, data3D_lons, lats, lons): """ Interpolate curtain[z,pos] (curtain[level,pos]) from data3D[z,y,x] diff --git a/mslib/utils/find_location.py b/mslib/utils/find_location.py new file mode 100644 index 000000000..3c1cca3c8 --- /dev/null +++ b/mslib/utils/find_location.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +""" + + mslib.utils.find_location + ~~~~~~~~~~~~~~~~~~~~~~~~~ + + Shows the name of a lat/lon coordinate + + This file is part of MSS. + + :copyright: Copyright 2021 May Bär + :copyright: Copyright 2021-2024 by the MSS team, see AUTHORS. + :license: APACHE-2.0, see LICENSE for details. + + Licensed 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. +""" + + +from mslib.utils.config import config_loader +from mslib.utils.coordinate import get_distance + + +def find_location(lat, lon, tolerance=5): + """ + Checks if a location is present at given coordinates + :param lat: latitude + :param lon: longitude + :param tolerance: maximum distance between location and coordinates in km + :return: None or lat/lon, name + """ + locations = config_loader(dataset='locations') + distances = sorted([(get_distance(lat, lon, loc_lat, loc_lon), loc) + for loc, (loc_lat, loc_lon) in locations.items()]) + if len(distances) > 0 and distances[0][0] <= tolerance: + return locations[distances[0][1]], distances[0][1] + else: + return None diff --git a/mslib/utils/get_projection_params.py b/mslib/utils/get_projection_params.py new file mode 100644 index 000000000..5b9090f9a --- /dev/null +++ b/mslib/utils/get_projection_params.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +""" + + mslib.utils.get_projection_params + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Transfers a projection string into a dictionary of projection parameters + + This file is part of MSS. + + :copyright: Copyright 2021 May Bär + :copyright: Copyright 2021-2024 by the MSS team, see AUTHORS. + :license: APACHE-2.0, see LICENSE for details. + + Licensed 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 logging + + +def get_projection_params(proj): + proj = proj.lower() + if proj.startswith("crs:"): + projid = proj[4:] + if projid == "84": + proj_params = { + "basemap": {"projection": "cyl"}, + "bbox": "degree"} + else: + raise ValueError("Only CRS code 84 is supported: '%s' given", proj) + + elif proj.startswith("auto:"): + raise ValueError("AUTO not supported") + + projid, unitsid, lon0, lat0 = proj[5:].split(",") + if projid == "42001": + proj_params = { + "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42002": + proj_params = { + "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42003": + proj_params = { + "basemap": {"projection": "ortho", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + else: + raise ValueError("unspecified AUTO code: '%s'", proj) + + elif proj.startswith("auto2:"): + raise ValueError("AUTO2 not supported") + + projid, factor, lon0, lat0 = proj[6:].split(",") + if projid == "42001": + proj_params = { + "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42002": + proj_params = { + "basemap": {"projection": "tmerc", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42003": + proj_params = { + "basemap": {"projection": "ortho", "lon_0": lon0, "lat_0": lat0}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42004": + proj_params = { + "basemap": {"projection": "cyl"}, + "bbox": f"meter({lon0},{lat0})"} + elif projid == "42005": + proj_params = { + "basemap": {"projection": "moll", "lon_0": lon0, "lat_0": lat0}, + "bbox": "meter???"} + else: + raise ValueError("unspecified AUTO2 code: '%s'", proj) + + elif proj.startswith("epsg:"): + epsg = proj[5:] + if epsg.startswith("777") and len(epsg) == 8: # user defined MSS code. deprecated. + logging.warning("Using deprecated MSS-specific EPSG code. Switch to 'MSS:stere' instead.") + lat_0, lon_0 = int(epsg[3:5]), int(epsg[5:]) + proj_params = { + "basemap": {"projection": "stere", "lat_0": lat_0, "lon_0": lon_0}, + "bbox": "degree"} + elif epsg.startswith("778") and len(epsg) == 8: # user defined MSS code. deprecated. + logging.warning("Using deprecated MSS-specific EPSG code. Switch to 'MSS:stere' instead.") + lat_0, lon_0 = int(epsg[3:5]), int(epsg[5:]) + proj_params = { + "basemap": {"projection": "stere", "lat_0": -lat_0, "lon_0": lon_0}, + "bbox": "degree"} + elif epsg in ("4258", "4326"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "degree"} + elif epsg in ("3031", "3412"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,-90)"} + elif epsg in ("3411", "3413", "3575", "3995"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,90)"} + elif epsg in ("3395", "3857"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(0,0)"} + elif epsg in ("4839"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(10.5,51)"} + elif epsg in ("31467"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(-20.9631343,0.0037502)"} + elif epsg in ("31468"): + proj_params = {"basemap": {"epsg": epsg}, "bbox": "meter(-25.4097892,0.0037466)"} + else: + raise ValueError("EPSG code not supported by basemap module: '%s'", proj) + + elif proj.startswith("mss:"): + # some MSS-specific codes + params = proj[4:].split(",") + name = params[0] + if name == "stere": + lon0, lat0, lat_ts = params[1:] + proj_params = { + "basemap": {"projection": name, "lat_0": lat0, "lon_0": lon0, "lat_ts": lat_ts}, + "bbox": "degree"} + elif name == "cass": + lon0, lat0 = params[1:] + proj_params = { + "basemap": {"projection": name, "lon_0": lon0, "lat_0": lat0}, + "bbox": "degree"} + elif name == "lcc": + lon0, lat0, lat1, lat2 = params[1:] + proj_params = { + "basemap": {"projection": name, "lon_0": lon0, "lat_0": lat0, "lat_1": lat1, "lat_2": lat2}, + "bbox": "degree"} + elif name == "merc": + lat_ts = params[1] + proj_params = { + "basemap": {"projection": name, "lat_ts": lat_ts}, + "bbox": "degree"} + else: + raise ValueError("unknown MSS projection: '%s'", proj) + + else: + raise ValueError("unknown projection: '%s'", proj) + logging.debug("Identified CRS '%s' as '%s'", proj, proj_params) + return proj_params diff --git a/mslib/utils/mssautoplot.py b/mslib/utils/mssautoplot.py index 0332ac4f2..1cef25218 100644 --- a/mslib/utils/mssautoplot.py +++ b/mslib/utils/mssautoplot.py @@ -58,6 +58,7 @@ from mslib.msui import mpl_pathinteractor as mpath from mslib.msui import flighttrack as ft from mslib.utils import config as conf +from mslib.utils.get_projection_params import get_projection_params from mslib.utils.auth import get_auth_from_url_and_name from mslib.utils.loggerdef import configure_mpl_logger from mslib.utils.verify_user_token import verify_user_token @@ -219,8 +220,7 @@ def __init__(self, cpath, msc_url=None, msc_auth_password=None, username=None, p filename = self.config["automated_plotting_flights"][0][3] if self.__class__.__name__ == "TopViewPlotting": try: - self.params = mslib.utils.coordinate.get_projection_params( - self.config["predefined_map_sections"][section]["CRS"].lower()) + self.params = get_projection_params(self.config["predefined_map_sections"][section]["CRS"].lower()) except KeyError as e: print(e) raise SystemExit("Invalid SECTION and/or CRS") diff --git a/tests/_test_utils/test_coordinate.py b/tests/_test_utils/test_coordinate.py index ba5b50456..818b783f1 100644 --- a/tests/_test_utils/test_coordinate.py +++ b/tests/_test_utils/test_coordinate.py @@ -31,6 +31,8 @@ import pytest import mslib.utils.coordinate as coordinate +from mslib.utils.find_location import find_location +from mslib.utils.get_projection_params import get_projection_params LOGGER = logging.getLogger(__name__) @@ -48,19 +50,19 @@ def test_get_distance(self): assert int(coordinate.get_distance(lat0, lon0, lat1, lon1)) == distance def test_find_location(self): - assert coordinate.find_location(50.92, 6.36) == ([50.92, 6.36], 'Juelich') - assert coordinate.find_location(50.9200002, 6.36) == ([50.92, 6.36], 'Juelich') + assert find_location(50.92, 6.36) == ([50.92, 6.36], 'Juelich') + assert find_location(50.9200002, 6.36) == ([50.92, 6.36], 'Juelich') class TestProjections: def test_get_projection_params(self): - assert coordinate.get_projection_params("epsg:4839") == {'basemap': {'epsg': '4839'}, 'bbox': 'meter(10.5,51)'} + assert get_projection_params("epsg:4839") == {'basemap': {'epsg': '4839'}, 'bbox': 'meter(10.5,51)'} with pytest.raises(ValueError): - coordinate.get_projection_params('auto2:42005') + get_projection_params('auto2:42005') with pytest.raises(ValueError): - coordinate.get_projection_params('auto:42001') + get_projection_params('auto:42001') with pytest.raises(ValueError): - coordinate.get_projection_params('crs:83') + get_projection_params('crs:83') class TestAngles: