Exemple #1
0
    def test_osm2padang(self):
        """OSM structure types maps to Padang vulnerability curves
        """

        hazard_filename = '%s/Shakemap_Padang_2009.asc' % HAZDATA
        exposure_filename = ('%s/OSM_building_polygons_20110905.shp'
                             % TESTDATA)

        # Calculate impact using API
        H = read_layer(hazard_filename)
        E = read_layer(exposure_filename)

        # Map from OSM attributes to the padang building classes
        Emap = osm2padang(E)

        for i, feature in enumerate(E.get_data()):

            vclass = int(Emap.get_data('VCLASS', i))

            levels = feature['levels']
            structure = feature['structure']
            msg = ('Unexpected VCLASS %i. '
                   'I have levels == %s and structure == %s.'
                   % (vclass, levels, structure))

            if levels is None or structure is None:
                assert vclass == 2, msg
                continue

            # Map string variable levels to integer
            if levels.endswith('+'):
                levels = 100

            try:
                levels = int(levels)
            except:
                # E.g. 'ILP jalan'
                assert vclass == 2, msg
                continue

            levels = int(levels)

            # Check the main cases
            if levels >= 10:
                assert vclass == 6, msg
            elif 4 <= levels < 10:
                assert vclass == 4, msg
            elif 1 <= levels < 4:
                if structure in ['plastered',
                                 'reinforced masonry',
                                 'reinforced_masonry']:
                    assert vclass == 7, msg
                elif structure == 'confined_masonry':
                    assert vclass == 8, msg
                elif 'kayu' in structure or 'wood' in structure:
                    assert vclass == 9, msg
                else:
                    assert vclass == 2, msg
            else:
                assert vclass == 2, msg
Exemple #2
0
    def test_aggregate(self):
        """Aggregation by boundaries works
        """

        # Name file names for hazard level and exposure
        boundary_filename = ('%s/kecamatan_jakarta_osm.shp' % TESTDATA)
        #data_filename = ('%s/Population_Jakarta_geographic.asc' % TESTDATA)

        # Get reference building impact data
        building_filename = ('%s/building_impact_scenario.shp' % TESTDATA)

        boundary_layer = read_layer(boundary_filename)
        building_layer = read_layer(building_filename)

        res = aggregate(data=building_layer,
                        boundaries=boundary_layer,
                        attribute_name='AFFECTED',
                        aggregation_function='count')

        #print res, len(res)
        #print boundary_layer, len(boundary_layer)
        msg = ('Number of aggregations %i should be the same as the '
               'number of specified boundaries %i' % (len(res),
                                                      len(boundary_layer)))
        assert len(res) == len(boundary_layer), msg
Exemple #3
0
    def test_osm2bnpb(self):
        """OSM structure types maps to BNPB vulnerability curves
        """

        hazard_filename = '%s/Shakemap_Padang_2009.asc' % HAZDATA
        exposure_filename = ('%s/OSM_building_polygons_20110905.shp'
                             % TESTDATA)

        # Calculate impact using API
        H = read_layer(hazard_filename)
        E = read_layer(exposure_filename)

        # Map from OSM attributes to the padang building classes
        Emap = osm2bnpb(E, target_attribute='VCLASS')

        for i, feature in enumerate(E.get_data()):
            try:
                vclass = Emap.get_data('VCLASS', i)
            except KeyError:
                print
                print i, Emap.get_data()[i]
                #import sys; sys.exit()
                pass

            levels = feature['levels']
            structure = feature['structure']
            msg = ('Unexpected VCLASS %s. '
                   'I have levels == %s and structure == %s.'
                   % (vclass, levels, structure))

            if levels is None or structure is None:
                assert vclass == 'URM', msg
                continue

            # Map string variable levels to integer
            if levels.endswith('+'):
                levels = 100

            try:
                levels = int(levels)
            except:
                # E.g. 'ILP jalan'
                assert vclass == 'URM', msg
                continue

            levels = int(levels)

            # Check the main cases
            if levels >= 4:
                assert vclass == 'RM', msg
            elif 1 <= levels < 4:
                if structure in ['reinforced_masonry', 'confined_masonry']:
                    assert vclass == 'RM', msg
                elif 'kayu' in structure or 'wood' in structure:
                    assert vclass == 'RM', msg
                else:
                    assert vclass == 'URM', msg
            else:
                assert vclass == 'URM', msg
    def getRunner(self):
        """ Factory to create a new runner thread.
        Requires three parameters to be set before execution
        can take place:

        * Hazard layer - a path to a raster (string)
        * Exposure layer - a path to a vector hazard layer (string).
        * Function - a function name that defines how the Hazard assessment
          will be computed (string).

        Args:
           None.
        Returns:
           None
        Raises:
           InsufficientParametersException if not all parameters are
           set.
        """
        self.__filename = None
        self.__result = None
        if not self.__hazard_layer or self.__hazard_layer == '':
            msg = tr('Error: Hazard layer not set.')
            raise InsufficientParametersException(msg)

        if not self.__exposure_layer or self.__exposure_layer == '':
            msg = tr('Error: Exposure layer not set.')
            raise InsufficientParametersException(msg)

        if not self.__function or self.__function == '':
            msg = tr('Error: Function not set.')
            raise InsufficientParametersException(msg)

        # Call impact calculation engine
        myHazardLayer = read_layer(makeAscii(self.__hazard_layer))
        myExposureLayer = read_layer(makeAscii(self.__exposure_layer))
        myFunctions = get_plugins(makeAscii(self.__function))
        myFunction = myFunctions[0][makeAscii(self.__function)]
        return ImpactCalculatorThread(myHazardLayer,
                                      myExposureLayer,
                                      myFunction)
    def test_getOptimalExtent(self):
        """Optimal extent is calculated correctly
        """

        exposure_path = os.path.join(TESTDATA, 'Population_2010.asc')
        hazard_path = os.path.join(TESTDATA,
                                   '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_res = [105.3000035, -8.3749995, 110.2914705, -5.5667785]
        view_port = [94.972335, -11.009721, 141.014002, 6.073612]

        bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
        assert numpy.allclose(bbox, ref_res, rtol=1.0e-12, atol=1.0e-12)

        bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
        assert numpy.allclose(bbox, ref_res, rtol=1.0e-12, atol=1.0e-12)

        view_port = [105.3000035,
                     -8.3749994999999995,
                     110.2914705,
                     -5.5667784999999999]
        bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
        assert numpy.allclose(bbox, ref_res,
                              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:
            getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
        except Exception, e:
            msg = 'Did not find expected error message in %s' % str(e)
            assert 'did not overlap' in str(e), msg
    def testRasterScaling(self):
        """Raster layers can be scaled when resampled

        This is a test for ticket #52

        Native test .asc data has

        Population_Jakarta_geographic.asc
        ncols         638
        nrows         649
        cellsize      0.00045228819716044

        Population_2010.asc
        ncols         5525
        nrows         2050
        cellsize      0.0083333333333333

        Scaling is necessary for raster data that represents density
        such as population per km^2
        """

        for test_filename in ['Population_Jakarta_geographic.asc',
                              'Population_2010.asc']:

            myRasterPath = ('%s/%s' % (TESTDATA, test_filename))

            # Get reference values
            R = read_layer(myRasterPath)
            R_min_ref, R_max_ref = R.get_extrema()
            native_resolution = R.get_resolution()

            # Get the Hazard extents as an array in EPSG:4326
            bounding_box = R.get_bounding_box()

            # Test for a range of resolutions
            for res in [0.02, 0.01, 0.005, 0.002, 0.001, 0.0005,  # Coarser
                        0.0002]:                                  # Finer

                # To save time only do two resolutions for the
                # large population set
                if test_filename.startswith('Population_2010'):
                    if res > 0.01 or res < 0.005:
                        break

                # Clip the raster to the bbox
                extraKeywords = {'resolution': native_resolution}
                myRasterLayer = QgsRasterLayer(myRasterPath, 'xxx')
                myResult = clipLayer(myRasterLayer, bounding_box, res,
                                     extraKeywords=extraKeywords)

                R = read_layer(myResult)
                A_native = R.get_data(scaling=False)
                A_scaled = R.get_data(scaling=True)

                sigma = (R.get_resolution()[0] / native_resolution[0]) ** 2

                # Compare extrema
                expected_scaled_max = sigma * numpy.nanmax(A_native)
                msg = ('Resampled raster was not rescaled correctly: '
                       'max(A_scaled) was %f but expected %f'
                       % (numpy.nanmax(A_scaled), expected_scaled_max))

                # FIXME (Ole): The rtol used to be 1.0e-8 -
                #              now it has to be 1.0e-6, otherwise we get
                #              max(A_scaled) was 12083021.000000 but
                #              expected 12083020.414316
                #              Is something being rounded to the nearest
                #              integer?
                assert numpy.allclose(expected_scaled_max,
                                      numpy.nanmax(A_scaled),
                                      rtol=1.0e-6, atol=1.0e-8), msg

                expected_scaled_min = sigma * numpy.nanmin(A_native)
                msg = ('Resampled raster was not rescaled correctly: '
                       'min(A_scaled) was %f but expected %f'
                       % (numpy.nanmin(A_scaled), expected_scaled_min))
                assert numpy.allclose(expected_scaled_min,
                                      numpy.nanmin(A_scaled),
                                      rtol=1.0e-8, atol=1.0e-12), msg

                # Compare elementwise
                msg = 'Resampled raster was not rescaled correctly'
                assert nanallclose(A_native * sigma, A_scaled,
                                   rtol=1.0e-8, atol=1.0e-8), msg

                # Check that it also works with manual scaling
                A_manual = R.get_data(scaling=sigma)
                msg = 'Resampled raster was not rescaled correctly'
                assert nanallclose(A_manual, A_scaled,
                                   rtol=1.0e-8, atol=1.0e-8), msg

                # Check that an exception is raised for bad arguments
                try:
                    R.get_data(scaling='bad')
                except:
                    pass
                else:
                    msg = 'String argument should have raised exception'
                    raise Exception(msg)

                try:
                    R.get_data(scaling='(1, 3)')
                except:
                    pass
                else:
                    msg = 'Tuple argument should have raised exception'
                    raise Exception(msg)

                # Check None option without keyword datatype == 'density'
                R.keywords['datatype'] = 'undefined'
                A_none = R.get_data(scaling=None)
                msg = 'Data should not have changed'
                assert nanallclose(A_native, A_none,
                                   rtol=1.0e-12, atol=1.0e-12), msg

                # Try with None and density keyword
                R.keywords['datatype'] = 'density'
                A_none = R.get_data(scaling=None)
                msg = 'Resampled raster was not rescaled correctly'
                assert nanallclose(A_scaled, A_none,
                                   rtol=1.0e-12, atol=1.0e-12), msg

                R.keywords['datatype'] = 'counts'
                A_none = R.get_data(scaling=None)
                msg = 'Data should not have changed'
                assert nanallclose(A_native, A_none,
                                   rtol=1.0e-12, atol=1.0e-12), msg
    def test_clipBoth(self):
        """Raster and Vector layers can be clipped
        """

        # Create a vector layer
        myName = 'padang'
        myVectorLayer = QgsVectorLayer(VECTOR_PATH, myName, 'ogr')
        msg = 'Did not find layer "%s" in path "%s"' % (myName,
                                                        VECTOR_PATH)
        assert myVectorLayer is not None, msg

        # Create a raster layer
        myName = 'shake'
        myRasterLayer = QgsRasterLayer(RASTERPATH, myName)

        msg = 'Did not find layer "%s" in path "%s"' % (myName,
                                                        RASTERPATH)
        assert myRasterLayer is not None, msg

        # Create a bounding box
        myViewportGeoExtent = [99.53, -1.22, 101.20, -0.36]

        # Get the Hazard extents as an array in EPSG:4326
        myHazardGeoExtent = [myRasterLayer.extent().xMinimum(),
                             myRasterLayer.extent().yMinimum(),
                             myRasterLayer.extent().xMaximum(),
                             myRasterLayer.extent().yMaximum()]

        # Get the Exposure extents as an array in EPSG:4326
        myExposureGeoExtent = [myVectorLayer.extent().xMinimum(),
                               myVectorLayer.extent().yMinimum(),
                               myVectorLayer.extent().xMaximum(),
                               myVectorLayer.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]
        myGeoExtent = getOptimalExtent(myHazardGeoExtent,
                                       myExposureGeoExtent,
                                       myViewportGeoExtent)

        # Clip the vector to the bbox
        myResult = clipLayer(myVectorLayer, myGeoExtent)

        # Check the output is valid
        assert os.path.exists(myResult)
        read_layer(myResult)

        # Clip the raster to the bbox
        myResult = clipLayer(myRasterLayer, myGeoExtent)

        # Check the output is valid
        assert os.path.exists(myResult)
        read_layer(myResult)

        # -------------------------------
        # Check the extra keywords option
        # -------------------------------
        # Clip the vector to the bbox
        myResult = clipLayer(myVectorLayer, myGeoExtent,
                             extraKeywords={'kermit': 'piggy'})

        # Check the output is valid
        assert os.path.exists(myResult)
        L = read_layer(myResult)
        kwds = L.get_keywords()
        msg = 'Extra keyword was not found in %s: %s' % (myResult, kwds)
        assert kwds['kermit'] == 'piggy'

        # Clip the raster to the bbox
        myResult = clipLayer(myRasterLayer, myGeoExtent,
                             extraKeywords={'zoot': 'animal'})

        # Check the output is valid
        assert os.path.exists(myResult)
        L = read_layer(myResult)
        kwds = L.get_keywords()

        msg = 'Extra keyword was not found in %s: %s' % (myResult, kwds)
        assert kwds['zoot'] == 'animal', msg