| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780 |
- #!/usr/bin/env python
- """An interface to the Earth Engine batch processing system.
- Use the static methods on the Export class to create export tasks, call start()
- on them to launch them, then poll status() to find out when they are finished.
- The public function styling uses camelCase to match the JavaScript names.
- """
- # pylint: disable=g-bad-name
- # pylint: disable=g-bad-import-order
- import json
- import re
- from . import _cloud_api_utils
- from . import data
- from . import ee_exception
- from . import geometry
- class Task(object):
- """A batch task that can be run on the EE batch processing system."""
- def __init__(self, task_id, task_type, state, config=None, name=None):
- """Creates a Task with the given ID and configuration.
- The constructor is not for public use. Instances can be obtained by:
- - Calling the static method Task.list().
- - Calling any of the methods on the Export static class.
- - Unpickling a previously pickled Task object.
- If you're looking for a task's status but don't need a full task object,
- ee.data.getTaskStatus() may be appropriate.
- Args:
- task_id: The task ID, originally obtained through ee.data.newTaskId().
- May be None if the ID is not yet known.
- task_type: The type of the task; one of the values in Task.Type.
- state: The state of the task; one of the values entries in Task.State.
- config: The task configuration dictionary. Only necessary if start()
- will be called. Fields shared by all tasks are:
- - description: The name of the task, a freeform string.
- - sourceUrl: An optional URL for the script that generated the task.
- Specific task types have other custom config fields.
- name: The name of the operation. Only relevant when using the cloud api.
- """
- self.id = self._request_id = task_id
- self.config = config and config.copy()
- self.workload_tag = data.getWorkloadTag()
- self.task_type = task_type
- self.state = state
- self.name = name
- class Type(object):
- EXPORT_IMAGE = 'EXPORT_IMAGE'
- EXPORT_MAP = 'EXPORT_TILES'
- EXPORT_TABLE = 'EXPORT_FEATURES'
- EXPORT_VIDEO = 'EXPORT_VIDEO'
- class State(object):
- UNSUBMITTED = 'UNSUBMITTED'
- READY = 'READY'
- RUNNING = 'RUNNING'
- COMPLETED = 'COMPLETED'
- FAILED = 'FAILED'
- CANCEL_REQUESTED = 'CANCEL_REQUESTED'
- CANCELLED = 'CANCELLED'
- # Export destinations.
- class ExportDestination(object):
- DRIVE = 'DRIVE'
- GCS = 'GOOGLE_CLOUD_STORAGE'
- ASSET = 'ASSET'
- FEATURE_VIEW = 'FEATURE_VIEW'
- def start(self):
- """Starts the task. No-op for started tasks."""
- if not self.config:
- raise ee_exception.EEException(
- 'Task config must be specified for tasks to be started.')
- if not self._request_id:
- self._request_id = data.newTaskId()[0]
- # Supply the workload tag, even if empty, to prevent it from being reset
- # later.
- if 'workloadTag' not in self.config:
- self.config['workloadTag'] = self.workload_tag
- if self.task_type == Task.Type.EXPORT_IMAGE:
- result = data.exportImage(self._request_id, self.config)
- elif self.task_type == Task.Type.EXPORT_MAP:
- result = data.exportMap(self._request_id, self.config)
- elif self.task_type == Task.Type.EXPORT_TABLE:
- result = data.exportTable(self._request_id, self.config)
- elif self.task_type == Task.Type.EXPORT_VIDEO:
- result = data.exportVideo(self._request_id, self.config)
- else:
- raise ee_exception.EEException(
- 'Unknown Task type "{}"'.format(self.task_type))
- if not self.id:
- self.id = _cloud_api_utils.convert_operation_name_to_task_id(
- result['name'])
- self.name = result['name']
- def status(self):
- """Fetches the current status of the task.
- Returns:
- A dictionary describing the current status of the task as it appears on
- the EE server. Includes the following fields:
- - state: One of the values in Task.State.
- - creation_timestamp_ms: The Unix timestamp of when the task was created.
- - update_timestamp_ms: The Unix timestamp of when the task last changed.
- - output_url: URL of the output. Appears only if state is COMPLETED.
- - error_message: Failure reason. Appears only if state is FAILED.
- May also include other fields.
- """
- if self.id:
- result = data.getTaskStatus(self.id)[0]
- if result['state'] == 'UNKNOWN':
- result['state'] = Task.State.UNSUBMITTED
- else:
- result = {'state': Task.State.UNSUBMITTED}
- return result
- def active(self):
- """Returns whether the task is still running."""
- return self.status()['state'] in (Task.State.READY,
- Task.State.RUNNING,
- Task.State.CANCEL_REQUESTED)
- def cancel(self):
- """Cancels the task."""
- data.cancelTask(self.id)
- @staticmethod
- def list():
- """Returns the tasks submitted to EE by the current user.
- These include all currently running tasks as well as recently canceled or
- failed tasks.
- Returns:
- A list of Tasks.
- """
- statuses = data.getTaskList()
- tasks = []
- for status in statuses:
- tasks.append(Task(status['id'],
- status.get('task_type'),
- status.get('state'),
- {'description': status.get('description')},
- status.get('name')))
- return tasks
- def __repr__(self):
- """Returns a string representation of the task."""
- if self.config and self.id:
- return '<Task %s %s: %s (%s)>' % (self.id, self.task_type,
- self.config['description'], self.state)
- elif self.config:
- return '<Task %s: %s (%s)>' % (self.task_type, self.config['description'],
- self.state)
- else:
- return '<Task "%s">' % self.id
- class Export(object):
- """A class with static methods to start export tasks."""
- def __init__(self):
- """Forbids class instantiation."""
- raise AssertionError('This class cannot be instantiated.')
- class image(object):
- """A static class with methods to start image export tasks."""
- def __init__(self):
- """Forbids class instantiation."""
- raise AssertionError('This class cannot be instantiated.')
- def __new__(cls, image, description='myExportImageTask', config=None):
- """Creates a task to export an EE Image to Google Drive or Cloud Storage.
- Args:
- image: The image to be exported.
- description: Human-readable name of the task.
- config: A dictionary that will be copied and used as parameters
- for the task:
- - region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the image's
- region.
- - scale: The resolution in meters per pixel.
- Defaults to the native resolution of the image assset unless
- a crs_transform is specified.
- - maxPixels: The maximum allowed number of pixels in the exported
- image. The task will fail if the exported region covers
- more pixels in the specified projection. Defaults to 100,000,000.
- - crs: The coordinate reference system of the exported image's
- projection. Defaults to the image's default projection.
- - crs_transform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported image's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image's native CRS transform.
- - dimensions: The dimensions of the exported image. Takes either a
- single positive integer as the maximum dimension or
- "WIDTHxHEIGHT" where WIDTH and HEIGHT are each positive integers.
- - skipEmptyTiles: If true, skip writing empty (i.e. fully-masked)
- image tiles. Defaults to false.
- If exporting to Google Drive (default):
- - driveFolder: The Google Drive Folder that the export will reside
- in. Note: (a) if the folder name exists at any level, the output
- is written to it, (b) if duplicate folder names exist, output is
- written to the most recently modified folder, (c) if the folder
- name does not exist, a new folder will be created at the root,
- and (d) folder names with separators (e.g. 'path/to/file') are
- interpreted as literal strings, not system paths. Defaults to
- Drive root.
- - driveFileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- If exporting to Google Cloud Storage:
- - outputBucket: The name of a Cloud Storage bucket for the export.
- - outputPrefix: Cloud Storage object name prefix for the export.
- Returns:
- An unstarted Task that exports the image.
- """
- config = (config or {}).copy()
- if 'driveFileNamePrefix' not in config and 'outputBucket' not in config:
- config['driveFileNamePrefix'] = description
- if 'driveFileNamePrefix' in config:
- return Export.image.toDrive(image, description, **config)
- else:
- return Export.image.toCloudStorage(image, description, **config)
- # Disable argument usage check; arguments are accessed using locals().
- # pylint: disable=unused-argument
- @staticmethod
- def toAsset(
- image,
- description='myExportImageTask',
- assetId=None,
- pyramidingPolicy=None,
- dimensions=None,
- region=None,
- scale=None,
- crs=None,
- crsTransform=None,
- maxPixels=None,
- **kwargs):
- """Creates a task to export an EE Image to an EE Asset.
- Args:
- image: The image to be exported.
- description: Human-readable name of the task.
- assetId: The destination asset ID.
- pyramidingPolicy: The pyramiding policy to apply to each band in the
- image, a dictionary keyed by band name. Values must be
- one of: "mean", "sample", "min", "max", or "mode".
- Defaults to "mean". A special key, ".default", may be used to
- change the default for all bands.
- dimensions: The dimensions of the exported image. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the image's
- region.
- scale: The resolution in meters per pixel. Defaults to the
- native resolution of the image assset unless a crsTransform
- is specified.
- crs: The coordinate reference system of the exported image's
- projection. Defaults to the image's default projection.
- crsTransform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported image's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image's native CRS transform.
- maxPixels: The maximum allowed number of pixels in the exported
- image. The task will fail if the exported region covers more
- pixels in the specified projection. Defaults to 100,000,000.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform'.
- Returns:
- An unstarted Task that exports the image as an Earth Engine asset.
- """
- config = _capture_parameters(locals(), ['image'])
- config = _prepare_image_export_config(image, config,
- Task.ExportDestination.ASSET)
- return _create_export_task(config, Task.Type.EXPORT_IMAGE)
- # Disable argument usage check; arguments are accessed using locals().
- # pylint: disable=unused-argument
- @staticmethod
- def toCloudStorage(image,
- description='myExportImageTask',
- bucket=None,
- fileNamePrefix=None,
- dimensions=None,
- region=None,
- scale=None,
- crs=None,
- crsTransform=None,
- maxPixels=None,
- shardSize=None,
- fileDimensions=None,
- skipEmptyTiles=None,
- fileFormat=None,
- formatOptions=None,
- **kwargs):
- """Creates a task to export an EE Image to Google Cloud Storage.
- Args:
- image: The image to be exported.
- description: Human-readable name of the task.
- bucket: The name of a Cloud Storage bucket for the export.
- fileNamePrefix: Cloud Storage object name prefix for the export.
- Defaults to the name of the task.
- dimensions: The dimensions of the exported image. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the image's
- region.
- scale: The resolution in meters per pixel. Defaults to the
- native resolution of the image assset unless a crsTransform
- is specified.
- crs: The coordinate reference system of the exported image's
- projection. Defaults to the image's default projection.
- crsTransform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported image's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image's native CRS transform.
- maxPixels: The maximum allowed number of pixels in the exported
- image. The task will fail if the exported region covers more
- pixels in the specified projection. Defaults to 100,000,000.
- shardSize: Size in pixels of the tiles in which this image will be
- computed. Defaults to 256.
- fileDimensions: The dimensions in pixels of each image file, if the
- image is too large to fit in a single file. May specify a
- single number to indicate a square shape, or a tuple of two
- dimensions to indicate (width,height). Note that the image will
- still be clipped to the overall image dimensions. Must be a
- multiple of shardSize.
- skipEmptyTiles: If true, skip writing empty (i.e. fully-masked)
- image tiles. Defaults to false.
- fileFormat: The string file format to which the image is exported.
- Currently only 'GeoTIFF' and 'TFRecord' are supported, defaults to
- 'GeoTIFF'.
- formatOptions: A dictionary of string keys to format specific options.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform'.
- Returns:
- An unstarted Task that exports the image to Google Cloud Storage.
- """
- config = _capture_parameters(locals(), ['image'])
- config = _prepare_image_export_config(image, config,
- Task.ExportDestination.GCS)
- return _create_export_task(config, Task.Type.EXPORT_IMAGE)
- @staticmethod
- def toDrive(image,
- description='myExportImageTask',
- folder=None,
- fileNamePrefix=None,
- dimensions=None,
- region=None,
- scale=None,
- crs=None,
- crsTransform=None,
- maxPixels=None,
- shardSize=None,
- fileDimensions=None,
- skipEmptyTiles=None,
- fileFormat=None,
- formatOptions=None,
- **kwargs):
- """Creates a task to export an EE Image to Drive.
- Args:
- image: The image to be exported.
- description: Human-readable name of the task.
- folder: The name of a unique folder in your Drive account to
- export into. Defaults to the root of the drive.
- fileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- dimensions: The dimensions of the exported image. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the image's
- region.
- scale: The resolution in meters per pixel. Defaults to the
- native resolution of the image assset unless a crsTransform
- is specified.
- crs: The coordinate reference system of the exported image's
- projection. Defaults to the image's default projection.
- crsTransform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported image's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image's native CRS transform.
- maxPixels: The maximum allowed number of pixels in the exported
- image. The task will fail if the exported region covers more
- pixels in the specified projection. Defaults to 100,000,000.
- shardSize: Size in pixels of the tiles in which this image will be
- computed. Defaults to 256.
- fileDimensions: The dimensions in pixels of each image file, if the
- image is too large to fit in a single file. May specify a
- single number to indicate a square shape, or a tuple of two
- dimensions to indicate (width,height). Note that the image will
- still be clipped to the overall image dimensions. Must be a
- multiple of shardSize.
- skipEmptyTiles: If true, skip writing empty (i.e. fully-masked)
- image tiles. Defaults to false.
- fileFormat: The string file format to which the image is exported.
- Currently only 'GeoTIFF' and 'TFRecord' are supported, defaults to
- 'GeoTIFF'.
- formatOptions: A dictionary of string keys to format specific options.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform', 'driveFolder', and 'driveFileNamePrefix'.
- Returns:
- An unstarted Task that exports the image to Drive.
- """
- config = _capture_parameters(locals(), ['image'])
- config = _prepare_image_export_config(image, config,
- Task.ExportDestination.DRIVE)
- return _create_export_task(config, Task.Type.EXPORT_IMAGE)
- # pylint: enable=unused-argument
- class map(object):
- """A class with a static method to start map export tasks."""
- def __init__(self):
- """Forbids class instantiation."""
- raise AssertionError('This class cannot be instantiated.')
- # Disable argument usage check; arguments are accessed using locals().
- # pylint: disable=unused-argument
- @staticmethod
- def toCloudStorage(image, description='myExportMapTask', bucket=None,
- fileFormat=None, path=None, writePublicTiles=None,
- maxZoom=None, scale=None, minZoom=None,
- region=None, skipEmptyTiles=None, mapsApiKey=None,
- **kwargs):
- """Creates a task to export an Image as a pyramid of map tiles.
- Exports a rectangular pyramid of map tiles for use with web map
- viewers. The map tiles will be accompanied by a reference
- index.html file that displays them using the Google Maps API,
- and an earth.html file for opening the map on Google Earth.
- Args:
- image: The image to export as tiles.
- description: Human-readable name of the task.
- bucket: The destination bucket to write to.
- fileFormat: The map tiles' file format, one of 'auto', 'png',
- or 'jpeg'. Defaults to 'auto', which means that opaque tiles
- will be encoded as 'jpg' and tiles with transparency will be
- encoded as 'png'.
- path: The string used as the output's path. A trailing '/'
- is optional. Defaults to the task's description.
- writePublicTiles: Whether to write public tiles instead of using the
- bucket's default object ACL. Defaults to True and requires the
- invoker to be an OWNER of bucket.
- maxZoom: The maximum zoom level of the map tiles to export.
- scale: The max image resolution in meters per pixel, as an alternative
- to 'maxZoom'. The scale will be converted to the most appropriate
- maximum zoom level at the equator.
- minZoom: The optional minimum zoom level of the map tiles to export.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Map tiles will be
- produced in the rectangular region containing this geometry.
- Defaults to the image's region.
- skipEmptyTiles: If true, skip writing empty (i.e. fully-transparent)
- map tiles. Defaults to false.
- mapsApiKey: Used in index.html to initialize the Google Maps API. This
- removes the "development purposes only" message from the map.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform'.
- Returns:
- An unstarted Task that exports the image to Google Cloud Storage.
- """
- config = _capture_parameters(locals(), ['image'])
- config = _prepare_map_export_config(image, config)
- return _create_export_task(config, Task.Type.EXPORT_MAP)
- # pylint: enable=unused-argument
- class table(object):
- """A class with static methods to start table export tasks."""
- def __init__(self):
- """Forbids class instantiation."""
- raise AssertionError('This class cannot be instantiated.')
- def __new__(cls, collection, description='myExportTableTask', config=None):
- """Export an EE FeatureCollection as a table.
- The exported table will reside in Google Drive, Cloud Storage, or as a
- FeatureView.
- Args:
- collection: The feature collection to be exported.
- description: Human-readable name of the task.
- config: A dictionary that will be copied and used as parameters
- for the task:
- - fileFormat: The output format: "CSV" (default), "GeoJSON", "KML",
- "KMZ", or "SHP".
- If exporting to Google Drive (default):
- - driveFolder: The Google Drive Folder that the export will reside
- in. Note: (a) if the folder name exists at any level, the output
- is written to it, (b) if duplicate folder names exist, output is
- written to the most recently modified folder, (c) if the folder
- name does not exist, a new folder will be created at the root,
- and (d) folder names with separators (e.g. 'path/to/file') are
- interpreted as literal strings, not system paths. Defaults to
- Drive root.
- - driveFileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- If exporting to Google Cloud Storage:
- - outputBucket: The name of a Cloud Storage bucket for the export.
- - outputPrefix: Cloud Storage object name prefix for the export.
- If exporting to FeatureView:
- - thinning_options: Options that control the density at which
- features are displayed per tile.
- - ranking_options: Options for assigning z-order ranks and thinning
- ranks to features.
- Returns:
- An unstarted Task that exports the table.
- """
- config = (config or {}).copy()
- if 'driveFileNamePrefix' not in config and 'outputBucket' not in config:
- config['driveFileNamePrefix'] = description
- if 'driveFileNamePrefix' in config:
- return Export.table.toDrive(collection, description, **config)
- else:
- return Export.table.toCloudStorage(collection, description, **config)
- # Disable argument usage check; arguments are accessed using locals().
- # pylint: disable=unused-argument
- @staticmethod
- def toCloudStorage(collection,
- description='myExportTableTask',
- bucket=None,
- fileNamePrefix=None,
- fileFormat=None,
- selectors=None,
- maxVertices=None,
- **kwargs):
- """Creates a task to export a FeatureCollection to Google Cloud Storage.
- Args:
- collection: The feature collection to be exported.
- description: Human-readable name of the task.
- bucket: The name of a Cloud Storage bucket for the export.
- fileNamePrefix: Cloud Storage object name prefix for the export.
- Defaults to the name of the task.
- fileFormat: The output format: "CSV" (default), "GeoJSON", "KML", "KMZ",
- "SHP", or "TFRecord".
- selectors: The list of properties to include in the output, as a list
- of strings or a comma-separated string. By default, all properties
- are included.
- maxVertices:
- Max number of uncut vertices per geometry; geometries with more
- vertices will be cut into pieces smaller than this size.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'outputBucket'.
- Returns:
- An unstarted Task that exports the table to Google Cloud Storage.
- """
- config = _capture_parameters(locals(), ['collection'])
- config = _prepare_table_export_config(collection, config,
- Task.ExportDestination.GCS)
- return _create_export_task(config, Task.Type.EXPORT_TABLE)
- @staticmethod
- def toDrive(collection,
- description='myExportTableTask',
- folder=None,
- fileNamePrefix=None,
- fileFormat=None,
- selectors=None,
- maxVertices=None,
- **kwargs):
- """Creates a task to export a FeatureCollection to Drive.
- Args:
- collection: The feature collection to be exported.
- description: Human-readable name of the task.
- folder: The name of a unique folder in your Drive account to
- export into. Defaults to the root of the drive.
- fileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- fileFormat: The output format: "CSV" (default), "GeoJSON", "KML",
- "KMZ", "SHP", or "TFRecord".
- selectors: The list of properties to include in the output, as a list
- of strings or a comma-separated string. By default, all properties
- are included.
- maxVertices:
- Max number of uncut vertices per geometry; geometries with more
- vertices will be cut into pieces smaller than this size.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'driveFolder' and 'driveFileNamePrefix'.
- Returns:
- An unstarted Task that exports the table.
- """
- config = _capture_parameters(locals(), ['collection'])
- config = _prepare_table_export_config(collection, config,
- Task.ExportDestination.DRIVE)
- return _create_export_task(config, Task.Type.EXPORT_TABLE)
- @staticmethod
- def toAsset(
- collection,
- description='myExportTableTask',
- assetId=None,
- maxVertices=None,
- **kwargs):
- """Creates a task to export a FeatureCollection to an EE table asset.
- Args:
- collection: The feature collection to be exported.
- description: Human-readable name of the task.
- assetId: The destination asset ID.
- maxVertices:
- Max number of uncut vertices per geometry; geometries with more
- vertices will be cut into pieces smaller than this size.
- **kwargs: Holds other keyword arguments that may have been deprecated.
- Returns:
- An unstarted Task that exports the table.
- """
- config = {
- 'description': description,
- 'assetId': assetId,
- 'maxVertices': maxVertices,
- }
- config = {k: v for k, v, in config.items() if v is not None}
- config = _prepare_table_export_config(collection, config,
- Task.ExportDestination.ASSET)
- return _create_export_task(config, Task.Type.EXPORT_TABLE)
- @staticmethod
- def toFeatureView(
- collection,
- description='myExportTableTask',
- assetId=None,
- ingestionTimeParameters=None,
- **kwargs):
- """Creates a task to export a FeatureCollection to a FeatureView.
- Args:
- collection: The feature collection to be exported.
- description: Human-readable name of the task.
- assetId: The destination asset ID.
- ingestionTimeParameters: The FeatureView ingestion time parameters.
- **kwargs: Holds other keyword arguments that may have been deprecated.
- Returns:
- An unstarted Task that exports the table.
- """
- config = {
- 'description': description,
- 'assetId': assetId,
- 'ingestionTimeParameters': ingestionTimeParameters,
- }
- config = {k: v for k, v, in config.items() if v is not None}
- config = _prepare_table_export_config(collection, config,
- Task.ExportDestination.FEATURE_VIEW)
- return _create_export_task(config, Task.Type.EXPORT_TABLE)
- class video(object):
- """A class with static methods to start video export task."""
- def __init__(self):
- """Forbids class instantiation."""
- raise AssertionError('This class cannot be instantiated.')
- def __new__(cls, collection, description='myExportVideoTask', config=None):
- """Exports an EE ImageCollection as a video.
- The exported video will reside in Google Drive or Cloud Storage.
- Args:
- collection: The image collection to be exported. The collection must
- only contain RGB images.
- description: Human-readable name of the task.
- config: A dictionary of configuration parameters for the task:
- - region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the first
- image's region.
- - scale: The resolution in meters per pixel.
- - crs: The coordinate reference system of the exported video's
- projection. Defaults to SR-ORG:6627.
- - crs_transform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported video's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image collection's native CRS transform.
- - dimensions: The dimensions of the exported video. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- - framesPerSecond: A number between .1 and 120 describing the
- framerate of the exported video.
- - maxPixels: The maximum number of pixels per frame.
- Defaults to 1e8 pixels per frame. By setting this explicitly,
- you may raise or lower the limit.
- - maxFrames: The maximum number of frames.
- Defaults to 1000 frames. By setting this explicitly, you may
- raise or lower the limit.
- If exporting to Google Drive (default):
- - driveFolder: The Google Drive Folder that the export will reside
- in. Note: (a) if the folder name exists at any level, the output
- is written to it, (b) if duplicate folder names exist, output is
- written to the most recently modified folder, (c) if the folder
- name does not exist, a new folder will be created at the root,
- and (d) folder names with separators (e.g. 'path/to/file') are
- interpreted as literal strings, not system paths. Defaults to
- Drive root.
- - driveFileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- If exporting to Google Cloud Storage:
- - outputBucket: The name of a Cloud Storage bucket for the export.
- - outputPrefix: Cloud Storage object name prefix for the export.
- Returns:
- An unstarted Task that exports the video.
- """
- config = (config or {}).copy()
- if 'driveFileNamePrefix' not in config and 'outputBucket' not in config:
- config['driveFileNamePrefix'] = description
- if 'driveFileNamePrefix' in config:
- return Export.video.toDrive(collection, description, **config)
- else:
- return Export.video.toCloudStorage(collection, description, **config)
- # Disable argument usage check; arguments are accessed using locals().
- # pylint: disable=unused-argument
- @staticmethod
- def toCloudStorage(collection, description='myExportVideoTask',
- bucket=None, fileNamePrefix=None, framesPerSecond=None,
- dimensions=None, region=None, scale=None, crs=None,
- crsTransform=None, maxPixels=None,
- maxFrames=None, **kwargs):
- """Creates a task to export an ImageCollection video to Cloud Storage.
- Args:
- collection: The image collection to be exported. The collection must
- only contain RGB images.
- description: Human-readable name of the task.
- bucket: The name of a Cloud Storage bucket for the export.
- fileNamePrefix: Cloud Storage object name prefix for the export.
- Defaults to the task's description.
- framesPerSecond: A number between .1 and 120 describing the
- framerate of the exported video.
- dimensions: The dimensions of the exported video. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the first
- image's region.
- scale: The resolution in meters per pixel.
- crs: The coordinate reference system of the exported video's
- projection. Defaults to SR-ORG:6627.
- crsTransform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported video's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image collection's native CRS transform.
- maxPixels: The maximum number of pixels per frame.
- Defaults to 1e8 pixels per frame. By setting this explicitly,
- you may raise or lower the limit.
- maxFrames: The maximum number of frames to export.
- Defaults to 1000 frames. By setting this explicitly, you may
- raise or lower the limit.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform'.
- Returns:
- An unstarted Task that exports the image collection
- to Google Cloud Storage.
- """
- config = _capture_parameters(locals(), ['collection'])
- config = _prepare_video_export_config(collection, config,
- Task.ExportDestination.GCS)
- return _create_export_task(config, Task.Type.EXPORT_VIDEO)
- @staticmethod
- def toDrive(collection, description='myExportVideoTask',
- folder=None, fileNamePrefix=None, framesPerSecond=None,
- dimensions=None, region=None, scale=None, crs=None,
- crsTransform=None, maxPixels=None, maxFrames=None, **kwargs):
- """Creates a task to export an ImageCollection as a video to Drive.
- Args:
- collection: The image collection to be exported. The collection must
- only contain RGB images.
- description: Human-readable name of the task.
- folder: The name of a unique folder in your Drive account to
- export into. Defaults to the root of the drive.
- fileNamePrefix: The Google Drive filename for the export.
- Defaults to the name of the task.
- framesPerSecond: A number between .1 and 120 describing the
- framerate of the exported video.
- dimensions: The dimensions of the exported video. Takes either a
- single positive integer as the maximum dimension or "WIDTHxHEIGHT"
- where WIDTH and HEIGHT are each positive integers.
- region: The lon,lat coordinates for a LinearRing or Polygon
- specifying the region to export. Can be specified as a nested
- lists of numbers or a serialized string. Defaults to the first
- image's region.
- scale: The resolution in meters per pixel.
- crs: The coordinate reference system of the exported video's
- projection. Defaults to SR-ORG:6627.
- crsTransform: A comma-separated string of 6 numbers describing
- the affine transform of the coordinate reference system of the
- exported video's projection, in the order: xScale, xShearing,
- xTranslation, yShearing, yScale and yTranslation. Defaults to
- the image collection's native CRS transform.
- maxPixels: The maximum number of pixels per frame.
- Defaults to 1e8 pixels per frame. By setting this explicitly,
- you may raise or lower the limit.
- maxFrames: The maximum number of frames to export.
- Defaults to 1000 frames. By setting this explicitly, you may
- raise or lower the limit.
- **kwargs: Holds other keyword arguments that may have been deprecated
- such as 'crs_transform'.
- Returns:
- An unstarted Task that exports the image collection to Drive.
- """
- config = _capture_parameters(locals(), ['collection'])
- config = _prepare_video_export_config(collection, config,
- Task.ExportDestination.DRIVE)
- return _create_export_task(config, Task.Type.EXPORT_VIDEO)
- def _CheckConfigDisallowedPrefixes(config, prefix):
- for key in config:
- if key.startswith(prefix):
- raise ee_exception.EEException(
- 'Export config parameter prefix "{}" disallowed, found "{}"'.
- format(prefix, key))
- # Mapping from file formats to prefixes attached to format specific config.
- FORMAT_PREFIX_MAP = {'GEOTIFF': 'tiff', 'TFRECORD': 'tfrecord'}
- # Configuration field specifying file format for image exports.
- IMAGE_FORMAT_FIELD = 'fileFormat'
- # Image format-specific options dictionary config field.
- IMAGE_FORMAT_OPTIONS_FIELD = 'formatOptions'
- # Format-specific options permitted in formatOptions config parameter.
- ALLOWED_FORMAT_OPTIONS = {
- 'tiffCloudOptimized', 'tiffFileDimensions', 'tfrecordPatchDimensions',
- 'tfrecordKernelSize', 'tfrecordCompressed', 'tfrecordMaxFileSize',
- 'tfrecordDefaultValue', 'tfrecordTensorDepths', 'tfrecordSequenceData',
- 'tfrecordCollapseBands', 'tfrecordMaskedThreshold'
- }
- def _ConvertConfigParams(config):
- """Converts numeric sequences into comma-separated string representations."""
- updatedConfig = {}
- # Non-Cloud API expects that pyramiding policy is a JSON string.
- if 'pyramidingPolicy' in config:
- updatedConfig['pyramidingPolicy'] = json.dumps(config['pyramidingPolicy'])
- for k, v in config.items():
- if v and isinstance(v, (list, tuple)):
- # Leave nested lists/tuples alone. We're only interested in converting
- # lists of strings or numbers.
- if not isinstance(v[0], (list, tuple)):
- updatedConfig[k] = ','.join(str(e) for e in v)
- return updatedConfig
- # TODO(user): This method and its uses are very hack-y, and once we're using One
- # Platform API we should stop sending arbitrary parameters from "options".
- def ConvertFormatSpecificParams(configDict):
- """Mutates configDict into server params by extracting format options.
- For example:
- {'fileFormat': 'GeoTIFF', 'formatOptions': {'cloudOptimized': true}}
- becomes:
- {'fileFormat': 'GeoTIFF', 'tiffCloudOptimized': true}
- Also performs checks to make sure any specified options are valid and/or
- won't collide with top level arguments when converted to server-friendly
- parameters.
- Args:
- configDict: A task config dict
- Raises:
- EEException: We were unable to create format specific parameters for the
- server.
- """
- formatString = 'GeoTIFF'
- if IMAGE_FORMAT_FIELD in configDict:
- formatString = configDict[IMAGE_FORMAT_FIELD]
- formatString = formatString.upper()
- if formatString not in FORMAT_PREFIX_MAP:
- raise ee_exception.EEException(
- 'Invalid file format. Currently only "GeoTIFF" and "TFRecord" is '
- 'supported.')
- if IMAGE_FORMAT_OPTIONS_FIELD in configDict:
- options = configDict.pop(IMAGE_FORMAT_OPTIONS_FIELD)
- if set(options) & set(configDict):
- raise ee_exception.EEException(
- 'Parameter specified at least twice: once in config, '
- 'and once in format options.')
- prefix = FORMAT_PREFIX_MAP[formatString]
- _CheckConfigDisallowedPrefixes(configDict, prefix)
- prefixedOptions = {}
- for key, value in options.items():
- prefixedKey = prefix + key[:1].upper() + key[1:]
- if prefixedKey not in ALLOWED_FORMAT_OPTIONS:
- raise ee_exception.EEException(
- '"{}" is not a valid option for "{}".'.format(
- key, formatString))
- prefixedOptions[prefixedKey] = value
- prefixedOptions.update(_ConvertConfigParams(prefixedOptions))
- configDict.update(prefixedOptions)
- def _prepare_image_export_config(image, config, export_destination):
- """Performs all preparation steps for an image export.
- Args:
- image: The Image to be exported.
- config: All the user-specified export parameters. May be modified.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A config dict containing all information required for the export.
- """
- # Supply some defaults.
- if (export_destination != Task.ExportDestination.ASSET and
- 'fileFormat' not in config):
- config['fileFormat'] = 'GeoTIFF'
- _canonicalize_parameters(config, export_destination)
- image, config = image.prepare_for_export(config)
- # Build an ExportImageRequest. Delete values from "config" as we go so we
- # can check at the end for any leftovers. Any computed objects will be
- # serialised in data.py before the request is sent.
- request = {}
- request['expression'] = image
- if 'description' in config:
- request['description'] = config.pop('description')
- if export_destination == Task.ExportDestination.ASSET:
- asset_export_options = {}
- asset_export_options[
- 'earthEngineDestination'] = _build_earth_engine_destination(config)
- # This can only be set by internal users.
- if 'tileSize' in config and 'shardSize' in config:
- raise ee_exception.EEException(
- 'Both "shardSize" and "tileSize" cannot be set.')
- if 'tileSize' in config:
- asset_export_options['tileSize'] = {
- 'value': int(config.pop('tileSize'))}
- # "shardSize" is the old name for "tileSize".
- if 'shardSize' in config:
- asset_export_options['tileSize'] = {'value': int(config.pop('shardSize'))}
- if 'pyramidingPolicy' in config:
- pyramiding_policy = config.pop('pyramidingPolicy')
- if '.default' in pyramiding_policy:
- asset_export_options[
- 'pyramidingPolicy'] = pyramiding_policy.pop('.default').upper()
- if pyramiding_policy:
- asset_export_options['pyramidingPolicyOverrides'] = {
- band: policy.upper() for band, policy in pyramiding_policy.items()
- }
- request['assetExportOptions'] = asset_export_options
- else:
- request['fileExportOptions'] = _build_image_file_export_options(
- config, export_destination)
- if 'maxPixels' in config:
- # This field is an Int64Value, so it needs an inner "value" field, and
- # the value itself is a string, not an integer, in the JSON encoding.
- request['maxPixels'] = {'value': str(int(config.pop('maxPixels')))}
- # This can only be set by internal users.
- if 'maxWorkers' in config:
- request['maxWorkers'] = {'value': int(config.pop('maxWorkers'))}
- # Of the remaining fields in ExportImageRequest:
- # - All the values that would go into the PixelGrid should have been folded
- # into the image's Expression.
- # - The request ID will be populated when the Task is created.
- # We've been deleting config parameters as we handle them. Anything left
- # over is a problem.
- if config:
- raise ee_exception.EEException(
- 'Unknown configuration options: {}.'.format(config))
- return request
- def _prepare_map_export_config(image, config):
- """Performs all preparation steps for a map export.
- Args:
- image: The Image to be exported.
- config: All the user-specified export parameters. May be modified.
- Returns:
- A config dict containing all information required for the export.
- """
- _canonicalize_parameters(config, Task.ExportDestination.GCS)
- # We have to protect the "scale" parameter as prepare_for_export will try
- # to interpret it inappropriately.
- scale = config.pop('scale', None)
- image, config = image.prepare_for_export(config)
- if scale is not None:
- config['scale'] = scale
- if 'fileFormat' not in config:
- config['fileFormat'] = 'auto'
- if 'writePublicTiles' not in config:
- config['writePublicTiles'] = True
- request = {}
- request['expression'] = image
- if 'description' in config:
- request['description'] = config.pop('description')
- request['tileOptions'] = _build_tile_options(config)
- request['tileExportOptions'] = _build_image_file_export_options(
- config, Task.ExportDestination.GCS)
- # This can only be set by internal users.
- if 'maxWorkers' in config:
- request['maxWorkers'] = {'value': int(config.pop('maxWorkers'))}
- if config:
- raise ee_exception.EEException(
- 'Unknown configuration options: {}.'.format(config))
- return request
- def _prepare_table_export_config(collection, config, export_destination):
- """Performs all preparation steps for a table export.
- Args:
- collection: The FeatureCollection to be exported.
- config: All the user-specified export parameters. May be modified.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A config dict containing all information required for the export.
- """
- if (export_destination != Task.ExportDestination.ASSET and
- export_destination != Task.ExportDestination.FEATURE_VIEW):
- if 'fileFormat' not in config:
- config['fileFormat'] = 'CSV'
- _canonicalize_parameters(config, export_destination)
- # Build an ExportMapRequest. Delete values from "config" as we go so we
- # can check at the end for any leftovers. Any computed objects will be
- # serialised in data.py before the request is sent.
- request = {}
- request['expression'] = collection
- if 'description' in config:
- request['description'] = config.pop('description')
- if export_destination == Task.ExportDestination.ASSET:
- request['assetExportOptions'] = {
- 'earthEngineDestination': _build_earth_engine_destination(config)
- }
- elif export_destination == Task.ExportDestination.FEATURE_VIEW:
- request['featureViewExportOptions'] = {
- 'featureViewDestination':
- _build_feature_view_destination(config),
- 'ingestionTimeParameters':
- build_ingestion_time_parameters(
- config.pop('ingestionTimeParameters', None))
- }
- else:
- request['fileExportOptions'] = _build_table_file_export_options(
- config, export_destination)
- if 'selectors' in config:
- # Strings have been turned into lists but we still might be holding a
- # tuple or other non-list iterable.
- request['selectors'] = list(config.pop('selectors'))
- if 'maxVertices' in config:
- request['maxVertices'] = {'value': int(config.pop('maxVertices'))}
- # This can only be set by internal users.
- if 'maxWorkers' in config:
- request['maxWorkers'] = {'value': int(config.pop('maxWorkers'))}
- if config:
- raise ee_exception.EEException(
- 'Unknown configuration options: {}.'.format(config))
- return request
- def _prepare_video_export_config(collection, config, export_destination):
- """Performs all preparation steps for a video export.
- Args:
- collection: The ImageCollection to be exported as a video.
- config: All the user-specified export parameters. May be modified.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A config dict containing all information required for the export.
- """
- _canonicalize_parameters(config, export_destination)
- if 'crs' not in config:
- config['crs'] = 'SR-ORG:6627'
- collection, config = collection.prepare_for_export(config)
- request = {}
- request['expression'] = collection
- if 'description' in config:
- request['description'] = config.pop('description')
- video_options = _build_video_options(config)
- if video_options:
- request['videoOptions'] = video_options
- request['fileExportOptions'] = _build_video_file_export_options(
- config, export_destination)
- # This can only be set by internal users.
- if 'maxWorkers' in config:
- request['maxWorkers'] = {'value': int(config.pop('maxWorkers'))}
- if config:
- raise ee_exception.EEException(
- 'Unknown configuration options: {}.'.format(config))
- return request
- def _build_image_file_export_options(config, export_destination):
- """Builds an ImageFileExportOptions from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the ImageFileExportOptions.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- An ImageFileExportOptions containing information extracted from config.
- """
- file_export_options = {}
- file_format = _cloud_api_utils.convert_to_image_file_format(
- config.pop('fileFormat'))
- file_export_options['fileFormat'] = file_format
- if export_destination == Task.ExportDestination.DRIVE:
- file_export_options['driveDestination'] = _build_drive_destination(
- config)
- elif export_destination == Task.ExportDestination.GCS:
- file_export_options[
- 'cloudStorageDestination'] = _build_cloud_storage_destination(
- config)
- else:
- raise ee_exception.EEException(
- '"{}" is not a valid export destination'.format(export_destination))
- file_format_options = config.pop(IMAGE_FORMAT_OPTIONS_FIELD, {})
- if file_format == 'GEO_TIFF':
- geo_tiff_options = {}
- if file_format_options.pop('cloudOptimized', False):
- geo_tiff_options['cloudOptimized'] = True
- file_dimensions = file_format_options.pop('fileDimensions', None)
- if 'fileDimensions' in config:
- if file_dimensions is not None:
- raise ee_exception.EEException('File dimensions specified twice.')
- file_dimensions = config.pop('fileDimensions')
- if file_dimensions is not None:
- if isinstance(file_dimensions, int):
- file_dimensions = (file_dimensions, file_dimensions)
- geo_tiff_options['tileDimensions'] = {
- 'width': file_dimensions[0],
- 'height': file_dimensions[1]
- }
- if config.pop('skipEmptyTiles', False):
- geo_tiff_options['skipEmptyFiles'] = True
- if config.get('shardSize', None):
- geo_tiff_options['tileSize'] = {'value': config.pop('shardSize')}
- if geo_tiff_options:
- file_export_options['geoTiffOptions'] = geo_tiff_options
- elif file_format == 'TF_RECORD_IMAGE':
- tf_record_options = {}
- if 'patchDimensions' in file_format_options:
- tile_dimensions = file_format_options.pop('patchDimensions')
- tf_record_options['tileDimensions'] = (
- _cloud_api_utils.convert_to_grid_dimensions(tile_dimensions))
- if 'kernelSize' in file_format_options:
- margin_dimensions = file_format_options.pop('kernelSize')
- tf_record_options['marginDimensions'] = (
- _cloud_api_utils.convert_to_grid_dimensions(margin_dimensions))
- if file_format_options.pop('compressed', False):
- tf_record_options['compress'] = True
- if 'maxFileSize' in file_format_options:
- # This field is an Int64Value, so it needs an inner "value" field, and
- # the value itself is a string, not an integer, in the JSON encoding.
- tf_record_options['maxSizeBytes'] = {
- 'value': str(int(file_format_options.pop('maxFileSize')))
- }
- if 'defaultValue' in file_format_options:
- tf_record_options['defaultValue'] = file_format_options.pop(
- 'defaultValue')
- if 'tensorDepths' in file_format_options:
- tensor_depths = file_format_options.pop('tensorDepths')
- if not isinstance(tensor_depths, dict):
- # This used to be a list of integers.
- raise ee_exception.EEException(
- 'tensorDepths must be a map from band name to the depth '
- 'of the tensor for that band')
- tf_record_options['tensorDepths'] = tensor_depths
- if file_format_options.pop('sequenceData', False):
- tf_record_options['sequenceData'] = True
- if file_format_options.pop('collapseBands', False):
- tf_record_options['collapseBands'] = True
- if 'maskedThreshold' in file_format_options:
- tf_record_options['maxMaskedRatio'] = {
- 'value': file_format_options.pop('maskedThreshold')
- }
- if tf_record_options:
- file_export_options['tfRecordOptions'] = tf_record_options
- if file_format_options:
- raise ee_exception.EEException(
- 'Unknown file format options: {}.'.format(file_format_options))
- return file_export_options
- def _build_table_file_export_options(config, export_destination):
- """Builds a TableFileExportOptions from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the TableFileExportOptions.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A TableFileExportOptions containing information extracted from config.
- """
- file_export_options = {}
- file_format = _cloud_api_utils.convert_to_table_file_format(
- config.pop('fileFormat'))
- file_export_options['fileFormat'] = file_format
- if export_destination == Task.ExportDestination.DRIVE:
- file_export_options['driveDestination'] = _build_drive_destination(
- config)
- elif export_destination == Task.ExportDestination.GCS:
- file_export_options[
- 'cloudStorageDestination'] = _build_cloud_storage_destination(
- config)
- else:
- raise ee_exception.EEException(
- '"{}" is not a valid export destination'.format(export_destination))
- return file_export_options
- def _build_video_options(config):
- """Builds a VideoOptions from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the VideoOptions.
- Returns:
- A VideoOptions containing information extracted from config.
- """
- video_options = {}
- if 'framesPerSecond' in config:
- video_options['framesPerSecond'] = config.pop('framesPerSecond')
- if 'maxFrames' in config:
- video_options['maxFrames'] = config.pop('maxFrames')
- if 'maxPixels' in config:
- video_options['maxPixelsPerFrame'] = {
- 'value': str(int(config.pop('maxPixels')))}
- return video_options
- def _build_video_file_export_options(config, export_destination):
- """Builds a VideoFileExportOptions from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the VideoFileExportOptions.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A VideoFileExportOptions containing information extracted from config.
- """
- file_export_options = {}
- # There's only one file format currently.
- file_export_options['fileFormat'] = 'MP4'
- if export_destination == Task.ExportDestination.DRIVE:
- file_export_options['driveDestination'] = _build_drive_destination(
- config)
- elif export_destination == Task.ExportDestination.GCS:
- file_export_options[
- 'cloudStorageDestination'] = _build_cloud_storage_destination(
- config)
- else:
- raise ee_exception.EEException(
- '"{}" is not a valid export destination'.format(export_destination))
- return file_export_options
- def _prepare_classifier_export_config(classifier, config, export_destination):
- """Performs all preparation steps for a classifier export.
- Args:
- classifier: The Classifier to be exported.
- config: All the user-specified export parameters. May be modified.
- export_destination: One of the Task.ExportDestination values.
- Returns:
- A config dict containing all information required for the export.
- """
- request = {}
- request['expression'] = classifier
- if 'description' in config:
- request['description'] = config.pop('description')
- if export_destination == Task.ExportDestination.ASSET:
- request['assetExportOptions'] = {
- 'earthEngineDestination': _build_earth_engine_destination(config)
- }
- else:
- raise ValueError('Only the "ASSET" destination type is supported.')
- return request
- def _build_drive_destination(config):
- """Builds a DriveDestination from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the DriveDestination.
- Returns:
- A DriveDestination containing information extracted from config.
- """
- drive_destination = {}
- if 'driveFolder' in config:
- drive_destination['folder'] = config.pop('driveFolder')
- if 'driveFileNamePrefix' in config:
- drive_destination['filenamePrefix'] = config.pop(
- 'driveFileNamePrefix')
- return drive_destination
- def _build_cloud_storage_destination(config):
- """Builds a CloudStorageDestination from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the CloudStorageDestination.
- Returns:
- A CloudStorageDestination containing information extracted from
- config.
- """
- cloud_storage_export_destination = {'bucket': config.pop('outputBucket')}
- if 'outputPrefix' in config:
- cloud_storage_export_destination['filenamePrefix'] = config.pop(
- 'outputPrefix')
- if config.pop('writePublicTiles', False):
- cloud_storage_export_destination['permissions'] = 'PUBLIC'
- return cloud_storage_export_destination
- def _build_tile_options(config):
- """Builds a TileOptions from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the TileOptions.
- Returns:
- A TileOptions containing information extracted from config.
- """
- tile_options = {}
- if 'maxZoom' in config:
- if 'scale' in config:
- raise ee_exception.EEException('Both maxZoom and scale are specified.')
- tile_options['endZoom'] = config.pop('maxZoom')
- if 'endZoom' in config:
- if 'scale' in config:
- raise ee_exception.EEException('Both endZoom and scale are specified.')
- tile_options['endZoom'] = config.pop('endZoom')
- if 'scale' in config:
- tile_options['scale'] = config.pop('scale')
- if 'minZoom' in config:
- tile_options['startZoom'] = config.pop('minZoom')
- if 'startZoom' in config:
- tile_options['startZoom'] = config.pop('startZoom')
- if config.pop('skipEmptyTiles', False):
- tile_options['skipEmpty'] = True
- if 'skipEmpty' in config:
- tile_options['skipEmpty'] = config.pop('skipEmpty')
- if 'mapsApiKey' in config:
- tile_options['mapsApiKey'] = config.pop('mapsApiKey')
- return tile_options
- def _build_earth_engine_destination(config):
- """Builds an EarthEngineDestination from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the EarthEngineDestination.
- Returns:
- An EarthEngineDestination containing information extracted from
- config.
- """
- return {
- 'name':
- _cloud_api_utils.convert_asset_id_to_asset_name(
- config.pop('assetId')),
- }
- def _build_feature_view_destination(config):
- """Builds a FeatureViewDestination from values in a config dict.
- Args:
- config: All the user-specified export parameters. Will be modified in-place
- by removing parameters used in the FeatureViewDestination.
- Returns:
- A FeatureViewDestination containing information extracted from
- config.
- """
- feature_view_destination = {
- 'name':
- _cloud_api_utils.convert_asset_id_to_asset_name(
- config.pop('assetId')),
- }
- return feature_view_destination
- def _get_rank_by_one_thing_rule(rule_str):
- """Returns a RankByOneThingRule dict created from the rank-by-one-thing rule.
- Args:
- rule_str: The rule string. The string is expected in the format:
- `rule_type rule_direction`. Valid rule types include `.minZoomLevel`,
- `.geometryType`, or an arbitrary string to represent attribute rules.
- Valid rule directions include `ASC` or `DESC`.
- Returns:
- A RankByOneThingRule object containing information extracted from rule_str.
- """
- matches = re.findall(r'^([\S]+.*)\s+(ASC|DESC)$', rule_str.strip())
- if not matches:
- raise ee_exception.EEException(
- ('Ranking rule format is invalid. Each rule should be defined by a '
- 'rule type and a direction (ASC or DESC), separated by a space. '
- 'Valid rule types are: .geometryType, .minZoomLevel, or a feature '
- 'property name.'))
- output = {}
- rule_type, rule_dir = matches[0]
- if rule_type == '.geometryType':
- output['rankByGeometryTypeRule'] = {}
- elif rule_type == '.minZoomLevel':
- output['rankByMinZoomLevelRule'] = {}
- else:
- output['rankByAttributeRule'] = {'attributeName': rule_type}
- if rule_dir.upper() == 'ASC':
- output['direction'] = 'ASCENDING'
- elif rule_dir.upper() == 'DESC':
- output['direction'] = 'DESCENDING'
- return output
- def _get_ranking_rule(rules):
- """Returns a RankingRule dict created from the rank-by-one-thing rules.
- Args:
- rules: A string representing comma separated rank-by-one-thing rules, or a
- list of rank-by-one-thing rule strings.
- Returns:
- A RankingRule object containing information extracted from rules.
- """
- if not rules:
- return None
- rules_arr = rules
- if isinstance(rules, str):
- rules_arr = rules.split(',')
- if isinstance(rules_arr, list):
- rank_by_one_thing_rules = list(
- map(_get_rank_by_one_thing_rule, rules_arr))
- return {'rankByOneThingRule': rank_by_one_thing_rules}
- raise ee_exception.EEException(
- ('Unable to build ranking rule from rules. Rules should '
- 'either be a comma-separated string or list of strings.'))
- def _build_thinning_options(config):
- """Returns a ThinningOptions dict created from the config.
- Args:
- config: The user-specified ingestion parameters. Will be modified in-place
- by removing parameters used in the ThinningOptions.
- Returns:
- A ThinningOptions object containing information extracted from config.
- """
- if not config:
- return None
- output = {}
- for key in ['maxFeaturesPerTile', 'thinningStrategy']:
- if key in config:
- output[key] = config.pop(key)
- return output
- def _build_ranking_options(config):
- """Returns a RankingOptions dict created from the config.
- Args:
- config: The user-specified export parameters. Will be modified in-place
- by removing parameters used in the RankingOptions.
- Returns:
- A RankingOptions object containing information extracted from config.
- """
- if not config:
- return None
- output = {}
- thinning_ranking = config.pop('thinningRanking', None)
- thinning_ranking_rule = _get_ranking_rule(thinning_ranking)
- if thinning_ranking_rule:
- output['thinningRankingRule'] = thinning_ranking_rule
- z_order_ranking = config.pop('zOrderRanking', None)
- z_order_ranking_rule = _get_ranking_rule(z_order_ranking)
- if z_order_ranking_rule:
- output['zOrderRankingRule'] = z_order_ranking_rule
- return output
- def build_ingestion_time_parameters(input_params):
- """Builds a FeatureViewIngestionTimeParameters from values in a params dict.
- Args:
- input_params: All the user-specified ingestions time parameters. Will be
- modified in-place to remove fields in FeatureViewIngestionTimeParameters.
- Returns:
- A FeatureViewIngestionTimeParameters containing information extracted from
- config.
- """
- output_params = {}
- thinning_options = _build_thinning_options(input_params)
- if thinning_options:
- output_params['thinningOptions'] = thinning_options
- ranking_options = _build_ranking_options(input_params)
- if ranking_options:
- output_params['rankingOptions'] = ranking_options
- if input_params:
- raise ee_exception.EEException(
- 'The following keys are unrecognized in the ingestion parameters: %s' %
- list(input_params.keys()))
- return output_params
- def _create_export_task(config, task_type):
- """Creates an export task.
- Args:
- config: Custom config fields for the task.
- task_type: The type of the task to create. One of Task.Type.
- Returns:
- An unstarted export Task.
- """
- return Task(None, task_type, Task.State.UNSUBMITTED, config)
- def _capture_parameters(all_locals, parameters_to_exclude):
- """Creates a parameter dict by copying all non-None locals.
- This is generally invoked as the first part of call processing, via
- something like
- _capture_parameters(locals(), ['image'])
- so that all call parameters can be pulled into a single dict.
- Args:
- all_locals: The dict of local variables.
- parameters_to_exclude: An iterable giving names of parameters that should
- be excluded from the result.
- Returns:
- A dict containing all the non-None values in all_locals, except for
- those listed in parameters_to_exclude.
- """
- result = {k: v for k, v in all_locals.items() if v is not None}
- for parameter_to_exclude in parameters_to_exclude:
- if parameter_to_exclude in result:
- del result[parameter_to_exclude]
- return result
- def _canonicalize_parameters(config, destination):
- """Canonicalizes a set of parameter names.
- For legacy and other reasons, there are multiple ways to specify some export
- parameters. This function applies canonicalization rules to simplify further
- processing. It validates that the canonicalization introduces no collisions.
- Note that config is changed in place and not returned.
- The parameter name mappings performed here are:
- crsTransform -> crs_transform
- bucket -> outputBucket
- fileNamePrefix, path -> outputPrefix or driveFileNamePrefix depending
- on whether the destination is GCS or Drive. "description" is used as
- the default value of outputPrefix or driveFileNamePrefix if nothing else
- provided a value.
- folder -> driveFolder
- If "fileFormat" is "GeoTIFF": tiffX -> formatOptions { x }
- If "fileFormat" is "TfRecord": tfrecordX -> formatOptions { x }
- The "region" parameter's value, if present, is processed with
- _canonicalize_region.
- The "selectors" parameter's value, if present and a string, is converted
- to a list by splitting at commas.
- Args:
- config: The configuration dictionary to be converted.
- destination: The type of destination targeted by the export.
- """
- if 'kwargs' in config:
- config.update(config['kwargs'])
- del config['kwargs']
- collision_error = 'Both {} and {} are specified.'
- def canonicalize_name(a, b):
- """Renames config[a] to config[b]."""
- if a in config:
- if b in config:
- raise ee_exception.EEException(collision_error.format(a, b))
- config[b] = config.pop(a)
- canonicalize_name('crsTransform', 'crs_transform')
- if 'region' in config:
- config['region'] = _canonicalize_region(config['region'])
- if 'selectors' in config and isinstance(config['selectors'], str):
- config['selectors'] = config['selectors'].split(',')
- if destination == Task.ExportDestination.GCS:
- canonicalize_name('bucket', 'outputBucket')
- canonicalize_name('fileNamePrefix', 'outputPrefix')
- # Only used with Export.map
- canonicalize_name('path', 'outputPrefix')
- if 'outputPrefix' not in config and 'description' in config:
- config['outputPrefix'] = config['description']
- elif destination == Task.ExportDestination.DRIVE:
- canonicalize_name('folder', 'driveFolder')
- canonicalize_name('fileNamePrefix', 'driveFileNamePrefix')
- if 'driveFileNamePrefix' not in config and 'description' in config:
- config['driveFileNamePrefix'] = config['description']
- elif (destination != Task.ExportDestination.ASSET and
- destination != Task.ExportDestination.FEATURE_VIEW):
- raise ee_exception.EEException('Unknown export destination.')
- if (IMAGE_FORMAT_FIELD in config and
- config[IMAGE_FORMAT_FIELD].upper() in FORMAT_PREFIX_MAP):
- prefix = FORMAT_PREFIX_MAP[config[IMAGE_FORMAT_FIELD].upper()]
- format_options = config.get(IMAGE_FORMAT_OPTIONS_FIELD, {})
- keys_to_delete = []
- for key, value in config.items():
- if key.startswith(prefix):
- # Transform like "tiffSomeKey" -> "someKey"
- remapped_key = key[len(prefix):]
- remapped_key = remapped_key[:1].lower() + remapped_key[1:]
- if remapped_key in format_options:
- raise ee_exception.EEException(
- collision_error.format(key, remapped_key))
- format_options[remapped_key] = value
- keys_to_delete.append(key)
- if format_options:
- config[IMAGE_FORMAT_OPTIONS_FIELD] = format_options
- for key in keys_to_delete:
- del config[key]
- def _canonicalize_region(region):
- """Converts a region parameter to a form appropriate for export."""
- region_error = ee_exception.EEException(
- 'Invalid format for "region" property. '
- 'See Export.image() documentation for more details.')
- # pylint: disable=bare-except
- # The Cloud API can accept arbitrary Geometries, even computed ones.
- # Thus, this function tries to turn its parameter into a Geometry.
- if isinstance(region, geometry.Geometry):
- return region
- if isinstance(region, str):
- try:
- region = json.loads(region)
- except:
- raise region_error
- # It's probably a list of coordinates - attempt to parse as a LineString or
- # Polygon.
- try:
- region = geometry.Geometry.LineString(region)
- except:
- try:
- region = geometry.Geometry.Polygon(region)
- except:
- raise region_error
- return region
|