def init_analysis(self): """Setup analysis to make it ready to work. .. note:: Copied or adapted from the dock """ self.analysis = Analysis() # Impact Function impact_function = self.impact_function_manager.get( self.parent.selected_function()['id']) impact_function.parameters = self.parent.if_params self.analysis.impact_function = impact_function # Layers self.analysis.hazard = self.parent.hazard_layer self.analysis.exposure = self.parent.exposure_layer self.analysis.aggregation = self.parent.aggregation_layer # TODO test if the implement aggregation layer works! # Variables self.analysis.clip_hard = self.clip_hard self.analysis.show_intermediate_layers = self.show_intermediate_layers viewport = viewport_geo_array(self.iface.mapCanvas()) self.analysis.viewport_extent = viewport # Extent if self.analysis.user_extent: self.analysis.user_extent = self.extent.user_extent self.analysis.user_extent_crs = self.extent.user_extent_crs
def init_analysis(self): """Setup analysis to make it ready to work. .. note:: Copied or adapted from the dock """ self.analysis = Analysis() # Layers self.analysis.hazard_layer = self.parent.hazard_layer self.analysis.exposure_layer = self.parent.exposure_layer self.analysis.aggregation_layer = self.parent.aggregation_layer # TODO test if the implement aggregation layer works! # noinspection PyTypeChecker self.analysis.hazard_keyword = self.keyword_io.read_keywords( self.parent.hazard_layer) self.analysis.exposure_keyword = self.keyword_io.read_keywords( self.parent.exposure_layer) # Need to check since aggregation layer is not mandatory if self.analysis.aggregation_layer: self.analysis.aggregation_keyword = self.keyword_io.read_keywords( self.parent.aggregation_layer) # Impact Function impact_function = self.impact_function_manager.get( self.parent.selected_function()['id']) impact_function.parameters = self.parent.if_params self.analysis.impact_function = impact_function # Variables self.analysis.clip_hard = self.clip_hard self.analysis.show_intermediate_layers = self.show_intermediate_layers self.analysis.run_in_thread_flag = self.run_in_thread_flag self.analysis.map_canvas = self.iface.mapCanvas() # Extent if self.parent.rbExtentUser.isChecked(): self.analysis.user_extent = self.extent.user_extent else: self.analysis.user_extent = None self.analysis.user_extent_crs = self.extent.user_extent_crs self.analysis.clip_to_viewport = self.parent.rbExtentScreen.isChecked()
class AnalysisHandler(QObject): """Analysis handler for the dock and the wizard.""" analysisDone = pyqtSignal(bool) # noinspection PyUnresolvedReferences def __init__(self, parent): """Constructor for the class. :param parent: Parent widget i.e. the wizard dialog. :type parent: QWidget """ QtCore.QObject.__init__(self) self.parent = parent # Do not delete this self.iface = parent.iface self.keyword_io = KeywordIO() self.impact_function_manager = ImpactFunctionManager() self.extent = Extent(self.iface) self.analysis = None # Values for settings these get set in read_settings. self.run_in_thread_flag = None self.zoom_to_impact_flag = None self.hide_exposure_flag = None self.clip_hard = None self.show_intermediate_layers = None self.show_rubber_bands = False self.last_analysis_rubberband = None # This is a rubber band to show what the AOI of the # next analysis will be. Also added in 2.1.0 self.next_analysis_rubberband = None self.read_settings() def enable_signal_receiver(self): """Setup dispatcher for all available signal from Analysis. .. note:: Adapted from the dock """ dispatcher.connect( self.show_busy, signal=BUSY_SIGNAL) dispatcher.connect( self.hide_busy, signal=NOT_BUSY_SIGNAL) dispatcher.connect( self.completed, signal=ANALYSIS_DONE_SIGNAL) # noinspection PyArgumentEqualDefault dispatcher.connect( self.show_dynamic_message, signal=DYNAMIC_MESSAGE_SIGNAL) # noinspection PyArgumentEqualDefault dispatcher.connect( self.parent.wvResults.static_message_event, signal=STATIC_MESSAGE_SIGNAL, sender=dispatcher.Any) # noinspection PyArgumentEqualDefault dispatcher.connect( self.parent.wvResults.error_message_event, signal=ERROR_MESSAGE_SIGNAL, sender=dispatcher.Any) def disable_signal_receiver(self): """Remove dispatcher for all available signal from Analysis. .. note:: Adapted from the dock """ dispatcher.disconnect( self.show_busy, signal=BUSY_SIGNAL) dispatcher.disconnect( self.hide_busy, signal=NOT_BUSY_SIGNAL) dispatcher.disconnect( self.completed, signal=ANALYSIS_DONE_SIGNAL) dispatcher.disconnect( self.show_dynamic_message, signal=DYNAMIC_MESSAGE_SIGNAL) def show_static_message(self, message): """Send a static message to the message viewer. Static messages cause any previous content in the MessageViewer to be replaced with new content. .. note:: Copied from the dock :param message: An instance of our rich message class. :type message: Message """ dispatcher.send( signal=STATIC_MESSAGE_SIGNAL, sender=self, message=message) def show_dynamic_message(self, sender, message): """Send a dynamic message to the message viewer. Dynamic messages are appended to any existing content in the MessageViewer. .. note:: Modified from the dock :param sender: The object that sent the message. :type sender: Object, None :param message: An instance of our rich message class. :type message: Message """ # TODO Hardcoded step - may overflow, if number of messages increase self.parent.pbProgress.setValue(self.parent.pbProgress.value() + 15) self.parent.wvResults.dynamic_message_event(sender, message) def show_error_message(self, error_message): """Send an error message to the message viewer. Error messages cause any previous content in the MessageViewer to be replaced with new content. .. note:: Copied from the dock :param error_message: An instance of our rich error message class. :type error_message: ErrorMessage """ dispatcher.send( signal=ERROR_MESSAGE_SIGNAL, sender=self, message=error_message) self.hide_busy() def read_settings(self): """Restore settings from QSettings. Do this on init and after changing options in the options dialog. """ settings = QSettings() flag = bool(settings.value( 'inasafe/showRubberBands', False, type=bool)) self.extent.show_rubber_bands = flag try: extent = settings.value('inasafe/analysis_extent', '', type=str) crs = settings.value('inasafe/analysis_extent_crs', '', type=str) except TypeError: # Any bogus stuff in settings and we just clear them extent = '' crs = '' if extent != '' and crs != '': extent = extent_string_to_array(extent) try: self.extent.user_extent = QgsRectangle(*extent) self.extent.user_extent_crs = QgsCoordinateReferenceSystem(crs) self.extent.show_user_analysis_extent() except TypeError: self.extent.user_extent = None self.extent.user_extent_crs = None flag = settings.value( 'inasafe/useThreadingFlag', False, type=bool) self.run_in_thread_flag = flag flag = settings.value( 'inasafe/setZoomToImpactFlag', True, type=bool) self.zoom_to_impact_flag = flag # whether exposure layer should be hidden after model completes flag = settings.value( 'inasafe/setHideExposureFlag', False, type=bool) self.hide_exposure_flag = flag # whether to 'hard clip' layers (e.g. cut buildings in half if they # lie partially in the AOI self.clip_hard = settings.value('inasafe/clip_hard', False, type=bool) # whether to show or not postprocessing generated layers self.show_intermediate_layers = settings.value( 'inasafe/show_intermediate_layers', False, type=bool) # whether to show or not dev only options self.developer_mode = settings.value( 'inasafe/developer_mode', False, type=bool) # whether to show or not a custom Logo self.organisation_logo_path = settings.value( 'inasafe/organisation_logo_path', default_organisation_logo_path(), type=str) flag = bool(settings.value( 'inasafe/showOrganisationLogoInDockFlag', True, type=bool)) def show_busy(self): """Lock buttons and enable the busy cursor.""" self.parent.pbnNext.setEnabled(False) self.parent.pbnBack.setEnabled(False) self.parent.pbnCancel.setEnabled(False) QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) self.parent.repaint() QtGui.qApp.processEvents() def hide_busy(self): """Unlock buttons A helper function to indicate processing is done.""" self.parent.pbnNext.setEnabled(True) self.parent.pbnBack.setEnabled(True) self.parent.pbnCancel.setEnabled(True) self.parent.repaint() QtGui.qApp.restoreOverrideCursor() def analysis_error(self, exception, message): """A helper to spawn an error and halt processing. An exception will be logged, busy status removed and a message displayed. .. note:: Copied from the dock :param message: an ErrorMessage to display :type message: ErrorMessage, Message :param exception: An exception that was raised :type exception: Exception """ self.hide_busy() LOGGER.exception(message) message = get_error_message(exception, context=message) self.show_error_message(message) self.analysisDone.emit(False) def setup_and_run_analysis(self): """Setup and execute the analysis""" self.enable_signal_receiver() self.show_busy() self.init_analysis() try: self.analysis.setup_analysis() except InsufficientOverlapError as e: raise e self.extent.show_last_analysis_extent( self.analysis.clip_parameters[1]) # Start the analysis self.analysis.run_analysis() self.disable_signal_receiver() def init_analysis(self): """Setup analysis to make it ready to work. .. note:: Copied or adapted from the dock """ self.analysis = Analysis() # Layers self.analysis.hazard_layer = self.parent.hazard_layer self.analysis.exposure_layer = self.parent.exposure_layer self.analysis.aggregation_layer = self.parent.aggregation_layer # TODO test if the implement aggregation layer works! # noinspection PyTypeChecker self.analysis.hazard_keyword = self.keyword_io.read_keywords( self.parent.hazard_layer) self.analysis.exposure_keyword = self.keyword_io.read_keywords( self.parent.exposure_layer) # Need to check since aggregation layer is not mandatory if self.analysis.aggregation_layer: self.analysis.aggregation_keyword = self.keyword_io.read_keywords( self.parent.aggregation_layer) # Impact Function impact_function = self.impact_function_manager.get( self.parent.selected_function()['id']) impact_function.parameters = self.parent.if_params self.analysis.impact_function = impact_function # Variables self.analysis.clip_hard = self.clip_hard self.analysis.show_intermediate_layers = self.show_intermediate_layers self.analysis.run_in_thread_flag = self.run_in_thread_flag self.analysis.map_canvas = self.iface.mapCanvas() # Extent if self.parent.rbExtentUser.isChecked(): self.analysis.user_extent = self.extent.user_extent else: self.analysis.user_extent = None self.analysis.user_extent_crs = self.extent.user_extent_crs self.analysis.clip_to_viewport = self.parent.rbExtentScreen.isChecked() def completed(self): """Slot activated when the process is done. .. note:: Adapted from the dock """ # Try to run completion code try: from datetime import datetime LOGGER.debug(datetime.now()) LOGGER.debug('get engine impact layer') LOGGER.debug(self.analysis is None) engine_impact_layer = self.analysis.get_impact_layer() # Load impact layer into QGIS qgis_impact_layer = read_impact_layer(engine_impact_layer) report = self.show_results( qgis_impact_layer, engine_impact_layer) except Exception, e: # pylint: disable=W0703 # FIXME (Ole): This branch is not covered by the tests self.analysis_error(e, self.tr('Error loading impact layer.')) else:
def analysis_setup(command_line_arguments, hazard, exposure, aggregation=None): """Sets up an analysis object. .. versionadded:: 3.2 :param command_line_arguments: User inputs. :type command_line_arguments: CommandLineArguments :param hazard: Hazard layer :type hazard: QgsLayer :param exposure: Exposure Layer :type exposure: QgsLayer :param aggregation: Aggregation Layer :type aggregation: QgsLayer :raises: Exception """ # IF impact_function_manager = ImpactFunctionManager() impact_function = impact_function_manager.get(command_line_arguments.impact_function) keyword_io = KeywordIO() try: from safe.utilities.analysis import Analysis except ImportError as ie: LOGGER.debug("Import error for Analysis module") print ie.message raise ImportError analysis = Analysis() analysis.impact_function = impact_function analysis.hazard = hazard analysis.exposure = exposure analysis.aggregation = aggregation # analysis.hazard_keyword = keyword_io.read_keywords(hazard) # analysis.exposure_keyword = keyword_io.read_keywords(exposure) analysis.clip_hard = False analysis.show_intermediate_layers = False analysis.run_in_thread_flag = False analysis.map_canvas = CANVAS # QSetting context settings = QSettings() crs = settings.value("inasafe/analysis_extent_crs", "", type=str) analysis.user_extent_crs = QgsCoordinateReferenceSystem(crs) try: analysis.user_extent = QgsRectangle( float(command_line_arguments.extent[0]), float(command_line_arguments.extent[1]), float(command_line_arguments.extent[2]), float(command_line_arguments.extent[3]), ) except AttributeError: print "No extents" pass analysis.setup_analysis() return analysis
class AnalysisHandler(QObject): """Analysis handler for the dock and the wizard.""" analysisDone = pyqtSignal(bool) # noinspection PyUnresolvedReferences def __init__(self, parent): """Constructor for the class. :param parent: Parent widget i.e. the wizard dialog. :type parent: QWidget """ QtCore.QObject.__init__(self) self.parent = parent # Do not delete this self.iface = parent.iface self.keyword_io = KeywordIO() self.extent = Extent(self.iface) self.analysis = None # Values for settings these get set in read_settings. self.run_in_thread_flag = None self.zoom_to_impact_flag = None self.hide_exposure_flag = None self.clip_hard = None self.show_intermediate_layers = None self.show_rubber_bands = False self.last_analysis_rubberband = None # This is a rubber band to show what the AOI of the # next analysis will be. Also added in 2.1.0 self.next_analysis_rubberband = None self.read_settings() def enable_signal_receiver(self): """Setup dispatcher for all available signal from Analysis. .. note:: Adapted from the dock """ dispatcher.connect(self.show_busy, signal=BUSY_SIGNAL) dispatcher.connect(self.hide_busy, signal=NOT_BUSY_SIGNAL) dispatcher.connect(self.completed, signal=ANALYSIS_DONE_SIGNAL) # noinspection PyArgumentEqualDefault dispatcher.connect(self.show_dynamic_message, signal=DYNAMIC_MESSAGE_SIGNAL) # noinspection PyArgumentEqualDefault dispatcher.connect(self.parent.wvResults.static_message_event, signal=STATIC_MESSAGE_SIGNAL, sender=dispatcher.Any) # noinspection PyArgumentEqualDefault dispatcher.connect(self.parent.wvResults.error_message_event, signal=ERROR_MESSAGE_SIGNAL, sender=dispatcher.Any) def disable_signal_receiver(self): """Remove dispatcher for all available signal from Analysis. .. note:: Adapted from the dock """ dispatcher.disconnect(self.show_busy, signal=BUSY_SIGNAL) dispatcher.disconnect(self.hide_busy, signal=NOT_BUSY_SIGNAL) dispatcher.disconnect(self.completed, signal=ANALYSIS_DONE_SIGNAL) dispatcher.disconnect(self.show_dynamic_message, signal=DYNAMIC_MESSAGE_SIGNAL) def show_static_message(self, message): """Send a static message to the message viewer. Static messages cause any previous content in the MessageViewer to be replaced with new content. .. note:: Copied from the dock :param message: An instance of our rich message class. :type message: Message """ dispatcher.send(signal=STATIC_MESSAGE_SIGNAL, sender=self, message=message) def show_dynamic_message(self, sender, message): """Send a dynamic message to the message viewer. Dynamic messages are appended to any existing content in the MessageViewer. .. note:: Modified from the dock :param sender: The object that sent the message. :type sender: Object, None :param message: An instance of our rich message class. :type message: Message """ # TODO Hardcoded step - may overflow, if number of messages increase self.parent.pbProgress.setValue(self.parent.pbProgress.value() + 15) self.parent.wvResults.dynamic_message_event(sender, message) def show_error_message(self, error_message): """Send an error message to the message viewer. Error messages cause any previous content in the MessageViewer to be replaced with new content. .. note:: Copied from the dock :param error_message: An instance of our rich error message class. :type error_message: ErrorMessage """ dispatcher.send(signal=ERROR_MESSAGE_SIGNAL, sender=self, message=error_message) self.hide_busy() def read_settings(self): """Restore settings from QSettings. Do this on init and after changing options in the options dialog. """ settings = QSettings() flag = bool(settings.value('inasafe/showRubberBands', False, type=bool)) self.extent.show_rubber_bands = flag try: extent = settings.value('inasafe/analysis_extent', '', type=str) crs = settings.value('inasafe/analysis_extent_crs', '', type=str) except TypeError: # Any bogus stuff in settings and we just clear them extent = '' crs = '' if extent != '' and crs != '': extent = extent_string_to_array(extent) try: self.extent.user_extent = QgsRectangle(*extent) self.extent.user_extent_crs = QgsCoordinateReferenceSystem(crs) self.extent.show_user_analysis_extent() except TypeError: self.extent.user_extent = None self.extent.user_extent_crs = None flag = settings.value('inasafe/useThreadingFlag', False, type=bool) self.run_in_thread_flag = flag flag = settings.value('inasafe/setZoomToImpactFlag', True, type=bool) self.zoom_to_impact_flag = flag # whether exposure layer should be hidden after model completes flag = settings.value('inasafe/setHideExposureFlag', False, type=bool) self.hide_exposure_flag = flag # whether to 'hard clip' layers (e.g. cut buildings in half if they # lie partially in the AOI self.clip_hard = settings.value('inasafe/clip_hard', False, type=bool) # whether to show or not postprocessing generated layers self.show_intermediate_layers = settings.value( 'inasafe/show_intermediate_layers', False, type=bool) # whether to show or not dev only options self.developer_mode = settings.value('inasafe/developer_mode', False, type=bool) # whether to show or not a custom Logo self.organisation_logo_path = settings.value( 'inasafe/organisation_logo_path', default_organisation_logo_path(), type=str) flag = bool( settings.value('inasafe/showOrganisationLogoInDockFlag', True, type=bool)) def show_busy(self): """Lock buttons and enable the busy cursor.""" self.parent.pbnNext.setEnabled(False) self.parent.pbnBack.setEnabled(False) self.parent.pbnCancel.setEnabled(False) QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) self.parent.repaint() QtGui.qApp.processEvents() def hide_busy(self): """Unlock buttons A helper function to indicate processing is done.""" self.parent.pbnNext.setEnabled(True) self.parent.pbnBack.setEnabled(True) self.parent.pbnCancel.setEnabled(True) self.parent.repaint() QtGui.qApp.restoreOverrideCursor() def analysis_error(self, exception, message): """A helper to spawn an error and halt processing. An exception will be logged, busy status removed and a message displayed. .. note:: Copied from the dock :param message: an ErrorMessage to display :type message: ErrorMessage, Message :param exception: An exception that was raised :type exception: Exception """ self.hide_busy() LOGGER.exception(message) message = get_error_message(exception, context=message) self.show_error_message(message) self.analysisDone.emit(False) def setup_and_run_analysis(self): """Setup and execute the analysis""" self.enable_signal_receiver() self.show_busy() self.init_analysis() try: self.analysis.setup_analysis() except InsufficientOverlapError as e: raise e self.extent.show_last_analysis_extent(self.analysis.clip_parameters[1]) # Start the analysis self.analysis.run_analysis() self.disable_signal_receiver() def init_analysis(self): """Setup analysis to make it ready to work. .. note:: Copied or adapted from the dock """ self.analysis = Analysis() # Layers self.analysis.hazard_layer = self.parent.hazard_layer self.analysis.exposure_layer = self.parent.exposure_layer self.analysis.aggregation_layer = self.parent.aggregation_layer # TODO test if the implement aggregation layer works! # noinspection PyTypeChecker self.analysis.hazard_keyword = self.keyword_io.read_keywords( self.parent.hazard_layer) self.analysis.exposure_keyword = self.keyword_io.read_keywords( self.parent.exposure_layer) # Need to check since aggregation layer is not mandatory if self.analysis.aggregation_layer: self.analysis.aggregation_keyword = self.keyword_io.read_keywords( self.parent.aggregation_layer) # Impact Function self.analysis.impact_function_id = self.parent.selected_function( )['id'] self.analysis.impact_function_parameters = self.parent.if_params # Variables self.analysis.clip_hard = self.clip_hard self.analysis.show_intermediate_layers = self.show_intermediate_layers self.analysis.run_in_thread_flag = self.run_in_thread_flag self.analysis.map_canvas = self.iface.mapCanvas() # Extent if self.parent.rbExtentUser.isChecked(): self.analysis.user_extent = self.extent.user_extent else: self.analysis.user_extent = None self.analysis.user_extent_crs = self.extent.user_extent_crs self.analysis.clip_to_viewport = self.parent.rbExtentScreen.isChecked() def completed(self): """Slot activated when the process is done. .. note:: Adapted from the dock """ # Try to run completion code try: from datetime import datetime LOGGER.debug(datetime.now()) LOGGER.debug('get engine impact layer') LOGGER.debug(self.analysis is None) engine_impact_layer = self.analysis.get_impact_layer() # Load impact layer into QGIS qgis_impact_layer = read_impact_layer(engine_impact_layer) report = self.show_results(qgis_impact_layer, engine_impact_layer) except Exception, e: # pylint: disable=W0703 # FIXME (Ole): This branch is not covered by the tests self.analysis_error(e, self.tr('Error loading impact layer.')) else:
def setUp(self): self.analysis = Analysis()
class TestAnalysis(unittest.TestCase): """Test for Analysis class.""" def setUp(self): self.analysis = Analysis() def test_get_optimal_extent(self): """Optimal extent is calculated correctly """ exposure_path = os.path.join(TESTDATA, 'Population_2010.asc') hazard_path = os.path.join(HAZDATA, 'Lembang_Earthquake_Scenario.asc') # Expected data haz_metadata = {'bounding_box': (105.3000035, -8.3749994999999995, 110.2914705, -5.5667784999999999), 'resolution': (0.0083330000000000001, 0.0083330000000000001)} exp_metadata = {'bounding_box': (94.972335000000001, -11.009721000000001, 141.0140016666665, 6.0736123333332639), 'resolution': (0.0083333333333333003, 0.0083333333333333003)} # Verify relevant metada is ok H = read_layer(hazard_path) E = read_layer(exposure_path) hazard_bbox = H.get_bounding_box() assert numpy.allclose(hazard_bbox, haz_metadata['bounding_box'], rtol=1.0e-12, atol=1.0e-12) exposure_bbox = E.get_bounding_box() assert numpy.allclose(exposure_bbox, exp_metadata['bounding_box'], rtol=1.0e-12, atol=1.0e-12) hazard_res = H.get_resolution() assert numpy.allclose(hazard_res, haz_metadata['resolution'], rtol=1.0e-12, atol=1.0e-12) exposure_res = E.get_resolution() assert numpy.allclose(exposure_res, exp_metadata['resolution'], rtol=1.0e-12, atol=1.0e-12) # First, do some examples that produce valid results ref_box = [105.3000035, -8.3749995, 110.2914705, -5.5667785] view_port = [94.972335, -11.009721, 141.014002, 6.073612] bbox = self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # testing with viewport clipping disabled bbox = self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, None) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) view_port = [105.3000035, -8.3749994999999995, 110.2914705, -5.5667784999999999] bbox = self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # Very small viewport fully inside other layers view_port = [106.0, -6.0, 108.0, -5.8] bbox = self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, view_port, rtol=1.0e-12, atol=1.0e-12) # viewport that intersects hazard layer view_port = [107.0, -6.0, 112.0, -3.0] ref_box = [107, -6, 110.2914705, -5.5667785] bbox = self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # Then one where boxes don't overlap view_port = [105.3, -4.3, 110.29, -2.5] try: self.analysis.get_optimal_extent( hazard_bbox, exposure_bbox, view_port) except InsufficientOverlapError, e: message = 'Did not find expected error message in %s' % str(e) assert 'did not overlap' in str(e), message else:
def analysis_execution(): from safe.test.utilities import get_qgis_app # get_qgis_app must be called before importing Analysis QGIS_APP, CANVAS, IFACE, PARENT = get_qgis_app() from safe.utilities.analysis import Analysis from safe.utilities.keyword_io import KeywordIO analysis = Analysis() arg = AnalysisArguments.read_arguments() register_impact_functions() registry = ImpactFunctionManager().registry function = registry.get_instance(arg.impact_function_name) hazard_layer = safe_to_qgis_layer(read_layer(arg.hazard_filename)) exposure_layer = safe_to_qgis_layer(read_layer(arg.exposure_filename)) if arg.aggregation_filename: aggregation_layer = safe_to_qgis_layer( read_layer(arg.aggregation_filename)) keywords_io = KeywordIO() try: analysis.map_canvas = IFACE.mapCanvas() analysis.hazard_layer = hazard_layer analysis.hazard_keyword = keywords_io.read_keywords(hazard_layer) analysis.exposure_layer = exposure_layer analysis.exposure_keyword = keywords_io.read_keywords(exposure_layer) if aggregation_layer: analysis.aggregation_layer = aggregation_layer analysis.aggregation_keyword = keywords_io.read_keywords( aggregation_layer) analysis.impact_function = function analysis.setup_analysis() print 'Setup analysis done' analysis.run_analysis() print 'Analysis done' except Exception as e: print e.message impact = analysis.impact_layer qgis_impact = safe_to_qgis_layer(impact) generate_styles(impact, qgis_impact) copy_impact_layer(impact, arg.impact_filename)
def test_clip_both(self): """Raster and Vector layers can be clipped.""" # Create a vector layer layer_name = 'padang' vector_layer = QgsVectorLayer(VECTOR_PATH, layer_name, 'ogr') message = ('Did not find layer "%s" in path "%s"' % (layer_name, VECTOR_PATH)) assert vector_layer.isValid(), message # Create a raster layer layer_name = 'shake' raster_layer = QgsRasterLayer(RASTERPATH, layer_name) message = ('Did not find layer "%s" in path "%s"' % (layer_name, RASTERPATH)) assert raster_layer.isValid(), message # Create a bounding box view_port_geo_extent = [99.53, -1.22, 101.20, -0.36] # Get the Hazard extents as an array in EPSG:4326 hazard_geo_extent = [ raster_layer.extent().xMinimum(), raster_layer.extent().yMinimum(), raster_layer.extent().xMaximum(), raster_layer.extent().yMaximum() ] # Get the Exposure extents as an array in EPSG:4326 exposure_geo_extent = [ vector_layer.extent().xMinimum(), vector_layer.extent().yMinimum(), vector_layer.extent().xMaximum(), vector_layer.extent().yMaximum() ] # Now work out the optimal extent between the two layers and # the current view extent. The optimal extent is the intersection # between the two layers and the viewport. # Extent is returned as an array [xmin,ymin,xmax,ymax] analysis = Analysis() geo_extent = analysis.get_optimal_extent(hazard_geo_extent, exposure_geo_extent, view_port_geo_extent) # Clip the vector to the bbox result = clip_layer(vector_layer, geo_extent) # Check the output is valid assert os.path.exists(result.source()) read_safe_layer(result.source()) # Clip the raster to the bbox result = clip_layer(raster_layer, geo_extent) # Check the output is valid assert os.path.exists(result.source()) read_safe_layer(result.source()) # ------------------------------- # Check the extra keywords option # ------------------------------- # Clip the vector to the bbox result = clip_layer(vector_layer, geo_extent, extra_keywords={'kermit': 'piggy'}) # Check the output is valid assert os.path.exists(result.source()) safe_layer = read_safe_layer(result.source()) keywords = safe_layer.get_keywords() # message = 'Extra keyword was not found in %s: %s' % (myResult, # keywords) assert keywords['kermit'] == 'piggy' # Clip the raster to the bbox result = clip_layer(raster_layer, geo_extent, extra_keywords={'zoot': 'animal'}) # Check the output is valid assert os.path.exists(result.source()) safe_layer = read_safe_layer(result.source()) keywords = safe_layer.get_keywords() message = ('Extra keyword was not found in %s: %s' % (result.source(), keywords)) assert keywords['zoot'] == 'animal', message
def test_clip_both(self): """Raster and Vector layers can be clipped.""" # Create a vector layer layer_name = 'padang' vector_layer = QgsVectorLayer(VECTOR_PATH, layer_name, 'ogr') message = ( 'Did not find layer "%s" in path "%s"' % (layer_name, VECTOR_PATH)) assert vector_layer.isValid(), message # Create a raster layer layer_name = 'shake' raster_layer = QgsRasterLayer(RASTERPATH, layer_name) message = ( 'Did not find layer "%s" in path "%s"' % (layer_name, RASTERPATH)) assert raster_layer.isValid(), message # Create a bounding box view_port_geo_extent = [99.53, -1.22, 101.20, -0.36] # Get the Hazard extents as an array in EPSG:4326 hazard_geo_extent = [ raster_layer.extent().xMinimum(), raster_layer.extent().yMinimum(), raster_layer.extent().xMaximum(), raster_layer.extent().yMaximum() ] # Get the Exposure extents as an array in EPSG:4326 exposure_geo_extent = [ vector_layer.extent().xMinimum(), vector_layer.extent().yMinimum(), vector_layer.extent().xMaximum(), vector_layer.extent().yMaximum() ] # Now work out the optimal extent between the two layers and # the current view extent. The optimal extent is the intersection # between the two layers and the viewport. # Extent is returned as an array [xmin,ymin,xmax,ymax] analysis = Analysis() geo_extent = analysis.get_optimal_extent( hazard_geo_extent, exposure_geo_extent, view_port_geo_extent) # Clip the vector to the bbox result = clip_layer(vector_layer, geo_extent) # Check the output is valid assert os.path.exists(result.source()) read_safe_layer(result.source()) # Clip the raster to the bbox result = clip_layer(raster_layer, geo_extent) # Check the output is valid assert os.path.exists(result.source()) read_safe_layer(result.source()) # ------------------------------- # Check the extra keywords option # ------------------------------- # Clip the vector to the bbox result = clip_layer( vector_layer, geo_extent, extra_keywords={'kermit': 'piggy'}) # Check the output is valid assert os.path.exists(result.source()) safe_layer = read_safe_layer(result.source()) keywords = safe_layer.get_keywords() # message = 'Extra keyword was not found in %s: %s' % (myResult, # keywords) assert keywords['kermit'] == 'piggy' # Clip the raster to the bbox result = clip_layer( raster_layer, geo_extent, extra_keywords={'zoot': 'animal'}) # Check the output is valid assert os.path.exists(result.source()) safe_layer = read_safe_layer(result.source()) keywords = safe_layer.get_keywords() message = ('Extra keyword was not found in %s: %s' % (result.source(), keywords)) assert keywords['zoot'] == 'animal', message
def analysis_setup(command_line_arguments, hazard, exposure, aggregation=None): """Sets up an analysis object. .. versionadded:: 3.2 :param command_line_arguments: User inputs. :type command_line_arguments: CommandLineArguments :param hazard: Hazard layer :type hazard: QgsLayer :param exposure: Exposure Layer :type exposure: QgsLayer :param aggregation: Aggregation Layer :type aggregation: QgsLayer :raises: Exception """ # IF impact_function_manager = ImpactFunctionManager() impact_function = impact_function_manager.get( command_line_arguments.impact_function) keyword_io = KeywordIO() try: from safe.utilities.analysis import Analysis except ImportError as ie: LOGGER.debug('Import error for Analysis module') print ie.message raise ImportError analysis = Analysis() analysis.impact_function = impact_function analysis.hazard = hazard analysis.exposure = exposure analysis.aggregation = aggregation # analysis.hazard_keyword = keyword_io.read_keywords(hazard) # analysis.exposure_keyword = keyword_io.read_keywords(exposure) analysis.clip_hard = False analysis.show_intermediate_layers = False analysis.run_in_thread_flag = False analysis.map_canvas = CANVAS # QSetting context settings = QSettings() crs = settings.value('inasafe/analysis_extent_crs', '', type=str) analysis.user_extent_crs = QgsCoordinateReferenceSystem(crs) try: analysis.user_extent = QgsRectangle( float(command_line_arguments.extent[0]), float(command_line_arguments.extent[1]), float(command_line_arguments.extent[2]), float(command_line_arguments.extent[3])) except AttributeError: print "No extents" pass analysis.setup_analysis() return analysis
def analysis_execution(): from safe.test.utilities import get_qgis_app # get_qgis_app must be called before importing Analysis QGIS_APP, CANVAS, IFACE, PARENT = get_qgis_app() from safe.utilities.analysis import Analysis from safe.utilities.keyword_io import KeywordIO analysis = Analysis() arg = AnalysisArguments.read_arguments() register_impact_functions() registry = ImpactFunctionManager().registry function = registry.get_instance(arg.impact_function_name) hazard_layer = safe_to_qgis_layer(read_layer(arg.hazard_filename)) exposure_layer = safe_to_qgis_layer(read_layer(arg.exposure_filename)) if arg.aggregation_filename: aggregation_layer = safe_to_qgis_layer(read_layer( arg.aggregation_filename)) keywords_io = KeywordIO() try: analysis.map_canvas = IFACE.mapCanvas() analysis.hazard_layer = hazard_layer analysis.hazard_keyword = keywords_io.read_keywords(hazard_layer) analysis.exposure_layer = exposure_layer analysis.exposure_keyword = keywords_io.read_keywords(exposure_layer) if aggregation_layer: analysis.aggregation_layer = aggregation_layer analysis.aggregation_keyword = keywords_io.read_keywords( aggregation_layer) analysis.impact_function = function analysis.setup_analysis() print 'Setup analysis done' analysis.run_analysis() print 'Analysis done' except Exception as e: print e.message impact = analysis.impact_layer qgis_impact = safe_to_qgis_layer(impact) generate_styles(impact, qgis_impact) copy_impact_layer(impact, arg.impact_filename)
class TestAnalysis(unittest.TestCase): """Test for Analysis class.""" def setUp(self): self.analysis = Analysis() def test_get_optimal_extent(self): """Optimal extent is calculated correctly """ exposure_path = os.path.join(TESTDATA, 'Population_2010.asc') hazard_path = os.path.join(HAZDATA, 'Lembang_Earthquake_Scenario.asc') # Expected data haz_metadata = { 'bounding_box': (105.3000035, -8.3749994999999995, 110.2914705, -5.5667784999999999), 'resolution': (0.0083330000000000001, 0.0083330000000000001) } exp_metadata = { 'bounding_box': (94.972335000000001, -11.009721000000001, 141.0140016666665, 6.0736123333332639), 'resolution': (0.0083333333333333003, 0.0083333333333333003) } # Verify relevant metada is ok H = read_layer(hazard_path) E = read_layer(exposure_path) hazard_bbox = H.get_bounding_box() assert numpy.allclose(hazard_bbox, haz_metadata['bounding_box'], rtol=1.0e-12, atol=1.0e-12) exposure_bbox = E.get_bounding_box() assert numpy.allclose(exposure_bbox, exp_metadata['bounding_box'], rtol=1.0e-12, atol=1.0e-12) hazard_res = H.get_resolution() assert numpy.allclose(hazard_res, haz_metadata['resolution'], rtol=1.0e-12, atol=1.0e-12) exposure_res = E.get_resolution() assert numpy.allclose(exposure_res, exp_metadata['resolution'], rtol=1.0e-12, atol=1.0e-12) # First, do some examples that produce valid results ref_box = [105.3000035, -8.3749995, 110.2914705, -5.5667785] view_port = [94.972335, -11.009721, 141.014002, 6.073612] bbox = self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # testing with viewport clipping disabled bbox = self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, None) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) view_port = [ 105.3000035, -8.3749994999999995, 110.2914705, -5.5667784999999999 ] bbox = self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # Very small viewport fully inside other layers view_port = [106.0, -6.0, 108.0, -5.8] bbox = self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, view_port, rtol=1.0e-12, atol=1.0e-12) # viewport that intersects hazard layer view_port = [107.0, -6.0, 112.0, -3.0] ref_box = [107, -6, 110.2914705, -5.5667785] bbox = self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, view_port) assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12) # Then one where boxes don't overlap view_port = [105.3, -4.3, 110.29, -2.5] try: self.analysis.get_optimal_extent(hazard_bbox, exposure_bbox, view_port) except InsufficientOverlapError, e: message = 'Did not find expected error message in %s' % str(e) assert 'did not overlap' in str(e), message else: