507 строки
14 KiB
Python
Исполняемый файл
507 строки
14 KiB
Python
Исполняемый файл
#!/usr/bin/env pytest
|
|
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
# $Id$
|
|
#
|
|
# Project: GDAL/OGR Test Suite
|
|
# Purpose: Tests Raster Attribute Table support in the HFA driver and in
|
|
# particular, changes related to RFC40.
|
|
# Author: Sam Gillingham <gillingham.sam@gmail.com>
|
|
#
|
|
###############################################################################
|
|
# Copyright (c) 2013, Sam Gillingham <gillingham.sam@gmail.com>
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
# copy of this software and associated documentation files (the "Software"),
|
|
# to deal in the Software without restriction, including without limitation
|
|
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
# and/or sell copies of the Software, and to permit persons to whom the
|
|
# Software is furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included
|
|
# in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
# DEALINGS IN THE SOFTWARE.
|
|
###############################################################################
|
|
|
|
import pytest
|
|
|
|
from osgeo import gdal
|
|
|
|
# All tests will be skipped if numpy is unavailable.
|
|
np = pytest.importorskip("numpy")
|
|
|
|
|
|
INT_DATA = np.array([197, 83, 46, 29, 1, 78, 23, 90, 12, 45])
|
|
DOUBLE_DATA = np.array([0.1, 43.2, 78.1, 9.9, 23.0, 0.92, 82.5, 0.0, 1.0, 99.0])
|
|
STRING_DATA = np.array(
|
|
["sddf", "wess", "grbgr", "dewd", "ddww", "qwsqw", "gbfgbf", "wwqw3", "e", ""]
|
|
)
|
|
STRING_DATA_INTS = np.array(
|
|
["197", "83", "46", "29", "1", "78", "23", "90", "12", "45"]
|
|
)
|
|
STRING_DATA_DOUBLES = np.array(
|
|
["0.1", "43.2", "78.1", "9.9", "23.0", "0.92", "82.5", "0.0", "1.0", "99.0"]
|
|
)
|
|
LONG_STRING_DATA = np.array(
|
|
[
|
|
"sdfsdfsdfs",
|
|
"sdweddw",
|
|
"sdewdweee",
|
|
"3423dedd",
|
|
"jkejjjdjd",
|
|
"edcdcdcdc",
|
|
"fcdkmk4m534m",
|
|
"edwededdd",
|
|
"dedwedew",
|
|
"wdedefrfrfrf",
|
|
]
|
|
)
|
|
|
|
|
|
class HFATestError(Exception):
|
|
pass
|
|
|
|
|
|
def CreateAndWriteRAT(fname):
|
|
"""
|
|
Creates file and writes some data
|
|
"""
|
|
# create
|
|
driver = gdal.GetDriverByName("HFA")
|
|
ds = driver.Create(fname, 10, 10, 1, gdal.GDT_Byte)
|
|
|
|
ds.SetGeoTransform([0, 1, 0, 0, 0, -1])
|
|
|
|
# write some image data
|
|
band = ds.GetRasterBand(1)
|
|
data = np.zeros((10, 10), np.uint8)
|
|
data[5, 5] = 20
|
|
band.WriteArray(data)
|
|
|
|
band.SetMetadataItem("LAYER_TYPE", "thematic")
|
|
|
|
rat = band.GetDefaultRAT()
|
|
rat.SetTableType(gdal.GRTT_THEMATIC)
|
|
|
|
# create some columns
|
|
if rat.CreateColumn("Ints", gdal.GFT_Integer, gdal.GFU_Generic) != gdal.CE_None:
|
|
raise HFATestError("Create column failed")
|
|
|
|
if rat.CreateColumn("Doubles", gdal.GFT_Real, gdal.GFU_Generic) != gdal.CE_None:
|
|
raise HFATestError("Create column failed")
|
|
|
|
if rat.CreateColumn("Strings", gdal.GFT_String, gdal.GFU_Generic) != gdal.CE_None:
|
|
raise HFATestError("Create column failed")
|
|
|
|
# for writing as different type
|
|
if (
|
|
rat.CreateColumn("IntAsDouble", gdal.GFT_Integer, gdal.GFU_Generic)
|
|
!= gdal.CE_None
|
|
):
|
|
raise HFATestError("Create column failed")
|
|
|
|
if (
|
|
rat.CreateColumn("IntsAsString", gdal.GFT_Integer, gdal.GFU_Generic)
|
|
!= gdal.CE_None
|
|
):
|
|
raise HFATestError("Create column failed")
|
|
|
|
if rat.CreateColumn("DoubleAsInt", gdal.GFT_Real, gdal.GFU_Generic) != gdal.CE_None:
|
|
raise HFATestError("Create column failed")
|
|
|
|
if (
|
|
rat.CreateColumn("DoubleAsString", gdal.GFT_Real, gdal.GFU_Generic)
|
|
!= gdal.CE_None
|
|
):
|
|
raise HFATestError("Create column failed")
|
|
|
|
if (
|
|
rat.CreateColumn("StringAsInt", gdal.GFT_String, gdal.GFU_Generic)
|
|
!= gdal.CE_None
|
|
):
|
|
raise HFATestError("Create column failed")
|
|
|
|
if (
|
|
rat.CreateColumn("StringAsDouble", gdal.GFT_String, gdal.GFU_Generic)
|
|
!= gdal.CE_None
|
|
):
|
|
raise HFATestError("Create column failed")
|
|
|
|
rat.SetRowCount(INT_DATA.size)
|
|
|
|
# some basic checks
|
|
if rat.GetRowCount() != INT_DATA.size:
|
|
raise HFATestError("Wrong RowCount")
|
|
|
|
if rat.GetColumnCount() != 9:
|
|
raise HFATestError("Wrong Column Count")
|
|
|
|
if rat.GetNameOfCol(1) != "Doubles":
|
|
raise HFATestError("Wrong Column Count")
|
|
|
|
if rat.GetUsageOfCol(1) != gdal.GFU_Generic:
|
|
raise HFATestError("Wrong column usage")
|
|
|
|
if rat.GetTypeOfCol(1) != gdal.GFT_Real:
|
|
raise HFATestError("Wrong column usage")
|
|
|
|
if rat.GetColOfUsage(gdal.GFU_Generic) != 0:
|
|
raise HFATestError("Wrong col of usage")
|
|
|
|
if not rat.ChangesAreWrittenToFile():
|
|
raise HFATestError("Wrong ChangesAreWrittenToFile")
|
|
|
|
# Write data
|
|
if rat.WriteArray(INT_DATA, 0) != gdal.CE_None:
|
|
raise HFATestError("Failed to write int column")
|
|
|
|
if rat.WriteArray(DOUBLE_DATA, 1) != gdal.CE_None:
|
|
raise HFATestError("Failed to write double column")
|
|
|
|
if rat.WriteArray(STRING_DATA, 2) != gdal.CE_None:
|
|
raise HFATestError("Failed to write string column")
|
|
|
|
# different types
|
|
if rat.WriteArray(DOUBLE_DATA, 3) != gdal.CE_None:
|
|
raise HFATestError("Failed to write doubles to int column")
|
|
|
|
if rat.WriteArray(STRING_DATA_INTS, 4) != gdal.CE_None:
|
|
raise HFATestError("Failed to write strings to int column")
|
|
|
|
if rat.WriteArray(INT_DATA, 5) != gdal.CE_None:
|
|
raise HFATestError("Failed to write ints to doubles column")
|
|
|
|
if rat.WriteArray(STRING_DATA_DOUBLES, 6) != gdal.CE_None:
|
|
raise HFATestError("Failed to write strings to doubles column")
|
|
|
|
if rat.WriteArray(INT_DATA, 7) != gdal.CE_None:
|
|
raise HFATestError("Failed to write ints to string column")
|
|
|
|
if rat.WriteArray(DOUBLE_DATA, 8) != gdal.CE_None:
|
|
raise HFATestError("Failed to write doubles to string column")
|
|
|
|
# print('Succeeding writing data')
|
|
# ds.FlushCache()
|
|
ds = None
|
|
|
|
|
|
def ReadAndCheckValues(fname, numrows):
|
|
ds = gdal.Open(fname)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
if rat.GetTableType() != gdal.GRTT_THEMATIC:
|
|
raise HFATestError("Wrong table type")
|
|
|
|
if rat.GetRowCount() != numrows:
|
|
raise HFATestError("Wrong number of rows")
|
|
|
|
data = rat.ReadAsArray(0, 0, 10)
|
|
if not (data == INT_DATA).all():
|
|
raise HFATestError("Int column does not match")
|
|
|
|
data = rat.ReadAsArray(1, 0, 10)
|
|
if not (data == DOUBLE_DATA).all():
|
|
raise HFATestError("double column does not match")
|
|
|
|
data = rat.ReadAsArray(2, 0, 10)
|
|
if not (data == STRING_DATA.astype(bytes)).all():
|
|
raise HFATestError("string column does not match")
|
|
|
|
data = rat.ReadAsArray(3, 0, 10)
|
|
if not (data == DOUBLE_DATA.astype(int)).all():
|
|
raise HFATestError("int as double column does not match")
|
|
|
|
data = rat.ReadAsArray(4, 0, 10)
|
|
if not (data == STRING_DATA_INTS.astype(int)).all():
|
|
raise HFATestError("int as string column does not match")
|
|
|
|
data = rat.ReadAsArray(5, 0, 10)
|
|
if not (data == INT_DATA).all():
|
|
raise HFATestError("double as int column does not match")
|
|
|
|
data = rat.ReadAsArray(6, 0, 10)
|
|
if not (data == STRING_DATA_DOUBLES.astype(np.double)).all():
|
|
raise HFATestError("double as string column does not match")
|
|
|
|
data = rat.ReadAsArray(7, 0, 10)
|
|
if not (data.astype(int) == INT_DATA).all():
|
|
raise HFATestError("string as int column does not match")
|
|
|
|
data = rat.ReadAsArray(8, 0, 10)
|
|
if not (data.astype(np.double) == DOUBLE_DATA).all():
|
|
raise HFATestError("string as int column does not match")
|
|
|
|
# print('succeeded reading')
|
|
ds = None
|
|
|
|
|
|
def CheckSetGetValues(fname):
|
|
# check the 'legacy' get and set value calls
|
|
ds = gdal.Open(fname, gdal.GA_Update)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
# write data
|
|
nrows = rat.GetRowCount()
|
|
for i in range(nrows):
|
|
# write some data slightly different
|
|
rat.SetValueAsInt(i, 0, int(INT_DATA[i] + 1))
|
|
rat.SetValueAsDouble(i, 1, DOUBLE_DATA[i] + 1)
|
|
s = STRING_DATA[i]
|
|
s = s + "z"
|
|
rat.SetValueAsString(i, 2, s)
|
|
|
|
# read data and check
|
|
for i in range(nrows):
|
|
if rat.GetValueAsInt(i, 0) != (INT_DATA[i] + 1):
|
|
raise HFATestError("GetValueAsInt not reading correctly")
|
|
if rat.GetValueAsDouble(i, 1) != (DOUBLE_DATA[i] + 1):
|
|
raise HFATestError("GetValueAsDouble not reading correctly")
|
|
s = STRING_DATA[i]
|
|
s = s + "z"
|
|
if rat.GetValueAsString(i, 2) != s:
|
|
raise HFATestError("GetValueAsString not reading correctly")
|
|
|
|
# no need to check different types as ValuesIO is checked for this above
|
|
# and these calls map to ValuesIO
|
|
|
|
# write back old
|
|
for i in range(nrows):
|
|
rat.SetValueAsInt(i, 0, int(INT_DATA[i]))
|
|
rat.SetValueAsDouble(i, 1, DOUBLE_DATA[i])
|
|
rat.SetValueAsString(i, 2, STRING_DATA[i])
|
|
|
|
# print("Get/SetValue OK")
|
|
# ds.FlushCache()
|
|
ds = None
|
|
|
|
|
|
def ExtendAndWrite(fname):
|
|
# write more data to the end of the RAT - will extend it
|
|
ds = gdal.Open(fname, gdal.GA_Update)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
noldrows = rat.GetRowCount()
|
|
|
|
# extend
|
|
nrows = noldrows + INT_DATA.size
|
|
rat.SetRowCount(nrows)
|
|
|
|
# write new data
|
|
if rat.WriteArray(INT_DATA, 0, 10) != gdal.CE_None:
|
|
raise HFATestError("Failed to write int column")
|
|
if rat.WriteArray(DOUBLE_DATA, 1, 10) != gdal.CE_None:
|
|
raise HFATestError("Failed to write double column")
|
|
if rat.WriteArray(STRING_DATA, 2, 10) != gdal.CE_None:
|
|
raise HFATestError("Failed to write string column")
|
|
|
|
# print('extend ok')
|
|
# ds.FlushCache()
|
|
ds = None
|
|
|
|
|
|
def CheckExtension(fname):
|
|
ds = gdal.Open(fname)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
data = rat.ReadAsArray(0, 10, 10)
|
|
if not (data == INT_DATA).all():
|
|
raise HFATestError("Int column does not match")
|
|
|
|
data = rat.ReadAsArray(1, 10, 10)
|
|
if not (data == DOUBLE_DATA).all():
|
|
raise HFATestError("Double column does not match")
|
|
|
|
data = rat.ReadAsArray(2, 10, 10)
|
|
if not (data == STRING_DATA.astype(bytes)).all():
|
|
raise HFATestError("String column does not match")
|
|
|
|
# print('extension data ok')
|
|
ds = None
|
|
|
|
|
|
def WriteLongStrings(fname):
|
|
# this will force the string column to be re-written to accommodate
|
|
# a longer string size
|
|
ds = gdal.Open(fname, gdal.GA_Update)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
if rat.WriteArray(LONG_STRING_DATA, 2, 10) != gdal.CE_None:
|
|
raise HFATestError("Failed to write string column")
|
|
|
|
# print("wrote long strings ok")
|
|
# ds.FlushCache()
|
|
ds = None
|
|
|
|
|
|
def CheckLongStrings(fname):
|
|
ds = gdal.Open(fname)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
data = rat.ReadAsArray(2, 10, 10)
|
|
if not (data == LONG_STRING_DATA.astype(bytes)).all():
|
|
raise HFATestError("String column does not match")
|
|
|
|
# print("checked long strings ok")
|
|
ds = None
|
|
|
|
|
|
def SetLinearBinning(fname):
|
|
ds = gdal.Open(fname, gdal.GA_Update)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
if rat.SetLinearBinning(0, 1) != gdal.CE_None:
|
|
raise HFATestError("Error in SetLinearBinning")
|
|
|
|
# print("set linear binning ok")
|
|
# ds.FlushCache()
|
|
ds = None
|
|
|
|
|
|
def CheckLinearBinning(fname):
|
|
ds = gdal.Open(fname)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
(state, mini, size) = rat.GetLinearBinning()
|
|
if not state:
|
|
raise HFATestError("GetLinearBinning failed")
|
|
|
|
if mini != 0 or size != 1:
|
|
raise HFATestError("GetLinearBinning values wrong")
|
|
|
|
if rat.GetRowOfValue(3) != 3:
|
|
raise HFATestError("GetRowOfValue value wrong")
|
|
|
|
# print('linear binning ok')
|
|
ds = None
|
|
|
|
|
|
def CheckClone(fname):
|
|
ds = gdal.Open(fname)
|
|
band = ds.GetRasterBand(1)
|
|
rat = band.GetDefaultRAT()
|
|
|
|
cloned = rat.Clone()
|
|
|
|
if cloned.GetTableType() != gdal.GRTT_THEMATIC:
|
|
raise HFATestError("Cloned into wrong table type")
|
|
if cloned.GetValueAsInt(0, 0) != 197:
|
|
raise HFATestError("Cloned into wrong int")
|
|
if cloned.GetValueAsDouble(5, 1) != 0.92:
|
|
raise HFATestError("Cloned into wrong double")
|
|
if cloned.GetValueAsString(1, 2) != "wess":
|
|
raise HFATestError("Cloned into wrong string")
|
|
|
|
# print("cloned ok")
|
|
ds = None
|
|
|
|
|
|
# basic tests
|
|
|
|
|
|
def test_hfa_rfc40_1():
|
|
return CreateAndWriteRAT("tmp/test.img")
|
|
|
|
|
|
def test_hfa_rfc40_2():
|
|
return ReadAndCheckValues("tmp/test.img", 10)
|
|
|
|
|
|
# the older interface
|
|
|
|
|
|
def test_hfa_rfc40_3():
|
|
return CheckSetGetValues("tmp/test.img")
|
|
|
|
|
|
# make sure original data not changed
|
|
|
|
|
|
def test_hfa_rfc40_4():
|
|
return ReadAndCheckValues("tmp/test.img", 10)
|
|
|
|
|
|
# make it longer - data will be re-written
|
|
|
|
|
|
def test_hfa_rfc40_5():
|
|
return ExtendAndWrite("tmp/test.img")
|
|
|
|
|
|
# make sure old data not changed
|
|
|
|
|
|
def test_hfa_rfc40_6():
|
|
return ReadAndCheckValues("tmp/test.img", 20)
|
|
|
|
|
|
# new data at the end ok?
|
|
|
|
|
|
def test_hfa_rfc40_7():
|
|
return CheckExtension("tmp/test.img")
|
|
|
|
|
|
# write some longer strings - string column will
|
|
# have to be re-written
|
|
|
|
|
|
def test_hfa_rfc40_8():
|
|
return WriteLongStrings("tmp/test.img")
|
|
|
|
|
|
# make sure old data not changed
|
|
|
|
|
|
def test_hfa_rfc40_9():
|
|
return ReadAndCheckValues("tmp/test.img", 20)
|
|
|
|
|
|
# check new data ok
|
|
|
|
|
|
def test_hfa_rfc40_10():
|
|
return CheckLongStrings("tmp/test.img")
|
|
|
|
|
|
# linear binning
|
|
|
|
|
|
def test_hfa_rfc40_11():
|
|
return SetLinearBinning("tmp/test.img")
|
|
|
|
|
|
# linear binning
|
|
|
|
|
|
def test_hfa_rfc40_12():
|
|
return CheckLinearBinning("tmp/test.img")
|
|
|
|
|
|
# clone
|
|
|
|
|
|
def test_hfa_rfc40_13():
|
|
return CheckClone("tmp/test.img")
|
|
|
|
|
|
# serialize not available from Python...
|
|
|
|
|
|
def test_hfa_rfc40_cleanup():
|
|
gdal.GetDriverByName("HFA").Delete("tmp/test.img")
|