def generateObsAtPixel(dem, sensor, col, lin): """ Generates an observations at a given column / line of a raster. :param col: (int) shooter's column. :param lin: (int) shooter's line. :return: (Observation) observation at col, pix. """ # handle outside points - put them back to the borders if col > dem.width(): col = dem.width() - 1 elif col < 0: col = 0 if lin > dem.height(): lin = dem.height() - 1 elif lin < 0: lin = 0 y, x = dem.pixelToCoordinates(col, lin) z = dem.bands()[col][lin] sensorY, sensorX, sensorZ = sensor['coordinates'] dx, dy, dz = x - sensorX, y - sensorY, z - sensorZ if dem.isGeographic(): # the more appropriate conversion would be a geodesic line - curve geometry dx = np.deg2rad(dx) * Enums.EARTH_RADIUS dy = np.deg2rad(dy) * np.pi * Enums.EARTH_RADIUS / 180 azimuth = np.rad2deg(np.arctan2(np.sqrt(dy**2 + dz**2), dx)) zenith = np.rad2deg(np.arctan2(dx, dz)) om = ObservationsManager() om.addObservation(azimuth, zenith, sensor['id']) return zenith, azimuth
def __init__(self, parent=None, settings=None): """ Class constructor. :param parent: (QWidget) any widget from Qt5 parent to this dialog. :param settings: (Settings) MOPA's settings database manager. """ super(ObservationWidget, self).__init__(parent) self.setupUi(self) self.parent = parent self.settings = settings if settings is not None else Settings() self._obsManager = ObservationsManager(self.settings) self.refresh(obsList=[])
def getAllObsFromSensor(self, sensor=None): """ Retrieves all observations made from a sensor. :param dem: (RasterLayer) DEM to be checked for sensors. :return: (list-of-Sensor) """ sensor = sensor or (self.currentSensor() or \ SensorsManager().newSensor()) if sensor.isValid(): return ObservationsManager().getObservationsFromSensor( sensor['id']) else: return ObservationsManager().allObservations()
def getObservationsFromSensor(self, sensorId): """ Gets all observations from a given sensor. :param sensorId: (int) sensor ID. :return: (list-of-Observation) observations made from a given sensor. """ return ObservationsManager().getObservationsFromSensor(sensorId)
def setupObservations(self): """ Sets observations to GUI. """ s = self.currentSensor() obsList = self.getAllObsFromSensor().values() if s is not None and s.isValid() \ else ObservationsManager().allObservations().values() obs = self.obsWidget.currentText() self.obsWidget.refresh(obsList) # try to keep the same selection self.obsWidget.setCurrentObservation(obs)
class ObservationWidget(QWidget, FORM_CLASS): observationAdded, observationEdited = pyqtSignal(Observation), pyqtSignal( Observation) selectionChanged = pyqtSignal(int) def __init__(self, parent=None, settings=None): """ Class constructor. :param parent: (QWidget) any widget from Qt5 parent to this dialog. :param settings: (Settings) MOPA's settings database manager. """ super(ObservationWidget, self).__init__(parent) self.setupUi(self) self.parent = parent self.settings = settings if settings is not None else Settings() self._obsManager = ObservationsManager(self.settings) self.refresh(obsList=[]) def clear(self): """ Clears observation combo box and GUI information, if any. """ self.obsComboBox.clear() def fillObsComboBox(self, obsList): """ Fills all given observations to the selection combo box. :param obsList: (list-of-Observation) observations to be listed on widget. """ self.clear() self.obsComboBox.addItem(self.tr("Select an observation...")) self.obsComboBox.addItems( ["Observation {0}".format(o['id']) for o in obsList]) def setCurrentObservation(self, obs): """ Sets current observation from its text as current selection on combo box. :param obs: (str) observation exhibition text. :return: (bool) whether selection was set. """ self.obsComboBox.setCurrentText(obs) return self.obsComboBox.currentText() == obs def currentText(self): """ Gets current text exhibited on combo box. :return: (str) current text. """ return self.obsComboBox.currentText() def refresh(self, obsList): """ Resets widget to initial state. :param obsList: (list-of-Observation) observations to be listed on widget. """ self.clear() self.fillObsComboBox(obsList) self.setObsInformation(self.currentObservation()) def obsIdFromIndex(self, idx): """ Gets the observation ID from item at the given index. If index is invalid None is returned. :param idx: (int) item index in the observation selection combo box. :return: (int) observation ID. """ if idx > 0 and self.obsComboBox.count() > idx: return int(self.obsComboBox.itemText(idx).split(" ")[-1]) return None def observationFromIndex(self, idx): """ Gets the observation from the indicated index. If index is invalid None is returned. :param idx: (int) item index in the observation selection combo box. :return: (Observation) observation instance from the indicated index. """ oid = self.obsIdFromIndex(idx) if oid is not None: return self._obsManager.observationFromId(oid) return None def obsId(self): """ Gets current observation's ID. Returns None if no selection was made. :return: (int) observation's ID. """ if self.obsComboBox.currentIndex() < 1: return None return int(self.obsComboBox.currentText().split(" ")[-1]) def currentObservation(self): """ Gets the observation object for current selection. :return: (Observation) an instance of Observation object for current selection. """ if self.obsId() is None: return None # should it be a new instance of observation obj? return self._obsManager.observationFromId(self.obsId()) def setObsInformation(self, obs): """ Sets observation information to widget interface. :param obs: (Observation) observation to have its info exposed. """ obs = obs or self._obsManager.newObservation() self.azLabel.setText( self.tr("Azimuth: {0:.2f}").format(obs['azimuth'])) self.zenLabel.setText( self.tr("Vertical angle: {0:.2f}").format(obs['zenith'])) self.dateLabel.setText( self.tr("Observation date: {0}").format(obs['date'])) title = self.tr("Event information") if obs.isValid(): title += self.tr(" from station ID = {0}").format(obs['sensorId']) self.groupBox.setTitle(title) def isEditable(self): """ Verifies whether current selection may be edited. :return: (bool) edition status. """ return not self.obsComboBox.currentIndex() < 1 @pyqtSlot(int, name="on_obsComboBox_currentIndexChanged") def checkEditButtonStatus(self, idx): """ Updates the edit push button enable status. :param idx: (int) current index. """ self.updateObservationPushButton.setEnabled(self.isEditable()) self.setObsInformation(self.currentObservation()) self.selectionChanged.emit(idx) def parametersFromForm(self, attributes): """ Sets the correct variable types from form info. :param attributes: (dict) form's info. :return: (dict) values reasigned to its correct variable type. """ try: attributes['id'] = int(attributes['id']) except: pass try: attributes['azimuth'] = float(attributes['azimuth']) except: pass try: attributes['zenith'] = float(attributes['zenith']) except: pass try: attributes['sensorId'] = int(attributes['sensorId']) except: pass if not isinstance(attributes['date'], str): try: attributes['date'] = str(attributes['date']) except: pass return attributes def checkFormValidity(self, form, checkIfExists=False): """ Checks form validity. :param form: (FeatureForm) form to have its contents checked. :param checkIfExists: (bool) indicates whether entry existance should be checked. :return: (bool) form validity status. """ attr = self.parametersFromForm(form.read()) ir = self._obsManager.newObservation().invalidationReason(attr) if checkIfExists and self._obsManager.idExists(attr['id']): ir = self.tr("Observation ID {0} already exists into the database.").\ format(attr['id']) form.setInvalidationMessage(ir) return ir == '' @pyqtSlot(bool, name='on_updateObservationPushButton_clicked') def openEditForm(self): """ Opens feature form for current selection in edition mode. """ form = FeatureForm(self.currentObservation(), True, self.parent) form.setWindowTitle(form.tr("Edit observation's attributes")) form.fieldReadOnly( 'id', True) # since it is an EDITION, id should be kept the same. form.okButtonClicked.connect(self.checkFormValidity) if form.exec_() == Enums.Finished: attr = self.parametersFromForm(form.read()) obs = self._obsManager.observationFromAttributes(attr) if obs.isValid(): self._obsManager.updateObservation(obs) self.obsComboBox.setItemText( self.obsComboBox.currentIndex(), self.tr("Observation {0}").format(obs['id'])) # and update its attributes to GUI self.setObsInformation(obs) form.blockSignals(True) del form self.observationEdited.emit(obs) @pyqtSlot(bool, name='on_addObservationPushButton_clicked') def openForm(self): """ Opens attribute form to be filled in order to add a new sensor. """ form = FeatureForm(self._obsManager.newObservation(), True, self.parent) form.setWindowTitle(self.tr("Add a new observation")) form.okButtonClicked.connect(lambda f: self.checkFormValidity(f, True)) if form.exec_() == Enums.Finished: attr = self.parametersFromForm(form.read()) obs = self._obsManager.observationFromAttributes(attr) if obs.isValid(): self._obsManager.addObservation( azimuth=obs['azimuth'], zenith=obs['zenith'],\ sensorId=obs['sensorId'] ) form.blockSignals(True) del form name = self.tr("Observation {0}").format(obs['id']) self.obsComboBox.addItem(name) self.observationAdded.emit(obs)
lin = dem.height() - 1 elif lin < 0: lin = 0 y, x = dem.pixelToCoordinates(col, lin) z = dem.bands()[col][lin] sensorY, sensorX, sensorZ = sensor['coordinates'] dx, dy, dz = x - sensorX, y - sensorY, z - sensorZ if dem.isGeographic(): # the more appropriate conversion would be a geodesic line - curve geometry dx = np.deg2rad(dx) * Enums.EARTH_RADIUS dy = np.deg2rad(dy) * np.pi * Enums.EARTH_RADIUS / 180 azimuth = np.rad2deg(np.arctan2(np.sqrt(dy**2 + dz**2), dx)) zenith = np.rad2deg(np.arctan2(dx, dz)) om = ObservationsManager() om.addObservation(azimuth, zenith, sensor['id']) return zenith, azimuth s = Settings() sm = SensorsManager(s) sensor = sm.getSensorFromId(3) om = ObservationsManager(s) demPath = ".dev/testing_data/sf-23-z-b/rj_srtm_90m_sirgas2000-23s.tif" dem = RasterLayer(demPath) generateObsAtPixel(dem, sensor, 102, 101) obs = om.getObservationsFromSensor(3)[17] sf = ShooterFinder(s) sf.findShooter(1, sensor, obs, dem) print(om.getObservationsFromSensor(3))