Beispiel #1
0
def masknetcdf(netcdf_filename, shp_filename, cl_field=None):
    if cl_field == None:
        # If no field is provided, assume first part of file name is the field to use
        head, tail = os.path.split(netcdf_filename)
        cl_field = tail.split(".")[0]

    # Open dataset
    data_source = gdal.Open(netcdf_filename)
    # Number of columns of each layer
    cols = data_source.RasterXSize
    #Number of rows of each layer
    rows = data_source.RasterYSize
    # Number of bands of each layer
    nbands = data_source.RasterCount
    # Year of the netcdf file
    year = int(netcdf_filename.split('.')[-2])

    #========================================
    # Importing data by bands as a dictionary
    #========================================
    datach = {}
    # First day of the year as reference
    yearc = str(year) + "-01-01"
    # Converting year in a datatime object
    fi_date = datetime.datetime.strptime(yearc, "%Y-%m-%d").date()
    # For loop of the layers that contains the netcdf file
    for i in range(1, nbands + 1):
        index_date = fi_date + datetime.timedelta(days=i - 1)
        in_band = data_source.GetRasterBand(i)
        # Converting default nan in np.na
        in_band_wnan = in_band.ReadAsArray()
        in_band_wnan[in_band_wnan == -9.9692100e+36] = np.nan
        datach[index_date.strftime("%Y-%m-%d")] = in_band_wnan

    #====================================
    # Parameters of transformation
    #====================================
    x = 0.5 * cols - rows
    delta_Lon = 360 / cols
    delta_Lat = 180 / (rows + x)
    if x == 0:
        LonUpper_Left = 0
        LatUpper_Left = 90
    else:
        LonUpper_Left = -delta_Lon / 2
        LatUpper_Left = delta_Lat * (rows / 2)
    gt = [LonUpper_Left, delta_Lon, 0, LatUpper_Left, 0, -delta_Lat]
    # Inverse affine transformation
    inv_gt = gdal.InvGeoTransform(gt)
    inv_gt

    #=====================================================================
    # Importing shapefile and transforming coordinates to rows and columns
    #=====================================================================
    # Calling driver
    driver = ogr.GetDriverByName('ESRI Shapefile')
    # Open dataset
    datasource1 = driver.Open(shp_filename, 1)
    # Get layer
    layer = datasource1.GetLayer()
    # Get number of features
    fc = layer.GetFeatureCount()
    # Creating lists for rows, columns and time index
    xt_p = []
    yt_p = []
    dayc = []
    for fea in layer:
        # Time
        a = fea.GetField("timestamp")[0:10]
        dayc.append(a)
        # Coord
        pt = fea.geometry()
        # Transforming coord
        xt, yt = gdal.ApplyGeoTransform(inv_gt, pt.GetX(), pt.GetY())
        xt_p.append(xt)
        yt_p.append(yt)

    #=================================
    # Extracting values by time
    #=================================
    # Converting list of days to array
    array_indexday = np.array(dayc)
    # Creating a vector of nan values
    value = np.zeros(fc)
    value[value == 0] = np.nan
    # For loop to extract values by time
    for j in np.unique(dayc):
        # Condition about the year of interest
        year_d = datetime.datetime.strptime(j, "%Y-%m-%d").year
        if year_d == year:
            # Match day of the features with the day of the band array
            index = np.where(array_indexday == j)[0].tolist()
            in_band = datach[j]
            # Extracting values of the layer that correspond to certain time
            for k in range(0, len(index)):
                data = in_band[int(yt_p[index[k]]), int(xt_p[index[k]])]
                value[index[k]] = data
        else:
            continue

    #============================
    # Loading values to shapefile
    #============================
    # Calling the shapefile again but in edition version (1)
    driver = ogr.GetDriverByName('ESRI Shapefile')
    datasource2 = driver.Open(shp_filename, 1)
    layer2 = datasource2.GetLayer()
    # Reset index
    datasource2.SyncToDisk()
    # List of the fields of the shapefile
    schema = []
    ldefn = layer2.GetLayerDefn()
    for n in range(ldefn.GetFieldCount()):
        fdefn = ldefn.GetFieldDefn(n)
        schema.append(fdefn.name)
    # So, if the field exists this function updates the field, otherwise, it will create
    # A new field with the specified name
    if np.any(np.array(schema) == cl_field):
        i = 0
        # For loop quering the existency of the value for certain period
        for fe in layer2:
            year_2 = datetime.datetime.strptime(dayc[i], "%Y-%m-%d").year
            if year_2 == year:
                fe.SetField(cl_field, value[i])
                layer2.SetFeature(fe)
            i = i + 1
    else:
        # Creating the the new field
        new_field = ogr.FieldDefn(cl_field, ogr.OFTReal)
        layer2.CreateField(new_field)
        i = 0
        for fe in layer2:
            fe.SetField(cl_field, value[i])
            layer2.SetFeature(fe)
            i = i + 1
    # Destroy data source shapefile
    datasource1.Destroy()
    datasource2.Destroy()
    # Close source netcdf
    data_source = None
    del value
    print(f"Done! Year: {year}; Field {cl_field}")
Beispiel #2
0
def pixelToMap(pX, pY, geoTransform):
    return gdal.ApplyGeoTransform(geoTransform, pX + 0.5, pY + 0.5)
Beispiel #3
0
def mapToPixel(mX, mY, geoTransform):
    (pX, pY) = gdal.ApplyGeoTransform(gdal.InvGeoTransform(geoTransform), mX,
                                      mY)
    return (int(pX), int(pY))
Beispiel #4
0
def geo_to_corner(point_coor, raster_geo):
    # 计算逆放射变换系数
    raster_inv_geo = gdal.InvGeoTransform(raster_geo)
    off_ulx, off_uly = map(round, gdal.ApplyGeoTransform(raster_inv_geo, point_coor[1], point_coor[0]))
    return off_ulx, off_uly
Beispiel #5
0
    def world_to_pix(self, x, y, proj=None):
        """
        Take world coordinates and return pixel coordinates

        *Arguments*:
         - x = the world x-coord.
         - y = the world y-coord.
         - proj = the coordinate system of the input coordinates. Default (None) uses the same system as this image. Otherwise
                   an osr.SpatialReference can be passed (HyImage.project), or an EPSG string (e.g. get_projection_EPSG(...)).

        *Returns*:
         - the pixel coordinates based on the affine transform stored in self.affine.
        """

        try:
            from osgeo import osr
            import osgeo.gdal as gdal
            from osgeo import ogr
        except:
            assert False, "Error - GDAL must be installed to work with spatial projections in hylite."

        # parse project
        if proj is None:
            proj = self.projection
        elif isinstance(proj, str) or isinstance(proj, int):
            epsg = proj
            if isinstance(epsg, str):
                try:
                    epsg = int(str.split(':')[1])
                except:
                    assert False, "Error - %s is an invalid EPSG code." % proj
            proj = osr.SpatialReference()
            proj.ImportFromEPSG(epsg)

        # check we have all the required info
        assert isinstance(proj, osr.SpatialReference
                          ), "Error - invalid spatial reference %s" % proj
        assert (not self.affine is None) and (
            not self.projection is None
        ), "Error - project information is undefined."

        # project to this images CS (if different)
        if not proj.IsSameGeogCS(self.projection):
            P = ogr.Geometry(ogr.wkbPoint)
            if proj.EPSGTreatsAsNorthingEasting():
                P.AddPoint(x, y)
            else:
                P.AddPoint(y, x)
            P.AssignSpatialReference(
                proj)  # tell the point what coordinates it's in
            P.AddPoint(x, y)
            P.TransformTo(
                self.projection)  # reproject it to the out spatial reference
            x, y = P.GetX(), P.GetY()
            if self.projection.EPSGTreatsAsLatLong(
            ):  # do we need to transpose?
                x, y = y, x  # we want lon,lat not lat,lon

        inv = gdal.InvGeoTransform(self.affine)
        assert not inv is None, "Error - could not invert affine transform?"

        #apply
        return gdal.ApplyGeoTransform(inv, x, y)
Beispiel #6
0
# print(in_files)

# 新建一幅大图
driver = gdal.GetDriverByName('GTiff')
columns = small_image_width * width_num
rows = small_image_height * height_num
read_information = gdal.Open(in_files[0])  # 读取一张获取信息
information_band = read_information.GetRasterBand(1)
# print(information_band.DataType)
# print(gdal.GDT_Byte, gdal.GDT_UInt16)  # 8位的图和16位的图 1 2
out_tif = driver.Create(output_path, columns, rows, 3, information_band.DataType)
information_geotrans = read_information.GetGeoTransform()  # 图像的坐标和分辨率信息等
information_proj = read_information.GetProjection()  # 图像的投影信息
out_tif.SetProjection(information_proj)  # 给大图设置投影信息
out_tif.SetGeoTransform(information_geotrans)  #

# 定义仿射逆变换
inv_geotrans = gdal.InvGeoTransform(information_geotrans)
for i, small_sat in enumerate(in_files):
    in_ds = gdal.Open(small_sat)
    in_gt = in_ds.GetGeoTransform()
    offset = gdal.ApplyGeoTransform(inv_geotrans, in_gt[0], in_gt[3])
    x, y = map(int, offset)  # x,y是开始写入时左上角像元行列号
    data = in_ds.ReadAsArray()
    # print('data.shape:', data.shape)  # (3, 512, 512)
    for k in range(3):  # 将三个波段依次写入大图对应位置
        out_tif.GetRasterBand(k + 1).WriteArray(data[k], x, y)
    # out_tif.WriteArray(data, x, y)
    print(f'第{i+1}张图完成')
    del in_ds