def redraw_yaxis(self): """ Redraws the y-axis on map after setting the values from sideview options dialog box""" self.checknconvert() vaxis = self.settings_dict["vertical_axis"] if vaxis == "pressure": # Compute the position of major and minor ticks. Major ticks are labelled. major_ticks = self._pres_maj[(self._pres_maj <= self.p_bot) & (self._pres_maj >= self.p_top)] minor_ticks = self._pres_min[(self._pres_min <= self.p_bot) & (self._pres_min >= self.p_top)] labels = [f"{int(_x / 100)}" if (_x / 100) - int(_x / 100) == 0 else f"{float(_x / 100)}" for _x 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] self.ax.set_ylabel("pressure (hPa)") elif vaxis == "pressure altitude": bot_km = thermolib.pressure2flightlevel(self.p_bot) * 0.03048 top_km = thermolib.pressure2flightlevel(self.p_top) * 0.03048 ma_dist, mi_dist = 4, 1.0 if (top_km - bot_km) <= 20: ma_dist, mi_dist = 1, 0.5 elif (top_km - bot_km) <= 40: ma_dist, mi_dist = 2, 0.5 major_heights = np.arange(0, top_km + 1, ma_dist) minor_heights = np.arange(0, top_km + 1, mi_dist) major_ticks = thermolib.flightlevel2pressure_a(major_heights / 0.03048) minor_ticks = thermolib.flightlevel2pressure_a(minor_heights / 0.03048) labels = major_heights self.ax.set_ylabel("pressure altitude (km)") elif vaxis == "flight level": bot_km = thermolib.pressure2flightlevel(self.p_bot) * 0.03048 top_km = thermolib.pressure2flightlevel(self.p_top) * 0.03048 ma_dist, mi_dist = 50, 10 if (top_km - bot_km) <= 10: ma_dist, mi_dist = 20, 10 elif (top_km - bot_km) <= 40: ma_dist, mi_dist = 40, 10 major_fl = np.arange(0, 2132, ma_dist) minor_fl = np.arange(0, 2132, mi_dist) major_ticks = thermolib.flightlevel2pressure_a(major_fl) minor_ticks = thermolib.flightlevel2pressure_a(minor_fl) labels = major_fl self.ax.set_ylabel("flight level (hft)") else: raise RuntimeError("Unsupported vertical axis type: '{}'".format(vaxis)) # Draw ticks and tick labels. self.ax.set_yticks(minor_ticks, minor=True) self.ax.set_yticks(major_ticks, minor=False) self.ax.set_yticklabels([], minor=True, fontsize=10) self.ax.set_yticklabels(labels, minor=False, fontsize=10) self.ax.set_ylim(self.p_bot, self.p_top)
def convert_pressure_to_vertical_axis_measure(vertical_axis, pressure): """ vertical_axis can take following values - pressure altitude - flight level - pressure """ if vertical_axis == "pressure": return float(pressure / 100) elif vertical_axis == "flight level": return pressure2flightlevel(pressure) elif vertical_axis == "pressure altitude": return pressure2flightlevel(pressure) / 32.8 else: return pressure
def test_pressure2flightlevel(): assert tl.pressure2flightlevel(50000.) == pytest.approx(182.8850) assert tl.pressure2flightlevel(10000.) == pytest.approx(530.8279) assert tl.pressure2flightlevel(3000.) == pytest.approx(782.4335) assert tl.pressure2flightlevel(550.) == pytest.approx(1151.9583) assert tl.pressure2flightlevel(80.) == pytest.approx(1626.8966) assert tl.pressure2flightlevel(40.) == pytest.approx(1804.2727) with pytest.raises(ValueError): tl.pressure2flightlevel(3.9) pss = np.arange(5., 100000., 100.) assert np.allclose([tl.pressure2flightlevel(_x) for _x in pss], tl.pressure2flightlevel_a(pss))
def test_pressure2flightlevel(): assert tl.pressure2flightlevel(50000) == pytest.approx(182.89130205844737) assert tl.pressure2flightlevel(10000) == pytest.approx(530.8390754393636) assert tl.pressure2flightlevel(3000) == pytest.approx(782.4486256345779) assert tl.pressure2flightlevel(550) == pytest.approx(1151.9849776810745) assert tl.pressure2flightlevel(80) == pytest.approx(1626.9512858549855) assert tl.pressure2flightlevel(40) == pytest.approx(1804.3261490037305) with pytest.raises(ValueError): tl.pressure2flightlevel(3.9) pss = np.arange(5., 100000., 100.) assert np.allclose([tl.pressure2flightlevel(_x) for _x in pss], tl.pressure2flightlevel_a(pss))
def button_release_insert_callback(self, event): """Called whenever a mouse button is released. From the click event's coordinates, best_index is calculated as the index of a vertex whose x coordinate > clicked x coordinate. This is the position where the waypoint is to be inserted. 'lat' and 'lon' are calculated as an average of each of the first waypoint in left and right neighbourhood of inserted waypoint. The coordinates are checked against "locations" defined in mss' config. A new waypoint with the coordinates, and name is inserted into the waypoints_model. """ if not self.showverts or event.button != 1 or event.inaxes is None: return y = event.ydata wpm = self.waypoints_model flightlevel = float(pressure2flightlevel(y)) [lat, lon], best_index = self.get_lat_lon(event) loc = find_location( lat, lon) # skipped tolerance which uses appropriate_epsilon_km if loc is not None: (lat, lon), location = loc else: location = "" new_wp = ft.Waypoint(lat, lon, flightlevel, location=location) wpm.insertRows(best_index, rows=1, waypoints=[new_wp]) self.redraw_figure() self._ind = None
def verticalunitsclicked(self, index): units = { "pressure": "hPa", "pressure altitude": "km", "flight level": "hft" } _translate = QtCore.QCoreApplication.translate unit = units[self.cbVerticalAxis.model().itemFromIndex(index).text()] currentunit = units[self.cbVerticalAxis.currentText()] if unit == currentunit: return self.setBotTopLimits("maximum") self.sbPbot.setSuffix(_translate("SideViewOptionsDialog", " " + unit)) self.sbPtop.setSuffix(_translate("SideViewOptionsDialog", " " + unit)) if unit == "hPa": self.sbPtop.setValue( thermolib.flightlevel2pressure( convert_to(self.sbPtop.value(), currentunit, "hft", 1)) / 100) self.sbPbot.setValue( thermolib.flightlevel2pressure( convert_to(self.sbPbot.value(), currentunit, "hft", 1)) / 100) elif currentunit == "hPa": self.sbPtop.setValue( convert_to( thermolib.pressure2flightlevel(self.sbPtop.value() * 100), "hft", unit)) self.sbPbot.setValue( convert_to( thermolib.pressure2flightlevel(self.sbPbot.value() * 100), "hft", unit)) else: self.sbPtop.setValue( convert_to(self.sbPtop.value(), currentunit, unit, 1)) self.sbPbot.setValue( convert_to(self.sbPbot.value(), currentunit, unit, 1)) self.setBotTopLimits( self.cbVerticalAxis.model().itemFromIndex(index).text())
def verticalunitsclicked(self, index): new_unit = self._suffixes[index] old_unit = self.sbPbot.suffix().strip() if new_unit == old_unit: return self.setBotTopLimits("maximum") for sb in (self.sbPbot, self.sbPtop): sb.setSuffix(" " + new_unit) if new_unit == "hPa": sb.setValue(thermolib.flightlevel2pressure( convert_to(sb.value(), old_unit, "hft", 1)) / 100) elif old_unit == "hPa": sb.setValue(convert_to( thermolib.pressure2flightlevel(sb.value() * 100), "hft", new_unit)) else: sb.setValue(convert_to(sb.value(), old_unit, new_unit, 1)) self.setBotTopLimits(self.cbVerticalAxis.currentText())
def setData(self, index, value, role=QtCore.Qt.EditRole, update=True): """Change a data element of the flight track; overrides the corresponding QAbstractTableModel method. NOTE: Performance computations loose their validity if a change is made. """ if index.isValid() and 0 <= index.row() < len(self.waypoints): waypoint = self.waypoints[index.row()] column = index.column() index2 = index # in most cases only one field is being changed if column == LOCATION: waypoint.location = variant_to_string(value) elif column == LAT: try: # The table fields accept basically any input. # If the string cannot be converted to "float" (raises ValueError), the user input is discarded. value = variant_to_float(value) except TypeError as ex: logging.error("unexpected error: %s %s %s %s", type(ex), ex, type(value), value) except ValueError as ex: logging.error("%s", ex) else: waypoint.lat = value waypoint.location = "" loc = find_location(waypoint.lat, waypoint.lon, 1e-3) if loc is not None: waypoint.lat, waypoint.lon = loc[0] waypoint.location = loc[1] # A change of position requires an update of the distances. if update: self.update_distances(index.row()) # Notify the views that items between the edited item and # the distance item of the corresponding waypoint have been # changed. # Delete the location name -- it won't be valid anymore # after its coordinates have been changed. index2 = self.createIndex(index.row(), LOCATION) elif column == LON: try: # The table fields accept basically any input. # If the string cannot be converted to "float" (raises ValueError), the user input is discarded. value = variant_to_float(value) except TypeError as ex: logging.error("unexpected error: %s %s %s %s", type(ex), ex, type(value), value) except ValueError as ex: logging.error("%s", ex) else: waypoint.lon = value waypoint.location = "" loc = find_location(waypoint.lat, waypoint.lon, 1e-3) if loc is not None: waypoint.lat, waypoint.lon = loc[0] waypoint.location = loc[1] if update: self.update_distances(index.row()) index2 = self.createIndex(index.row(), LOCATION) elif column == FLIGHTLEVEL: try: # The table fields accept basically any input. # If the string cannot be converted to "float" (raises ValueError), the user input is discarded. flightlevel = variant_to_float(value) pressure = float( thermolib.flightlevel2pressure(flightlevel)) except TypeError as ex: logging.error("unexpected error: %s %s %s %s", type(ex), ex, type(value), value) except ValueError as ex: logging.error("%s", ex) else: waypoint.flightlevel = flightlevel waypoint.pressure = pressure if update: self.update_distances(index.row()) # need to notify view of the second item that has been # changed as well. index2 = self.createIndex(index.row(), PRESSURE) elif column == PRESSURE: try: # The table fields accept basically any input. # If the string cannot be converted to "float" (raises ValueError), the user input is discarded. pressure = variant_to_float( value) * 100 # convert hPa to Pa if pressure > 200000: raise ValueError flightlevel = float( round(thermolib.pressure2flightlevel(pressure))) pressure = float( thermolib.flightlevel2pressure(flightlevel)) except TypeError as ex: logging.error("unexpected error: %s %s %s %s", type(ex), ex, type(value), value) except ValueError as ex: logging.error("%s", ex) else: waypoint.pressure = pressure waypoint.flightlevel = flightlevel if update: self.update_distances(index.row()) index2 = self.createIndex(index.row(), FLIGHTLEVEL) else: waypoint.comments = variant_to_string(value) self.modified = True # Performance computations loose their validity if a change is made. if update: self.dataChanged.emit(index, index2) return True return False