API docs more or less here: https://gippy.readthedocs.io/en/latest/quickstart.html
The diffs here mostly represent actual changes to gips code for PR #401. The conversion wasn't perfect; see See Missing or Regressed Features below.
Many of the changes followed a regular pattern of naming changes. Classes are
still in CamelCase
. Methods and functions all changed to python_case
.
Examples:
- v = GeoWhatever(*args).GetSomeValue()
+ v = GeoWhatever(*args).some_value() # getters lose their 'Get'
- GeoWhatever(*args).SetSomeValue(v)
+ GeoWhatever(*args).set_some_value(v) # setters retain the 'set_'
The constants used to specify data types (gippy.GDT_SomeType
) are gone; just
use strings as you would with numpy:
- imgout = gippy.GeoImage(fout, img, gippy.GDT_Float32, 2)
+ imgout = gippy.GeoImage.create_from(img, fout, 2, 'float32')
Don't call gippy, call utils.verbosity
; this way gips tracking its own
verbosity is future-proofed:
- v = gippy.Options.verbose()
+ v = utils.verbosity()
- gippy.Options.SetVerbose(args.verbose)
+ utils.verbosity(args.verbose)
Get & set gippy options mostly as before:
- os.putenv(
- 'GDAL_NUM_THREADS',
- str(int(gippy.Options.NumCores()))
- )
+ os.putenv('GDAL_NUM_THREADS', str(int(gippy.Options.cores())))
# in parser code:
if 'format' in args:
- gippy.Options.SetDefaultFormat(args.format)
+ gippy.Options.set_defaultformat(args.format)
if 'chunksize' in args:
- gippy.Options.SetChunkSize(args.chunksize)
+ gippy.Options.set_chunksize(args.chunksize)
if 'numprocs' in args:
- gippy.Options.SetNumCores(args.numprocs)
+ gippy.Options.set_cores(args.numprocs)
gippy.Recti
is renamed to Chunks but isn't accessible, present workaround:
# setup
- roi = gippy.Recti(pixx - 1, pixy - 1, 3, 3)
+ x0, y0, x1, y1 = pixx - 1, pixy - 1, pixx + 2, pixy + 2
# usage - note performance hit due to larger read:
- vals = img[0].Read(roi).squeeze()
+ vals = img[0].read()[x0:x1,y0:y1].squeeze()
- variances = img[1].Read(roi)
+ variances = img[1].read()[x0:x1,y0:y1]
# you can also:
import gippy
+# temporary hack because gippy deletes gippy.gippy from its module scope
+gippy.gippy = sys.modules['gippy.gippy']
# then in working code, use it as a drop-in replacement for Recti:
- ch = gippy.Recti(chunk[0], chunk[1], chunk[2], chunk[3])
+ ch = gippy.gippy.Chunk(chunk[0], chunk[1], chunk[2], chunk[3])
Indices call changed radically. One call used to create multiple index product files. Now it assumes you want to put many indices layered into the same file, so we have to work around that. Full loop given for context:
# from landsatData._process_indices:
- gippy_input = {} # map prod types to temp output filenames for feeding to gippy
- tempfps_to_ptypes = {} # map temp output filenames to prod types, for AddFile
- for prod_type, pt_split in indices.items():
- temp_fp = self.temp_product_filename(sensor, prod_type)
- gippy_input[pt_split[0]] = temp_fp
- tempfps_to_ptypes[temp_fp] = prod_type
-
- prodout = Indices(image, gippy_input, metadata) # used to call once
-
- for temp_fp in prodout.values():
+ verbose_out("Starting on {} indices: {}".format(len(indices), indices.keys()), 2)
+ for prod_and_args, split_p_and_a in indices.items():
+ verbose_out("Starting on {}".format(prod_and_args), 3)
+ temp_fp = self.temp_product_filename(sensor, prod_and_args)
+ # indices() assumes many indices per file; we just want one
+ imgout = algorithms.indices(image, [split_p_and_a[0]], temp_fp)
+ imgout.add_meta(metadata)
archived_fp = self.archive_temp_path(temp_fp)
- self.AddFile(sensor, tempfps_to_ptypes[temp_fp], archived_fp)
+ self.AddFile(sensor, prod_and_args, archived_fp)
Fmask is a simple spelling change
# difference in import isn't significant here, just refactoring:
- imgout = Fmask(reflimg, fname, tolerance, dilation)
+ imgout = algorithms.fmask(reflimg, fname, tolerance, dilation)
Linear transform is also a simple spelling change but segfaults for gippy 1.0:
- imgout = LinearTransform(tmpimg, fname, arr)
+ imgout = algorithms.linear_transform(tmpimg, fname, arr)
The cookie cutter call cas reorganized arguments:
# note alltouch is removed because it's an AGS-gippy feature only:
- CookieCutter(
- images, self.spatial.site, fout, res[0], res[1],
- crop, interpolation, {}, alltouch,
- )
+ # "" == default to the projection used by the GeoFeature self.spatial.site
+ algorithms.cookie_cutter(images, fout, self.spatial.site, crop, "",
+ res[0], res[1], interpolation)
For more cases & info see https://gippy.readthedocs.io/en/latest/quickstart.html#working-with-images
The GeoImages factory is gone but replaced trivially:
- images = gippy.GeoImages(filenames)
+ images = [gippy.GeoImage(f) for f in filenames]
The four-argument constructor is a factory now:
- imgout = gippy.GeoImage(ofname, img, dtype, len(bands))
+ imgout = gippy.GeoImage.create_from(tmp, img, len(bands), dtype)
The more-than-four arugment constrctor is also a factory now; note MANY arguments defaulted here:
- imgout = gippy.GeoImage(temp_fp, xsz, ysz, 1, dtype)
+ imgout = gippy.GeoImage.create(temp_fp, xsz, ysz, 1,
+ dtype=str(data.dtype))
Several calls are just simple renames:
# metadata
- imgout.SetMeta(pmeta)
+ imgout.add_meta(pmeta)
# band name
- imgout.SetBandName(str(b), i + 1)
+ imgout.set_bandname(str(b), i + 1)
# image filename & basename
- prodout[key] = imgout.Filename()
+ prodout[key] = imgout.filename()
- VerboseOut(' %s' % (img.Basename()), 2)
+ verbose_out(' %s' % (img.basename()), 2)
# gain
- imgout.SetGain(gain)
+ imgout.set_gain(gain)
# offset
- imgout.SetOffset(offset)
+ imgout.set_offset(offset)
# nodata
- imgout.SetNoData(-32768)
+ imgout.set_nodata(-32768)
- vals[numpy.where(vals == img[0].NoDataValue())] = numpy.nan
+ vals[numpy.where(vals == img[0].nodata())] = numpy.nan
# affine
- imgout.SetAffine(geo)
+ imgout.set_affine(geo)
# projection
- imgout.SetProjection(PROJ)
+ imgout.set_srs(PROJ)
- vecname = transform(vector.Filename(), img.Projection())
+ vecname = transform(vector.filename(), img.srs())
# Process renamed to save
- abimg.Process()
+ abimg.save()
- gippy.GeoImage(fin).Process(fout)
+ gippy.GeoImage(fin).save(fout)
# read & return data as a numpy array; but see below for important caveat:
- qadata = qaimg.Read()
+ qadata = qaimg.read()
# compute mean
- img.Mean(imgout[0])
+ img.mean(imgout[0])
# masking
- img.AddMask(mask[0]).Process().ClearMasks()
+ img.add_mask(mask[0]).save(img.filename()).clear_masks()
# name seems unusually different but implementation is believed to be identical:
- tmpimg.PruneBands(['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'])
+ tmpimg.select(['BLUE', 'GREEN', 'RED', 'NIR', 'SWIR1', 'SWIR2'])
# iteration: Use len(img) instead of img.NumBands():
- for band in range(0, img.NumBands()):
+ for band in range(len(img)):
# But for some reason you can also (note images[0] is a GeoImage here):
+ for b in range(0, images[0].nbands()):
Color table support is a special case. It seems incomplete in gippy 1.0:
+ # TODO gippy 1.0 supports add_colortable and clear_colortable but there's no way to
+ # get the colortable, and CopyColorTable is no longer supported; what's needed is:
+ # imgout[b].add_colortbale(images[0][b].colortable())
+ # original was:
+ # imgout.CopyColorTable(images[0])
+ verbose_out("Not copying color table to {};"
+ " not supported by gippy 1.0".format(os.path.basename(outfile)), 2)
In gips our use case is entirely covered by simple renames:
# write
- imgout[i].Write(arr.astype(npdtype))
+ imgout[i].write(arr.astype(npdtype))
# read
- data = img[band].Read()
+ data = img[band].read()
# getters (presumably setters follow the pattern)
- mask = img[band].DataMask()
+ mask = img[band].data_mask()
- nd = images[0][0].NoDataValue()
- srs = images[0].Projection()
+ nd = images[0][0].nodata()
+ srs = images[0].srs()
- [(reflimg[band].Resolution().x(),
+ reflimg[b].resolution() for b in (a_obj.visbands + a_obj.lwbands)))
- color = rad_image[i].Description()
+ color = rad_image[i].description()
# metadata, getting and setting; there's a missing method but it's trivially
# worked around:
- for b in range(0, images[0].NumBands()):
- imgout[b].CopyMeta(images[0][b])
+ for b in range(0, images[0].nbands()):
+ imgout[b].add_meta(images[0][b].meta())
Our use of GeoVector is simple enough that simple method re-spelling is sufficient:
# Several getters:
- self.feature = (feature.Filename(), feature.LayerName(), feature.FID())
+ self.feature = (feature.filename(), feature.layer_name(), feature.fid())
- self.sitename = feature.Basename()
+ self.sitename = feature.basename()
- srs = osr.SpatialReference(vector.Projection())
+ srs = osr.SpatialReference(vector.srs())
- e = utils.open_vector(cls.get_setting('tiles'), cls._tile_attribute)[tileid].Extent()
+ e = utils.open_vector(cls.get_setting('tiles'), cls._tile_attribute)[tileid].extent()
# setting the primary key:
- vector.SetPrimaryKey(key)
+ vector.set_primary_key(key)
These features are warned about or else raise NotImplementedErrors, and only affect certain products or options for gips commands:
GeoImage(...).read()
always returns an nparray of'float64'
regardless of typing info saved to the GeoImage beforehand.read_raw()
seems to do otherwise but isn't exposed to python.GeoImage(...).SetUnits()
is not available.gippy.gippy
is deleted bygippy
at import time; see problem related toRecti
above.algorithms.linear_transform
segfaults, breaking landsat's tcap product.algorithms.acca
has an array IndexError, breaking landsat's acca product.algorithms.cookie_cutter
segfaults whencrop=True
; error message just prior:Error creating /tmp/zs/zonalsummary/0/1970001_user_ukwn0.tifAttempt to create -2668x284 dataset is illegal,sizes must be larger than zero. Segmentation fault (core dumped)
- color table support is incomplete, causing minor feature loss to
gips_project
, whose output files presumably won't have color tables. - AGS-gippy features aren't present in gippy 1.0, so there is loss of function:
- alltouch, an option for
algorithms.cookie_cutter
, is absent, so that option doesn't function forgips_project
. gips.algorithms.AddShadowMask
is a also absent, thus landsat'sbqashadow
product can't be generated.
- alltouch, an option for
gippy.Recti
workaround isgippy.gippy.Chunk