def test_convert_grid_to_raster(self): """Test converting grid.xml to raster (tif file)""" grid_title = 'Earthquake' grid_source = 'USGS' output_raster = unique_filename( prefix='result_grid', suffix='.tif', dir=temp_dir('test')) result = convert_mmi_data( GRID_PATH, grid_title, grid_source, output_path=output_raster, algorithm=NEAREST_NEIGHBOUR) expected_result = output_raster.replace( '.tif', '-%s.tif' % NEAREST_NEIGHBOUR) self.assertEqual( result, expected_result, 'Result path not as expected') exists = os.path.exists(result) self.assertTrue(exists, 'File result : %s does not exist' % result) exists = os.path.exists(result[:-3] + 'xml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'xml') exists = os.path.exists(result[:-3] + 'qml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'qml')
def test_export_import_setting(self): """Test for export_setting method.""" profile_file = unique_filename( suffix='.json', dir='population_preference') original_settings = { 'key': 'value', 'key_bool': True, 'population_preference': generate_default_profile(), 'key_int': 1, 'key_float': 2.0 } # Write for key, value in list(original_settings.items()): set_setting(key, value, self.qsettings) # Export inasafe_settings = export_setting(profile_file, self.qsettings) # Check result self.assertTrue(os.path.exists(profile_file)) self.assertEqual(inasafe_settings['key'], 'value') self.assertEqual( inasafe_settings['population_preference'], generate_default_profile()) # Import read_setting = import_setting(profile_file, self.qsettings) self.assertDictEqual(inasafe_settings, read_setting) self.assertDictEqual(original_settings, read_setting)
def test_convert_grid_to_raster_with_ascii(self): """Test converting grid.xml to raster (tif file)""" grid_title = 'Earthquake' grid_source = 'USGS' output_raster = unique_filename( prefix='result_grid', suffix='.tif', dir=temp_dir('test')) result = convert_mmi_data( GRID_PATH, grid_title, grid_source, algorithm=USE_ASCII, output_path=output_raster) expected_result = output_raster.replace('.tif', '-%s.tif' % USE_ASCII) self.assertEqual( result, expected_result, 'Result path not as expected') exists = os.path.exists(result) self.assertTrue(exists, 'File result : %s does not exist' % result) exists = os.path.exists(result[:-3] + 'xml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'xml') exists = os.path.exists(result[:-3] + 'qml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'qml') tif_file = load_layer(result)[0] keywords = tif_file.keywords self.assertEqual(keywords['hazard'], hazard_earthquake['key']) population_classification = list(keywords['thresholds'][ exposure_population['key']].keys())[0] self.assertEqual( population_classification, earthquake_mmi_scale['key'])
def print_map_to_pdf(self, output_path): """Generate the printout for our final map as pdf. :param output_path: Path on the file system to which the pdf should be saved. If None, a generated file name will be used. :type output_path: str :returns: File name of the output file (equivalent to filename if provided). :rtype: str """ LOGGER.debug('InaSAFE Map print_to_pdf called') self.setup_composition() try: self.load_template() except TemplateLoadingError: raise self.draw_composition() if output_path is None: output_path = unique_filename( prefix='report', suffix='.pdf', dir=temp_dir()) self.composition.exportAsPDF(output_path) return output_path
def testSqliteWriting(self): """Test that writing a dataset to sqlite works.""" keywords = read_keywords(SHP_BASE + '.keywords') layer = Vector(data=SHP_BASE + '.shp', keywords=keywords) test_dir = temp_dir(sub_dir='test') test_file = unique_filename(suffix='.sqlite', dir=test_dir) layer.write_to_file(test_file, sublayer='foo')
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario( DOCK, hazard='Classified Flood', exposure='Population', function='Be affected by each hazard class', function_id='ClassifiedRasterHazardPopulationFunction') self.assertTrue(result, message) fake_dir = test_data_path() scenario_file = unique_filename(prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = str(DOCK.get_exposure_layer().publicSource()) hazard_layer = str(DOCK.get_hazard_layer().publicSource()) relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual('exposure\\pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard\\classified_flood_20_20.asc', relative_hazard) else: self.assertEqual('exposure/pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard/classified_flood_20_20.asc', relative_hazard)
def read_from_qgis_native(self, qgis_layer): """Read raster data from qgis layer QgsRasterLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file * GetDataError if can't create copy of qgis_layer's dataProvider """ if not qgis_imported: # FIXME (DK): this branch isn't covered by test msg = ('Used data is QgsRasterLayer instance, ' 'but QGIS is not avialable.') raise TypeError(msg) base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) pipe = QgsRasterPipe() provider = qgis_layer.dataProvider() if not pipe.set(provider.clone()): msg = "Cannot set pipe provider" raise GetDataError(msg) file_writer.writeRaster(pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) # Write keywords if any write_keywords(self.keywords, base_name + '.keywords') self.read_from_file(file_name)
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario( DOCK, hazard='Classified Flood in Jakarta', exposure='Penduduk Jakarta', function='Be affected by each hazard class', function_id='Classified Hazard Population Impact Function') self.assertTrue(result, message) fake_dir = os.path.dirname(TESTDATA) scenario_file = unique_filename(prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = str(DOCK.get_exposure_layer().publicSource()) hazard_layer = str(DOCK.get_hazard_layer().publicSource()) relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual('test\\Population_Jakarta_geographic.asc', relative_exposure) self.assertEqual('hazard\\jakarta_flood_category_123.asc', relative_hazard) else: self.assertEqual('test/Population_Jakarta_geographic.asc', relative_exposure) self.assertEqual('hazard/jakarta_flood_category_123.asc', relative_hazard)
def clip_raster(raster, column_count, row_count, output_extent): """Clip raster to specified extent, width and height. Note there is similar utility in safe_qgis.utilities.clipper, but it uses gdal whereas this one uses native QGIS. :param raster: Raster :type raster: QgsRasterLayer :param column_count: Desired width in pixels of new raster :type column_count: Int :param row_count: Desired height in pixels of new raster :type row_count: Int :param output_extent: Extent of the clipped region :type output_extent: QgsRectangle :returns: Clipped region of the raster :rtype: QgsRasterLayer """ provider = raster.dataProvider() pipe = QgsRasterPipe() pipe.set(provider.clone()) base_name = unique_filename() file_name = base_name + ".tif" file_writer = QgsRasterFileWriter(file_name) file_writer.writeRaster(pipe, column_count, row_count, output_extent, raster.crs()) return QgsRasterLayer(file_name, "clipped_raster")
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario( self.DOCK, hazard='Classified Flood', exposure='Population') self.assertTrue(result, message) fake_dir = standard_data_path() scenario_file = unique_filename( prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = self.DOCK.get_exposure_layer().publicSource() hazard_layer = self.DOCK.get_hazard_layer().publicSource() relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual( 'exposure\\pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual( 'hazard\\classified_flood_20_20.asc', relative_hazard) else: self.assertEqual( 'exposure/pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual( 'hazard/classified_flood_20_20.asc', relative_hazard)
def read_from_qgis_native(self, qgis_layer): """Read raster data from qgis layer QgsRasterLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file * GetDataError if can't create copy of qgis_layer's dataProvider """ base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) pipe = QgsRasterPipe() provider = qgis_layer.dataProvider() if not pipe.set(provider.clone()): msg = "Cannot set pipe provider" raise GetDataError(msg) file_writer.writeRaster( pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) # Write keywords if any write_iso19115_metadata(file_name, self.keywords) self.read_from_file(file_name)
def read_from_qgis_native(self, qgis_layer): """Read and unpack vector data from qgis layer QgsVectorLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file """ # FIXME (DK): this branch isn't covered by test if not QGIS_IS_AVAILABLE: msg = ('Used data is QgsVectorLayer instance, ' 'but QGIS is not available.') raise TypeError(msg) base_name = unique_filename() file_name = base_name + '.shp' error = QgsVectorFileWriter.writeAsVectorFormat( qgis_layer, file_name, "UTF8", qgis_layer.crs(), "ESRI Shapefile" ) if error != QgsVectorFileWriter.NoError: # FIXME (DK): this branch isn't covered by test msg = ('Can not save data in temporary file.') raise IOError(msg) # Write keywords if any write_keywords(self.keywords, base_name + '.keywords') self.read_from_file(file_name)
def test_convert_grid_to_raster_with_ascii(self): """Test converting grid.xml to raster (tif file)""" grid_title = 'Earthquake' grid_source = 'USGS' output_raster = unique_filename(prefix='result_grid', suffix='.tif', dir=temp_dir('test')) result = convert_mmi_data(GRID_PATH, grid_title, grid_source, algorithm=USE_ASCII, output_path=output_raster) expected_result = output_raster.replace('.tif', '-%s.tif' % USE_ASCII) self.assertEqual(result, expected_result, 'Result path not as expected') exists = os.path.exists(result) self.assertTrue(exists, 'File result : %s does not exist' % result) exists = os.path.exists(result[:-3] + 'xml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'xml') exists = os.path.exists(result[:-3] + 'qml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'qml') tif_file = load_layer(result)[0] keywords = tif_file.keywords self.assertEqual(keywords['hazard'], hazard_earthquake['key']) population_classification = keywords['thresholds'][ exposure_population['key']].keys()[0] self.assertEqual(population_classification, earthquake_mmi_scale['key'])
def test_sorted_impacted_cities(self): """Test getting impacted cities sorted by mmi then population.""" working_dir = shakemap_extract_dir() shake_event = ShakeEvent( working_dir=working_dir, event_id=SHAKE_ID, data_is_local_flag=True) table = shake_event.sorted_impacted_cities() file_path = unique_filename( prefix='test_sorted_impacted_cities', suffix='.txt', dir=temp_dir('test')) cities_file = file(file_path, 'w') cities_file.writelines(str(table)) cities_file.close() table = str(table).replace(', \'', ',\n\'') table += '\n' fixture_path = os.path.join( data_dir(), 'tests', 'test_sorted_impacted_cities.txt') cities_file = file(fixture_path) expected_string = cities_file.read() cities_file.close() expected_string = expected_string.replace(', \'', ',\n\'') self.max_diff = None message = 'Expectation:\n%s, Got\n%s' % (expected_string, table) self.assertEqual(expected_string, table, message)
def clip_raster(raster, column_count, row_count, output_extent): """Clip raster to specified extent, width and height. Note there is similar utility in safe_qgis.utilities.clipper, but it uses gdal whereas this one uses native QGIS. :param raster: Raster :type raster: QgsRasterLayer :param column_count: Desired width in pixels of new raster :type column_count: Int :param row_count: Desired height in pixels of new raster :type row_count: Int :param output_extent: Extent of the clipped region :type output_extent: QgsRectangle :returns: Clipped region of the raster :rtype: QgsRasterLayer """ provider = raster.dataProvider() pipe = QgsRasterPipe() pipe.set(provider.clone()) base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) file_writer.writeRaster(pipe, column_count, row_count, output_extent, raster.crs()) return QgsRasterLayer(file_name, 'clipped_raster')
def test_standard_properties(self): metadata = AggregationLayerMetadata(unique_filename()) with self.assertRaises(KeyError): metadata.get_property('non_existing_key') # from BaseMetadata metadata.get_property('organisation')
def test_export_import_setting(self): """Test for export_setting method.""" profile_file = unique_filename(suffix='.json', dir='population_preference') original_settings = { 'key': 'value', 'key_bool': True, 'population_preference': generate_default_profile(), 'key_int': 1, 'key_float': 2.0 } # Write for key, value in list(original_settings.items()): set_setting(key, value, self.qsettings) # Export inasafe_settings = export_setting(profile_file, self.qsettings) # Check result self.assertTrue(os.path.exists(profile_file)) self.assertEqual(inasafe_settings['key'], 'value') self.assertEqual(inasafe_settings['population_preference'], generate_default_profile()) # Import read_setting = import_setting(profile_file, self.qsettings) self.assertDictEqual(inasafe_settings, read_setting) self.assertDictEqual(original_settings, read_setting)
def test_converting(self): """Test converting grif file to tiff.""" dialog = ShakemapConverterDialog(PARENT, IFACE) dialog.use_output_default.setEnabled(False) grid_path = standard_data_path( 'hazard', 'shake_data', '20131105060809', 'output', 'grid.xml') output_raster = unique_filename( prefix='result_grid', suffix='.tif', dir=temp_dir('test')) dialog.load_result.setEnabled(True) dialog.load_result.setChecked(False) dialog.input_path.setText(grid_path) dialog.nearest_mode.setChecked(True) dialog.output_path.setText(output_raster) button = dialog.button_box.button(QDialogButtonBox.Ok) button.click() msg = 'Raster is not created' output_path = '%s-nearest.tif' % output_raster[:-4] self.assertTrue(os.path.exists(output_path), msg)
def create_grid(size): """Create a polygonal grid using Processing. :param size: The cell size. :type size: int :return: The grid layer in memory. :rtype: QgsVectorLayer """ output_filename = unique_filename(prefix='grid', suffix='.shp') result = processing.runalg( 'qgis:vectorgrid', '336199.970553,352338.397991,7636164.67975,7648562.41208', size, # X spacing size, # Y spacing 0, # Output as polygons output_filename) layer = QgsVectorLayer(output_filename, 'grid', 'ogr') layer.setCrs(QgsCoordinateReferenceSystem(32740)) remove_fields(layer, ['xmin', 'xmax', 'ymin', 'ymax']) # Make a copy in memory memory = create_memory_layer( 'grid', layer.geometryType(), layer.crs(), layer.fields()) copy_layer(layer, memory) print "NB cells : %s" % layer.featureCount() return memory
def read_from_qgis_native(self, qgis_layer): """Read raster data from qgis layer QgsRasterLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file * GetDataError if can't create copy of qgis_layer's dataProvider """ base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) pipe = QgsRasterPipe() provider = qgis_layer.dataProvider() if not pipe.set(provider.clone()): msg = "Cannot set pipe provider" raise GetDataError(msg) file_writer.writeRaster( pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) # Write keywords if any write_keywords(self.keywords, base_name + '.keywords') self.read_from_file(file_name)
def Xtest_print_impact_table(self): """Test print impact table to pdf.""" impact_layer_path = test_data_path( 'impact', 'population_affected_entire_area.shp') layer, _ = load_layer(impact_layer_path) # noinspection PyUnresolvedReferences,PyArgumentList QgsMapLayerRegistry.instance().addMapLayer(layer) # noinspection PyCallingNonCallable rect = QgsRectangle(106.8194, -6.2108, 106.8201, -6.1964) CANVAS.setExtent(rect) CANVAS.refresh() template = resources_path('qgis-composer-templates', 'a4-portrait-blue.qpt') report = ImpactReport(IFACE, template, layer) report.template = template # just to cover set template out_path = unique_filename(prefix='test_print_impact_table', suffix='.pdf', dir=temp_dir('test')) report.print_impact_table(out_path) # Check the file exists message = 'Rendered output does not exist: %s' % out_path self.assertTrue(os.path.exists(out_path), message) # Check the file is not corrupt message = 'The output file %s is corrupt' % out_path out_size = os.stat(out_path).st_size self.assertTrue(out_size > 0, message)
def clone_raster_layer(name, extension, include_keywords, source_directory, target_directory="test"): """Helper function that copies a test raster. :param name: The default name for the raster layer. :type name: str :param extension: The extension of the raster file. :type extension: str :param include_keywords: Include keywords file if True. :type include_keywords: bool :param source_directory: Directory where the file is located. :type source_directory: str :param target_directory: Subdirectory in InaSAFE temp dir that we want to put the files into. Default to 'testing'. :type target_directory: str """ extensions = [".prj", ".sld", "qml", ".prj", extension] if include_keywords: extensions.append(".xml") temp_path = unique_filename(dir=temp_dir(target_directory)) # copy to temp file for ext in extensions: src_path = os.path.join(source_directory, name + ext) if os.path.exists(src_path): trg_path = temp_path + ext shutil.copy2(src_path, trg_path) raster_path = "%s%s" % (temp_path, extension) layer = QgsRasterLayer(raster_path, os.path.basename(raster_path)) return layer
def html_to_file(html, file_path=None, open_browser=False): """Save the html to an html file adapting the paths to the filesystem. if a file_path is passed, it is used, if not a unique_filename is generated. :param html: the html for the output file. :type html: str :param file_path: the path for the html output file. :type file_path: str :param open_browser: if true open the generated html in an external browser :type open_browser: bool """ if file_path is None: file_path = unique_filename(suffix='.html') # Ensure html is in unicode for codecs module html = get_unicode(html) with codecs.open(file_path, 'w', encoding='utf-8') as f: f.write(html) if open_browser: open_in_browser(file_path)
def test_print_default_template(self): """Test printing report to pdf using default template works.""" impact_layer_path = test_data_path( 'impact', 'population_affected_entire_area.shp') layer, _ = load_layer(impact_layer_path) # noinspection PyUnresolvedReferences QgsMapLayerRegistry.instance().addMapLayer(layer) # noinspection PyCallingNonCallable rect = QgsRectangle(106.8194, -6.2108, 106.8201, -6.1964) CANVAS.setExtent(rect) CANVAS.refresh() template = resources_path( 'qgis-composer-templates', 'inasafe-portrait-a4.qpt') report = ImpactReport(IFACE, template, layer) out_path = unique_filename( prefix='map_default_template_test', suffix='.pdf', dir=temp_dir('test')) report.print_map_to_pdf(out_path) # Check the file exists message = 'Rendered output does not exist: %s' % out_path self.assertTrue(os.path.exists(out_path), message) # Check the file is not corrupt message = 'The output file %s is corrupt' % out_path out_size = os.stat(out_path).st_size self.assertTrue(out_size > 0, message) # Check the components in composition are default components if qgis_version() < 20500: safe_logo = report.composition.getComposerItemById( 'safe-logo').pictureFile() north_arrow = report.composition.getComposerItemById( 'north-arrow').pictureFile() org_logo = report.composition.getComposerItemById( 'organisation-logo').pictureFile() else: safe_logo = report.composition.getComposerItemById( 'safe-logo').picturePath() north_arrow = report.composition.getComposerItemById( 'north-arrow').picturePath() org_logo = report.composition.getComposerItemById( 'organisation-logo').picturePath() expected_safe_logo = resources_path( 'img', 'logos', 'inasafe-logo-url.svg') expected_north_arrow = resources_path( 'img', 'north_arrows', 'simple_north_arrow.png') expected_org_logo = resources_path('img', 'logos', 'supporters.png') message = 'The safe logo path is not the default one' self.assertEqual(expected_safe_logo, safe_logo, message) message = 'The north arrow path is not the default one' self.assertEqual(expected_north_arrow, north_arrow, message) message = 'The organisation logo path is not the default one' self.assertEqual(expected_org_logo, org_logo, message)
def test_convert_grid_to_raster(self): """Test converting grid.xml to raster (tif file) """ grid_path = os.path.join(TESTDATA, 'grid.xml') grid_title = 'Earthquake' grid_source = 'USGS' output_raster = unique_filename( prefix='result_grid', suffix='.tif', dir=temp_dir('test')) result = convert_mmi_data( grid_path, grid_title, grid_source, output_raster) expected_result = output_raster.replace('.tif', '-nearest.tif') self.assertEqual( result, expected_result, 'Result path not as expected') exists = os.path.exists(result) self.assertTrue(exists, 'File result : %s does not exist' % result) exists = os.path.exists(result[:-3] + 'keywords') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'keywords') exists = os.path.exists(result[:-3] + 'qml') self.assertTrue( exists, 'File result : %s does not exist' % result[:-3] + 'qml')
def clone_shp_layer( name, include_keywords, source_directory, target_directory='test'): """Helper function that copies a test shp layer and returns it. :param name: The default name for the shp layer. :type name: str :param include_keywords: Include keywords file if True. :type include_keywords: bool :param source_directory: Directory where the file is located. :type source_directory: str :param target_directory: Subdirectory in InaSAFE temp dir that we want to put the files into. Default to 'test'. :type target_directory: str """ extensions = ['.shp', '.shx', '.dbf', '.prj'] if include_keywords: extensions.append('.keywords') temp_path = unique_filename(dir=temp_dir(target_directory)) # copy to temp file for ext in extensions: src_path = os.path.join(source_directory, name + ext) if os.path.exists(src_path): target_path = temp_path + ext shutil.copy2(src_path, target_path) shp_path = '%s.shp' % temp_path layer = QgsVectorLayer(shp_path, os.path.basename(shp_path), 'ogr') return layer
def test_relative_path(self): """Test we calculate the relative paths correctly when saving scenario. """ result, message = setup_scenario(self.DOCK, hazard='Classified Flood', exposure='Population') self.assertTrue(result, message) fake_dir = standard_data_path() scenario_file = unique_filename(prefix='scenarioTest', suffix='.txt', dir=fake_dir) exposure_layer = layer_from_combo( self.DOCK.exposure_layer_combo).publicSource() hazard_layer = layer_from_combo( self.DOCK.hazard_layer_combo).publicSource() relative_exposure = self.save_scenario_dialog.relative_path( scenario_file, exposure_layer) relative_hazard = self.save_scenario_dialog.relative_path( scenario_file, hazard_layer) if 'win32' in sys.platform: # windows self.assertEqual('exposure\\pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard\\classified_flood_20_20.asc', relative_hazard) else: self.assertEqual('exposure/pop_binary_raster_20_20.asc', relative_exposure) self.assertEqual('hazard/classified_flood_20_20.asc', relative_hazard)
def read_from_qgis_native(self, qgis_layer): """Read and unpack vector data from qgis layer QgsVectorLayer. A stub is used now: save all data in a file, then call safe.read_from_file Raises: * TypeError if qgis is not avialable * IOError if can't store temporary file """ # FIXME (DK): this branch isn't covered by test if not QGIS_IS_AVAILABLE: msg = ('Used data is QgsVectorLayer instance, ' 'but QGIS is not avialable.') raise TypeError(msg) base_name = unique_filename() file_name = base_name + '.shp' error = QgsVectorFileWriter.writeAsVectorFormat( qgis_layer, file_name, "UTF8", qgis_layer.crs(), "ESRI Shapefile" ) if error != QgsVectorFileWriter.NoError: # FIXME (DK): this branch isn't covered by test msg = ('Can not save data in temporary file.') raise IOError(msg) # Write keywords if any write_keywords(self.keywords, base_name + '.keywords') self.read_from_file(file_name)
def clone_shp_layer(name, include_keywords, source_directory, target_directory='test'): """Helper function that copies a test shp layer and returns it. :param name: The default name for the shp layer. :type name: str :param include_keywords: Include keywords file if True. :type include_keywords: bool :param source_directory: Directory where the file is located. :type source_directory: str :param target_directory: Subdirectory in InaSAFE temp dir that we want to put the files into. Default to 'test'. :type target_directory: str """ extensions = ['.shp', '.shx', '.dbf', '.prj'] if include_keywords: extensions.append('.keywords') extensions.append('.xml') temp_path = unique_filename(dir=temp_dir(target_directory)) # copy to temp file for ext in extensions: src_path = os.path.join(source_directory, name + ext) if os.path.exists(src_path): target_path = temp_path + ext shutil.copy2(src_path, target_path) shp_path = '%s.shp' % temp_path layer = QgsVectorLayer(shp_path, os.path.basename(shp_path), 'ogr') return layer
def test_print_default_template(self): """Test printing report to pdf using default template works.""" impact_layer_path = test_data_path( 'impact', 'population_affected_entire_area.shp') layer, _ = load_layer(impact_layer_path) # noinspection PyUnresolvedReferences,PyArgumentList QgsMapLayerRegistry.instance().addMapLayer(layer) # noinspection PyCallingNonCallable rect = QgsRectangle(106.8194, -6.2108, 106.8201, -6.1964) CANVAS.setExtent(rect) CANVAS.refresh() template = resources_path('qgis-composer-templates', 'a4-portrait-blue.qpt') report = ImpactReport(IFACE, template, layer) out_path = unique_filename(prefix='map_default_template_test', suffix='.pdf', dir=temp_dir('test')) report.print_map_to_pdf(out_path) # Check the file exists message = 'Rendered output does not exist: %s' % out_path self.assertTrue(os.path.exists(out_path), message) # Check the file is not corrupt message = 'The output file %s is corrupt' % out_path out_size = os.stat(out_path).st_size self.assertTrue(out_size > 0, message) # Check the components in composition are default components if qgis_version() < 20500: safe_logo = report.composition.getComposerItemById( 'inasafe-logo').pictureFile() north_arrow = report.composition.getComposerItemById( 'north-arrow').pictureFile() org_logo = report.composition.getComposerItemById( 'organisation-logo').pictureFile() else: safe_logo = report.composition.getComposerItemById( 'white-inasafe-logo').picturePath() north_arrow = report.composition.getComposerItemById( 'north-arrow').picturePath() org_logo = report.composition.getComposerItemById( 'organisation-logo').picturePath() expected_safe_logo = resources_path('img', 'logos', 'inasafe-logo-url-white.svg') expected_north_arrow = resources_path('img', 'north_arrows', 'simple_north_arrow.png') expected_org_logo = resources_path('img', 'logos', 'supporters.png') message = ('The safe logo path is not the default one: %s isn\'t %s' % (expected_safe_logo, safe_logo)) self.assertEqual(expected_safe_logo, safe_logo, message) message = 'The north arrow path is not the default one' self.assertEqual(expected_north_arrow, north_arrow, message) message = 'The organisation logo path is not the default one' self.assertEqual(expected_org_logo, org_logo, message)
def Xtest_print_impact_table(self): """Test print impact table to pdf.""" impact_layer_path = test_data_path( 'impact', 'population_affected_entire_area.shp') layer, _ = load_layer(impact_layer_path) # noinspection PyUnresolvedReferences,PyArgumentList QgsMapLayerRegistry.instance().addMapLayer(layer) # noinspection PyCallingNonCallable rect = QgsRectangle(106.8194, -6.2108, 106.8201, -6.1964) CANVAS.setExtent(rect) CANVAS.refresh() template = resources_path( 'qgis-composer-templates', 'a4-portrait-blue.qpt') report = ImpactReport(IFACE, template, layer) report.template = template # just to cover set template out_path = unique_filename( prefix='test_print_impact_table', suffix='.pdf', dir=temp_dir('test')) report.print_impact_table(out_path) # Check the file exists message = 'Rendered output does not exist: %s' % out_path self.assertTrue(os.path.exists(out_path), message) # Check the file is not corrupt message = 'The output file %s is corrupt' % out_path out_size = os.stat(out_path).st_size self.assertTrue(out_size > 0, message)
def smooth_shakemap(shakemap_layer_path, output_file_path='', active_band=1, smoothing_method=NUMPY_SMOOTHING, smoothing_sigma=0.9): """Make a smoother shakemap layer from a shake map. :param shakemap_layer_path: The shake map raster layer path. :type shakemap_layer_path: basestring :param active_band: The band which the data located, default to 1. :type active_band: int :param smoothing_method: The smoothing method that wanted to be used. :type smoothing_method: NONE_SMOOTHING, NUMPY_SMOOTHING, SCIPY_SMOOTHING :param smooth_sigma: parameter for gaussian filter used in smoothing function. :type smooth_sigma: float :returns: The contour of the shake map layer. :rtype: QgsRasterLayer """ # Set output path if not output_file_path: output_file_path = unique_filename(suffix='.tiff', dir=temp_dir()) # convert to numpy shakemap_file = gdal.Open(shakemap_layer_path) shakemap_array = np.array( shakemap_file.GetRasterBand(active_band).ReadAsArray()) # do smoothing if smoothing_method == NUMPY_SMOOTHING: smoothed_array = convolve(shakemap_array, gaussian_kernel(smoothing_sigma)) else: smoothed_array = shakemap_array # Create smoothed shakemap raster layer driver = gdal.GetDriverByName('GTiff') smoothed_shakemap_file = driver.Create(output_file_path, shakemap_file.RasterXSize, shakemap_file.RasterYSize, 1) smoothed_shakemap_file.GetRasterBand(1).WriteArray(smoothed_array) # CRS smoothed_shakemap_file.SetProjection(shakemap_file.GetProjection()) smoothed_shakemap_file.SetGeoTransform(shakemap_file.GetGeoTransform()) smoothed_shakemap_file.FlushCache() del smoothed_shakemap_file if not os.path.isfile(output_file_path): raise FileNotFoundError( tr('The smoothed shakemap is not created. It should be at ' '{output_file_path}'.format(output_file_path=output_file_path))) return output_file_path
def test_sqlite_writing(self): """Test that writing a dataset to sqlite works.""" keywords = {} layer = Vector(data=SHP_BASE + '.shp', keywords=keywords) test_dir = temp_dir(sub_dir='test') test_file = unique_filename(suffix='.sqlite', dir=test_dir) layer.write_to_file(test_file, sublayer='foo') self.assertTrue(os.path.exists(test_file))
def test_sqlite_writing(self): """Test that writing a dataset to sqlite works.""" keywords = read_keywords(SHP_BASE + ".keywords") layer = Vector(data=SHP_BASE + ".shp", keywords=keywords) test_dir = temp_dir(sub_dir="test") test_file = unique_filename(suffix=".sqlite", dir=test_dir) layer.write_to_file(test_file, sublayer="foo") self.assertTrue(os.path.exists(test_file))
def test_save_scenario(self): """Test saving Current scenario.""" result, message = setup_scenario( DOCK, hazard='Classified Flood', exposure='Population', function='Be affected by each hazard class', function_id='ClassifiedRasterHazardPopulationFunction') self.assertTrue(result, message) # Enable on-the-fly reprojection set_canvas_crs(GEOCRS, True) set_jakarta_extent(dock=DOCK) # create unique file scenario_file = unique_filename( prefix='scenarioTest', suffix='.txt', dir=temp_dir('test')) self.save_scenario_dialog.save_scenario( scenario_file_path=scenario_file) with open(scenario_file) as f: data = f.readlines() title = data[0][:-1] exposure = data[1][:-1] hazard = data[2][:-1] function = data[3][:-1] extent = data[4][:-1] self.assertTrue( os.path.exists(scenario_file), 'File %s does not exist' % scenario_file) self.assertTrue( title == '[Classified Flood]', 'Title is not the same') self.assertTrue( exposure.startswith('exposure =') and exposure.endswith( 'pop_binary_raster_20_20.asc'), 'Exposure is not the same') self.assertTrue( hazard.startswith('hazard =') and hazard.endswith( 'classified_flood_20_20.asc'), 'Hazard is not the same') self.assertTrue( function == ( 'function = ClassifiedRasterHazardPopulationFunction'), 'Impact function is not same') # TODO: figure out why this changed between releases if qgis_version() < 20400: # For QGIS 2.0 expected_extent = ( 'extent = 106.313333, -6.380000, 107.346667, -6.070000') self.assertEqual(expected_extent, extent) else: # for QGIS 2.4 expected_extent = ( 'extent = 106.287500, -6.380000, 107.372500, -6.070000') self.assertEqual(expected_extent, expected_extent)
def test_save_scenario(self): """Test saving Current scenario.""" result, message = setup_scenario( self.DOCK, hazard='Classified Flood', exposure='Population', function='Be affected', function_id='ClassifiedRasterHazardPopulationFunction') self.assertTrue(result, message) # Enable on-the-fly reprojection set_canvas_crs(GEOCRS, True) set_jakarta_extent(dock=self.DOCK) # create unique file scenario_file = unique_filename( prefix='scenarioTest', suffix='.txt', dir=temp_dir('test')) self.save_scenario_dialog.save_scenario( scenario_file_path=scenario_file) with open(scenario_file) as f: data = f.readlines() title = data[0][:-1] exposure = data[1][:-1] hazard = data[2][:-1] function = data[3][:-1] extent = data[4][:-1] self.assertTrue( os.path.exists(scenario_file), 'File %s does not exist' % scenario_file) self.assertTrue( title == '[Classified Flood]', 'Title is not the same') self.assertTrue( exposure.startswith('exposure =') and exposure.endswith( 'pop_binary_raster_20_20.asc'), 'Exposure is not the same') self.assertTrue( hazard.startswith('hazard =') and hazard.endswith( 'classified_flood_20_20.asc'), 'Hazard is not the same') self.assertTrue( function == ( 'function = ClassifiedRasterHazardPopulationFunction'), 'Impact function is not same') # TODO: figure out why this changed between releases if qgis_version() < 20400: # For QGIS 2.0 expected_extent = ( 'extent = 106.313333, -6.380000, 107.346667, -6.070000') self.assertEqual(expected_extent, extent) else: # for QGIS 2.4 expected_extent = ( 'extent = 106.287500, -6.380000, 107.372500, -6.070000') self.assertEqual(expected_extent, expected_extent)
def shakemap_contour(shakemap_layer_path, output_file_path='', active_band=1): """Creating contour from a shakemap layer. :param shakemap_layer_path: The shake map raster layer path. :type shakemap_layer_path: basestring :param output_file_path: The path where the contour will be saved. :type output_file_path: basestring :param active_band: The band which the data located, default to 1. :type active_band: int :returns: The contour of the shake map layer path. :rtype: basestring """ # Set output path if not output_file_path: output_file_path = unique_filename(suffix='.shp', dir=temp_dir()) output_directory = os.path.dirname(output_file_path) output_file_name = os.path.basename(output_file_path) output_base_name = os.path.splitext(output_file_name)[0] # Based largely on # http://svn.osgeo.org/gdal/trunk/autotest/alg/contour.py driver = ogr.GetDriverByName('ESRI Shapefile') ogr_dataset = driver.CreateDataSource(output_file_path) if ogr_dataset is None: # Probably the file existed and could not be overriden raise ContourCreationError( 'Could not create datasource for:\n%s. Check that the file ' 'does not already exist and that you do not have file system ' 'permissions issues' % output_file_path) layer = ogr_dataset.CreateLayer('contour') for contour_field in contour_fields: field_definition = create_ogr_field_from_definition(contour_field) layer.CreateField(field_definition) shakemap_data = gdal.Open(shakemap_layer_path, GA_ReadOnly) # see http://gdal.org/java/org/gdal/gdal/gdal.html for these options contour_interval = 0.5 contour_base = 0 fixed_level_list = [] use_no_data_flag = 0 no_data_value = -9999 id_field = 0 # first field defined above elevation_field = 1 # second (MMI) field defined above try: gdal.ContourGenerate(shakemap_data.GetRasterBand(active_band), contour_interval, contour_base, fixed_level_list, use_no_data_flag, no_data_value, layer, id_field, elevation_field) except Exception, e: LOGGER.exception('Contour creation failed') raise ContourCreationError(str(e))
def test_json_write_no_metadata(self): """Test write metadata for no metadata layer file.""" with open(EXISTING_GENERIC_JSON) as f: expected_json = f.read() self.assertTrue(os.path.isfile(EXISTING_NO_METADATA)) self.assertFalse(os.path.isfile(EXISTING_NO_METADATA[:-3] + 'xml')) self.assertFalse(os.path.isfile(EXISTING_NO_METADATA[:-3] + 'json')) metadata = self.generate_test_metadata(EXISTING_NO_METADATA) json_filename = unique_filename(suffix='.json', dir=TEMP_DIR) metadata.write_to_file(json_filename) with open(json_filename) as f: written_json = f.read() self.assertEquals(expected_json, written_json) xml_filename = unique_filename(suffix='.xml', dir=TEMP_DIR) metadata.write_to_file(xml_filename) print xml_filename
def test_copy_keywords(self): """Test we can copy the keywords.""" out_path = unique_filename( prefix='test_copy_keywords', suffix='.keywords') self.keyword_io.copy_keywords(self.raster_layer, out_path) copied_keywords = read_file_keywords(out_path) expected_keywords = self.expected_raster_keywords message = 'Got:\n%s\nExpected:\n%s\nSource:\n%s' % ( copied_keywords, expected_keywords, out_path) self.assertEquals(copied_keywords, expected_keywords, message)
def test_copy_keywords(self): """Test we can copy the keywords.""" out_path = unique_filename( prefix='test_copy_keywords', suffix='.keywords') self.keyword_io.copy_keywords(self.raster_layer, out_path) copied_keywords = read_file_keywords(out_path) expected_keywords = self.expected_raster_keywords message = 'Got:\n%s\nExpected:\n%s\nSource:\n%s' % ( copied_keywords, expected_keywords, out_path) self.assertDictEqual(copied_keywords, expected_keywords, message)
def test_json_write(self): metadata = self.generate_test_metadata() with open(EXISTING_IMPACT_JSON) as f: expected_json = f.read() filename = unique_filename(suffix='.json', dir=TEMP_DIR) metadata.write_to_file(filename) with open(filename) as f: written_json = f.read() self.assertEquals(expected_json, written_json)
def test_standard_properties(self): metadata = ExposureLayerMetadata(unique_filename()) with self.assertRaises(KeyError): metadata.get_property('non_existing_key') # from BaseMetadata metadata.get_property('title') # from ExposureLayerMetadata metadata.get_property('exposure') metadata.get_property('exposure_unit')
def test_xml_to_json_to_xml(self): generated_metadata = OutputLayerMetadata(EXISTING_IMPACT_FILE, xml_uri=EXISTING_IMPACT_XML) with open(EXISTING_IMPACT_XML) as f: expected_metadata = f.read() json_tmp_file = unique_filename(suffix='.json', dir=TEMP_DIR) generated_metadata.write_to_file(json_tmp_file) read_tmp_metadata = OutputLayerMetadata(EXISTING_IMPACT_FILE, json_uri=json_tmp_file) self.assertEquals(expected_metadata, read_tmp_metadata.xml)
def test_xml_to_json_to_xml(self): generated_metadata = ImpactLayerMetadata( EXISTING_IMPACT_FILE, xml_uri=EXISTING_IMPACT_XML) with open(EXISTING_IMPACT_XML) as f: expected_metadata = f.read() json_tmp_file = unique_filename(suffix='.json', dir=TEMP_DIR) generated_metadata.write_to_file(json_tmp_file) read_tmp_metadata = ImpactLayerMetadata(EXISTING_IMPACT_FILE, json_uri=json_tmp_file) self.assertEquals(expected_metadata, read_tmp_metadata.xml)
def accept(self): """Process the layer for multi buffering and generate a new layer. .. note:: This is called on OK click. """ # set parameter from dialog input_layer = self.layer.currentLayer() output_path = self.output_form.text() radius = self.get_classification() # monkey patch keywords so layer works on multi buffering function input_layer.keywords = {'inasafe_fields': {}} # run multi buffering self.output_layer = multi_buffering(input_layer, radius) # save output layer to data store and check whether user # provide the output path. if output_path: self.output_directory, self.output_filename = ( os.path.split(output_path)) self.output_filename, self.output_extension = ( os.path.splitext(self.output_filename)) # if user do not provide the output path, create a temporary file. else: self.output_directory = temp_dir(sub_dir='work') self.output_filename = ( unique_filename( prefix='hazard_layer', suffix='.geojson', dir=self.output_directory)) self.output_filename = os.path.split(self.output_filename)[1] self.output_filename, self.output_extension = ( os.path.splitext(self.output_filename)) self.data_store = Folder(self.output_directory) if self.output_extension == '.shp': self.data_store.default_vector_format = 'shp' elif self.output_extension == '.geojson': self.data_store.default_vector_format = 'geojson' self.data_store.add_layer(self.output_layer, self.output_filename) # add output layer to map canvas self.output_layer = self.data_store.layer(self.output_filename) QgsMapLayerRegistry.instance().addMapLayers( [self.output_layer]) self.iface.setActiveLayer(self.output_layer) self.iface.zoomToActiveLayer() self.done(QtGui.QDialog.Accepted) if self.keyword_wizard_checkbox.isChecked(): self.launch_keyword_wizard()
def polygonize_gdal( raster, threshold_min=0.0, threshold_max=float('inf')): """ Function to polygonize raster. Areas (pixels) with threshold_min < pixel_values < threshold_max will be converted to polygons. :param raster: Raster layer :type raster: QgsRasterLayer :param threshold_min: Value that splits raster to flooded or not flooded. :type threshold_min: float :param threshold_max: Value that splits raster to flooded or not flooded. :type threshold_max: float :returns: Polygonal geometry :rtype: QgsGeometry """ # save qgis raster to disk base_name = unique_filename() file_name = base_name + '.tif' file_writer = QgsRasterFileWriter(file_name) pipe = QgsRasterPipe() provider = raster.dataProvider() if not pipe.set(provider.clone()): msg = "Cannot set pipe provider" raise GetDataError(msg) file_writer.writeRaster( pipe, provider.xSize(), provider.ySize(), provider.extent(), provider.crs()) ( inside_file_name, inside_layer_name, outside_file_name, outside_layer_name ) = polygonize_thresholds(file_name, threshold_min, threshold_max) inside_layer = \ QgsVectorLayer(inside_file_name, inside_layer_name, 'ogr') outside_layer = \ QgsVectorLayer(outside_file_name, outside_layer_name, 'ogr') if inside_layer.featureCount() == 0: return None, None else: return inside_layer, outside_layer
def test_local_cities(self): """Test that we can retrieve the cities local to the event""" working_dir = shakemap_extract_dir() shake_event = ShakeEvent( working_dir=working_dir, event_id=SHAKE_ID, data_is_local_flag=True) # Get teh mem layer cities_layer = shake_event.local_cities_memory_layer() provider = cities_layer.dataProvider() expected_feature_count = 2 self.assertEquals(provider.featureCount(), expected_feature_count) strings = [] request = QgsFeatureRequest() for feature in cities_layer.getFeatures(request): # fetch map of attributes attributes = cities_layer.dataProvider().attributeIndexes() for attribute_key in attributes: strings.append("%d: %s\n" % ( attribute_key, feature[attribute_key])) strings.append('------------------\n') LOGGER.debug('Mem table:\n %s' % strings) file_path = unique_filename(prefix='test_local_cities', suffix='.txt', dir=temp_dir('test')) cities_file = file(file_path, 'w') cities_file.writelines(strings) cities_file.close() fixture_path = os.path.join(data_dir(), 'tests', 'test_local_cities.txt') cities_file = file(fixture_path) expected_string = cities_file.readlines() cities_file.close() diff = difflib.unified_diff(expected_string, strings) diff_list = list(diff) diff_string = '' for _, myLine in enumerate(diff_list): diff_string += myLine message = ('Diff is not zero length:\n' 'Control file: %s\n' 'Test file: %s\n' 'Diff:\n%s' % (fixture_path, file_path, diff_string)) self.assertEqual(diff_string, '', message)