def load_from_txt(filename): name = os.path.basename(filename.replace(".txt", "").strip()) waypoints = [] _dirname, _name = os.path.split(filename) _fs = open_fs(_dirname) with _fs.open(_name, "r") as in_file: pos = [] for line in in_file: if line.startswith("#"): continue if line.startswith("Index"): pos.append(0) # 0 pos.append(line.find("Location")) # 1 pos.append(line.find("Lat (+-90)")) # 2 pos.append(line.find("Lon (+-180)")) # 3 pos.append(line.find("Flightlevel")) # 4 pos.append(line.find("Pressure (hPa)")) # 5 pos.append(line.find("Leg dist. (km)")) # 6 pos.append(line.find("Cum. dist. (km)")) # 7 pos.append(line.find("Comments")) # 8 continue if line.startswith("Track name: "): continue if len(pos) == 0: raise SyntaxError( "TXT Import could not parse column headings.") if len(line) < max(pos): raise SyntaxError(f"TXT Import could not parse line: '{line}'") wp = ft.Waypoint() attr_names = [ "location", "lat", "lon", "flightlevel", "pressure", "distance_to_prev", "distance_total", "comments" ] setattr(wp, attr_names[0], line[pos[1]:pos[2]].strip()) setattr(wp, attr_names[7], line[pos[8]:].strip()) for i in range(2, len(pos) - 1): if pos[i] >= 0: if i == 5: setattr(wp, attr_names[i - 1], float(line[pos[i]:pos[i + 1]].strip()) * 100.) else: setattr(wp, attr_names[i - 1], float(line[pos[i]:pos[i + 1]].strip())) else: if i == 5: logging.debug('calculate pressure from FL ' + str( thermolib.flightlevel2pressure( float(wp.flightlevel)))) setattr( wp, attr_names[i - 1], thermolib.flightlevel2pressure( float(wp.flightlevel))) waypoints.append(wp) return name, waypoints
def checknconvert(self): """ Checks for current units of axis and convert the upper and lower limit to pa(pascals) for the internal computation by code """ if self.settings_dict["vertical_axis"] == "pressure altitude": self.p_bot = thermolib.flightlevel2pressure(self.settings_dict["vertical_extent"][0] * 32.80) self.p_top = thermolib.flightlevel2pressure(self.settings_dict["vertical_extent"][1] * 32.80) elif self.settings_dict["vertical_axis"] == "flight level": self.p_bot = thermolib.flightlevel2pressure(self.settings_dict["vertical_extent"][0]) self.p_top = thermolib.flightlevel2pressure(self.settings_dict["vertical_extent"][1])
def test_flightlevel2pressure(): assert tl.flightlevel2pressure(182.8850) == pytest.approx(50000) assert tl.flightlevel2pressure(530.8279) == pytest.approx(10000) assert tl.flightlevel2pressure(782.4335) == pytest.approx(3000) assert tl.flightlevel2pressure(1151.9583) == pytest.approx(550) assert tl.flightlevel2pressure(1626.8966) == pytest.approx(80) assert tl.flightlevel2pressure(1804.2727) == pytest.approx(40) with pytest.raises(ValueError): tl.flightlevel2pressure(72000 / 30.48) fls = np.arange(0, 71000, 1000) / 30.48 assert np.allclose([tl.flightlevel2pressure(_x) for _x in fls], tl.flightlevel2pressure_a(fls))
def test_flightlevel2pressure(): assert tl.flightlevel2pressure(182.8913020844737) == pytest.approx(50000) assert tl.flightlevel2pressure(530.8390754393636) == pytest.approx(10000) assert tl.flightlevel2pressure(782.4486256345779) == pytest.approx(3000) assert tl.flightlevel2pressure(1151.9849776810745) == pytest.approx(550) assert tl.flightlevel2pressure(1626.9512858549855) == pytest.approx(80) assert tl.flightlevel2pressure(1804.3261490037305) == pytest.approx(40) with pytest.raises(ValueError): tl.flightlevel2pressure(72000 / 30.48) fls = np.arange(0, 71000, 1000) / 30.48 assert np.allclose([tl.flightlevel2pressure(_x) for _x in fls], tl.flightlevel2pressure_a(fls))
def __init__(self, lat=0, lon=0, flightlevel=0, location="", comments=""): self.location = location locations = config_loader(dataset='locations', default=mss_default.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) 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
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 draw_flight_levels(self): """Draw horizontal lines indicating the altitude of the flight levels. """ # Remove currently displayed flight level artists. for artist in self.fl_label_list: artist.remove() self.fl_label_list = [] # Plot lines indicating flight level altitude. ax = self.ax for level in self.flightlevels: pressure = thermolib.flightlevel2pressure(level) self.fl_label_list.append(ax.axhline(pressure, color='k')) self.fl_label_list.append(ax.text(0.1, pressure, f"FL{level:d}")) self.draw()
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 load_from_flitestar(filename): waypoints = [] _dirname, _name = os.path.split(filename) _fs = open_fs(_dirname) with _fs.open(_name, 'r') as f: firstline = f.readline() if not firstline.startswith( "# FliteStar/FliteMap generated flight plan."): raise SyntaxError("The file does not seem to be a FliteStar file!") for line in f: if line.startswith('FWP'): line = line.split() if len(line) < 10: raise SyntaxError(f"Line {line} has less than 9 fields.") alt = round(float(line[-1]) / 100., 2) if line[4] == 'N': NS = 1. elif line[4] == 'S': NS = -1. else: NS = np.nan lat = round((float(line[5]) + (float(line[6]) / 60.)) * NS, 3) if line[7] == 'E': EW = 1. elif line[7] == 'W': EW = -1. else: EW = np.nan lon = round((float(line[8]) + (float(line[9]) / 60.)) * EW, 3) wp = ft.Waypoint() wp.location = line[3] wp.lat = float(lat) wp.lon = float(lon) wp.flightlevel = float(alt) wp.pressure = thermolib.flightlevel2pressure( float(wp.flightlevel)) waypoints.append(wp) name = os.path.basename(filename).strip('.txt') return name, waypoints
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