Beispiel #1
0
def endmembers_by_query(rast, query, gt, wkt, dd=False):
    '''
    Returns a list of endmember locations based on a provided query, e.g.:
    > query = rast[1,...] < -25 # Band 2 should be less than -25
    > endmembers_by_query(rast, query, gt, wkt)
    Arguments:
        rast    The raster array to find endmembers within
        query   A NumPy boolean array representing a query in the feature space
        gt      The GDAL GeoTransform
        wkt     The GDAL WKT projection
        dd      True for coordinates in decimal degrees
    '''
    assert isinstance(rast, np.ndarray), 'Requires a NumPy array'
    shp = rast.shape
    idx = np.indices((shp[-2], shp[-1]))

    # Execute query on the indices (pixel locations), then return the coordinates
    return list(
        pixel_to_xy([(x, y) for y, x in idx[:, query].T], gt, wkt, dd=dd))
Beispiel #2
0
    def get_idx_as_kml(self, path, gt, wkt, data_dict=None):
        '''
        Exports a KML file containing the locations of the extracted endmembers
        as point markers.
        '''
        # Despite that the HSI cube is the transpose of our raster array, the
        #   coordinates returned by `get_idx()` are already in the right order
        #   (longitude, latitude) because the (m by n) == (y by x) order
        #   transposed is (n by m) == (x by y); the row index is the latitude
        #   and the column index is the longitude.
        coords = pixel_to_xy(self.get_idx(), gt=gt, wkt=wkt, dd=True)

        if any(map(lambda x: x[0] == 0 and x[1] == 0, self.get_idx())):
            print('Warning: Target endmember chosen at (0,0)')
            print('One or more endmembers may be photometric shade')

        if data_dict is None:
            data_dict = {
                'wavelength': range(1,
                                    len(coords) + 1),
                'wavelength units': 'MNF Component',
                'z plot titles': ['', '']
            }

        ico = 'http://maps.google.com/mapfiles/kml/paddle/%i.png'
        pmarks = []
        for i, pair in enumerate(coords):
            pmarks.append(
                KML.Placemark(
                    KML.Style(KML.IconStyle(KML.Icon(KML.href(ico %
                                                              (i + 1))))),
                    KML.name(data_dict['wavelength units'] + ' %d' % (i + 1)),
                    KML.Point(KML.coordinates('%f,%f' % pair))))

        doc = KML.kml(KML.Folder(*pmarks))
        with open(path, 'wb') as source:
            source.write(etree.tostring(doc, pretty_print=True))
Beispiel #3
0
    def get_idx_as_shp(self, path, gt, wkt):
        '''
        Exports a Shapefile containing the locations of the extracted
        endmembers. Assumes the coordinates are in decimal degrees.
        '''
        coords = pixel_to_xy(self.get_idx(), gt=gt, wkt=wkt, dd=True)

        driver = ogr.GetDriverByName('ESRI Shapefile')
        ds = driver.CreateDataSource(path)
        srs = osr.SpatialReference()
        srs.ImportFromEPSG(4326)

        layer = ds.CreateLayer(path.split('.')[0], srs, ogr.wkbPoint)
        for pair in coords:
            feature = ogr.Feature(layer.GetLayerDefn())

            # Create the point from the Well Known Text
            point = ogr.CreateGeometryFromWkt('POINT(%f %f)' % pair)
            feature.SetGeometry(point)  # Set the feature geometry
            layer.CreateFeature(feature)  # Create the feature in the layer
            feature.Destroy()  # Destroy the feature to free resources

        # Destroy the data source to free resources
        ds.Destroy()
Beispiel #4
0
    def on_draw(self, output_dir=None):
        def get_data_in_selection(c1, c2):
            condition = np.logical_and(c1, c2).reshape(shp2)
            # Get the X and Y pixel coordinates within the bounding boxes
            cx = ravel_and_filter(np.where(condition, xdata, nodata_array).T,
                                  nodata=self.__nodata__)
            cy = ravel_and_filter(np.where(condition, ydata, nodata_array).T,
                                  nodata=self.__nodata__)

            # Zip the X and Y arrays into an X,Y array
            # NOTE: We flip the Y and X here because the `xdata` are column
            #   indices and `ydata` are row indices, but as pixel coordinates
            #   the row number is a Y-axis cordinate, column number is
            #   an X-axis coordinate
            return np.dstack((cy[:, 0], cx[:, 0]))

        shp = self.features.shape
        shp2 = (shp[0], shp[1], 1)  # Shape for a single band
        # Array of X coordinates
        xdata = np.repeat([np.arange(0, shp[1])], shp[0], axis=0).reshape(shp2)
        # Array of Y coordinates
        ydata = np.repeat([np.arange(0, shp[0])], shp[1],
                          axis=0).T.reshape(shp2)
        nodata_array = np.ones(shp2) * self.__nodata__  # Make NoData array
        tmp = self.features.reshape((shp[0] * shp[1], shp[-1]))

        # Start with top-left, end with bottom-right
        if self.x0 < self.x1:
            if self.y0 > self.y1:
                selection = get_data_in_selection(
                    np.logical_and(tmp[:, 0] > self.x0, tmp[:, 1] < self.y0),
                    np.logical_and(tmp[:, 0] < self.x1, tmp[:, 1] > self.y1))

            # Start with bottom-left, end with top-right
            else:
                selection = get_data_in_selection(
                    np.logical_and(tmp[:, 0] > self.x0, tmp[:, 1] > self.y0),
                    np.logical_and(tmp[:, 0] < self.x1, tmp[:, 1] < self.y1))

        # Start with bottom-right, end with top-left
        else:
            if self.y0 < self.y1:
                selection = get_data_in_selection(
                    np.logical_and(tmp[:, 0] < self.x0, tmp[:, 1] > self.y0),
                    np.logical_and(tmp[:, 0] > self.x1, tmp[:, 1] < self.y1))

            # Start with top-right, end with bottom-left
            else:
                selection = get_data_in_selection(
                    np.logical_and(tmp[:, 0] < self.x0, tmp[:, 1] < self.y0),
                    np.logical_and(tmp[:, 0] > self.x1, tmp[:, 1] > self.y1))

        # Limit to N random features
        if selection.shape[1] >= self.__sel_limit__:
            rfeatures = np.random.choice(np.arange(0, selection.shape[1]),
                                         size=self.__sel_limit__,
                                         replace=False)
            rfeatures.sort(
            )  # Make it easier to get iterate through them in order
            selection = selection[:, rfeatures, :]

        file_path = os.path.join(
            (output_dir or self.__wd__), 'FeatureSpace_selection_%s_%d' %
            ((self.keyword or ''), self.__drawing_index__))
        points = pixel_to_xy(selection[0, :],
                             self.__gt__,
                             self.__wkt__,
                             dd=False)
        points_dd = pixel_to_xy(selection[0, :],
                                self.__gt__,
                                self.__wkt__,
                                dd=True)

        # If a source EPSG is known, convert the output to KML
        if self.epsg is not None:
            # Convert to WGS 84
            poly_geom = point_to_pixel_geometry(points,
                                                source_epsg=self.epsg,
                                                target_epsg=4326)

            # We want to create Placemarks with both a Point and
            #   a Polygon geometry in each
            pmarks = []
            for i, poly in enumerate(poly_geom):
                pm = KML_POLY_TEMPLATE % (
                    ','.join(map(str,
                                 points[i])),  # The (projected) coordinates
                    '<Point><coordinates>%f,%f</coordinates></Point>' %
                    points_dd[i],
                    poly.ExportToKML()  # The KML Polygon feature
                )
                pmarks.append(pm)
            doc = KML_DOC_TEMPLATE % (KML_POLY_STYLE, ''.join(pmarks))
            # Write out the coordinates as a KML file
            with open('%s.kml' % file_path, 'w') as stream:
                stream.write(doc)

            if self.__verbose__:
                sys.stdout.write(
                    "Wrote selection's coordinates in geographic space to: %s.kml\n"
                    % file_path)

        else:
            sys.stdout.write(
                "Warning: Source SRS not known; cannot output KML file\n")