Esempio n. 1
0
    def read(self,
             service_url,
             timeout=config_loader(dataset="WMS_request_timeout")):
        """Get and parse a WMS capabilities document, returning an
        elementtree instance

        service_url is the base url, to which is appended the service,
        version, and request parameters
        """
        getcaprequest = self.capabilities_url(service_url)

        # Don't specify a version if it is to be determined
        getcaprequest = getcaprequest.replace("&version=None",
                                              "").replace("?version=None", "")

        proxies = config_loader(dataset="proxies")

        # now split it up again to use the generic openURL function...
        spliturl = getcaprequest.split('?')
        u = openURL(spliturl[0],
                    spliturl[1],
                    method='Get',
                    auth=self.auth,
                    proxies=proxies)

        # (mss) Store capabilities document.
        self.capabilities_document = strip_bom(u.read())
        return etree.fromstring(self.capabilities_document)
Esempio n. 2
0
 def test_sample_config_file(self):
     utils_path = os.path.dirname(os.path.abspath(utils.__file__))
     config_file = os.path.join(
         utils_path,
         '../',
         '../',
         'docs',
         'samples',
         'config',
         'mss',
         'mss_settings.json.sample',
     )
     read_config_file(path=config_file)
     data = config_loader(dataset="new_flighttrack_flightlevel")
     assert data == 250
     with pytest.raises(KeyError):
         config_loader(dataset="UNDEFINED")
     with pytest.raises(KeyError):
         assert config_loader(dataset="UNDEFINED")
     with pytest.raises(FileNotFoundError):
         config_file = os.path.join(
             utils_path,
             '../',
             '../',
             'docs',
             'samples',
             'config',
             'mss',
             'non_existent_mss_settings.json.sample',
         )
         read_config_file(config_file)
Esempio n. 3
0
def get_pickertype(tag, typ):
    default = config_loader(dataset="filepicker_default")
    if typ is None:
        if tag is None:
            typ = default
        else:
            typ = config_loader(dataset=tag)
    return typ
Esempio n. 4
0
 def test_add_user(self):
     self._connect_to_mscolab()
     self._create_user("something", "*****@*****.**", "something")
     assert config_loader(
         dataset="MSCOLAB_mailid") == "*****@*****.**"
     assert config_loader(dataset="MSCOLAB_password") == "something"
     # assert self.window.stackedWidget.currentWidget() == self.window.newuserPage
     assert self.main_window.usernameLabel.text() == 'something'
     assert self.main_window.mscolab.connect_window is None
Esempio n. 5
0
 def test_sample_config_file(self):
     config_file = os.path.join(
         self.sample_path,
         'msui_settings.json.sample',
     )
     read_config_file(path=config_file)
     data = config_loader(dataset="new_flighttrack_flightlevel")
     assert data == 250
     with pytest.raises(KeyError):
         config_loader(dataset="UNDEFINED")
     with pytest.raises(KeyError):
         assert config_loader(dataset="UNDEFINED")
Esempio n. 6
0
    def _add_hexagon(self):
        table_view = self.view.tableWayPoints
        waypoints_model = self.view.waypoints_model
        params = self._get_parameters()

        if params["radius"] < 0.01:
            QtWidgets.QMessageBox.warning(
                self, "Add hexagon",
                "You cannot create a hexagon with zero radius!")
            return
        points = create_hexagon(params["center_lat"], params["center_lon"],
                                params["radius"], params["angle"],
                                params["direction"] == "clockwise")
        index = table_view.currentIndex()
        if not index.isValid():
            row = 0
            flightlevel = config_loader(dataset="new_flighttrack_flightlevel")
        else:
            row = index.row() + 1
            flightlevel = waypoints_model.waypoint_data(row - 1).flightlevel
        waypoints = []
        for i, point in enumerate(points):
            waypoints.append(
                ft.Waypoint(lon=float(point[1]),
                            lat=float(point[0]),
                            flightlevel=float(flightlevel),
                            comments=f"Hexagon {(i + 1):d}"))
        waypoints_model.insertRows(row,
                                   rows=len(waypoints),
                                   waypoints=waypoints)
        index = waypoints_model.index(row, 0)
        table_view.setCurrentIndex(index)
        table_view.resizeRowsToContents()
Esempio n. 7
0
    def __init__(self, lat=0, lon=0, flightlevel=0, location="", comments=""):
        self.location = location
        locations = config_loader(dataset='locations')
        if location in locations:
            self.lat, self.lon = locations[location]
        else:
            self.lat = lat
            self.lon = lon
        self.flightlevel = flightlevel
        self.pressure = thermolib.flightlevel2pressure(flightlevel *
                                                       units.hft).magnitude
        self.distance_to_prev = 0.
        self.distance_total = 0.
        self.comments = comments

        # Performance fields (for values read from the flight performance
        # service).
        self.leg_time = None  # time from previous waypoint
        self.cum_time = None  # total time of flight
        self.utc_time = None  # time in UTC since given takeoff time
        self.leg_fuel = None  # fuel consumption since previous waypoint
        self.rem_fuel = None  # total fuel consumption
        self.weight = None  # aircraft gross weight
        self.ceiling_alt = None  # aircraft ceiling altitude
        self.ascent_rate = None  # aircraft ascent rate

        self.wpnumber_major = None
        self.wpnumber_minor = None
Esempio n. 8
0
    def createEditor(self, parent, option, index):
        """
        Create a combobox listing predefined locations in the LOCATION
        column.
        """
        if index.column() == LOCATION:
            combobox = QtWidgets.QComboBox(parent)
            locations = config_loader(dataset='locations')
            adds = list(locations.keys())
            if self.parent() is not None:
                for loc in [
                        wp.location for wp in
                        self.parent().waypoints_model.all_waypoint_data()
                        if wp.location != ""
                ]:
                    if loc not in adds:
                        adds.append(loc)
            combobox.addItems(sorted(adds))

            combobox.setEditable(True)
            return combobox
        else:
            # All other columns get the standard editor.
            return QtWidgets.QItemDelegate.createEditor(
                self, parent, option, index)
Esempio n. 9
0
    def setModelData(self, editor, model, index):
        """
        For the LOCATION column: If the user selects a location from the
        combobox, get the corresponding coordinates.
        """
        if index.column() == LOCATION:
            loc = editor.currentText()
            locations = config_loader(dataset='locations')
            if loc in locations:
                lat, lon = locations[loc]
                # Don't update distances and flight performance twice, hence
                # set update=False for LAT.
                model.setData(index.sibling(index.row(), LAT),
                              QtCore.QVariant(lat),
                              update=False)
                model.setData(index.sibling(index.row(), LON),
                              QtCore.QVariant(lon))
            else:
                for wp in self.parent().waypoints_model.all_waypoint_data():
                    if loc == wp.location:
                        lat, lon = wp.lat, wp.lon
                        # Don't update distances and flight performance twice, hence
                        # set update=False for LAT.
                        model.setData(index.sibling(index.row(), LAT),
                                      QtCore.QVariant(lat),
                                      update=False)
                        model.setData(index.sibling(index.row(), LON),
                                      QtCore.QVariant(lon))

            model.setData(index, QtCore.QVariant(editor.currentText()))
        else:
            QtWidgets.QItemDelegate.setModelData(self, editor, model, index)
Esempio n. 10
0
    def changeMapSection(self, index=0, only_kwargs=False):
        """
        Change the current map section to one of the predefined regions.
        """
        # Get the initial projection parameters from the tables in mss_settings.
        current_map_key = self.cbChangeMapSection.currentText()
        predefined_map_sections = config_loader(
            dataset="predefined_map_sections")
        current_map = predefined_map_sections.get(current_map_key, {
            "CRS": current_map_key,
            "map": {}
        })
        proj_params = get_projection_params(current_map["CRS"])

        # Create a keyword arguments dictionary for basemap that contains
        # the projection parameters.
        kwargs = current_map["map"]
        kwargs.update({
            "CRS": current_map["CRS"],
            "BBOX_UNITS": proj_params["bbox"],
            "OPERATION_NAME": self.waypoints_model.name
        })
        kwargs.update(proj_params["basemap"])

        if only_kwargs:
            # Return kwargs dictionary and do NOT redraw the map.
            return kwargs

        logging.debug("switching to map section '%s' - '%s'", current_map_key,
                      kwargs)
        self.mpl.canvas.redraw_map(kwargs)
        self.mpl.navbar.clear_history()
Esempio n. 11
0
    def __init__(self,
                 url,
                 version=None,
                 xml=None,
                 username=None,
                 password=None,
                 parse_remote_metadata=False,
                 headers=None,
                 timeout=config_loader(dataset="WMS_request_timeout"),
                 auth=None):
        """Initialize."""

        if auth:
            if username:
                auth.username = username
            if password:
                auth.password = password
        self.url = url
        self.version = version
        self.timeout = timeout
        self.headers = headers
        self._capabilities = None
        self.auth = auth or Authentication(username, password)

        # Authentication handled by Reader
        reader = WMSCapabilitiesReader(self.version,
                                       url=self.url,
                                       headers=headers,
                                       auth=self.auth)
        if xml:
            # read from stored xml
            self._capabilities = reader.readString(xml)
        else:
            # read from server
            self._capabilities = reader.read(self.url, timeout=self.timeout)

        self.request = reader.request
        if not self.version:
            self.version = self._capabilities.attrib["version"]
            if self.version not in ["1.1.1", "1.3.0"]:
                self.version = "1.1.1"
            reader.version = self.version

        self.WMS_NAMESPACE = "{http://www.opengis.net/wms}" if self.version == "1.3.0" else ""
        self.OGC_NAMESPACE = "{http://www.opengis.net/ogc}" if self.version == "1.3.0" else ""

        # avoid building capabilities metadata if the
        # response is a ServiceExceptionReport
        se = self._capabilities.find('ServiceException')
        if se is not None:
            err_message = str(se.text).strip()
            raise ServiceException(err_message)

        # (mss) Store capabilities document.
        self.capabilities_document = reader.capabilities_document
        # (mss)

        # build metadata objects
        self._buildMetadata(parse_remote_metadata)
Esempio n. 12
0
 def test_option_types(self):
     # check if all config options are added to the appropriate type of options
     config_keys = set(config_loader(default=True).keys())
     option_types = set(mss_default.fixed_dict_options +
                        mss_default.key_value_options +
                        list(mss_default.dict_option_structure.keys()) +
                        list(mss_default.list_option_structure.keys()))
     assert config_keys == option_types
Esempio n. 13
0
 def test_existing_config_file_different_parameters(self):
     """
     on a user defined mss_settings_json without a defined num_labels this test should return its default value
     """
     create_mss_settings_file('{"num_interpolation_points": 20 }')
     if not fs.open_fs(MSS_CONFIG_PATH).exists("mss_settings.json"):
         pytest.skip('undefined test mss_settings.json')
     with fs.open_fs(MSS_CONFIG_PATH) as file_dir:
         file_content = file_dir.readtext("mss_settings.json")
     assert "num_labels" not in file_content
     default_data = config_loader(default=True)
     config_file = fs.path.combine(MSS_CONFIG_PATH, "mss_settings.json")
     read_config_file(path=config_file)
     data = config_loader()
     assert data["num_labels"] == default_data["num_labels"]
     num_labels = config_loader(dataset="num_labels")
     assert num_labels == default_data["num_labels"]
     num_interpolation_points = config_loader(
         dataset="num_interpolation_points")
     assert num_interpolation_points == 20
     assert data["num_interpolation_points"] == 20
     with pytest.raises(KeyError):
         config_loader(dataset="UNDEFINED")
     with pytest.raises(KeyError):
         assert config_loader(dataset="UNDEFINED")
Esempio n. 14
0
 def test_add_users_with_updating_credentials_in_config_file(
         self, mockmessage):
     create_msui_settings_file(
         '{"MSCOLAB_mailid": "*****@*****.**", "MSCOLAB_password": "******"}'
     )
     read_config_file()
     # check current settings
     assert config_loader(
         dataset="MSCOLAB_mailid") == "*****@*****.**"
     assert config_loader(dataset="MSCOLAB_password") == "something"
     self._connect_to_mscolab()
     assert self.window.mscolab_server_url is not None
     self._create_user("anand", "*****@*****.**", "anand")
     # check changed settings
     assert config_loader(dataset="MSCOLAB_mailid") == "*****@*****.**"
     assert config_loader(dataset="MSCOLAB_password") == "anand"
     # check user is logged in
     assert self.main_window.usernameLabel.text() == "anand"
Esempio n. 15
0
 def openTool(self, index):
     """
     Slot that handles requests to open tool windows.
     """
     index = self.controlToBeCreated(index)
     if index >= 0:
         if index == WMS:
             # Open a WMS control widget.
             title = "Web Service Plot Control"
             widget = wms.LSecWMSControlWidget(
                 default_WMS=config_loader(dataset="default_LSEC_WMS"),
                 waypoints_model=self.waypoints_model,
                 view=self.mpl.canvas,
                 wms_cache=config_loader(dataset="wms_cache"))
             self.mpl.canvas.waypoints_interactor.signal_get_lsec.connect(widget.call_get_lsec)
         else:
             raise IndexError("invalid control index")
         # Create the actual dock widget containing <widget>.
         self.createDockWidget(index, title, widget)
Esempio n. 16
0
 def update_predefined_maps(self, extra=None):
     self.cbChangeMapSection.clear()
     predefined_map_sections = config_loader(
         dataset="predefined_map_sections")
     self.cbChangeMapSection.addItems(sorted(
         predefined_map_sections.keys()))
     if extra is not None and len(extra) > 0:
         self.cbChangeMapSection.insertSeparator(
             self.cbChangeMapSection.count())
         self.cbChangeMapSection.addItems(sorted(extra))
Esempio n. 17
0
 def test_modify_config_file_with_existing_parameters(self):
     """
     Test to check if modify_config_file properly modifies a key-value pair in the config file
     """
     create_msui_settings_file('{"MSCOLAB_mailid": "*****@*****.**"}')
     if not fs.open_fs(MSUI_CONFIG_PATH).exists("msui_settings.json"):
         pytest.skip('undefined test msui_settings.json')
     data_to_save_in_config_file = {"MSCOLAB_mailid": "*****@*****.**"}
     modify_config_file(data_to_save_in_config_file)
     config_file = fs.path.combine(MSUI_CONFIG_PATH, "msui_settings.json")
     read_config_file(path=config_file)
     data = config_loader()
     assert data["MSCOLAB_mailid"] == "*****@*****.**"
Esempio n. 18
0
 def update_predefined_maps(self, extra=None):
     current_map_key = self.cbChangeMapSection.currentText()
     self.cbChangeMapSection.clear()
     predefined_map_sections = config_loader(
         dataset="predefined_map_sections")
     self.cbChangeMapSection.addItems(sorted(
         predefined_map_sections.keys()))
     if extra is not None and len(extra) > 0:
         self.cbChangeMapSection.insertSeparator(
             self.cbChangeMapSection.count())
         self.cbChangeMapSection.addItems(sorted(extra))
     # set initial map key again
     if current_map_key in predefined_map_sections.keys():
         self.cbChangeMapSection.setCurrentText(current_map_key)
Esempio n. 19
0
    def openTool(self, index):
        """
        Slot that handles requests to open control windows.
        """
        index = self.controlToBeCreated(index)
        if index >= 0:
            if index == WMS:
                # Create a new WMSDockWidget.
                title = "Web Map Service (Top View)"
                widget = wc.HSecWMSControlWidget(
                    default_WMS=config_loader(dataset="default_WMS"),
                    view=self.mpl.canvas,
                    wms_cache=config_loader(dataset="wms_cache"))
                widget.signal_disable_cbs.connect(self.disable_cbs)
                widget.signal_enable_cbs.connect(self.enable_cbs)
            elif index == SATELLITE:
                title = "Satellite Track Prediction"
                widget = sat.SatelliteControlWidget(parent=self,
                                                    view=self.mpl.canvas)
            elif index == REMOTESENSING:
                title = "Remote Sensing Tools"
                widget = rs.RemoteSensingControlWidget(parent=self,
                                                       view=self.mpl.canvas)
            elif index == KMLOVERLAY:
                title = "KML Overlay"
                widget = kml.KMLOverlayControlWidget(parent=self,
                                                     view=self.mpl.canvas)
            elif index == AIRDATA:
                title = "Airdata"
                widget = ad.AirdataDockwidget(parent=self,
                                              view=self.mpl.canvas)
            else:
                raise IndexError("invalid control index")

            # Create the actual dock widget containing <widget>.
            self.createDockWidget(index, title, widget)
Esempio n. 20
0
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
Esempio n. 21
0
    def __init__(self,
                 token,
                 op_id,
                 user,
                 operation_name,
                 conn,
                 parent=None,
                 mscolab_server_url=config_loader(dataset="default_MSCOLAB")):
        """
        token: access_token
        op_id: operation id
        user: logged in user
        operation_name: name of operation,
        conn: socket connection
        parent: parent of widget
        mscolab_server_url: server url of mscolab
        """
        super(MSColabVersionHistory, self).__init__(parent)
        self.setupUi(self)
        # Initialise Variables
        self.token = token
        self.op_id = op_id
        self.user = user
        self.operation_name = operation_name
        self.conn = conn
        self.mscolab_server_url = mscolab_server_url

        # Event handlers
        self.refreshBtn.clicked.connect(self.handle_refresh)
        self.checkoutBtn.clicked.connect(self.handle_undo)
        self.nameVersionBtn.clicked.connect(self.handle_named_version)
        self.deleteVersionNameBtn.clicked.connect(
            self.handle_delete_version_name)
        self.versionFilterCB.currentIndexChanged.connect(
            lambda: self.load_all_changes())
        self.changes.currentItemChanged.connect(self.preview_change)
        # Setup UI
        self.deleteVersionNameBtn.setVisible(False)
        self.set_label_text()
        self.set_change_list_style()
        self.toggle_version_buttons(False)
        self.load_current_waypoints()
        self.load_all_changes()
Esempio n. 22
0
def verify_user_token(mscolab_server_url, token):

    if config_loader(dataset="mscolab_skip_verify_user_token"):
        return True

    data = {"token": token}
    try:
        r = requests.get(f'{mscolab_server_url}/test_authorized', data=data)
    except requests.exceptions.SSLError:
        logging.debug("Certificate Verification Failed")
        return False
    except requests.exceptions.InvalidSchema:
        logging.debug("Invalid schema of url")
        return False
    except requests.exceptions.ConnectionError as ex:
        logging.error("unexpected error: %s %s", type(ex), ex)
        return False
    except requests.exceptions.MissingSchema as ex:
        # self.mscolab_server_url can be None??
        logging.error("unexpected error: %s %s", type(ex), ex)
        return False
    return r.text == "True"
Esempio n. 23
0
 def test_existing_empty_config_file(self):
     """
     on a user defined empty mss_settings_json this test should return the default value for num_labels
     """
     create_mss_settings_file('{ }')
     if not fs.open_fs(MSS_CONFIG_PATH).exists("mss_settings.json"):
         pytest.skip('undefined test mss_settings.json')
     with fs.open_fs(MSS_CONFIG_PATH) as file_dir:
         file_content = file_dir.readtext("mss_settings.json")
     assert ":" not in file_content
     default_data = config_loader(default=True)
     config_file = fs.path.combine(MSS_CONFIG_PATH, "mss_settings.json")
     read_config_file(path=config_file)
     data = config_loader()
     assert data["num_labels"] == default_data["num_labels"]
     num_labels = config_loader(dataset="num_labels")
     assert num_labels == default_data["num_labels"]
     with pytest.raises(KeyError):
         config_loader(dataset="UNDEFINED")
     with pytest.raises(KeyError):
         assert config_loader(dataset="UNDEFINED")
Esempio n. 24
0
    def __init__(self,
                 token,
                 op_id,
                 user,
                 operation_name,
                 access_level,
                 conn,
                 parent=None,
                 mscolab_server_url=config_loader(dataset="default_MSCOLAB")):
        """
        token: access_token
        op_id: operation id
        user: logged in user
        operation_name: active operation name,
        access_level: access level of user logged in
        conn: to send messages, recv messages, if a direct slot-signal can't be setup
            to be connected at parents'
        parent: widget parent
        mscolab_server_url: server url for mscolab
        """
        super(MSColabChatWindow, self).__init__(parent)
        self.setupUi(self)

        self.mscolab_server_url = mscolab_server_url
        self.token = token
        self.user = user
        self.op_id = op_id
        self.operation_name = operation_name
        self.conn = conn
        self.access_level = access_level
        self.text = ""
        self.attachment = None
        self.attachment_type = None
        self.active_edit_id = None
        self.active_message_reply = None
        self.current_search_index = None
        self.markdown = Markdown(
            extensions=['nl2br', 'sane_lists',
                        DeregisterSyntax()])
        self.messageText = MessageTextEdit(self.centralwidget)
        self.setup_message_text()
        # Signals
        self.searchMessageLineEdit.textChanged.connect(
            self.handle_search_text_changed)
        self.searchPrevBtn.clicked.connect(self.handle_prev_message_search)
        self.searchNextBtn.clicked.connect(self.handle_next_message_search)
        self.previewBtn.clicked.connect(self.toggle_preview)
        self.sendMessageBtn.clicked.connect(self.send_message)
        self.uploadBtn.clicked.connect(self.handle_upload)
        self.editMessageBtn.clicked.connect(self.edit_message)
        self.cancelBtn.clicked.connect(self.send_message_state)
        # Socket Connection handlers
        self.conn.signal_operation_permissions_updated.connect(
            self.handle_permissions_updated)
        self.conn.signal_message_receive.connect(self.handle_incoming_message)
        self.conn.signal_message_reply_receive.connect(
            self.handle_incoming_message_reply)
        self.conn.signal_message_edited.connect(self.handle_message_edited)
        self.conn.signal_message_deleted.connect(self.handle_deleted_message)
        # Set Label text
        self.set_label_text()
        # Hide Edit Message section
        self.send_message_state()
        # load all users
        self.load_users()
        # load messages
        self.load_all_messages()
        if access_level == "viewer":
            self.messageText.setEnabled(False)
            self.previewBtn.setEnabled(False)
            self.uploadBtn.setEnabled(False)
            self.sendMessageBtn.setEnabled(False)
Esempio n. 25
0
from mslib.msui.mss_qt import get_open_filename, get_save_filename, show_popup
from mslib.msui.mss_qt import ui_configuration_editor_window as ui_conf
from PyQt5 import QtWidgets, QtCore, QtGui
from mslib.msui.constants import MSS_SETTINGS
from mslib.msui.icons import icons
from mslib.utils.config import MissionSupportSystemDefaultConfig as mss_default
from mslib.utils.config import config_loader, dict_raise_on_duplicates_empty, merge_data

from mslib.support.qt_json_view import delegate
from mslib.support.qt_json_view.view import JsonView
from mslib.support.qt_json_view.model import JsonModel
from mslib.support.qt_json_view.datatypes import match_type, DataType, TypeRole, ListType

InvalidityRole = TypeRole + 1
DummyRole = TypeRole + 2
default_options = config_loader(default=True)


def get_root_index(index, parents=False):
    parent_list = []
    while index.parent().isValid():
        index = index.parent()
        parent_list.append(index)
    parent_list.reverse()
    if parents:
        return index, parent_list
    return index


class JsonDelegate(delegate.JsonDelegate):
    def paint(self, painter, option, index):
Esempio n. 26
0
    def __init__(self, parent=None):
        super(ConfigurationEditorWindow, self).__init__(parent)
        self.setupUi(self)

        options = config_loader()
        self.path = MSS_SETTINGS
        self.last_saved = copy.deepcopy(options)

        self.optCb.addItem("All")
        for option in sorted(options.keys(), key=str.lower):
            self.optCb.addItem(option)

        # Create view and place in parent widget
        self.view = JsonView()
        self.view.setItemDelegate(JsonDelegate())
        self.view.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.jsonWidget.setLayout(QtWidgets.QVBoxLayout())
        self.jsonWidget.layout().setContentsMargins(0, 0, 0, 0)
        self.jsonWidget.layout().addWidget(self.view)

        # Create proxy model for filtering
        self.proxy_model = JsonSortFilterProxyModel()
        self.json_model = JsonModel(data=options,
                                    editable_keys=True,
                                    editable_values=True)
        self.json_model.setHorizontalHeaderLabels(['Option', 'Value'])

        # Set view model
        self.proxy_model.setSourceModel(self.json_model)
        self.view.setModel(self.proxy_model)

        # Setting proxy model and view attributes
        self.proxy_model.setFilterKeyColumn(0)

        # Add actions to toolbar
        self.import_file_action = QtWidgets.QAction(
            QtGui.QIcon(icons("config_editor", "Folder-new.svg")),
            "Import config", self)
        self.import_file_action.setStatusTip(
            "Import an external configuration file")
        self.toolBar.addAction(self.import_file_action)

        self.save_file_action = QtWidgets.QAction(
            QtGui.QIcon(icons("config_editor", "Document-save.svg")),
            "Save config", self)
        self.save_file_action.setStatusTip("Save current configuration")
        self.toolBar.addAction(self.save_file_action)

        self.export_file_action = QtWidgets.QAction(
            QtGui.QIcon(icons("config_editor", "Document-save-as.svg")),
            "Export config", self)
        self.export_file_action.setStatusTip("Export current configuration")
        self.toolBar.addAction(self.export_file_action)

        # Button signals
        self.optCb.currentIndexChanged.connect(self.set_option_filter)
        self.addOptBtn.clicked.connect(self.add_option_handler)
        self.removeOptBtn.clicked.connect(self.remove_option_handler)
        self.restoreDefaultsBtn.clicked.connect(self.restore_defaults)
        self.moveUpTb.clicked.connect(lambda: self.move_option(move=1))
        self.moveDownTb.clicked.connect(lambda: self.move_option(move=-1))

        # File action signals
        self.import_file_action.triggered.connect(self.import_config)
        self.save_file_action.triggered.connect(self.save_config)
        self.export_file_action.triggered.connect(self.export_config)

        # View/Model signals
        self.view.selectionModel().selectionChanged.connect(
            self.tree_selection_changed)
        self.json_model.dataChanged.connect(self.update_view)

        # set behaviour of widgets
        self.moveUpTb.hide()
        self.moveDownTb.hide()
        self.moveUpTb.setAutoRaise(True)
        self.moveUpTb.setArrowType(QtCore.Qt.UpArrow)
        self.moveUpTb.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
        self.moveDownTb.setAutoRaise(True)
        self.moveDownTb.setArrowType(QtCore.Qt.DownArrow)
        self.moveDownTb.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)

        self.moveUpTb.setEnabled(False)
        self.moveDownTb.setEnabled(False)
        self.addOptBtn.setEnabled(False)
        self.removeOptBtn.setEnabled(False)
        self.restoreDefaultsBtn.setEnabled(False)

        # set tooltip and make keys non-editable
        self.set_noneditable_items(QtCore.QModelIndex())

        # json view attributes
        self.view.setAlternatingRowColors(True)
        self.view.setColumnWidth(0, self.view.width() // 2)

        # Add invalidity roles and update status of keys
        self.update_view()

        self.restart_on_save = True
Esempio n. 27
0
 def test_default_config(self):
     data = config_loader(default=True)
     assert isinstance(data, dict)
     assert data == config_loader(default=True)
     assert data["num_labels"] == 10
     assert data["num_interpolation_points"] == 201
Esempio n. 28
0
 def test_default_config_dataset(self):
     default_data = config_loader(default=True)
     num_labels = config_loader(dataset="num_labels", default=True)
     assert num_labels == default_data["num_labels"]
Esempio n. 29
0
def main():
    parser = argparse.ArgumentParser(description="""
       This script automatically retrieves and stores a set of plots for the
       configured flights. The configuration is placed within the normal
       MSS frontend JSON file. E.g.

       "automated_plotting": {
           "flights": [
               ["ST25", "01 SADPAP (stereo)", "500,50",
                "ST25-joern.ftml",
                "2019-07-01T00:00:00Z", "2019-09-01T12:00:00Z"]
           ],
           "hsecs": [
               ["https://mss-server/campaigns2019",
                "ecmwf.PVTropo01", "default", "4.0"],
               ["https://mss-server/campaigns2019",
                "ecmwf.ertel_potential_vorticity_pl", "ertel_potential_vorticity_bh", "200.0"]
           ],
           "vsecs": [
               ["https://mss-server/campaigns2019",
                "ecmwf.VS_ertel_potential_vorticity_ml", "ertel_potential_vorticity_bh"],
               ["https://mss-server/campaigns2019",
                "ecmwf.TroposphereInversionLayer", ""]
           ]
       }

       will plot flight "ST25" with configured map section "01 SADPAP (stereo)" and
       vertical range 500hPa to 50hPa from the given FTML file for init time
       "2019-07-01T00:00:00Z" and valid time "2019-09-01T12:00:00Z". The plots
       are defined in the hsecs (horizontal cross-sections) and vsecs (vertical
       cross-sections) entries given each the URL of the server, the layer name, the style,
       and, for hsec only, the elevation to plot (if necessary).
    """)
    parser.add_argument("-v",
                        "--version",
                        help="show version",
                        action="store_true",
                        default=False)
    parser.add_argument("--debug",
                        help="show debugging log messages on console",
                        action="store_true",
                        default=False)
    parser.add_argument(
        "--logfile",
        help="Specify logfile location. Set to empty string to disable.",
        action="store",
        default=os.path.join(mslib.msui.constants.MSUI_CONFIG_PATH,
                             "msui.log"))
    args = parser.parse_args()

    if args.version:
        print(
            "***********************************************************************"
        )
        print("\n            Mission Support System (mss_retriever)\n")
        print(
            "***********************************************************************"
        )
        print("Documentation: http://mss.rtfd.io")
        print("Version:", mslib.__version__)
        sys.exit()

    mslib.utils.setup_logging(args)
    read_config_file(path=mslib.msui.constants.MSUI_SETTINGS)
    config = config_loader()
    num_interpolation_points = config["num_interpolation_points"]
    num_labels = config["num_labels"]
    tick_index_step = num_interpolation_points // num_labels

    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["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]]
        wp_presss = [
            thermolib.flightlevel2pressure(wp[2] * units.hft).magnitude
            for wp in wps
        ]
        for url, layer, style, elevation in config["automated_plotting"][
                "hsecs"]:
            fig.clear()
            ax = fig.add_subplot(111, zorder=99)
            bm = mslib.msui.mpl_map.MapCanvas(ax=ax, **(params["basemap"]))

            # plot path and labels
            bm.plot(wp_lons,
                    wp_lats,
                    color="blue",
                    marker="o",
                    linewidth=2,
                    markerfacecolor="red",
                    latlon=True,
                    markersize=4,
                    zorder=100)
            for i, (lon, lat, loc) in enumerate(zip(wp_lons, wp_lats,
                                                    wp_locs)):
                textlabel = f"{loc if loc else str(i)}   "
                x, y = bm(lon, lat)
                plt.text(x, y, textlabel, **TEXT_CONFIG)
            plt.tight_layout()

            # retrieve and draw WMS image
            ax_bounds = plt.gca().bbox.bounds
            width, height = int(round(ax_bounds[2])), int(round(ax_bounds[3]))
            bbox = params['basemap']
            req = requests.get(
                url,
                auth=tuple(config["WMS_login"][url]),
                params={
                    "version":
                    "1.3.0",
                    "request":
                    "GetMap",
                    "format":
                    "image/png",
                    "exceptions":
                    "XML",
                    "crs":
                    config["predefined_map_sections"][section]["CRS"],
                    "layers":
                    layer,
                    "styles":
                    style,
                    "elevation":
                    elevation,
                    "dim_init_time":
                    init_time,
                    "time":
                    time,
                    "width":
                    width,
                    "height":
                    height,
                    "bbox":
                    f"{bbox['llcrnrlat']},{bbox['llcrnrlon']},{bbox['urcrnrlat']},{bbox['urcrnrlon']}"
                })
            if req.headers['Content-Type'] == "text/xml":
                print(flight, section, vertical, filename, init_time, time)
                print(url, layer, style, elevation)
                print("WMS Error:")
                print(req.text)
                exit(1)
            image_io = io.BytesIO(req.content)
            img = PIL.Image.open(image_io)
            bm.imshow(img, interpolation="nearest", origin="upper")
            bm.drawcoastlines()
            bm.drawcountries()

            fig.savefig(f"{flight}_{layer}.png")

        # prepare vsec plots
        path = [(wp[0], wp[1], datetime.datetime.now()) for wp in wps]
        lats, lons = mslib.utils.coordinate.path_points(
            [_x[0] for _x in path], [_x[1] for _x in path],
            numpoints=num_interpolation_points + 1,
            connection="greatcircle")
        intermediate_indexes = []
        ipoint = 0
        for i, (lat, lon) in enumerate(zip(lats, lons)):
            if abs(lat - wps[ipoint][0]) < 1E-10 and abs(
                    lon - wps[ipoint][1]) < 1E-10:
                intermediate_indexes.append(i)
                ipoint += 1
            if ipoint >= len(wps):
                break

        for url, layer, style in config["automated_plotting"]["vsecs"]:
            fig.clear()

            # setup ticks and labels
            ax = fig.add_subplot(111, zorder=99)
            ax.set_yscale("log")
            p_bot, p_top = [float(x) * 100 for x in vertical.split(",")]
            bbox = ",".join(
                str(x) for x in (num_interpolation_points, p_bot / 100,
                                 num_labels, p_top / 100))
            ax.grid(visible=True)
            ax.patch.set_facecolor("None")
            pres_maj = mslib.msui.mpl_qtwidget.MplSideViewCanvas._pres_maj
            pres_min = mslib.msui.mpl_qtwidget.MplSideViewCanvas._pres_min
            major_ticks = pres_maj[(pres_maj <= p_bot) & (pres_maj >= p_top)]
            minor_ticks = pres_min[(pres_min <= p_bot) & (pres_min >= p_top)]
            labels = [
                f"{int(_mt / 100)}" if
                (_mt / 100.) - int(_mt / 100.) == 0 else f"{float(_mt / 100)}"
                for _mt in major_ticks
            ]
            if len(labels) > 20:
                labels = [
                    "" if _x.split(".")[-1][0] in "975" else _x
                    for _x in labels
                ]
            elif len(labels) > 10:
                labels = [
                    "" if _x.split(".")[-1][0] in "9" else _x for _x in labels
                ]
            ax.set_ylabel("pressure (hPa)")
            ax.set_yticks(minor_ticks, minor=True)
            ax.set_yticks(major_ticks, minor=False)
            ax.set_yticklabels([], minor=True, fontsize=10)
            ax.set_yticklabels(labels, minor=False, fontsize=10)
            ax.set_ylim(p_bot, p_top)
            ax.set_xlim(0, num_interpolation_points)
            ax.set_xticks(range(0, num_interpolation_points, tick_index_step))
            ax.set_xticklabels([
                f"{x[0]:2.1f}, {x[1]:2.1f}"
                for x in zip(lats[::tick_index_step], lons[::tick_index_step])
            ],
                               rotation=25,
                               fontsize=10,
                               horizontalalignment="right")
            ax.set_xlabel("lat/lon")

            # plot path and waypoint labels
            ax.plot(intermediate_indexes,
                    wp_presss,
                    color="blue",
                    marker="o",
                    linewidth=2,
                    markerfacecolor="red",
                    markersize=4)
            for i, (idx, press, loc) in enumerate(
                    zip(intermediate_indexes, wp_presss, wp_locs)):
                textlabel = f"{loc if loc else str(i)} "
                plt.text(idx + 1, press, textlabel, rotation=90, **TEXT_CONFIG)
            plt.tight_layout()

            # retrieve and draw WMS image
            ax_bounds = plt.gca().bbox.bounds
            width, height = int(round(ax_bounds[2])), int(round(ax_bounds[3]))
            req = requests.get(url,
                               auth=tuple(config["WMS_login"][url]),
                               params={
                                   "version":
                                   "1.3.0",
                                   "request":
                                   "GetMap",
                                   "format":
                                   "image/png",
                                   "exceptions":
                                   "XML",
                                   "crs":
                                   "VERT:LOGP",
                                   "layers":
                                   layer,
                                   "styles":
                                   style,
                                   "dim_init_time":
                                   init_time,
                                   "time":
                                   time,
                                   "width":
                                   width,
                                   "height":
                                   height,
                                   "path":
                                   ",".join(f"{wp[0]:.2f},{wp[1]:.2f}"
                                            for wp in wps),
                                   "bbox":
                                   bbox
                               })

            if req.headers['Content-Type'] == "text/xml":
                print(flight, section, vertical, filename, init_time, time)
                print(url, layer, style)
                print("WMS Error:")
                print(req.text)
                exit(1)
            image_io = io.BytesIO(req.content)
            img = PIL.Image.open(image_io)
            imgax = fig.add_axes(ax.get_position(),
                                 frameon=True,
                                 xticks=[],
                                 yticks=[],
                                 label="ax2",
                                 zorder=0)
            imgax.imshow(img,
                         interpolation="nearest",
                         aspect="auto",
                         origin="upper")
            imgax.set_xlim(0, img.size[0] - 1)
            imgax.set_ylim(img.size[1] - 1, 0)

            plt.savefig(f"{flight}_{layer}.png")
Esempio n. 30
0
    def __init__(self,
                 token,
                 op_id,
                 user,
                 operation_name,
                 operations,
                 conn,
                 parent=None,
                 mscolab_server_url=config_loader(dataset="default_MSCOLAB")):
        """
        token: access token
        op_id: operation id
        conn: connection to send/receive socket messages
        """
        super(MSColabAdminWindow, self).__init__(parent)
        self.setupUi(self)

        self.mscolab_server_url = mscolab_server_url
        self.token = token
        self.op_id = op_id
        self.user = user
        self.operation_name = operation_name
        self.operations = operations
        self.conn = conn

        self.addUsers = []
        self.modifyUsers = []

        # Button click handlers
        self.addUsersBtn.clicked.connect(self.add_selected_users)
        self.modifyUsersBtn.clicked.connect(self.modify_selected_users)
        self.deleteUsersBtn.clicked.connect(self.delete_selected_users)
        self.importPermissionsBtn.clicked.connect(self.import_permissions)
        self.selectAllAddBtn.clicked.connect(
            lambda: self.select_all(self.addUsersTable))
        self.deselectAllAddBtn.clicked.connect(
            lambda: self.deselect_all(self.addUsersTable))
        self.selectAllModifyBtn.clicked.connect(
            lambda: self.select_all(self.modifyUsersTable))
        self.deselectAllModifyBtn.clicked.connect(
            lambda: self.deselect_all(self.modifyUsersTable))

        index = self.addUsersPermission.findText("collaborator",
                                                 QtCore.Qt.MatchFixedString)
        if index >= 0:
            self.addUsersPermission.setCurrentIndex(index)
        # Search filter
        self.addUsersSearch.textChanged.connect(
            lambda text: self.search_user_filter(text, self.addUsersTable))
        self.modifyUsersSearch.textChanged.connect(
            lambda text: self.search_user_filter(text, self.modifyUsersTable))
        self.modifyUsersPermissionFilter.currentTextChanged.connect(
            self.apply_permission_filter)

        # Setting handlers for connection manager
        self.conn.signal_operation_permissions_updated.connect(
            self.handle_permissions_updated)

        self.set_label_text()
        self.load_import_operations()
        self.load_users_without_permission()
        self.load_users_with_permission()