예제 #1
0
def raster_overlap(file_A, file_B, outpath, NoData_A=None, NoData_B=None):
    """
    Finds overlaping area between two raster images.
     
    this function examines two images and outputs a raster identifying pixels where both
    rasters have non-NoData values. Output raster has 1's where both images have data and
    0's where one or both images are missing data.

    inputs:
        file_A      the first file
        file_B      the second file
        outpath     the output filename for the desired output. must end in ".tif"
        NoData_A    the NoData value of file A
        NoData_B    the NoData value of file B

    This function automatically invokes
        clip_and_snap
        null_define
    """

    if not is_rast(file_A) or not is_rast(file_B):
        raise Exception(' both inputs must be rasters!')

    # load the rasters as numpy arays.
    a, metaA = to_numpy(file_A)
    b, metaB = to_numpy(file_B)

    # set no_datas
    if NoData_A is None:
        NoData_A = metaA.NoData_Value
    if NoData_B is None:
        NoData_B = metaB.NoData_Value

    # spatially match the rasters
    print('preparing input rasters!')
    clip_and_snap(file_A, file_B, outpath.replace(".shp", ".tif"), NoData_B)

    # reload the rasters as numpy arrays now that spatial matching is done
    a, metaA = to_numpy(file_A)
    b, metaB = to_numpy(file_B)

    # create work matrix and find the overlap
    print('Finding overlaping pixels!')
    Workmatrix = a.mask + b.mask
    Workmatrix = Workmatrix.astype('uint8')
    Workmatrix[Workmatrix == 1] = 2

    print('Saving overlap file!')
    metaA.numpy_datatype = 'uint8'
    from_numpy(Workmatrix,
               metaA,
               outpath.replace(".shp", ".tif"),
               NoData_Value=2)
    arcpy.RasterToPolygon_conversion(outpath.replace(".shp", ".tif"),
                                     outpath.replace(".tif", ".shp"),
                                     'NO_SIMPLIFY')

    return metaA, metaB
예제 #2
0
def raster_overlap(file_A, file_B, outpath, NoData_A = None, NoData_B = None):
    """
    Finds overlaping area between two raster images. this function examines
    two images and outputs a raster identifying pixels where both rasters have
    non-NoData values. Output raster has 1's where both images have data and
    0's where one or both images are missing data.

    :param file_A:      the first file
    :param file_B:      the second file
    :param outpath:     the output filename for the desired output. must end in ".tif"
    :param NoData_A:    the NoData value of file A
    :param NoData_B:    the NoData value of file B

    :return outpath:    filepath to raster created by this function.

    This function automatically invokes
        * clip_and_snap
        * null_define
    """
    
    if not is_rast(file_A) or not is_rast(file_B):
        raise Exception('both inputs must be rasters!')


    # load the rasters as numpy arays.
    a, metaA = to_numpy(file_A)
    b, metaB = to_numpy(file_B)

    # set no_datas
    if NoData_A is None:
        NoData_A = metaA.NoData_Value
    if NoData_B is None:
        NoData_B = metaB.NoData_Value

    # spatially match the rasters
    print('preparing input rasters!')
    clip_and_snap(file_A, file_B, outpath.replace(".shp",".tif"), NoData_B)

    # reload the rasters as numpy arrays now that spatial matching is done
    a, metaA = to_numpy(file_A)
    b, metaB = to_numpy(file_B)

    # create work matrix and find the overlap
    print('Finding overlaping pixels!')
    Workmatrix = a.mask + b.mask
    Workmatrix = Workmatrix.astype('uint8')
    Workmatrix[Workmatrix == 1] = 2
                
    print('Saving overlap file!')
    metaA.numpy_datatype = 'uint8'
    from_numpy(Workmatrix, metaA, outpath.replace(".shp",".tif"), NoData_Value = 2)
    arcpy.RasterToPolygon_conversion(outpath.replace(".shp",".tif"),
                                     outpath.replace(".tif",".shp"),
                                     'NO_SIMPLIFY')
    
    return outpath
예제 #3
0
def enf_rastlist(filelist):

    """
    ensures a list of inputs filepaths contains only valid raster types
    """

    # first place the input through the same requirements of any filelist
    filelist        = core.enf_filelist(filelist)
    new_filelist    = []

    for filename in filelist:

        if os.path.isfile(filename):
            if is_rast(filename):
                new_filelist.append(filename)

    return new_filelist
예제 #4
0
def enf_rastlist(filelist):

    """
    ensures a list of inputs filepaths contains only valid raster types
    """

    # first place the input through the same requirements of any filelist
    filelist        = core.enf_filelist(filelist)
    new_filelist    = []

    for filename in filelist:

        if os.path.isfile(filename):
            if is_rast(filename):
                new_filelist.append(filename)

    return new_filelist
예제 #5
0
def enf_rastlist(filelist):
    """
    Ensures a list of inputs filepaths contains only valid raster types

    :param filelist:        a list of filepaths that contains some raster filetypes
    :return new_filelist:   a list of filepaths with all non-raster files removed
    """

    # first place the input through the same requirements of any filelist
    filelist        = core.enf_filelist(filelist)
    new_filelist    = []

    for filename in filelist:

        if os.path.isfile(filename):
            if is_rast(filename):
                new_filelist.append(filename)

    return new_filelist
예제 #6
0
파일: to_numpy.py 프로젝트: tklug26/dnppy
def to_numpy(raster, numpy_datatype = None):

    """
    Wrapper for arcpy.RasterToNumpyArray with better metadata handling
    
     This is just a wraper for the RasterToNumPyArray function within arcpy, but it also
     extracts out all the spatial referencing information that will probably be needed
     to save the raster after desired manipulations have been performed.
     also see raster.from_numpy function in this module.

     inputs:
       Raster              Any raster supported by the arcpy.RasterToNumPyArray function
       numpy_datatype      must be a string equal to any of the types listed at the following
                           address [http://docs.scipy.org/doc/numpy/user/basics.types.html]
                           for example: 'uint8' or 'int32' or 'float32'
     outputs:
       numpy_rast          the numpy array version of the input raster
       Metadata            An object with the following attributes.
           .Xmin            the left edge
           .Ymin            the bottom edge
           .Xmax            the right edge
           .Ymax            the top edge
           .Xsize           the number of columns
           .Ysize           the number of rows
           .cellWidth       resolution in x direction
           .cellHeight      resolution in y direction
           .projection      the projection information to give the raster
           .NoData_Value    the numerical value which represents NoData in this raster

     Usage example:
       call this function with  " rast,Metadata = to_numpy(Raster) "
       perform numpy manipulations as you please
       then save the array with " raster.from_numpy(rast,Metadata,output)   "
    """

    # create a metadata object and assign attributes to it


    # read in the raster as an array
    if is_rast(raster):

        numpy_rast  = arcpy.RasterToNumPyArray(raster)
        ys, xs      = numpy_rast.shape
        meta        = metadata(raster, xs, ys)

        if numpy_datatype is None:
            numpy_datatype = meta.numpy_datatype

        numpy_rast = numpy_rast.astype(numpy_datatype)

        # mask NoData values from the array
        if 'float' in numpy_datatype:
            numpy_rast[numpy_rast == meta.NoData_Value] = numpy.nan
            numpy_rast = numpy.ma.masked_array(numpy_rast, numpy.isnan(numpy_rast),
                                               dtype = numpy_datatype)

        elif 'int' in numpy_datatype: # (numpy.nan not supported by ints)
            mask = numpy.zeros(numpy_rast.shape)
            mask[numpy_rast != meta.NoData_Value] = False    # do not mask
            mask[numpy_rast == meta.NoData_Value] = True     # mask
            numpy_rast = numpy.ma.masked_array(numpy_rast, mask,
                                               dtype = numpy_datatype)

    else:  
        raise Exception("Raster '{0}'does not exist".format(raster))

    return numpy_rast, meta
예제 #7
0
def project_resample(filelist,
                     reference_file,
                     outdir=False,
                     resampling_type=None,
                     cell_size=None):
    """
    Wrapper for multiple arcpy projecting functions. Projects to reference file
    
     Inputs a filelist and a reference file, then projects all rasters or feature classes
     in the filelist to match the projection of the reference file. Writes new files with a
     "_p" appended to the end of the input filenames. This also will perform resampling.

     Inputs:
       filelist            list of files to be projected
       outdir              optional desired output directory. If none is specified, output files
                           will be named with '_p' as a suffix.
       reference_file      Either a file with the desired projection, or a .prj file.
       resampling type     exactly as the input for arcmaps project_Raster_management function
       cell_size           exactly as the input for arcmaps project_Raster_management function

     Output:
       Spatial reference   spatial referencing information for further checking.
    """

    output_filelist = []
    # sanitize inputs
    core.exists(reference_file)

    rasterlist = enf_rastlist(filelist)
    featurelist = core.enf_featlist(filelist)
    cleanlist = rasterlist + featurelist

    # ensure output directory exists
    if not os.path.exists(outdir):
        os.makedirs(outdir)

    # grab data about the spatial reference of the reference file. (prj or otherwise)
    if reference_file[-3:] == 'prj':
        Spatial_Reference = arcpy.SpatialReference(reference_file)
    else:
        Spatial_Reference = arcpy.Describe(reference_file).spatialReference

        # determine cell size
        if cell_size is None:
            cx = arcpy.GetRasterProperties_management(reference_file,
                                                      "CELLSIZEX").getOutput(0)
            cy = arcpy.GetRasterProperties_management(reference_file,
                                                      "CELLSIZEY").getOutput(0)
            cell_size = "{0} {1}".format(cx, cy)

    # determine wether coordinate system is projected or geographic and print info
    if Spatial_Reference.type == 'Projected':
        print('Found {0} projected coord system'.format(
            Spatial_Reference.PCSName))
    else:
        print('Found {0} geographic coord system'.format(
            Spatial_Reference.GCSName))

    for filename in cleanlist:

        # create the output filename
        outname = core.create_outname(outdir, filename, 'p')
        output_filelist.append(Spatial_Reference)

        # use ProjectRaster_management for rast files
        if is_rast(filename):
            arcpy.ProjectRaster_management(filename, outname,
                                           Spatial_Reference, resampling_type,
                                           cell_size)
            print('Wrote projected and resampled file to {0}'.format(outname))

        # otherwise, use Project_management for featureclasses and featurelayers
        else:
            arcpy.Project_management(filename, outname, Spatial_Reference)
            print('Wrote projected file to {0}'.format(outname))

    print("finished projecting!")
    return output_filelist
예제 #8
0
def to_numpy(raster, numpy_datatype = None):

    """
    Wrapper for arcpy.RasterToNumpyArray with better metadata handling
    
     This is just a wraper for the RasterToNumPyArray function within arcpy, but it also
     extracts out all the spatial referencing information that will probably be needed
     to save the raster after desired manipulations have been performed.
     also see raster.from_numpy function in this module.

     inputs:
       Raster              Any raster supported by the arcpy.RasterToNumPyArray function
       numpy_datatype      must be a string equal to any of the types listed at the following
                           address [http://docs.scipy.org/doc/numpy/user/basics.types.html]
                           for example: 'uint8' or 'int32' or 'float32'
     outputs:
       numpy_rast          the numpy array version of the input raster
       Metadata            An object with the following attributes.
           .Xmin            the left edge
           .Ymin            the bottom edge
           .Xmax            the right edge
           .Ymax            the top edge
           .Xsize           the number of columns
           .Ysize           the number of rows
           .cellWidth       resolution in x direction
           .cellHeight      resolution in y direction
           .projection      the projection information to give the raster
           .NoData_Value    the numerical value which represents NoData in this raster

     Usage example:
       call this function with  " rast,Metadata = to_numpy(Raster) "
       perform numpy manipulations as you please
       then save the array with " raster.from_numpy(rast,Metadata,output)   "
    """

    # create a metadata object and assign attributes to it


    # perform some checks to convert to supported data format
    if not is_rast(raster):
        try:
            print("Raster '{0}' may not be supported, converting to tif".format(raster))
            tifraster = raster + ".tif"
            if not os.path.exists(raster + ".tif"):
                arcpy.CompositeBands_management(raster, tifraster)

            raster = tifraster
        except:
            raise Exception("Raster type could not be recognized")


    # read in the raster as a numpy array
    numpy_rast  = arcpy.RasterToNumPyArray(raster)

    # build metadata for multi band raster
    if len(numpy_rast.shape) == 3:
        zs, ys, xs  = numpy_rast.shape
        meta = []

        for i in range(zs):
            bandpath = raster + "\\Band_{0}".format(i+1)
            meta.append(metadata(bandpath, xs, ys))

        if numpy_datatype is None:
            numpy_datatype = meta[0].numpy_datatype


    # build metadata for single band raster
    else:
        ys, xs  = numpy_rast.shape
        meta  = metadata(raster, xs, ys)

        if numpy_datatype is None:
            numpy_datatype = meta.numpy_datatype

    numpy_rast = numpy_rast.astype(numpy_datatype)

    # mask NoData values from the array
    if 'float' in numpy_datatype:
        numpy_rast[numpy_rast == meta.NoData_Value] = numpy.nan
        numpy_rast = numpy.ma.masked_array(numpy_rast, numpy.isnan(numpy_rast),
                                           dtype = numpy_datatype)

    elif 'int' in numpy_datatype: # (numpy.nan not supported by ints)
        mask = numpy.zeros(numpy_rast.shape)
        mask[numpy_rast != meta.NoData_Value] = False    # do not mask
        mask[numpy_rast == meta.NoData_Value] = True     # mask
        numpy_rast = numpy.ma.masked_array(numpy_rast, mask,
                                           dtype = numpy_datatype)


    return numpy_rast, meta
예제 #9
0
def gap_fill_interpolate(in_rasterpath,
                         out_rasterpath,
                         model=None,
                         max_cell_dist=None,
                         min_points=None):
    """
    Fills gaps in raster data by spatial kriging interpolation. This should only
    be used to fill small gaps in continuous datasets (like a DEM), and in
    instances where it makes sense. This function creates a feature class
    layer of points where pixels are not NoData, then performs a "kriging"
    interpolation on the point data to rebuild a uniform grid with a value
    at every location, thus filling gaps.

    WARNING: This script is processing intensive and may take a while to run
    even for modestly sized datasets.

    :param in_rasterpath:   input filepath to raster to fill gaps
    :param out_rasterpath:  filepath to store output gap filled raster in
    :param model:           type of kriging model to run, options include
                            "SPHERICAL", "CIRCULAR", "EXPONENTIAL",
                            "GAUSSIAN", and "LINEAR"
    :param max_cell_dist:   The maximum number of cells to interpolate between,
                            data gaps which do not have at least "min_points"
                            points within this distance will not be filled.
    :param min_points:      Minimum number of surrounding points to use in determining
                            value at missing cell.

    :return out_rasterpath: Returns path to file created by this function
    """

    # check inputs
    if not is_rast(in_rasterpath):
        raise Exception(
            "input raster path {0} is invalid!".format(in_rasterpath))

    if max_cell_dist is None:
        max_cell_dist = 10

    if min_points is None:
        min_points = 4

    if model is None:
        model = "SPHERICAL"

    # set environments
    arcpy.env.overwriteOutput = True
    arcpy.env.snapRaster = in_rasterpath
    arcpy.CheckOutExtension("Spatial")

    # make a point shapefile version of input raster
    print("Creating point grid from input raster")
    head, tail = os.path.split(in_rasterpath)
    shp_path = core.create_outname(head, tail, "shp", "shp")
    dbf_path = shp_path.replace(".shp", ".dbf")
    field = "GRID_CODE"

    arcpy.RasterToPoint_conversion(in_rasterpath, shp_path, "VALUE")

    # find the bad rows who GRID_CODE is 1, these should be NoData
    print("Finding points with NoData entries")
    bad_row_FIDs = []

    rows = arcpy.UpdateCursor(dbf_path)

    for row in rows:
        grid_code = getattr(row, field)
        if grid_code == 1:
            bad_row_FIDs.append(row.FID)
    del rows

    # go back through the list and perform the deletions
    numbad = len(bad_row_FIDs)
    print("Deleting {0} points with NoData values".format(numbad))
    rows = arcpy.UpdateCursor(dbf_path)
    for i, row in enumerate(rows):
        if row.FID in bad_row_FIDs:
            rows.deleteRow(row)

    # set up the parameters for kriging
    print("Setting up for kriging")

    _, meta = to_numpy(in_rasterpath)

    model = model
    cell_size = meta.cellHeight  # from input raster
    lagSize = None
    majorRange = None
    partialSill = None
    nugget = None
    distance = float(cell_size) * float(max_cell_dist)  # fn input
    min_points = min_points  # fn input

    a = arcpy.sa.KrigingModelOrdinary()
    kmodel = arcpy.sa.KrigingModelOrdinary("SPHERICAL",
                                           lagSize=lagSize,
                                           majorRange=majorRange,
                                           partialSill=partialSill,
                                           nugget=nugget)

    kradius = arcpy.sa.RadiusFixed(distance=distance,
                                   minNumberOfPoints=min_points)

    # execute kriging
    print("Performing interpolation by kriging, this may take a while!")
    outkriging = arcpy.sa.Kriging(shp_path,
                                  field,
                                  kmodel,
                                  cell_size=cell_size,
                                  search_radius=kradius)
    outkriging.save(out_rasterpath)

    return out_rasterpath
예제 #10
0
def project_resample(filelist, reference_file, outdir = False,
                   resampling_type = None, cell_size = None):

    """
    Wrapper for multiple arcpy projecting functions. Projects to reference file
    
     Inputs a filelist and a reference file, then projects all rasters or feature classes
     in the filelist to match the projection of the reference file. Writes new files with a
     "_p" appended to the end of the input filenames. This also will perform resampling.

     Inputs:
       filelist            list of files to be projected
       outdir              optional desired output directory. If none is specified, output files
                           will be named with '_p' as a suffix.
       reference_file      Either a file with the desired projection, or a .prj file.
       resampling type     exactly as the input for arcmaps project_Raster_management function
       cell_size           exactly as the input for arcmaps project_Raster_management function

     Output:
       Spatial reference   spatial referencing information for further checking.
    """

    output_filelist = []
    # sanitize inputs
    core.exists(reference_file)
           
    rasterlist  = enf_rastlist(filelist)
    featurelist = core.enf_featlist(filelist)
    cleanlist   = rasterlist + featurelist

    # ensure output directory exists
    if not os.path.exists(outdir):
        os.makedirs(outdir)
        
    # grab data about the spatial reference of the reference file. (prj or otherwise)
    if reference_file[-3:]=='prj':
        Spatial_Reference = arcpy.SpatialReference(reference_file)
    else:
        Spatial_Reference = arcpy.Describe(reference_file).spatialReference

        # determine cell size
        if cell_size is None:
            cx = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEX").getOutput(0)
            cy = arcpy.GetRasterProperties_management(reference_file, "CELLSIZEY").getOutput(0)
            cell_size = "{0} {1}".format(cx,cy)

        
    # determine wether coordinate system is projected or geographic and print info
    if Spatial_Reference.type == 'Projected':
        print('Found {0} projected coord system'.format(Spatial_Reference.PCSName))
    else:
        print('Found {0} geographic coord system'.format(Spatial_Reference.GCSName))


    for filename in cleanlist:
        
        # create the output filename
        outname = core.create_outname(outdir, filename, 'p')
        output_filelist.append(Spatial_Reference)

        # use ProjectRaster_management for rast files
        if is_rast(filename):
            arcpy.ProjectRaster_management(filename,
                        outname, Spatial_Reference, resampling_type, cell_size)
            print('Wrote projected and resampled file to {0}'.format(outname))
                
        # otherwise, use Project_management for featureclasses and featurelayers
        else:
            arcpy.Project_management(filename,outname,Spatial_Reference)
            print('Wrote projected file to {0}'.format(outname))

    print("finished projecting!")
    return output_filelist
예제 #11
0
def gap_fill_interpolate(in_rasterpath, out_rasterpath, model = None,
                         max_cell_dist = None, min_points = None):
    """
    Fills gaps in raster data by spatial kriging interpolation. This should only
    be used to fill small gaps in continuous datasets (like a DEM), and in
    instances where it makes sense. This function creates a feature class
    layer of points where pixels are not NoData, then performs a "kriging"
    interpolation on the point data to rebuild a uniform grid with a value
    at every location, thus filling gaps.

    WARNING: This script is processing intensive and may take a while to run
    even for modestly sized datasets.

    :param in_rasterpath:   input filepath to raster to fill gaps
    :param out_rasterpath:  filepath to store output gap filled raster in
    :param model:           type of kriging model to run, options include
                            "SPHERICAL", "CIRCULAR", "EXPONENTIAL",
                            "GAUSSIAN", and "LINEAR"
    :param max_cell_dist:   The maximum number of cells to interpolate between,
                            data gaps which do not have at least "min_points"
                            points within this distance will not be filled.
    :param min_points:      Minimum number of surrounding points to use in determining
                            value at missing cell.

    :return out_rasterpath: Returns path to file created by this function
    """

    # check inputs
    if not is_rast(in_rasterpath):
        raise Exception("input raster path {0} is invalid!".format(in_rasterpath))

    if max_cell_dist is None:
        max_cell_dist = 10

    if min_points is None:
        min_points = 4

    if model is None:
        model = "SPHERICAL"

    # set environments
    arcpy.env.overwriteOutput = True
    arcpy.env.snapRaster = in_rasterpath
    arcpy.CheckOutExtension("Spatial")


    # make a point shapefile version of input raster
    print("Creating point grid from input raster")
    head, tail = os.path.split(in_rasterpath)
    shp_path = core.create_outname(head, tail, "shp", "shp")
    dbf_path = shp_path.replace(".shp",".dbf")
    field = "GRID_CODE"

    arcpy.RasterToPoint_conversion(in_rasterpath, shp_path, "VALUE")

    # find the bad rows who GRID_CODE is 1, these should be NoData
    print("Finding points with NoData entries")
    bad_row_FIDs = []

    rows = arcpy.UpdateCursor(dbf_path)

    for row in rows:
        grid_code = getattr(row, field)
        if grid_code == 1:
            bad_row_FIDs.append(row.FID)
    del rows

    # go back through the list and perform the deletions
    numbad = len(bad_row_FIDs)
    print("Deleting {0} points with NoData values".format(numbad))
    rows = arcpy.UpdateCursor(dbf_path)
    for i, row in enumerate(rows):
        if row.FID in bad_row_FIDs:
            rows.deleteRow(row)

    # set up the parameters for kriging
    print("Setting up for kriging")

    _, meta = to_numpy(in_rasterpath)

    model       = model
    cell_size   = meta.cellHeight                           # from input raster
    lagSize     = None
    majorRange  = None
    partialSill = None
    nugget      = None
    distance    = float(cell_size) * float(max_cell_dist)   # fn input
    min_points  = min_points                                # fn input

    a = arcpy.sa.KrigingModelOrdinary()
    kmodel = arcpy.sa.KrigingModelOrdinary("SPHERICAL",
                                           lagSize = lagSize,
                                           majorRange = majorRange,
                                           partialSill = partialSill,
                                           nugget = nugget)

    kradius = arcpy.sa.RadiusFixed(distance = distance,
                                   minNumberOfPoints = min_points)

    # execute kriging
    print("Performing interpolation by kriging, this may take a while!")
    outkriging = arcpy.sa.Kriging(shp_path, field, kmodel,
                                  cell_size = cell_size,
                                  search_radius = kradius)
    outkriging.save(out_rasterpath)

    return out_rasterpath
예제 #12
0
def to_numpy(raster, numpy_datatype=None):
    """
    Wrapper for arcpy.RasterToNumpyArray with better metadata handling
    
     This is just a wraper for the RasterToNumPyArray function within arcpy, but it also
     extracts out all the spatial referencing information that will probably be needed
     to save the raster after desired manipulations have been performed.
     also see raster.from_numpy function in this module.

     inputs:
       Raster              Any raster supported by the arcpy.RasterToNumPyArray function
       numpy_datatype      must be a string equal to any of the types listed at the following
                           address [http://docs.scipy.org/doc/numpy/user/basics.types.html]
                           for example: 'uint8' or 'int32' or 'float32'
     outputs:
       numpy_rast          the numpy array version of the input raster
       Metadata            An object with the following attributes.
           .Xmin            the left edge
           .Ymin            the bottom edge
           .Xmax            the right edge
           .Ymax            the top edge
           .Xsize           the number of columns
           .Ysize           the number of rows
           .cellWidth       resolution in x direction
           .cellHeight      resolution in y direction
           .projection      the projection information to give the raster
           .NoData_Value    the numerical value which represents NoData in this raster

     Usage example:
       call this function with  " rast,Metadata = to_numpy(Raster) "
       perform numpy manipulations as you please
       then save the array with " raster.from_numpy(rast,Metadata,output)   "
    """

    # create a metadata object and assign attributes to it

    # perform some checks to convert to supported data format
    if not is_rast(raster):
        try:
            print(
                "Raster '{0}' may not be supported, converting to tif".format(
                    raster))
            tifraster = raster + ".tif"
            if not os.path.exists(raster + ".tif"):
                arcpy.CompositeBands_management(raster, tifraster)

            raster = tifraster
        except:
            raise Exception("Raster type could not be recognized")

    # read in the raster as a numpy array
    numpy_rast = arcpy.RasterToNumPyArray(raster)

    # build metadata for multi band raster
    if len(numpy_rast.shape) == 3:
        zs, ys, xs = numpy_rast.shape
        meta = []

        for i in range(zs):
            bandpath = raster + "\\Band_{0}".format(i + 1)
            meta.append(metadata(bandpath, xs, ys))

        if numpy_datatype is None:
            numpy_datatype = meta[0].numpy_datatype

    # build metadata for single band raster
    else:
        ys, xs = numpy_rast.shape
        meta = metadata(raster, xs, ys)

        if numpy_datatype is None:
            numpy_datatype = meta.numpy_datatype

    numpy_rast = numpy_rast.astype(numpy_datatype)

    # mask NoData values from the array
    if 'float' in numpy_datatype:
        numpy_rast[numpy_rast == meta.NoData_Value] = numpy.nan
        numpy_rast = numpy.ma.masked_array(numpy_rast,
                                           numpy.isnan(numpy_rast),
                                           dtype=numpy_datatype)

    elif 'int' in numpy_datatype:  # (numpy.nan not supported by ints)
        mask = numpy.zeros(numpy_rast.shape)
        mask[numpy_rast != meta.NoData_Value] = False  # do not mask
        mask[numpy_rast == meta.NoData_Value] = True  # mask
        numpy_rast = numpy.ma.masked_array(numpy_rast,
                                           mask,
                                           dtype=numpy_datatype)

    return numpy_rast, meta
예제 #13
0
def to_numpy(raster, numpy_datatype = None):

    """
    Wrapper for arcpy.RasterToNumpyArray with better metadata handling

    This is just a wraper for the RasterToNumPyArray function within arcpy, but it also
    extracts out all the spatial referencing information that will probably be needed
    to save the raster after desired manipulations have been performed.
    also see raster.from_numpy function in this module.

    :param raster:         Any raster supported by the arcpy.RasterToNumPyArray function
    :param numpy_datatype: must be a string equal to any of the types listed at the following
                           address [http://docs.scipy.org/doc/numpy/user/basics.types.html]
                           for example: 'uint8' or 'int32' or 'float32'

    :return numpy_rast:   the numpy array version of the input raster
    :return Metadata:     a metadata object. see ``raster.metadata``
    """

    # perform some checks to convert to supported data format
    if not is_rast(raster):
        try:
            print("Raster '{0}' may not be supported, converting to tif".format(raster))
            tifraster = raster + ".tif"
            if not os.path.exists(raster + ".tif"):
                arcpy.CompositeBands_management(raster, tifraster)

            raster = tifraster
        except:
            raise Exception("Raster type could not be recognized")


    # read in the raster as a numpy array
    numpy_rast  = arcpy.RasterToNumPyArray(raster)

    # build metadata for multi band raster
    if len(numpy_rast.shape) == 3:
        zs, ys, xs  = numpy_rast.shape
        meta = []

        for i in range(zs):
            bandpath = raster + "\\Band_{0}".format(i+1)
            meta.append(metadata(bandpath, xs, ys))

        if numpy_datatype is None:
            numpy_datatype = meta[0].numpy_datatype


    # build metadata for single band raster
    else:
        ys, xs  = numpy_rast.shape
        meta  = metadata(raster, xs, ys)

        if numpy_datatype is None:
            numpy_datatype = meta.numpy_datatype

    numpy_rast = numpy_rast.astype(numpy_datatype)

    # mask NoData values from the array
    if 'float' in numpy_datatype:
        numpy_rast[numpy_rast == meta.NoData_Value] = numpy.nan
        numpy_rast = numpy.ma.masked_array(numpy_rast, numpy.isnan(numpy_rast),
                                           dtype = numpy_datatype)

    elif 'int' in numpy_datatype: # (numpy.nan not supported by ints)
        mask = numpy.zeros(numpy_rast.shape)
        mask[numpy_rast != meta.NoData_Value] = False    # do not mask
        mask[numpy_rast == meta.NoData_Value] = True     # mask
        numpy_rast = numpy.ma.masked_array(numpy_rast, mask,
                                           dtype = numpy_datatype)

    return numpy_rast, meta
예제 #14
0
def to_numpy(raster, numpy_datatype=None):
    """
    Wrapper for arcpy.RasterToNumpyArray with better metadata handling

    This is just a wraper for the RasterToNumPyArray function within arcpy, but it also
    extracts out all the spatial referencing information that will probably be needed
    to save the raster after desired manipulations have been performed.
    also see raster.from_numpy function in this module.

    :param raster:         Any raster supported by the arcpy.RasterToNumPyArray function
    :param numpy_datatype: must be a string equal to any of the types listed at the following
                           address [http://docs.scipy.org/doc/numpy/user/basics.types.html]
                           for example: 'uint8' or 'int32' or 'float32'

    :return numpy_rast:   the numpy array version of the input raster
    :return Metadata:     a metadata object. see ``raster.metadata``
    """

    # perform some checks to convert to supported data format
    if not is_rast(raster):
        try:
            print(
                "Raster '{0}' may not be supported, converting to tif".format(
                    raster))
            tifraster = raster + ".tif"
            if not os.path.exists(raster + ".tif"):
                arcpy.CompositeBands_management(raster, tifraster)

            raster = tifraster
        except:
            raise Exception("Raster type could not be recognized")

    # read in the raster as a numpy array
    numpy_rast = arcpy.RasterToNumPyArray(raster)

    # build metadata for multi band raster
    if len(numpy_rast.shape) == 3:
        zs, ys, xs = numpy_rast.shape
        meta = []

        for i in range(zs):
            bandpath = raster + "\\Band_{0}".format(i + 1)
            meta.append(metadata(bandpath, xs, ys))

        if numpy_datatype is None:
            numpy_datatype = meta[0].numpy_datatype

    # build metadata for single band raster
    else:
        ys, xs = numpy_rast.shape
        meta = metadata(raster, xs, ys)

        if numpy_datatype is None:
            numpy_datatype = meta.numpy_datatype

    numpy_rast = numpy_rast.astype(numpy_datatype)

    # mask NoData values from the array
    if 'float' in numpy_datatype:
        numpy_rast[numpy_rast == meta.NoData_Value] = numpy.nan
        numpy_rast = numpy.ma.masked_array(numpy_rast,
                                           numpy.isnan(numpy_rast),
                                           dtype=numpy_datatype)

    elif 'int' in numpy_datatype:  # (numpy.nan not supported by ints)
        mask = numpy.zeros(numpy_rast.shape)
        mask[numpy_rast != meta.NoData_Value] = False  # do not mask
        mask[numpy_rast == meta.NoData_Value] = True  # mask
        numpy_rast = numpy.ma.masked_array(numpy_rast,
                                           mask,
                                           dtype=numpy_datatype)

    return numpy_rast, meta