Example #1
0
def create_blank_file(input_filename, output_filename, value=255):
    '''
    following example in 
    http://geoexamples.blogspot.com/2012/12/raster-calculations-with-gdal-and-numpy.html

    Created GeoTiff format file called output_filename
    with same properties as input_filename.
    
    Limitations: this version limited to single band copy
    but could easily be extended by user

    input_filename  : string. Name of input file
    output_filename : string. Name of output file
    '''
    # open input and get data
    g = gdal.Open(input_filename, gdal.GA_ReadOnly)
    inband = g.GetRasterBand(1)
    indata = inband.ReadAsArray()
    # declare and open output and get data
    driver = gdal.GetDriverByName("GTiff")
    gOut = driver.Create(output_filename, \
             g.RasterXSize, g.RasterYSize, \
             1, inband.DataType, options=['COMPRESS=LZW'])
    outband = gOut.GetRasterBand(1)

    # write value to output
    # and copy other info
    gdalnumeric.BandWriteArray(outband, value + indata * 0)
    gdalnumeric.CopyDatasetInfo(g, gOut)

    # close the file
    del gOut
    return (output_filename)
Example #2
0
def create_images():
    source_folder = 'source_tiffs'
    source_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                               source_folder)

    if not os.path.exists(source_path):
        os.mkdir(source_path)

    gdal_driver = gdal.GetDriverByName(OUTPUT_FORMAT)

    for tile_name, tile_values in TILES.items():
        output_file_name = os.path.join(source_folder, tile_name)

        if os.path.isfile(output_file_name):
            os.remove(output_file_name)

        output_file = gdal_driver.Create(
            output_file_name,
            tile_x,
            tile_y,
            tile_bands,
            gdal.GDT_Int16  # Int16 to enable NoData value of -999
        )

        output_file.SetGeoTransform(GEO_TRANSFORM[tile_name])
        output_file.SetProjection(TileMerger.SOURCE_FILE_PROJECTION)

        target_band = output_file.GetRasterBand(tile_bands)
        target_band.SetNoDataValue(2550)  # From MODSCAG spec
        gdalnumeric.BandWriteArray(target_band, tile_values)

        del target_band
        del output_file
Example #3
0
def raster_file(tmp_input_path):
    file_name = str(tmp_input_path / FILE_NAME)
    output_file = GDAL_DRIVER.Create(file_name, BAND_VALUES.shape[1],
                                     BAND_VALUES.shape[0], gdal.GDT_Byte)

    output_file.SetGeoTransform(GEO_TRANSFORM)
    output_file.SetProjection(PROJECTION.ExportToWkt())

    target_band = output_file.GetRasterBand(1)
    target_band.SetNoDataValue(NO_DATA_VALUE)
    gdalnumeric.BandWriteArray(target_band, BAND_VALUES)

    del target_band
    del output_file

    return file_name
Example #4
0
    def copy_into(self, output_file, source_band=1, target_band=1):
        """
        Copy data to target file and filter according to the type given in
        the initializer.

        output_file -- gdal.Dataset object for the file into which some or all
        of this file may be copied.
        """
        t_geotransform = output_file.GetGeoTransform()
        t_ulx = t_geotransform[0]
        t_uly = t_geotransform[3]
        t_pixel_width = t_geotransform[1]
        t_pixel_height = t_geotransform[5]

        # Intersection region
        tgw_ulx = max(t_ulx, self.ulx)
        if t_pixel_height < 0:
            tgw_uly = min(t_uly, self.uly)
        else:
            tgw_uly = max(t_uly, self.uly)

        # Target window in pixel coordinates.
        tw_xoff = int((tgw_ulx - t_ulx) / t_pixel_width + 0.1)
        tw_yoff = int((tgw_uly - t_uly) / t_pixel_height + 0.1)

        source_file = gdal.Open(self.filename, gdalconst.GA_ReadOnly)

        target_band = output_file.GetRasterBand(target_band)

        source_values = gdalnumeric.BandReadAsArray(
            source_file.GetRasterBand(source_band),
            buf_type=gdal.GDT_Float32
        )

        no_data_value = target_band.GetNoDataValue()
        # Filter by upper and lower band threshold values
        source_values[source_values < self.lower_limit] = no_data_value
        source_values[source_values > self.upper_limit] = no_data_value

        gdalnumeric.BandWriteArray(
            target_band, source_values, xoff=tw_xoff, yoff=tw_yoff
        )

        del source_values
        del source_file
Example #5
0
    def __copy_band_data(self):
        target_band = self.output_file.GetRasterBand(self.BAND_NUMBER)
        target_band.SetNoDataValue(self.BAND_NO_DATA_VALUE)

        source_values = gdalnumeric.BandReadAsArray(
            self.mosaic_vrt.GetRasterBand(self.BAND_NUMBER),
            buf_type=self.BAND_DATA_TYPE,
        )

        # Filter by upper and lower band threshold values
        source_values[(source_values < self.lower_limit) | (
            source_values > self.upper_limit)] = self.BAND_NO_DATA_VALUE

        gdalnumeric.BandWriteArray(target_band, source_values)
        target_band.FlushCache()
        target_band.SetMetadata(self.BAND_METADATA[self.source_type])

        del target_band
        del source_values
Example #6
0
def merge_swe_with_sca(swe_file, sca_file):
    output_file_name = os.path.join(os.path.dirname(sca_file.GetDescription()),
                                    'SWE_by_SCA.tif')

    swe_by_sca = gdal.GetDriverByName('MEM').CreateCopy(
        output_file_name, sca_file, 0)
    swe_by_sca_band = swe_by_sca.GetRasterBand(1)

    modis_band = sca_file.GetRasterBand(1)
    sca_data = np.ma.masked_values(modis_band.ReadAsArray(),
                                   modis_band.GetNoDataValue(),
                                   copy=False)
    sca_data = sca_data / 100

    swe_band = swe_file.GetRasterBand(1)
    swe_data = np.ma.masked_values(swe_band.ReadAsArray(),
                                   swe_band.GetNoDataValue(),
                                   copy=False)

    gdalnumeric.BandWriteArray(swe_by_sca_band,
                               (sca_data * swe_data).astype(np.int16))

    swe_by_sca_band.SetMetadata({
        'Description': 'Snow Water Equivalent',
        'Unit': 'mm'
    })
    swe_by_sca_band.ComputeStatistics(0)
    swe_by_sca_band.FlushCache()

    del modis_band, sca_data
    del swe_band, swe_data
    del swe_by_sca_band

    # GDAL Translate is more efficient with compression for some unknown reason
    gdal.Translate(output_file_name,
                   swe_by_sca,
                   format='GTiff',
                   creationOptions=[
                       "COMPRESS=LZW", "TILED=YES", "BIGTIFF=IF_SAFER",
                       "NUM_THREADS=ALL_CPUS"
                   ])

    del swe_by_sca
Example #7
0
    def __hdf_to_tif(self):
        data = self.northern_swe()

        self._tif_file = self.GDAL_DRIVER.Create(
            os.path.join(self._file_dir, 'North_SWE_25k_nsidc.tif'),
            data.shape[1],
            data.shape[0],
            1,
            gdalconst.GDT_Int16,
        )
        self.tif_file.SetGeoTransform([
            self.NSIDC_NORTH_UL_X, self.SOURCE_SPAT_RES, 0,
            self.NSIDC_NORTH_UL_Y, 0, -self.SOURCE_SPAT_RES
        ])
        self.tif_file.SetProjection(self.NSIDC_EASE_GRID_NORTH.ExportToWkt())

        band = self.tif_file.GetRasterBand(1)
        band.SetNoDataValue(self.NO_DATA_VALUE)
        gdalnumeric.BandWriteArray(band, data)

        band.FlushCache()

        del data
        del band
Example #8
0
    def writeRasterFileFromNumpy(self, pOutNumpy_, outFileName_,
                                 pInitRasterFile_):
        """
        Program description: 

        INPUT_PARAMETERS:
        inputValue_      - 

        COMMENTS:
        """

        #Write Gdal file from numpy array
        outRasterFileName = tkFileDialog.asksaveasfilename(
            defaultextension='TIFF',
            filetypes=[('TIFF', '*.tif')],
            initialdir=self.workspace,
            initialfile=outFileName_,
            parent=tkRoot,
            title='Save output raster file (GDAL)')

        #!!! Only for TIFF, one Numpy band and Float data implemented here
        pDriver = gdal.GetDriverByName("GTiff")
        pOutRasterDataset = pDriver.Create(
            outRasterFileName, pInitRasterFile_.RasterXSize,
            pInitRasterFile_.RasterYSize, 1,
            GDT_Float32)  #New file, settings from original file
        gdalnumeric.CopyDatasetInfo(
            pInitRasterFile_, pOutRasterDataset
        )  #Copy metadata information from original file to new file
        gdalnumeric.BandWriteArray(pOutRasterDataset.GetRasterBand(1),
                                   pOutNumpy_)  # Copy numpy-data to new file

        #Close datasets
        pOutRasterDataset = None

        return
Example #9
0
def doit(opts, args):
    # pylint: disable=unused-argument

    if opts.debug:
        print("gdal_calc.py starting calculation %s" % (opts.calc))

    # set up global namespace for eval with all functions of gdalnumeric
    global_namespace = dict([(key, getattr(gdalnumeric, key))
                             for key in dir(gdalnumeric) if not key.startswith('__')])
    if opts.user_namespace:
        global_namespace.update(opts.user_namespace)

    if not opts.calc:
        raise Exception("No calculation provided.")
    elif not opts.outF and opts.format.upper() != 'MEM':
        raise Exception("No output file provided.")

    if opts.format is None:
        opts.format = GetOutputDriverFor(opts.outF)

    if not hasattr(opts, "color_table"):
        opts.color_table = None
    if not opts.extent:
        opts.extent = EXTENT_IGNORE
    else:
        opts.extent = parse_extent(opts.extent)

    compatible_gt_eps = 0.000001
    gt_diff_support = {
        GT_INCOMPATIBLE_OFFSET: opts.extent != EXTENT_FAIL,
        GT_INCOMPATIBLE_PIXEL_SIZE: False,
        GT_INCOMPATIBLE_ROTATION: False,
        GT_NON_ZERO_ROTATION: False,
    }
    gt_diff_error = {
        GT_INCOMPATIBLE_OFFSET: 'different offset',
        GT_INCOMPATIBLE_PIXEL_SIZE: 'different pixel size',
        GT_INCOMPATIBLE_ROTATION: 'different rotation',
        GT_NON_ZERO_ROTATION: 'non zero rotation',
    }

    ################################################################
    # fetch details of input layers
    ################################################################

    # set up some lists to store data for each band
    myFileNames = []  # input filenames
    myFiles = []  # input DataSets
    myBands = []  # input bands
    myAlphaList = []  # input alpha letter that represents each input file
    myDataType = []  # string representation of the datatype of each input file
    myDataTypeNum = []  # datatype of each input file
    myNDV = []  # nodatavalue for each input file
    DimensionsCheck = None  # dimensions of the output
    Dimensions = []  # Dimensions of input files
    ProjectionCheck = None  # projection of the output
    GeoTransformCheck = None  # GeoTransform of the output
    GeoTransforms = []  # GeoTransform of each input file
    GeoTransformDiffer = False  # True if we have inputs with different GeoTransforms
    myTempFileNames = []  # vrt filename from each input file
    myAlphaFileLists = []  # list of the Alphas which holds a list of inputs

    # loop through input files - checking dimensions
    for alphas, filenames in opts.input_files.items():
        if isinstance(filenames, (list, tuple)):
            # alpha is a list of files
            myAlphaFileLists.append(alphas)
        elif is_path_like(filenames) or isinstance(filenames, gdal.Dataset):
            # alpha is a single filename or a Dataset
            filenames = [filenames]
            alphas = [alphas]
        else:
            # I guess this alphas should be in the global_namespace,
            # It would have been better to pass it as user_namepsace, but I'll accept it anyway
            global_namespace[alphas] = filenames
            continue
        for alpha, filename in zip(alphas*len(filenames), filenames):
            if not alpha.endswith("_band"):
                # check if we have asked for a specific band...
                if "%s_band" % alpha in opts.input_files:
                    myBand = opts.input_files["%s_band" % alpha]
                else:
                    myBand = 1

                myF_is_ds = not is_path_like(filename)
                if myF_is_ds:
                    myFile = filename
                    filename = None
                else:
                    filename = str(filename)
                    myFile = gdal.Open(filename, gdal.GA_ReadOnly)
                if not myFile:
                    raise IOError("No such file or directory: '%s'" % filename)

                myFileNames.append(filename)
                myFiles.append(myFile)
                myBands.append(myBand)
                myAlphaList.append(alpha)
                dt = myFile.GetRasterBand(myBand).DataType
                myDataType.append(gdal.GetDataTypeName(dt))
                myDataTypeNum.append(dt)
                myNDV.append(None if opts.hideNoData else myFile.GetRasterBand(myBand).GetNoDataValue())

                # check that the dimensions of each layer are the same
                myFileDimensions = [myFile.RasterXSize, myFile.RasterYSize]
                if DimensionsCheck:
                    if DimensionsCheck != myFileDimensions:
                        GeoTransformDiffer = True
                        if opts.extent in [EXTENT_IGNORE, EXTENT_FAIL]:
                            raise Exception("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" %
                                            (filename, myFileDimensions[0], myFileDimensions[1], DimensionsCheck[0], DimensionsCheck[1]))
                else:
                    DimensionsCheck = myFileDimensions

                # check that the Projection of each layer are the same
                myProjection = myFile.GetProjection()
                if ProjectionCheck:
                    if opts.projectionCheck and ProjectionCheck != myProjection:
                        raise Exception(
                            "Error! Projection of file %s %s are different from other files %s.  Cannot proceed" %
                            (filename, myProjection, ProjectionCheck))
                else:
                    ProjectionCheck = myProjection

                # check that the GeoTransforms of each layer are the same
                myFileGeoTransform = myFile.GetGeoTransform(can_return_null=True)
                if opts.extent == EXTENT_IGNORE:
                    GeoTransformCheck = myFileGeoTransform
                else:
                    Dimensions.append(myFileDimensions)
                    GeoTransforms.append(myFileGeoTransform)
                    if not GeoTransformCheck:
                        GeoTransformCheck = myFileGeoTransform
                    else:
                        my_gt_diff = gt_diff(GeoTransformCheck, myFileGeoTransform, eps=compatible_gt_eps, diff_support=gt_diff_support)
                        if my_gt_diff not in [GT_SAME, GT_ALMOST_SAME]:
                            GeoTransformDiffer = True
                            if my_gt_diff not in [GT_COMPATIBLE_DIFF]:
                                raise Exception(
                                    "Error! GeoTransform of file {} {} is incompatible ({}), first file GeoTransform is {}. Cannot proceed".
                                        format(filename, myFileGeoTransform, gt_diff_error[my_gt_diff], GeoTransformCheck))
                if opts.debug:
                    print("file %s: %s, dimensions: %s, %s, type: %s" % (
                        alpha, filename, DimensionsCheck[0], DimensionsCheck[1], myDataType[-1]))

    # process allBands option
    allBandsIndex = None
    allBandsCount = 1
    if opts.allBands:
        if len(opts.calc) > 1:
            raise Exception("Error! --allBands implies a single --calc")
        try:
            allBandsIndex = myAlphaList.index(opts.allBands)
        except ValueError:
            raise Exception("Error! allBands option was given but Band %s not found.  Cannot proceed" % (opts.allBands))
        allBandsCount = myFiles[allBandsIndex].RasterCount
        if allBandsCount <= 1:
            allBandsIndex = None
    else:
        allBandsCount = len(opts.calc)

    if opts.extent not in [EXTENT_IGNORE, EXTENT_FAIL] and (GeoTransformDiffer or not isinstance(opts.extent, EXTENT)):
        raise Exception('Error! mixing different GeoTransforms/Extents is not supported yet.')

    ################################################################
    # set up output file
    ################################################################

    # open output file exists
    if opts.outF and os.path.isfile(opts.outF) and not opts.overwrite:
        if allBandsIndex is not None:
            raise Exception("Error! allBands option was given but Output file exists, must use --overwrite option!")
        if len(opts.calc) > 1:
            raise Exception("Error! multiple calc options were given but Output file exists, must use --overwrite option!")
        if opts.debug:
            print("Output file %s exists - filling in results into file" % (opts.outF))

        myOut = gdal.Open(opts.outF, gdal.GA_Update)
        if myOut is None:
            error = 'but cannot be opened for update'
        elif [myOut.RasterXSize, myOut.RasterYSize] != DimensionsCheck:
            error = 'but is the wrong size'
        elif ProjectionCheck and ProjectionCheck != myOut.GetProjection():
            error = 'but is the wrong projection'
        elif GeoTransformCheck and GeoTransformCheck != myOut.GetGeoTransform(can_return_null=True):
            error = 'but is the wrong geotransform'
        else:
            error = None
        if error:
            raise Exception("Error! Output exists, %s.  Use the --overwrite option to automatically overwrite the existing file" % error)

        myOutB = myOut.GetRasterBand(1)
        myOutNDV = myOutB.GetNoDataValue()
        myOutType = myOutB.DataType

    else:
        if opts.outF:
            # remove existing file and regenerate
            if os.path.isfile(opts.outF):
                os.remove(opts.outF)
            # create a new file
            if opts.debug:
                print("Generating output file %s" % (opts.outF))
        else:
            opts.outF = ''

        # find data type to use
        if not opts.type:
            # use the largest type of the input files
            myOutType = max(myDataTypeNum)
        else:
            myOutType = opts.type
            if isinstance(myOutType, str):
                myOutType = gdal.GetDataTypeByName(myOutType)

        # create file
        myOutDrv = gdal.GetDriverByName(opts.format)
        myOut = myOutDrv.Create(
            opts.outF, DimensionsCheck[0], DimensionsCheck[1], allBandsCount,
            myOutType, opts.creation_options)

        # set output geo info based on first input layer
        if not GeoTransformCheck:
            GeoTransformCheck = myFiles[0].GetGeoTransform(can_return_null=True)
        if GeoTransformCheck:
            myOut.SetGeoTransform(GeoTransformCheck)

        if not ProjectionCheck:
            ProjectionCheck = myFiles[0].GetProjection()
        if ProjectionCheck:
            myOut.SetProjection(ProjectionCheck)

        if opts.NoDataValue is None:
            myOutNDV = None if opts.hideNoData else DefaultNDVLookup[myOutType]  # use the default noDataValue for this datatype
        elif isinstance(opts.NoDataValue, str) and opts.NoDataValue.lower() == 'none':
            myOutNDV = None  # not to set any noDataValue
        else:
            myOutNDV = opts.NoDataValue  # use the given noDataValue

        for i in range(1, allBandsCount + 1):
            myOutB = myOut.GetRasterBand(i)
            if myOutNDV is not None:
                myOutB.SetNoDataValue(myOutNDV)
            if opts.color_table:
                # set color table and color interpretation
                if is_path_like(opts.color_table):
                    raise Exception('Error! reading a color table from a file is not supported yet')
                myOutB.SetRasterColorTable(opts.color_table)
                myOutB.SetRasterColorInterpretation(gdal.GCI_PaletteIndex)

            myOutB = None  # write to band

    myOutTypeName = gdal.GetDataTypeName(myOutType)
    if opts.debug:
        print("output file: %s, dimensions: %s, %s, type: %s" % (opts.outF, myOut.RasterXSize, myOut.RasterYSize, myOutTypeName))

    ################################################################
    # find block size to chop grids into bite-sized chunks
    ################################################################

    # use the block size of the first layer to read efficiently
    myBlockSize = myFiles[0].GetRasterBand(myBands[0]).GetBlockSize()
    # find total x and y blocks to be read
    nXBlocks = (int)((DimensionsCheck[0] + myBlockSize[0] - 1) / myBlockSize[0])
    nYBlocks = (int)((DimensionsCheck[1] + myBlockSize[1] - 1) / myBlockSize[1])
    myBufSize = myBlockSize[0] * myBlockSize[1]

    if opts.debug:
        print("using blocksize %s x %s" % (myBlockSize[0], myBlockSize[1]))

    # variables for displaying progress
    ProgressCt = -1
    ProgressMk = -1
    ProgressEnd = nXBlocks * nYBlocks * allBandsCount

    ################################################################
    # start looping through each band in allBandsCount
    ################################################################

    for bandNo in range(1, allBandsCount + 1):

        ################################################################
        # start looping through blocks of data
        ################################################################

        # store these numbers in variables that may change later
        nXValid = myBlockSize[0]
        nYValid = myBlockSize[1]

        # loop through X-lines
        for X in range(0, nXBlocks):

            # in case the blocks don't fit perfectly
            # change the block size of the final piece
            if X == nXBlocks - 1:
                nXValid = DimensionsCheck[0] - X * myBlockSize[0]

            # find X offset
            myX = X * myBlockSize[0]

            # reset buffer size for start of Y loop
            nYValid = myBlockSize[1]
            myBufSize = nXValid * nYValid

            # loop through Y lines
            for Y in range(0, nYBlocks):
                ProgressCt += 1
                if 10 * ProgressCt / ProgressEnd % 10 != ProgressMk and not opts.quiet:
                    ProgressMk = 10 * ProgressCt / ProgressEnd % 10
                    from sys import version_info
                    if version_info >= (3, 0, 0):
                        exec('print("%d.." % (10*ProgressMk), end=" ")')
                    else:
                        exec('print 10*ProgressMk, "..",')

                # change the block size of the final piece
                if Y == nYBlocks - 1:
                    nYValid = DimensionsCheck[1] - Y * myBlockSize[1]
                    myBufSize = nXValid * nYValid

                # find Y offset
                myY = Y * myBlockSize[1]

                # create empty buffer to mark where nodata occurs
                myNDVs = None

                # make local namespace for calculation
                local_namespace = {}

                val_lists = defaultdict(list)

                # fetch data for each input layer
                for i, Alpha in enumerate(myAlphaList):

                    # populate lettered arrays with values
                    if allBandsIndex is not None and allBandsIndex == i:
                        myBandNo = bandNo
                    else:
                        myBandNo = myBands[i]
                    myval = gdalnumeric.BandReadAsArray(myFiles[i].GetRasterBand(myBandNo),
                                                        xoff=myX, yoff=myY,
                                                        win_xsize=nXValid, win_ysize=nYValid)
                    if myval is None:
                        raise Exception('Input block reading failed from filename %s' % filename[i])

                    # fill in nodata values
                    if myNDV[i] is not None:
                        # myNDVs is a boolean buffer.
                        # a cell equals to 1 if there is NDV in any of the corresponding cells in input raster bands.
                        if myNDVs is None:
                            # this is the first band that has NDV set. we initializes myNDVs to a zero buffer
                            # as we didn't see any NDV value yet.
                            myNDVs = numpy.zeros(myBufSize)
                            myNDVs.shape = (nYValid, nXValid)
                        myNDVs = 1 * numpy.logical_or(myNDVs == 1, myval == myNDV[i])

                    # add an array of values for this block to the eval namespace
                    if Alpha in myAlphaFileLists:
                        val_lists[Alpha].append(myval)
                    else:
                        local_namespace[Alpha] = myval
                    myval = None

                for lst in myAlphaFileLists:
                    local_namespace[lst] = val_lists[lst]

                # try the calculation on the array blocks
                calc = opts.calc[bandNo-1 if len(opts.calc) > 1 else 0]
                try:
                    myResult = eval(calc, global_namespace, local_namespace)
                except:
                    print("evaluation of calculation %s failed" % (calc))
                    raise

                # Propagate nodata values (set nodata cells to zero
                # then add nodata value to these cells).
                if myNDVs is not None and myOutNDV is not None:
                    myResult = ((1 * (myNDVs == 0)) * myResult) + (myOutNDV * myNDVs)
                elif not isinstance(myResult, numpy.ndarray):
                    myResult = numpy.ones((nYValid, nXValid)) * myResult

                # write data block to the output file
                myOutB = myOut.GetRasterBand(bandNo)
                if gdalnumeric.BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY) != 0:
                    raise Exception('Block writing failed')
                myOutB = None  # write to band

    # remove temp files
    for idx, tempFile in enumerate(myTempFileNames):
        myFiles[idx] = None
        os.remove(tempFile)

    gdal.ErrorReset()
    myOut.FlushCache()
    if gdal.GetLastErrorMsg() != '':
        raise Exception('Dataset writing failed')

    if not opts.quiet:
        print("100 - Done")

    return myOut
Example #10
0
def doit(opts, args):
    # pylint: disable=unused-argument

    if opts.debug:
        print("gdal_calc.py starting calculation %s" % (opts.calc))

    # set up global namespace for eval with all functions of gdalnumeric
    global_namespace = dict([(key, getattr(gdalnumeric, key))
                             for key in dir(gdalnumeric) if not key.startswith('__')])

    if not opts.calc:
        raise Exception("No calculation provided.")
    elif not opts.outF:
        raise Exception("No output file provided.")

    if opts.format is None:
        opts.format = GetOutputDriverFor(opts.outF)

    ################################################################
    # fetch details of input layers
    ################################################################

    # set up some lists to store data for each band
    myFiles = []
    myBands = []
    myAlphaList = []
    myDataType = []
    myDataTypeNum = []
    myNDV = []
    DimensionsCheck = None

    # loop through input files - checking dimensions
    for myI, myF in opts.input_files.items():
        if not myI.endswith("_band"):
            # check if we have asked for a specific band...
            if "%s_band" % myI in opts.input_files:
                myBand = opts.input_files["%s_band" % myI]
            else:
                myBand = 1

            myFile = gdal.Open(myF, gdal.GA_ReadOnly)
            if not myFile:
                raise IOError("No such file or directory: '%s'" % myF)

            myFiles.append(myFile)
            myBands.append(myBand)
            myAlphaList.append(myI)
            myDataType.append(gdal.GetDataTypeName(myFile.GetRasterBand(myBand).DataType))
            myDataTypeNum.append(myFile.GetRasterBand(myBand).DataType)
            myNDV.append(myFile.GetRasterBand(myBand).GetNoDataValue())
            # check that the dimensions of each layer are the same
            if DimensionsCheck:
                if DimensionsCheck != [myFile.RasterXSize, myFile.RasterYSize]:
                    raise Exception("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" %
                                    (myF, myFile.RasterXSize, myFile.RasterYSize, DimensionsCheck[0], DimensionsCheck[1]))
            else:
                DimensionsCheck = [myFile.RasterXSize, myFile.RasterYSize]

            if opts.debug:
                print("file %s: %s, dimensions: %s, %s, type: %s" % (myI, myF, DimensionsCheck[0], DimensionsCheck[1], myDataType[-1]))

    # process allBands option
    allBandsIndex = None
    allBandsCount = 1
    if opts.allBands:
        try:
            allBandsIndex = myAlphaList.index(opts.allBands)
        except ValueError:
            raise Exception("Error! allBands option was given but Band %s not found.  Cannot proceed" % (opts.allBands))
        allBandsCount = myFiles[allBandsIndex].RasterCount
        if allBandsCount <= 1:
            allBandsIndex = None

    ################################################################
    # set up output file
    ################################################################

    # open output file exists
    if os.path.isfile(opts.outF) and not opts.overwrite:
        if allBandsIndex is not None:
            raise Exception("Error! allBands option was given but Output file exists, must use --overwrite option!")
        if opts.debug:
            print("Output file %s exists - filling in results into file" % (opts.outF))
        myOut = gdal.Open(opts.outF, gdal.GA_Update)
        if [myOut.RasterXSize, myOut.RasterYSize] != DimensionsCheck:
            raise Exception("Error! Output exists, but is the wrong size.  Use the --overwrite option to automatically overwrite the existing file")
        myOutB = myOut.GetRasterBand(1)
        myOutNDV = myOutB.GetNoDataValue()
        myOutType = gdal.GetDataTypeName(myOutB.DataType)

    else:
        # remove existing file and regenerate
        if os.path.isfile(opts.outF):
            os.remove(opts.outF)
        # create a new file
        if opts.debug:
            print("Generating output file %s" % (opts.outF))

        # find data type to use
        if not opts.type:
            # use the largest type of the input files
            myOutType = gdal.GetDataTypeName(max(myDataTypeNum))
        else:
            myOutType = opts.type

        # create file
        myOutDrv = gdal.GetDriverByName(opts.format)
        myOut = myOutDrv.Create(
            opts.outF, DimensionsCheck[0], DimensionsCheck[1], allBandsCount,
            gdal.GetDataTypeByName(myOutType), opts.creation_options)

        # set output geo info based on first input layer
        myOut.SetGeoTransform(myFiles[0].GetGeoTransform())
        myOut.SetProjection(myFiles[0].GetProjection())

        if opts.NoDataValue is not None:
            myOutNDV = opts.NoDataValue
        else:
            myOutNDV = DefaultNDVLookup[myOutType]

        for i in range(1, allBandsCount + 1):
            myOutB = myOut.GetRasterBand(i)
            myOutB.SetNoDataValue(myOutNDV)
            # write to band
            myOutB = None

    if opts.debug:
        print("output file: %s, dimensions: %s, %s, type: %s" % (opts.outF, myOut.RasterXSize, myOut.RasterYSize, myOutType))

    ################################################################
    # find block size to chop grids into bite-sized chunks
    ################################################################

    # use the block size of the first layer to read efficiently
    myBlockSize = myFiles[0].GetRasterBand(myBands[0]).GetBlockSize()
    # find total x and y blocks to be read
    nXBlocks = (int)((DimensionsCheck[0] + myBlockSize[0] - 1) / myBlockSize[0])
    nYBlocks = (int)((DimensionsCheck[1] + myBlockSize[1] - 1) / myBlockSize[1])
    myBufSize = myBlockSize[0] * myBlockSize[1]

    if opts.debug:
        print("using blocksize %s x %s" % (myBlockSize[0], myBlockSize[1]))

    # variables for displaying progress
    ProgressCt = -1
    ProgressMk = -1
    ProgressEnd = nXBlocks * nYBlocks * allBandsCount

    ################################################################
    # start looping through each band in allBandsCount
    ################################################################

    for bandNo in range(1, allBandsCount + 1):

        ################################################################
        # start looping through blocks of data
        ################################################################
        
        # store these numbers in variables that may change later
        nXValid = myBlockSize[0]
        nYValid = myBlockSize[1]

        # loop through X-lines
        for X in range(0, nXBlocks):

            # in case the blocks don't fit perfectly
            # change the block size of the final piece
            if X == nXBlocks - 1:
                nXValid = DimensionsCheck[0] - X * myBlockSize[0]

            # find X offset
            myX = X * myBlockSize[0]

            # reset buffer size for start of Y loop
            nYValid = myBlockSize[1]
            myBufSize = nXValid * nYValid

            # loop through Y lines
            for Y in range(0, nYBlocks):
                ProgressCt += 1
                if 10 * ProgressCt / ProgressEnd % 10 != ProgressMk and not opts.quiet:
                    ProgressMk = 10 * ProgressCt / ProgressEnd % 10
                    from sys import version_info
                    if version_info >= (3, 0, 0):
                        exec('print("%d.." % (10*ProgressMk), end=" ")')
                    else:
                        exec('print 10*ProgressMk, "..",')

                # change the block size of the final piece
                if Y == nYBlocks - 1:
                    nYValid = DimensionsCheck[1] - Y * myBlockSize[1]
                    myBufSize = nXValid * nYValid

                # find Y offset
                myY = Y * myBlockSize[1]

                # create empty buffer to mark where nodata occurs
                myNDVs = None

                # make local namespace for calculation
                local_namespace = {}

                # fetch data for each input layer
                for i, Alpha in enumerate(myAlphaList):

                    # populate lettered arrays with values
                    if allBandsIndex is not None and allBandsIndex == i:
                        myBandNo = bandNo
                    else:
                        myBandNo = myBands[i]
                    myval = gdalnumeric.BandReadAsArray(myFiles[i].GetRasterBand(myBandNo),
                                                        xoff=myX, yoff=myY,
                                                        win_xsize=nXValid, win_ysize=nYValid)

                    # fill in nodata values
                    if myNDV[i] is not None:
                        if myNDVs is None:
                            myNDVs = numpy.zeros(myBufSize)
                            myNDVs.shape = (nYValid, nXValid)
                        myNDVs = 1 * numpy.logical_or(myNDVs == 1, myval == myNDV[i])

                    # add an array of values for this block to the eval namespace
                    local_namespace[Alpha] = myval
                    myval = None

                # try the calculation on the array blocks
                try:
                    myResult = eval(opts.calc, global_namespace, local_namespace)
                except:
                    print("evaluation of calculation %s failed" % (opts.calc))
                    raise

                # Propagate nodata values (set nodata cells to zero
                # then add nodata value to these cells).
                if myNDVs is not None:
                    myResult = ((1 * (myNDVs == 0)) * myResult) + (myOutNDV * myNDVs)
                elif not isinstance(myResult, numpy.ndarray):
                    myResult = numpy.ones((nYValid, nXValid)) * myResult

                # write data block to the output file
                myOutB = myOut.GetRasterBand(bandNo)
                gdalnumeric.BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY)

    if not opts.quiet:
        print("100 - Done")
Example #11
0
def main():
    # initiate the parser
    parser = argparse.ArgumentParser(
        description='Summarize a set of rasters layers.')
    parser.add_argument('files', nargs='+', help='input raster file(s)')
    parser.add_argument('--outfile', '-o', required=True, help='output raster')
    band_help = 'bands to summarize. ' + \
        'single file: bands in this file to summarize (default all bands); ' + \
        'multiple files: bands in corresponding files to summarize (default = 1)'
    parser.add_argument('--bands', '-b', nargs='+', type=int, help=band_help)
    function_help = 'function to apply to cell values across layers.' + \
        'meannz gives a mean of the non-zero values.' + \
        'count counts the number layers with non-negative values for each cell.' + \
        'richness counts the number of layers with positive values for each cell.'
    parser.add_argument('--function',
                        '-f',
                        dest='summary_function',
                        default='mean',
                        choices=[
                            'mean', 'median', 'max', 'sum', 'meannz', 'count',
                            'richness'
                        ],
                        help="summarization function (default = 'mean')")
    parser.add_argument(
        '--block_size',
        '-s',
        nargs=2,
        type=int,
        help='x and y dimensions of blocks to process (default based on input)'
    )
    parser.add_argument(
        '--nrows',
        '-n',
        type=int,
        help=
        'number of rows to process in a single block (block_size ignored if provided)'
    )
    parser.add_argument('--overwrite',
                        '-w',
                        action="store_true",
                        help='overwrite existing file')
    parser.add_argument(
        '--creation-option',
        '--co',
        dest='creation_options',
        default=[],
        action='append',
        help=
        'passes one or more creation options to the output format driver multiple'
    )
    parser.add_argument('--quiet',
                        '-q',
                        action="store_true",
                        help='supress messages')

    # read arguments from the command line
    args = parser.parse_args()

    # summarize multiple bands of same file or bands across files
    if len(args.files) == 1:
        # use all bands if not specified
        if not args.bands:
            b = gdal.Open(args.files[0], gdal.GA_ReadOnly).RasterCount
            args.bands = [i for i in range(1, b + 1)]
        # elif len(args.bands) == 1:
        #     raise Exception('For a single input file, provide multiple bands to summarize over.')
        args.files = [args.files[0]] * len(args.bands)
    else:
        # use band 1 if not specified
        if not args.bands:
            args.bands = [1] * len(args.files)
        elif len(args.bands) == 1:
            args.bands = [args.bands[0]] * len(args.files)
        elif len(args.bands) != len(args.files):
            raise Exception(
                'The number of bands must be 1 or equal to the number of input files.'
            )

    # set up some default nodatavalues for each datatype
    ndv_lookup = {
        'Byte': 255,
        'UInt16': 65535,
        'Int16': -32767,
        'UInt32': 4294967293,
        'Int32': -2147483647,
        'Float32': 3.402823466E+38,
        'Float64': 1.7976931348623158E+308
    }

    stack = []
    in_type = []
    in_ndv = []
    raster_dim = None
    block_size = None
    out_transform = None
    out_projection = None
    # pass over files to get metadata and check arguments
    for i in range(len(args.files)):
        f = args.files[i]
        b = args.bands[i]
        s = gdal.Open(f, gdal.GA_ReadOnly)

        # check that file exists
        if not s:
            raise IOError('No such file or directory: {}'.format(f))

        # check that band is valid
        if b > s.RasterCount:
            raise IOError('Invalid band number ({}) for file: {}'.format(b, f))

        # get specified band
        r = s.GetRasterBand(b)

        # store raster file
        stack.append(s)

        # metadata
        in_type.append(r.DataType)
        dt_name = gdal.GetDataTypeName(r.DataType).lower()
        in_ndv.append(np.float64(r.GetNoDataValue()).astype(dt_name))

        # check that the dimensions of each layer are the same
        if raster_dim:
            if raster_dim != [s.RasterXSize, s.RasterYSize]:
                raise Exception('Input files have different dimensions.')
        else:
            raster_dim = [s.RasterXSize, s.RasterYSize]

        # block size to chop grids into bite-sized chunks
        if not block_size:
            # use the block size of the first layer to read efficiently
            # or use user provided block size
            if not args.nrows:
                if not args.block_size:
                    block_size = s.GetRasterBand(1).GetBlockSize()
                else:
                    # block size can't be larger than raster dimensions
                    block_size = np.minimum(args.block_size,
                                            raster_dim).tolist()
            else:
                block_size = [raster_dim[0], min(raster_dim[1], args.nrows)]

        # get geo info from first layer
        if not out_transform:
            out_transform = s.GetGeoTransform()
        if not out_projection:
            out_projection = s.GetProjection()

    # prepare output file
    if os.path.isfile(args.outfile) and not args.overwrite:
        raise Exception(
            "Output exists, use the --overwrite to overwrite the existing file"
        )
    else:
        # remove existing file and regenerate
        if os.path.isfile(args.outfile):
            os.remove(args.outfile)

        # for sum use the largest type of the input files
        # otherise use a value suitable for the function
        if args.summary_function == 'sum':
            out_type = gdal.GetDataTypeName(max(in_type))
            out_type_np = out_type.lower()
            np_nan = 0
        elif args.summary_function == 'mean':
            out_type = 'Float32'
            out_type_np = out_type.lower()
            np_nan = np.nan
        elif args.summary_function == 'median':
            out_type = 'Float32'
            out_type_np = out_type.lower()
            np_nan = np.nan
        elif args.summary_function == 'max':
            out_type = 'Float32'
            out_type_np = out_type.lower()
            np_nan = np.nan
        elif args.summary_function == 'meannz':
            out_type = 'Float32'
            out_type_np = out_type.lower()
            np_nan = np.nan
        elif args.summary_function == 'count':
            out_type = 'Int16'
            out_type_np = out_type.lower()
            np_nan = -1
        elif args.summary_function == 'richness':
            out_type = 'Int16'
            out_type_np = out_type.lower()
            np_nan = -1

        # create file
        out_driver = gdal.GetDriverByName('GTiff')
        r_out = out_driver.Create(args.outfile, raster_dim[0], raster_dim[1],
                                  1, gdal.GetDataTypeByName(out_type),
                                  args.creation_options)

        # set output geo info based on first input layer
        r_out.SetGeoTransform(out_transform)
        r_out.SetProjection(out_projection)

        # set no data value
        out_ndv = ndv_lookup[out_type]
        out_ndv_np = np.float64(out_ndv).astype(out_type_np)
        r_out.GetRasterBand(1).SetNoDataValue(out_ndv)

    # find total x and y blocks to be read
    xblocks = math.ceil(raster_dim[0] / block_size[0])
    yblocks = math.ceil(raster_dim[1] / block_size[1])

    # loop through blocks of data
    # store these numbers in variables that may change later
    xvalid = block_size[0]
    yvalid = block_size[1]

    # variables for displaying progress
    progress_cnt = -1
    progress_stp = 0
    progress_end = xblocks * yblocks
    progress_stps = [round(progress_end * i / 100) for i in range(0, 101, 10)]

    # message
    if not args.quiet:
        m = "Processing {} X {} raster (cols X rows) in {} blocks of {} X {}"
        m = m.format(raster_dim[0], raster_dim[1], xblocks * yblocks,
                     block_size[0], block_size[1])
        print(m)

    # loop through x dimension
    for x in range(0, xblocks):
        # in case the blocks don't fit perfectly
        # change the block size of the final piece
        if x == xblocks - 1:
            xvalid = raster_dim[0] - x * block_size[0]

        # find x offset
        x_off = x * block_size[0]

        # reset buffer size for start of Y loop
        yvalid = block_size[1]

        # loop through y dimension
        for y in range(0, yblocks):
            # progress bar
            progress_cnt += 1
            if progress_cnt == progress_stps[progress_stp] and not args.quiet:
                print('%d...' % (10 * progress_stp), end="", flush=True)
                progress_stp += 1

            # change the block size of the final piece
            if y == yblocks - 1:
                yvalid = raster_dim[1] - y * block_size[1]

            # find y offset
            y_off = y * block_size[1]

            # create empty buffer to mark where nodata occurs
            ndv_buffer = None

            # make array to store block
            block = np.empty(shape=(len(stack), yvalid, xvalid),
                             dtype='float32')

            # fetch data for each input layer
            for i in range(len(stack)):
                vals = gdalnumeric.BandReadAsArray(stack[i].GetRasterBand(
                    args.bands[i]),
                                                   xoff=x_off,
                                                   yoff=y_off,
                                                   win_xsize=xvalid,
                                                   win_ysize=yvalid)
                if out_type != "Int16":
                    vals = vals.astype(out_type_np)

                # fill in nodata values
                if in_ndv[i] is not None:
                    vals[vals == in_ndv[i]] = np_nan

                # add block to array
                block[i] = vals
                vals = None

            # ignore empty slice warnings
            with warnings.catch_warnings():
                warnings.simplefilter('ignore', category=RuntimeWarning)
                if args.summary_function == 'sum':
                    result = np.nansum(block, axis=0)
                elif args.summary_function == 'mean':
                    result = np.nanmean(block, axis=0)
                elif args.summary_function == 'median':
                    result = np.nanmedian(block, axis=0)
                elif args.summary_function == 'max':
                    result = np.nanmax(block, axis=0)
                elif args.summary_function == 'meannz':
                    block = np.ma.masked_equal(block, 0)
                    result = np.nanmean(block, axis=0)
                elif args.summary_function == 'count':
                    result = np.nansum(block >= 0, axis=0)
                elif args.summary_function == 'richness':
                    result = np.nansum(block > 0, axis=0)

            # replace nan with no data value
            result[np.isnan(result)] = out_ndv_np

            # write data block to the output file
            gdalnumeric.BandWriteArray(r_out.GetRasterBand(1),
                                       result,
                                       xoff=x_off,
                                       yoff=y_off)

    # end progress bar
    if not args.quiet:
        print('100 - Done')
    def run(self):

        self._abort = False

        self.progress.emit("Starting RasterBender", float(0), float(0))

        #####################################
        # Step 1 : create the delaunay mesh #
        #####################################

        self.progress.emit("Loading delaunay mesh...", float(0), float(0))

        # Create the delaunay triangulation
        triangles, pointsA, pointsB, hull, constraints = triangulate.triangulate(
            self.pairsLayer, self.pairsLimitToSelection, self.constraintsLayer,
            self.constraintsLimitToSelection, self.bufferValue)

        ###############################
        # Step 2. Opening the dataset #
        ###############################

        self.progress.emit(
            "Opening the dataset... This shouldn't be too long...", float(0),
            float(0))

        #Open the dataset
        gdal.UseExceptions()

        # Read the source data into numpy arrays
        dsSource = gdal.Open(self.sourcePath, gdal.GA_ReadOnly)

        sourceDataR = gdalnumeric.BandReadAsArray(dsSource.GetRasterBand(1))
        sourceDataG = gdalnumeric.BandReadAsArray(dsSource.GetRasterBand(2))
        sourceDataB = gdalnumeric.BandReadAsArray(dsSource.GetRasterBand(3))

        # Get the transformation
        pixW = float(dsSource.RasterXSize - 1)  #width in pixel
        pixH = float(dsSource.RasterYSize - 1)  #width in pixel
        mapW = float(dsSource.RasterXSize) * dsSource.GetGeoTransform()[
            1]  #width in map units
        mapH = float(dsSource.RasterYSize) * dsSource.GetGeoTransform()[
            5]  #width in map units
        offX = dsSource.GetGeoTransform()[0]  #offset in map units
        offY = dsSource.GetGeoTransform()[3]  #offset in map units

        # Open the target into numpy array
        #dsTarget = gdal.Open(self.targetPath, gdal.GA_Update )
        driver = gdal.GetDriverByName("GTiff")
        dsTarget = driver.CreateCopy(self.targetPath, dsSource, 0)
        #dsTarget.SetGeoTransform( dsSource.GetGeoTransform() )
        dsTarget = None  #close

        def xyToQgsPoint(x, y):
            return QgsPoint(offX + mapW * (x / pixW), offY + mapH * (y / pixH))

        def qgsPointToXY(qgspoint):
            return (int((qgspoint.x() - offX) / mapW * pixW),
                    int((qgspoint.y() - offY) / mapH * pixH))

        #######################################
        # Step 3A. Looping through the blocks #
        #######################################

        #Loop through every block
        blockCountX = dsSource.RasterXSize // self.blockSize + 1
        blockCountY = dsSource.RasterYSize // self.blockSize + 1
        blockCount = blockCountX * blockCountY
        blockI = 0

        displayTotal = dsSource.RasterXSize * dsSource.RasterYSize
        displayStep = min((self.blockSize**2) / 20,
                          10000)  # update gui every n steps

        self.progress.emit("Starting computation... This can take a while...",
                           float(0), float(0))

        for blockNumY in range(0, blockCountY):
            blockOffsetY = blockNumY * self.blockSize
            blockH = min(self.blockSize, dsSource.RasterYSize - blockOffsetY)
            if blockH <= 0: continue

            for blockNumX in range(0, blockCountX):
                blockOffsetX = blockNumX * self.blockSize
                blockW = min(self.blockSize,
                             dsSource.RasterXSize - blockOffsetX)
                if blockW <= 0: continue

                blockI += 1
                pixelCount = blockW * blockH
                pixelI = 0

                blockRectangle = QgsRectangle(
                    xyToQgsPoint(blockOffsetX, blockOffsetY),
                    xyToQgsPoint(blockOffsetX + blockW, blockOffsetY + blockH)
                )  # this is the shape of the block, used for optimization

                # We check if the block intersects the hull, if not, we skip it
                if not hull.intersects(blockRectangle):
                    self.progress.emit(
                        "Block %i out of %i is out of the convex hull, we skip it..."
                        % (blockI, blockCount), float(0),
                        float(blockI / float(blockCount)))
                    continue

                # We create the trifinder for the block
                blockTrifinder = trifinder.Trifinder(pointsB, triangles,
                                                     blockRectangle)

                targetDataR = gdalnumeric.BandReadAsArray(
                    dsSource.GetRasterBand(1), blockOffsetX, blockOffsetY,
                    blockW, blockH)
                targetDataG = gdalnumeric.BandReadAsArray(
                    dsSource.GetRasterBand(2), blockOffsetX, blockOffsetY,
                    blockW, blockH)
                targetDataB = gdalnumeric.BandReadAsArray(
                    dsSource.GetRasterBand(3), blockOffsetX, blockOffsetY,
                    blockW, blockH)

                #######################################
                # Step 3B. Looping through the pixels #
                #######################################

                # Loop through every pixel
                for y in range(0, blockH):
                    for x in range(0, blockW):
                        # If abort was called, we finish the process
                        if self._abort:
                            self.error.emit(
                                "Aborted on pixel %i out of %i on block %i out of %i..."
                                % (pixelI, pixelCount, blockI, blockCount),
                                float(0), float(0))
                            return

                        pixelI += 1

                        # Ever now and then, we update the status
                        if pixelI % displayStep == 0:
                            self.progress.emit(
                                "Working on pixel %i out of %i on block %i out of %i... Trifinder has %i triangles"
                                % (pixelI, pixelCount, blockI, blockCount,
                                   len(blockTrifinder.triangles)),
                                float(pixelI) / float(pixelCount),
                                float(blockI) / float(blockCount))

                        # We find in which triangle the point lies using the trifinder.
                        p = xyToQgsPoint(blockOffsetX + x, blockOffsetY + y)
                        tri = blockTrifinder.find(p)
                        if tri is None:
                            # If it's in no triangle, we don't change it
                            continue

                        # If it's in a triangle, we transform the coordinates
                        newP = trimapper.map(p, pointsB[tri[0]],
                                             pointsB[tri[1]], pointsB[tri[2]],
                                             pointsA[tri[0]], pointsA[tri[1]],
                                             pointsA[tri[2]])

                        newX, newY = qgsPointToXY(newP)

                        # TODO : this would maybe get interpolated results
                        #ident = sourceRaster.dataProvider().identify( pt, QgsRaster.IdentifyFormatValue)
                        #targetDataR[y][x] = ident.results()[1]
                        #targetDataG[y][x] = ident.results()[2]
                        #targetDataB[y][x] = ident.results()[3]

                        try:
                            if newY < 0 or newX < 0:
                                raise IndexError()  #avoid looping
                            targetDataR[y][x] = sourceDataR[newY][newX]
                            targetDataG[y][x] = sourceDataG[newY][newX]
                            targetDataB[y][x] = sourceDataB[newY][newX]
                        except IndexError, e:
                            targetDataR[y][x] = 0
                            targetDataG[y][x] = 0
                            targetDataB[y][x] = 0

                # Write to the image

                dsTarget = gdal.Open(self.targetPath, gdal.GA_Update)

                gdalnumeric.BandWriteArray(dsTarget.GetRasterBand(1),
                                           targetDataR, blockOffsetX,
                                           blockOffsetY)
                gdalnumeric.BandWriteArray(dsTarget.GetRasterBand(2),
                                           targetDataG, blockOffsetX,
                                           blockOffsetY)
                gdalnumeric.BandWriteArray(dsTarget.GetRasterBand(3),
                                           targetDataB, blockOffsetX,
                                           blockOffsetY)

                dsTarget = None
Example #13
0
def files_mean(file_array, filename_out):
    myFiles=[]
    myNDV=[]
    DimensionsCheck=None
    allBandsCount=1
    myOutNDV=-32767

    for (i, filename) in enumerate(file_array):
        if os.path.isfile(filename):
            myFile = gdal.Open(filename, gdal.GA_ReadOnly)
            if not myFile:
                raise IOError("No such file or directory: '%s'" % myFile)
            myFiles.append(myFile)
            myNDV.append(myFile.GetRasterBand(1).GetNoDataValue())
            if DimensionsCheck:
                if DimensionsCheck != [myFile.RasterXSize, myFile.RasterYSize]:
                    raise Exception("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" % (myF, myFile.RasterXSize, myFile.RasterYSize, DimensionsCheck[0], DimensionsCheck[1]))
            else:
                DimensionsCheck = [myFile.RasterXSize, myFile.RasterYSize]

    if os.path.isfile(filename_out):
        os.remove(filename_out)

    myBlockSize=myFiles[0].GetRasterBand(1).GetBlockSize();
    # store these numbers in variables that may change later
    nXValid = myBlockSize[0]
    nYValid = myBlockSize[1]
    # find total x and y blocks to be read
    nXBlocks = (int)((DimensionsCheck[0] + myBlockSize[0] - 1) / myBlockSize[0]);
    nYBlocks = (int)((DimensionsCheck[1] + myBlockSize[1] - 1) / myBlockSize[1]);
    myBufSize = myBlockSize[0]*myBlockSize[1]

    myOutDrv = gdal.GetDriverByName('GTiff')
    myOut = myOutDrv.Create(filename_out, DimensionsCheck[0], DimensionsCheck[1], 1,gdal.GDT_Float32)

    # set output geo info based on first input layer
    myOut.SetGeoTransform(myFiles[0].GetGeoTransform())
    myOut.SetProjection(myFiles[0].GetProjection())

    for bandNo in range(1,allBandsCount+1):
        for X in range(0,nXBlocks):
            if X==nXBlocks-1:
                nXValid = DimensionsCheck[0] - X * myBlockSize[0]
                myBufSize = nXValid*nYValid

            # find X offset
            myX=X*myBlockSize[0]

            # reset buffer size for start of Y loop
            nYValid = myBlockSize[1]
            myBufSize = nXValid*nYValid

            # loop through Y lines
            for Y in range(0,nYBlocks):
                # change the block size of the final piece
                if Y==nYBlocks-1:
                    nYValid = DimensionsCheck[1] - Y * myBlockSize[1]
                    myBufSize = nXValid*nYValid
                # find Y offset
                myY=Y*myBlockSize[1]
                # create empty buffer to mark where nodata occurs
                myNDVs = None
                # make local namespace for calculation
                local_namespace = []
                for (i, myFile) in enumerate(myFiles):
                    myval=gdalnumeric.BandReadAsArray(myFile.GetRasterBand(1),
                                            xoff=myX, yoff=myY,
                                            win_xsize=nXValid, win_ysize=nYValid)
                    # fill in nodata values
                    if myNDV[i] is not None:
                        if myNDVs is None:
                            myNDVs = numpy.zeros(myBufSize)
                            myNDVs.shape=(nYValid,nXValid)
                        myNDVs=1*numpy.logical_or(myNDVs==1, myval==myNDV[i])

                    local_namespace.append(myval)
                    myval=None

                # calculate mean between bands using Numpy
                myResult = numpy.mean(local_namespace, axis=0)

                if myNDVs is not None:
                    myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
                elif not isinstance(myResult, numpy.ndarray):
                    myResult = numpy.ones( (nYValid,nXValid) ) * myResult

                myOutB=myOut.GetRasterBand(bandNo)
                gdalnumeric.BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY)
    return

    # how to use it
    files_mean(['./input_01.tif', './input_02.tif', './input_02.tif', ...  './input_n.tif',],'./output.tif')
Example #14
0
    def write_tif(self, outname, data2write= False, dtype = 1, nodata = False, option = 'COMPRESS=DEFLATE'):
        '''dtype: ....
        
            if nodata set to True the orig nodata value will be assigned to the raster,
            if it is not a double ( in this case no nodata will be assigned)
            
            write_tif(outname, data2write=False, dtype=1, nodata=False, option='Compress=Deflate')
            
            dtypes:
                0 --> Int16
                1 --> Int32
                2 --> UIit16
                3 --> UInt32
                4 --> Float32
                5 --> Float64
                6 --> UInt8
                
        '''
        dtypeL = [zz_gdalcon.GDT_Int16, zz_gdalcon.GDT_Int32,
                  zz_gdalcon.GDT_UInt16, zz_gdalcon.GDT_UInt32,
                  zz_gdalcon.GDT_Float32, zz_gdalcon.GDT_Float64,
                  zz_gdalcon.GDT_Byte]
        try:
            if type(data2write) != type(self.data):
                data2write = self.data                
                  
            if len(data2write.shape)==3:
                nr_of_bands = data2write.shape[0]
            elif len(data2write.shape)==2:
                nr_of_bands = 1
            else:
                raise NameError('ERROR: in Number of Bands')

            if not 'int' in str(np.result_type(data2write)):
                dataOut = self.driver.Create(outname, self.columns, self.rows, nr_of_bands, dtypeL[dtype])
            else:
                dataOut = self.driver.Create(outname, self.columns, self.rows, nr_of_bands, dtypeL[dtype], options=[option])

            #dataOut.SetGeoTransform(self.intif.GetGeoTransform())
            zz_gdalnum.CopyDatasetInfo(self.intif, dataOut)

            for band in range(nr_of_bands):
                bandOut = dataOut.GetRasterBand(band+1)
                
                if nodata:
                    #test if nodate can be set
                    if isinstance(nodata, bool) and 'e' not in str(self.nodata):
                        nodata = self.nodata
                    if 'e' in str(nodata):
                        nodata = False
                    if nodata:
                        bandOut.SetNoDataValue(nodata)
                        
                if nr_of_bands==1:
                    zz_gdalnum.BandWriteArray(bandOut,data2write)
                else:
                    zz_gdalnum.BandWriteArray(bandOut,data2write[band,:,:])
                bandOut = None
            dataOut = None
            #print 0
        except IOError as e:
            print "I/O error({0}): {1}".format(e.errno, e.strerror)
        except ValueError:
            print ("Could not write the nodata value")
        except:
            print "Unexpected error:", sys.exc_info()
Example #15
0
def write_tif(file_with_srid,full_output_name, data, dtype= 1, nodata=None, option=False ):
    '''
        write data to tif

        >>> write_tif(file_with_srid, full_output_name, data, 1, nodata=None, option=False)

        file_wite_srid   --> the original file with spatial infromations
        full_output_name --> path + filename + tile type e.g.: r'c:\\temp\\file1.tif'
        data             --> data you want to write to tif
        dtype            --> Output data type (int, float ...)
                             input number between 0 and 5:
                                - 0 --> Int16
                                - 1 --> Int32
                                - 2 --> UInt16
                                - 3 --> UInt32
                                - 4 --> Float32
                                - 5 --> Float64
                                - 6 --> UInt8
                         --> default is Int32
        nodata           --> by default there will be no NoData Value asigned
                               if True:
                                  it will put the max Value for Unsigned Integers
                                  it will put the min Value for signed Integers and floats
                               if you put a Value --> this Value will be the NoData Value
        option           --> "COMPRESS=DEFLATE"


        if data is a 3d array it will write all bands to the tif (in single bands)
    '''

    dtypeL = [zz_gdalcon.GDT_Int16,
              zz_gdalcon.GDT_Int32,
              zz_gdalcon.GDT_UInt16,
              zz_gdalcon.GDT_UInt32,
              zz_gdalcon.GDT_Float32,
              zz_gdalcon.GDT_Float64,
              zz_gdalcon.GDT_Byte]

    try:
        inTiff, driver, inCols, inRows = read_tif_info(file_with_srid)
        if len(data.shape)==3:
            nr_of_bands = data.shape[0]
        elif len(data.shape)==2:
            nr_of_bands = 1
        else:
            print('error in Bands')
            sys.exit(1)
        #print(nr_of_bands)
        if option:
            dataOut = driver.Create(full_output_name,inCols,inRows,nr_of_bands, dtypeL[dtype],options=[option])
        else:
            dataOut = driver.Create(full_output_name,inCols,inRows,nr_of_bands, dtypeL[dtype])
        zz_gdalnum.CopyDatasetInfo(inTiff,dataOut)
        for band in range(nr_of_bands):
            bandOut = dataOut.GetRasterBand(band+1)
            if nodata is not None:
                bandOut.SetNoDataValue(nodata)
            if nr_of_bands==1:
                zz_gdalnum.BandWriteArray(bandOut,data)
            else:
                zz_gdalnum.BandWriteArray(bandOut,data[band,:,:])
            bandOut = None
        dataOut = None
    except IOError as e:
        print "I/O error({0}): {1}".format(e.errno, e.strerror)
    except ValueError:
        print ("Could not write the nodata value")
    except:
        print "Unexpected error:", sys.exc_info()
Example #16
0
def compare ( TET_tem_path, SST_tem_path, outputFile ):
    if os.path.exists(outputFile) == False:
        os.mkdir(outputFile)
    elif os.path.exists(outputFile) == True:
        return
    
    os.chdir(outputFile)
    
    TET_tem = gdal.Open(TET_tem_path)
    SST_tem = gdal.Open(SST_tem_path)
    
    MIR_band = TET_tem.GetRasterBand(1)
    TIR_band = TET_tem.GetRasterBand(2)
    SST_band = SST_tem.GetRasterBand(1)
    
    MIR_data = MIR_band.ReadAsArray()
    TIR_data = TIR_band.ReadAsArray()
    SST_data = SST_band.ReadAsArray()
    
    default_tem = 274.15 * np.ones(SST_data.shape)
    
#    MIR_deg = MIR_data + default_tem
#    TIR_deg = TIR_data + default_tem

    SST_K = SST_data + default_tem
    diff_MIR = MIR_data - SST_K
    diff_TIR = TIR_data - SST_K
    
    logic1 = np.where(np.absolute(diff_MIR)>50)
    diff_MIR[logic1] = 0
            
    logic2 = np.where(np.absolute(diff_TIR)>50)
    diff_TIR[logic2] = 0
    
    diff_MIR_max = diff_MIR.max()
    diff_TIR_max = diff_TIR.max()
    
    diff_MIR_min = diff_MIR.min()
    diff_TIR_min = diff_TIR.min()
    
    diff_MIR_mean = diff_MIR.mean()
    diff_TIR_mean = diff_TIR.mean()
    
    diff_MIR_std = diff_MIR.std()
    diff_TIR_std = diff_TIR.std()
    
    diff_MIR_median = np.median(diff_MIR[diff_MIR.nonzero()])
    diff_TIR_median = np.median(diff_TIR[diff_TIR.nonzero()])
    
    abs_diff_MIR = np.absolute(diff_MIR)
    abs_diff_TIR = np.absolute(diff_TIR)
    
    abs_diff_MIR_mean = abs_diff_MIR.mean()
    abs_diff_TIR_mean = abs_diff_TIR.mean()
    
    abs_diff_MIR_std = abs_diff_MIR.std()
    abs_diff_TIR_std = abs_diff_TIR.std()
    
    f = open( os.path.join(outputFile, 'statistics_info.txt'), 'w' )
    
    f.write('Difference between SST and TET temperature.\n')
    f.write('MIR band.\tUnit: degrees Celsius.\n')
    f.write('Maximum: %s.\nMinimum: %s.\n' %(str(diff_MIR_max), str(diff_MIR_min)))
    f.write('Mean: %s.\nStandard Deviation: %s.\nMedian Value: %s.\n' %(str(diff_MIR_mean), str(diff_MIR_std), str(diff_MIR_median)))
    f.write('Absolute Mean: %s.\nAbsolute Standard Deviation: %s.\n\n' %(str(abs_diff_MIR_mean), str(abs_diff_MIR_std)))
    
    f.write('Difference between SST and TET temperature.\n')
    f.write('TIR band.\tUnit: degrees Celsius.\n')
    f.write('Maximum: %s.\nMinimum: %s.\n' %(str(diff_TIR_max), str(diff_TIR_min)))
    f.write('Mean: %s.\nStandard Deviation: %s.\nMedian Value: %s.\n' %(str(diff_TIR_mean), str(diff_TIR_std), str(diff_TIR_median)))
    f.write('Absolute Mean: %s.\nAbsolute Standard Deviation: %s.\n' %(str(abs_diff_TIR_mean), str(abs_diff_TIR_std)))
    
    f.close()
            
    driver = gdal.GetDriverByName('GTiff')
    
    MIR_out = driver.Create('diff_MIR.tif', TET_tem.RasterXSize, TET_tem.RasterYSize, 1, MIR_band.DataType)
    gdalnumeric.CopyDatasetInfo(TET_tem, MIR_out)
    MIR_bandOut = MIR_out.GetRasterBand(1)
    MIR_bandOut.SetNoDataValue(0.0)
    gdalnumeric.BandWriteArray(MIR_bandOut, diff_MIR)
    
    TIR_out = driver.Create('diff_TIR.tif', TET_tem.RasterXSize, TET_tem.RasterYSize, 1, TIR_band.DataType)
    gdalnumeric.CopyDatasetInfo(TET_tem, TIR_out)
    TIR_bandOut = TIR_out.GetRasterBand(1)
    TIR_bandOut.SetNoDataValue(0.0)
    gdalnumeric.BandWriteArray(TIR_bandOut, diff_TIR)
    
    print 'end'