def test_windowsDrawingArtifacts(self): """Test that windows rendering does not make artifacts""" # sometimes spurious lines are drawn on the layout myMap = Map(IFACE) myMap.setupComposition() myPdfPath = os.path.join(temp_dir(), 'outArtifactsTest.pdf') myMap.setupPrinter(myPdfPath) myPixmap = QtGui.QPixmap(10, 10) myPixmap.fill(QtGui.QColor(250, 250, 250)) myFilename = os.path.join(temp_dir(), 'greyBox') myPixmap.save(myFilename, 'PNG') for i in range(10, 190, 10): myPicture = QgsComposerPicture(myMap.composition) myPicture.setPictureFile(myFilename) myPicture.setFrame(False) myPicture.setItemPosition(i, # x i, # y 10, # width 10) # height myMap.composition.addItem(myPicture) # Same drawing drawn directly as a pixmap myPixmapItem = myMap.composition.addPixmap(myPixmap) myPixmapItem.setOffset(i, i + 20) # Same drawing using our drawPixmap Helper myWidthMM = 1 myMap.drawPixmap(myPixmap, myWidthMM, i, i + 40) myMap.renderPrintout() myUnwantedHash = 'd05e9223d50baf8bb147475aa96d6ba3' myHash = hashForFile(myPdfPath) # when this test no longer matches our broken render hash # we know the issue is fixed myMessage = 'Windows map render still draws with artifacts.' assert myHash != myUnwantedHash, myMessage
def test_constructor(self): """Test create shake data.""" local_path = os.path.join(temp_dir('realtime-test'), 'shakemaps') try: event_one = ShakeData(working_dir=local_path) event_two = ShakeData(working_dir=temp_dir('realtime-test'), event=SHAKE_ID) self.assertEqual(event_one.event_id, SHAKE_ID) self.assertEqual(event_two.event_id, SHAKE_ID) except: raise
def test_constructor(self): """Test create shake data.""" local_path = os.path.join(temp_dir('realtime-test'), 'shakemaps') try: event_one = ShakeData(working_dir=local_path) event_two = ShakeData( working_dir=temp_dir('realtime-test'), event=SHAKE_ID) self.assertEqual(event_one.event_id, SHAKE_ID) self.assertEqual(event_two.event_id, SHAKE_ID) except: raise
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_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 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 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 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 test_addClassToLegend(self): """Test we can add a class to the map legend.""" myLayer, myType = loadLayer('test_shakeimpact.shp') del myType myMap = Map(IFACE) myMap.setImpactLayer(myLayer) myMap.legend = None myColour = QtGui.QColor(12, 34, 126) myMap.addClassToLegend(myColour, theMin=None, theMax=None, theCategory=None, theLabel='bar') myMap.addClassToLegend(myColour, theMin=None, theMax=None, theCategory=None, theLabel='foo') myPath = os.path.join(temp_dir(), 'addClassToLegend.png') myMap.legend.save(myPath, 'PNG') # As we have discovered, different versions of Qt and # OS platforms cause different output, so hashes are a list # of 'known good' renders. myExpectedHashes = ['', # win '67c0f45792318298664dd02cc0ac94c3', # ub12.04xiner 'ea0702782c2ed5d950c427fbe1743858', # ub11.04-64 '53e0ba1144e071ad41756595d29bf444', # ub12.04 '0681c3587305074bc9272f456fb4dd09', # ub12.04 xvfb 'a37443d70604bdc8c279576b424a158c', # ub12.04-64 # ub11.04-64 laptop '944cee3eb9d916816b60ef41e8069683', # binary read 'de3ceb6547ffc6c557d031c0b7ee9e75', # wVistaSP2-32 '', ] assertHashesForFile(myExpectedHashes, myPath)
def setUp(self): """Setup before each test.""" # Download files (which are local files) to realtime-test temp folder local_path = os.path.join(temp_dir('realtime-test')) shake_data = standard_data_path('hazard', 'shake_data', SHAKE_ID) shutil.copytree( shake_data, os.path.join(local_path, 'shakemaps', SHAKE_ID))
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('.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_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 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) 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 setUp(self): """Runs before each test.""" # noinspection PyUnresolvedReferences self.map_layer_registry = QgsMapLayerRegistry.instance() self.register_layers() # Create Impact Merge Dialog self.impact_merge_dialog = ImpactMergeDialog(PARENT, IFACE) # Create test dir test_data_dir = temp_dir('test') test_impact_merge_dir = os.path.join( test_data_dir, 'test-impact-merge') if not os.path.exists(test_impact_merge_dir): os.makedirs(test_impact_merge_dir) # Create test dir for aggregated # noinspection PyUnresolvedReferences test_aggregated_dir = os.path.join( test_impact_merge_dir, 'aggregated') if not os.path.exists(test_aggregated_dir): os.makedirs(test_aggregated_dir) # Create test dir for entire test_entire_dir = os.path.join( test_impact_merge_dir, 'entire') if not os.path.exists(test_entire_dir): os.makedirs(test_entire_dir)
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 test_log_file_path(self): """Test the log_file_path returns correct path.""" log_temp_dir = temp_dir('logs') actual_path = os.path.join(log_temp_dir, 'inasafe.log') message = 'Actual log path: %s, I got %s' % ( actual_path, log_file_path()) self.assertEqual(actual_path, log_file_path(), message)
def setUp(self): """Setup before each test.""" # Download files (which are local files) to realtime-test temp folder local_path = os.path.join(temp_dir('realtime-test')) shake_data = test_data_path('hazard', 'shake_data', SHAKE_ID) shutil.copytree( shake_data, os.path.join(local_path, 'shakemaps', SHAKE_ID))
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 extentToKml(theExtent): """A helper to get a little kml doc for an extent so that we can use it with gdal warp for clipping.""" myBottomLeftCorner = '%f,%f' % (theExtent[0], theExtent[1]) myTopLeftCorner = '%f,%f' % (theExtent[0], theExtent[3]) myTopRightCorner = '%f,%f' % (theExtent[2], theExtent[3]) myBottomRightCorner = '%f,%f' % (theExtent[2], theExtent[1]) myKml = ("""<?xml version="1.0" encoding="utf-8" ?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <Folder> <Placemark> <Polygon> <outerBoundaryIs> <LinearRing> <coordinates> %s %s %s %s %s </coordinates> </LinearRing> </outerBoundaryIs> </Polygon> </Placemark> </Folder> </Document> </kml>""" % (myBottomLeftCorner, myTopLeftCorner, myTopRightCorner, myBottomRightCorner, myBottomLeftCorner)) myFilename = tempfile.mkstemp('.kml', 'extent_', temp_dir())[1] myFile = file(myFilename, 'wt') myFile.write(myKml) myFile.close() return myFilename
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 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_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 test_generate_html_reports(self): """Test generate_html_reports function.""" self.mock_the_dialog(test_entire_mode=False) self.impact_merge_dialog.prepare_input() self.impact_merge_dialog.validate_all_layers() first_postprocessing_report = self.impact_merge_dialog.first_impact["postprocessing_report"] second_postprocessing_report = self.impact_merge_dialog.second_impact["postprocessing_report"] first_report = "<body>" + first_postprocessing_report + "</body>" second_report = "<body>" + second_postprocessing_report + "</body>" # Now create a dom document for each first_document = minidom.parseString(first_report) second_document = minidom.parseString(second_report) first_impact_tables = first_document.getElementsByTagName("table") second_impact_tables = second_document.getElementsByTagName("table") first_report_dict = self.impact_merge_dialog.generate_report_dictionary_from_dom(first_impact_tables) second_report_dict = self.impact_merge_dialog.generate_report_dictionary_from_dom(second_impact_tables) self.impact_merge_dialog.generate_html_reports(first_report_dict, second_report_dict) # There should be 4 HTML files generated on temp_dir() html_list = glob(os.path.join(temp_dir(), "*.html")) expected_html_number = 4 self.assertEqual(len(html_list), expected_html_number)
def test_generate_html_reports(self): """Test generate_html_reports function.""" self.mock_the_dialog(test_entire_mode=False) self.impact_merge_dialog.prepare_input() self.impact_merge_dialog.validate_all_layers() first_postprocessing_report = \ self.impact_merge_dialog.first_impact['postprocessing_report'] second_postprocessing_report = \ self.impact_merge_dialog.second_impact['postprocessing_report'] first_report = ('<body>' + first_postprocessing_report + '</body>') second_report = ('<body>' + second_postprocessing_report + '</body>') # Now create a dom document for each first_document = minidom.parseString(first_report) second_document = minidom.parseString(second_report) first_impact_tables = first_document.getElementsByTagName('table') second_impact_tables = second_document.getElementsByTagName('table') first_report_dict = \ self.impact_merge_dialog.generate_report_dictionary_from_dom( first_impact_tables) second_report_dict = \ self.impact_merge_dialog.generate_report_dictionary_from_dom( second_impact_tables) self.impact_merge_dialog.generate_html_reports(first_report_dict, second_report_dict) # There should be 4 HTML files generated html_list = glob( os.path.join(temp_dir(self.impact_merge_dialog.__class__.__name__), '*.html')) expected_html_number = 4 self.assertEqual(len(html_list), expected_html_number)
def Xtest_renderTable(self): """Test that html renders nicely. Commented out for now until we work out how to get webkit to do offscreen rendering nicely.""" myFilename = 'test_floodimpact.tif' myLayer, myType = loadLayer(myFilename) CANVAS.refresh() del myType myMessage = 'Layer is not valid: %s' % myFilename assert myLayer.isValid(), myMessage myMap = Map(IFACE) myMap.setImpactLayer(myLayer) myPixmap = myMap.renderImpactTable() assert myPixmap is not None myExpectedWidth = 500 myExpectedHeight = 300 myMessage = 'Invalid width - got %s expected %s' % ( myPixmap.width(), myExpectedWidth) assert myPixmap.width() == myExpectedWidth, myMessage myMessage = 'Invalid height - got %s expected %s' % ( myPixmap.height(), myExpectedHeight) assert myPixmap.height() == myExpectedHeight myPath = os.path.join(temp_dir(), 'renderImpactTable.png') myPixmap.save(myPath, 'PNG') myExpectedHash = 'c9164d5c2bb85c6081905456ab827f3e' assertHashForFile(myExpectedHash, myPath)
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 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 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 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_setup_dialog(self): """Test Setup Options Dialog.""" dialog = OptionsDialog( parent=PARENT, iface=IFACE, qsetting='InaSAFETest') self.assertIsNotNone(dialog) # Check default values self.assertEqual( dialog.cbxVisibleLayersOnly.isChecked(), inasafe_default_settings['visibleLayersOnlyFlag']) self.assertEqual( dialog.cbxSetLayerNameFromTitle.isChecked(), inasafe_default_settings['set_layer_from_title_flag']) self.assertEqual( dialog.cbxZoomToImpact.isChecked(), inasafe_default_settings['setZoomToImpactFlag']) self.assertEqual( dialog.cbxHideExposure.isChecked(), inasafe_default_settings['setHideExposureFlag']) self.assertEqual( dialog.cbxUseSelectedFeaturesOnly.isChecked(), inasafe_default_settings['useSelectedFeaturesOnly']) self.assertEqual( dialog.leKeywordCachePath.text(), inasafe_default_settings['keywordCachePath']) self.assertEqual( dialog.template_warning_checkbox.isChecked(), inasafe_default_settings['template_warning_verbose']) self.assertEqual( dialog.organisation_on_dock_checkbox.isChecked(), inasafe_default_settings['showOrganisationLogoInDockFlag']) self.assertEqual( dialog.cbxDevMode.isChecked(), inasafe_default_settings['developer_mode']) self.assertEqual( dialog.leNorthArrowPath.text(), default_north_arrow_path()) self.assertEqual( dialog.leOrganisationLogoPath.text(), supporters_logo_path()) self.assertEqual(dialog.leReportTemplatePath.text(), '') self.assertEqual(dialog.txtDisclaimer.toPlainText(), disclaimer()) self.assertEqual( dialog.leUserDirectoryPath.text(), temp_dir('impacts')) self.assertEqual( dialog.iso19115_organization_le.text(), inasafe_default_settings['ISO19115_ORGANIZATION']) self.assertEqual( dialog.iso19115_url_le.text(), inasafe_default_settings['ISO19115_URL']) self.assertEqual( dialog.iso19115_email_le.text(), inasafe_default_settings['ISO19115_EMAIL']) self.assertEqual( dialog.iso19115_title_le.text(), inasafe_default_settings['ISO19115_TITLE']) self.assertEqual( dialog.iso19115_license_le.text(), inasafe_default_settings['ISO19115_LICENSE'])
def print_map_to_pdf(self, impact_report): """Print map to PDF given MapReport instance. :param impact_report: Impact Report instance that is ready to print :type impact_report: ImpactReport """ impact_report.setup_composition() # Get Filename map_title = impact_report.map_title if map_title is not None: default_file_name = map_title + '.pdf' default_file_name = default_file_name.replace(' ', '_') else: self.show_error_message(self.tr('Keyword "map_title" not found.')) return # Get output path # noinspection PyCallByClass,PyTypeChecker output_path = QtGui.QFileDialog.getSaveFileName( self.parent, self.tr('Write to PDF'), os.path.join(temp_dir(), default_file_name), self.tr('Pdf File (*.pdf)')) output_path = str(output_path) if output_path is None or output_path == '': self.show_dynamic_message( self, m.Message(m.Heading(self.tr('Map Creator'), **WARNING_STYLE), m.Text(self.tr('Printing cancelled!')))) return try: map_pdf_path, table_pdf_path = impact_report.print_to_pdf( output_path) # Make sure the file paths can wrap nicely: wrapped_map_path = map_pdf_path.replace(os.sep, '<wbr>' + os.sep) wrapped_table_path = table_pdf_path.replace( os.sep, '<wbr>' + os.sep) status = m.Message( m.Heading(self.tr('Map Creator'), **INFO_STYLE), m.Paragraph( self. tr('Your PDF was created....opening using the default PDF ' 'viewer on your system. The generated pdfs were saved ' 'as:')), m.Paragraph(wrapped_map_path), m.Paragraph(self.tr('and')), m.Paragraph(wrapped_table_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(table_pdf_path)) # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker QtGui.QDesktopServices.openUrl( QtCore.QUrl.fromLocalFile(map_pdf_path)) self.show_dynamic_message(self, status) except TemplateLoadingError, e: self.show_error_message(get_error_message(e))
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_get_list_event_ids(self): """Test get_list_event_ids.""" local_path = os.path.join(temp_dir('realtime-test'), 'shakemaps') shake_data = ShakeData(working_dir=local_path) list_id = shake_data.get_list_event_ids() expected_list_id = [SHAKE_ID] message = 'I got %s for the event ID in the server, Expectation %s' % ( list_id, expected_list_id) self.assertEqual(list_id, expected_list_id, message)
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 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_inasafeMap(self): """Test making a pdf using the Map class.""" myLayer, myType = loadLayer('test_shakeimpact.shp') del myType myCanvasLayer = QgsMapCanvasLayer(myLayer) CANVAS.setLayerSet([myCanvasLayer]) myMap = Map(IFACE) myRect = QgsRectangle(106.7894, -6.2308, 106.8004, -6.2264) CANVAS.setExtent(myRect) CANVAS.refresh() myMap.setImpactLayer(myLayer) myPath = os.path.join(temp_dir(), 'outCustom.pdf') if os.path.exists(myPath): os.remove(myPath) myMap.makePdf(myPath) assert os.path.exists(myPath) # ,, note:: Template writing is experimental myMap.writeTemplate(os.path.join(temp_dir(), 'template.qpt'))
def test_setup_dialog(self): """Test Setup Options Dialog.""" dialog = OptionsDialog( parent=PARENT, iface=IFACE, qsetting=INASAFE_TEST) self.assertIsNotNone(dialog) # Check default values self.assertEqual( dialog.cbxVisibleLayersOnly.isChecked(), inasafe_default_settings['visibleLayersOnlyFlag']) self.assertEqual( dialog.cbxSetLayerNameFromTitle.isChecked(), inasafe_default_settings['set_layer_from_title_flag']) self.assertEqual( dialog.cbxZoomToImpact.isChecked(), inasafe_default_settings['setZoomToImpactFlag']) self.assertEqual( dialog.cbxHideExposure.isChecked(), inasafe_default_settings['setHideExposureFlag']) self.assertEqual( dialog.cbxUseSelectedFeaturesOnly.isChecked(), inasafe_default_settings['useSelectedFeaturesOnly']) self.assertEqual( dialog.leKeywordCachePath.text(), inasafe_default_settings['keywordCachePath']) self.assertEqual( dialog.template_warning_checkbox.isChecked(), inasafe_default_settings['template_warning_verbose']) self.assertEqual( dialog.organisation_on_dock_checkbox.isChecked(), inasafe_default_settings['showOrganisationLogoInDockFlag']) self.assertEqual( dialog.cbxDevMode.isChecked(), inasafe_default_settings['developer_mode']) self.assertEqual( dialog.leNorthArrowPath.text(), default_north_arrow_path()) self.assertEqual( dialog.organisation_logo_path_line_edit.text(), supporters_logo_path()) self.assertEqual(dialog.leReportTemplatePath.text(), '') self.assertEqual(dialog.txtDisclaimer.toPlainText(), disclaimer()) self.assertEqual( dialog.leUserDirectoryPath.text(), temp_dir('impacts')) self.assertEqual( dialog.organisation_line_edit.text(), inasafe_default_settings['ISO19115_ORGANIZATION']) self.assertEqual( dialog.website_line_edit.text(), inasafe_default_settings['ISO19115_URL']) self.assertEqual( dialog.email_line_edit.text(), inasafe_default_settings['ISO19115_EMAIL']) self.assertEqual( dialog.license_line_edit.text(), inasafe_default_settings['ISO19115_LICENSE'])
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 accept(self): """Process the layer and field and generate a new layer. .. note:: This is called on OK click. """ # run minimum needs calculator try: success, self.result_layer = ( self.minimum_needs(self.layer.currentLayer())) if not success: return except Exception as e: error_name, traceback = humanise_exception(e) message = ( 'Problem(s) occured. \n%s \nDiagnosis: \n%s' % ( error_name, traceback)) display_critical_message_box( title=self.tr('Error while calculating minimum needs'), message=message) return # remove monkey patching keywords del self.result_layer.keywords # write memory layer to file system settings = QSettings() default_user_directory = settings.value( 'inasafe/defaultUserDirectory', defaultValue='') if default_user_directory: output_directory = os.path.join( default_user_directory, 'minimum_needs_calculator') if not os.path.exists(output_directory): os.makedirs(output_directory) else: output_directory = temp_dir(sub_dir='minimum_needs_calculator') output_layer_name = os.path.split(self.result_layer.name())[1] # If normal filename doesn't exist, then use normal filename random_string_length = len(output_layer_name.split('_')[-1]) normal_filename = output_layer_name[:-(random_string_length + 1)] if not os.path.exists(os.path.join(output_directory, normal_filename)): output_layer_name = normal_filename data_store = Folder(output_directory) data_store.default_vector_format = 'geojson' data_store.add_layer(self.result_layer, output_layer_name) self.result_layer = data_store.layer(output_layer_name) # noinspection PyArgumentList QgsMapLayerRegistry.instance().addMapLayers( [data_store.layer(self.result_layer.name())]) self.done(QtGui.QDialog.Accepted)
def accept(self): """Process the layer and field and generate a new layer. .. note:: This is called on OK click. """ # run minimum needs calculator try: success, self.result_layer = ( self.minimum_needs(self.layer.currentLayer())) if not success: return except Exception as e: error_name, traceback = humanise_exception(e) message = ( 'Problem(s) occured. \n%s \nDiagnosis: \n%s' % ( error_name, traceback)) display_critical_message_box( title=self.tr('Error while calculating minimum needs'), message=message) return # remove monkey patching keywords del self.result_layer.keywords # write memory layer to file system settings = QSettings() default_user_directory = settings.value( 'inasafe/defaultUserDirectory', defaultValue='') if default_user_directory: output_directory = os.path.join( default_user_directory, 'minimum_needs_calculator') if not os.path.exists(output_directory): os.makedirs(output_directory) else: output_directory = temp_dir(sub_dir='minimum_needs_calculator') output_layer_name = os.path.split(self.result_layer.name())[1] # If normal filename doesn't exist, then use normal filename random_string_length = len(output_layer_name.split('_')[-1]) normal_filename = output_layer_name[:-(random_string_length + 1)] if not os.path.exists(os.path.join(output_directory, normal_filename)): output_layer_name = normal_filename data_store = Folder(output_directory) data_store.default_vector_format = 'geojson' data_store.add_layer(self.result_layer, output_layer_name) self.result_layer = data_store.layer(output_layer_name) # noinspection PyArgumentList QgsProject.instance().addMapLayers( [data_store.layer(self.result_layer.name())]) self.done(QtWidgets.QDialog.Accepted)
def test_extract(self): """Test extracting data to be used in earth quake realtime.""" local_path = os.path.join(temp_dir('realtime-test'), 'shakemaps') shake_data = ShakeData(working_dir=local_path) shake_data.extract() final_grid_xml_file = os.path.join( shake_data.extract_dir(), 'grid.xml') self.assertTrue( os.path.exists(final_grid_xml_file), 'grid.xml not found')
def tearDown(self): """Runs after each test.""" # Remove Map Layers if len(self.map_layer_registry.mapLayers().values()) > 0: self.map_layer_registry.removeAllMapLayers() # Delete test dir test_data_dir = temp_dir('test') test_impact_merge_dir = os.path.join( test_data_dir, 'test-impact-merge') shutil.rmtree(test_impact_merge_dir)
def test_get_latest_event_id(self): """Test get latest event id.""" local_path = os.path.join(temp_dir('realtime-test'), 'shakemaps') shake_data = ShakeData(working_dir=local_path) latest_id = shake_data.get_latest_event_id() # The latest event ID should be = SHAKE_ID since there's only one expected_event_id = SHAKE_ID message = 'I got %s for this latest event id, Expectation %s' % ( latest_id, expected_event_id) self.assertEqual(expected_event_id, latest_id, message)
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()