def test_get_raster_data(self):
        """Test that raster data can be retrieved from server and read into Python Raster object.
        """

        for coverage_name, reference_range in [('shakemap_padang_20090930', [3.025794, 8.00983]),
                                               ('population_padang_1', [50., 1835.]),
                                               ('population_padang_2', [50., 1835.]), 
                                               ('fatality_padang_1', [4.08928e-07, 0.5672711486]),
                                               ('fatality_padang_2', [4.08928e-07, 1.07241])]:
    
            # Upload first to make sure data is there
            self.api.create_workspace(geoserver_username, geoserver_userpass, geoserver_url, test_workspace_name)

            lh = self.api.create_geoserver_layer_handle(geoserver_username, 
                                                        geoserver_userpass, 
                                                        geoserver_url, 
                                                        coverage_name,
                                                        test_workspace_name)

            upload_filename = 'data/%s.asc' % coverage_name
            res = self.api.upload_geoserver_layer(upload_filename, lh)
            assert res.startswith('SUCCESS'), res                
    
            # Get bounding box for the uploaded TIF file
            bounding_box = get_bounding_box('%s.tif' % coverage_name)
    
                            
            # Download using the API and test that the data is the same.
            raster = self.api.get_raster_data(lh,
                                              bounding_box)
                                             
        
            #ref_shape = (254, 250) # FIXME (Ole): This is what it should be
            ref_shape = (253, 249)  # but Geoserver shrinks it by one row and one column?????????
            
            data = raster.get_data(nan=True)
            
            shape = data.shape
            msg = 'Got shape %s, should have been %s' % (shape, ref_shape)        
            assert numpy.allclose(shape, ref_shape), msg
        
            # Now compare the numerical data
            reference_raster = read_coverage(upload_filename)
            ref_data = reference_raster.get_data(nan=True)
        
            # Range
            assert numpy.allclose([numpy.nanmin(ref_data[:]), numpy.nanmax(ref_data[:])], 
                                  reference_range)        
            assert numpy.allclose([numpy.nanmin(data[:]), numpy.nanmax(data[:])], 
                                  reference_range)
                           
            # Sum up (ignoring NaN) and compare
            refsum = numpy.nansum(numpy.abs(ref_data))
            actualsum = numpy.nansum(numpy.abs(data))            
            
            #print 
            #print 'Ref vs act and diff', refsum, actualsum, abs(refsum - actualsum), abs(refsum - actualsum)/refsum
            assert abs(refsum - actualsum)/refsum < 1.0e-2

            
            # Check that raster data can be written back (USING COMPLETE HACK)
            try:
                i += 1
            except:
                i = 0
                
            layername = 'stored_raster_%i' % i    
            output_file = 'data/%s.asc' % layername
            write_coverage_to_ascii(raster.data, output_file, 
                                    xllcorner = bounding_box[0],
                                    yllcorner = bounding_box[1],
                                    cellsize=0.030741064,
                                    nodata_value=-9999,
                                    projection=open('data/%s.prj' % coverage_name).read())
                                                
            # And upload it again
            lh = self.api.create_geoserver_layer_handle(geoserver_username, 
                                                        geoserver_userpass, 
                                                        geoserver_url, 
                                                        '',
                                                        test_workspace_name)

            self.api.upload_geoserver_layer(output_file, lh)
            
            # Check that layer is there
            found = False
            page = get_web_page(os.path.join(geoserver_url, 'rest/layers'), 
                                username=geoserver_username, 
                                password=geoserver_userpass)
            for line in page:
                if line.find('rest/layers/%s.html' % layername) > 0:
                    found = True
                                                                                                          
            assert found
Exemplo n.º 2
0
    def calculate(self, hazards, exposures, impact_function_id, impact, bounding_box, comment):
        """Calculate the Impact Geo as a function of Hazards and Exposures
        
        Arguments
            impact_function_id=Id of the impact function to be run 
                               (fully qualified path (from base path))
            hazards = A list of hazard levels .. [H1,H2..HN] each H is a geoserver layer path 
                      where each layer follows the format 
                      username:userpass@geoserver_url:layer_name 
                      (Look at REST for inspiration)
            exposure = A list of exposure levels ..[E1,E2...EN] each E is a 
                       geoserver layer path
            impact = Handle to output impact level layer
            bounding_box = ...
            comment = String with comment for output metadata
        
        Returns
            string: 'SUCCESS' if complete, otherwise Exception is raised

                     
        Note
            hazards and exposure may be lists of handles or just a single handle each.             
        """
        
        # Make sure hazards and exposures are lists
        if type(hazards) != type([]):
            hazards = [hazards]
            
        if type(exposures) != type([]):
            exposures = [exposures]            
        
        # Download data - FIXME(Ole): Currently only raster
        
        hazard_layers = []
        for hazard in hazards:
            raster = self.get_raster_data(hazard, bounding_box)
            H = raster.get_data()
            hazard_layers.append(H)

        exposure_layers = []
        for exposure in exposures:
            raster = self.get_raster_data(exposure, bounding_box)
            E = raster.get_data()
            exposure_layers.append(E)
                        
        # Pass hazard and exposure arrays on to plugin    
        # FIXME, for the time being we just calculate the fatality function assuming only one of each layer.
        
        H = hazard_layers[0]
        E = exposure_layers[0]

        # Calculate impact
        a = 0.97429
        b = 11.037
        F = 10**(a*H-b)*E    
        
        # Upload result (FIXME(Ole): still super hacky and not at all general)
        username, userpass, geoserver_url, layer_name, workspace = self.split_geoserver_layer_handle(impact)
        
        output_file = 'data/%s.asc' % layer_name
        write_coverage_to_ascii(F, output_file, 
                                xllcorner = bounding_box[0],
                                yllcorner = bounding_box[1],
                                cellsize=0.030741064,
                                nodata_value=-9999,
                                # FIXME(Ole): Need to get projection for haz and exp from GeoServer. For now use example.
                                projection=open('data/test_grid.prj').read()) 
                                                
        # And upload it again
        lh = self.create_geoserver_layer_handle(username, 
                                                userpass, 
                                                geoserver_url, 
                                                '',
                                                workspace)

        self.upload_geoserver_layer(output_file, lh)
        
        
        return 'SUCCES'