Python
The Python SDK is a convenient way to access Fathom's global flood risk intelligence data.
Note
The Fathom Python SDK only supports Python 3.9+
If you have an existing Python environment set up, you can add fathom-global-client-sdk
to your existing
requirements.txt file and install as normal.
Warning
With the release of the new V2 API, the Python SDK code has been moved into a different folder structure. To use the new V2 API, change your imports from
from fathom import Client
from proto.fathom import fathom_pb2, fathom_pb2_grpc
to
from fathom.sdk.v2 import Client
from fathom.api.v2 import fathom_pb2, fathom_pb2_grpc
To keep using the V1 API, only the client import should be changed to
from fathom.sdk.v1 import Client
# protobuf imports stay the same
Old imports will keep working for the time being, but will be removed in a future release.
Manual Installation
To use the Fathom Python module into a new virtualenv, proceed with the following steps.
# ensure you have the right requirements
python3 -m ensurepip
# Go to your project directory
cd /path/to/working/dir/
# Create a virtualenv in the 'venv' folder and activate it
python3 -m venv venv
source venv/bin/activate
# Install the package from pypi into the virtualenv
pip3 install fathom-global-client-sdk
Example
"""An example usage of the Fathom API client."""
import os
from fathom.sdk.v2 import Client, point, polygon, write_tiffs
if __name__ == "__main__":
client = Client(
os.getenv("FATHOM_CLIENT_ID"),
os.getenv("FATHOM_CLIENT_SECRET"),
os.getenv("FATHOM_API_ADDR"),
)
layer_ids = [
"GLOBAL-1ARCSEC-00_OFFSET-1in10-PLUVIAL-DEFENDED-DEPTH-2020-PERCENTILE50-v0.0.0_test",
"GLOBAL-1ARCSEC-00_OFFSET-1in100-PLUVIAL-DEFENDED-DEPTH-2020-PERCENTILE50-v0.0.0_test",
]
# Get from points
pt = point(lat=51.996147, lng=-2.159495)
points_response = client.geo.get_points(([pt]), layer_ids)
# Or using a polygon
poly = polygon(
[
point(51.45, 0),
point(51.55, 0),
point(51.55, -0.1),
point(51.45, -0.1),
point(51.45, 0),
]
)
polygon_response = client.geo.get_polygon(poly, layer_ids)
write_tiffs(
polygon_response,
output_dir,
)
To use the 'asynchronous' large portfolio API as described in the portfolio documentation, you should
use the portfolio
client member like below snippet:
client = Client(...)
create_task_response = client.portfolio.create_task(...)
See the documentation for PortfolioClient
for an in depth example of how to use
it.
Loading from vector files
The Fathom Python SDK also supports loading polygons from:
- KML files
- KMZ archives
- ESRI shapefiles
- GeoPackage files
from fathom.sdk.v2 import Client
client = Client(...)
polygon_stats = client.vector_file_name.get_polygon_stats(
"/path/to/file.kmz", layer_ids=[...]
)
In any of these files, the same restrictions as described in the basic usage documentation apply. Each file must contain exactly 1 polygon geometry and no other geometries.
Reference
Exceptions
SDK-specific exceptions are defined in the fathom.sdk.exceptions
package.
V2 API
Client(client_id, client_secret, api_address='api.fathom.global', msg_channel_size=FATHOM_GRPC_CHANNEL_MSG_SIZE, *, grpc_interceptors=None)
Constructs a new Client, connected to a remote server.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
client_id
|
str
|
Client ID to identify a registered client on the authorization server. |
required |
client_secret
|
str
|
Client Secret used with client_id to get an access token. |
required |
api_address
|
str
|
Address of the Fathom API server. |
'api.fathom.global'
|
msg_channel_size
|
int
|
gRPC message channel size, it is 10MB by default but if you will be dealing with data size larger than the default, you can configure the size. |
FATHOM_GRPC_CHANNEL_MSG_SIZE
|
Attributes:
Name | Type | Description |
---|---|---|
geo |
GeoClient
|
Client to talk to the geospatial data API |
geojson |
GeoJSONClient
|
Client to talk to the geospatial data API using GeoJSON |
vector_file_name |
VectorFileClient
|
Client to talk to the geospatial data API using vector file formats |
portfolio |
PortfolioClient
|
Client to talk to the large portfolio API |
GeoClient(base_client)
dataclass
A sub-client for synchronously fetching data for points or polygons.
get_points(points, layer_ids, project_id=None)
Returns data pertaining to a list of lat-lng coordinates.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
points
|
List[Point]
|
A list of coordinates. |
required |
layer_ids
|
List[str]
|
The identifiers of the types of data being requested. |
required |
project_id
|
Optional[str]
|
Identifier to differentiate projects using the API. |
None
|
get_polygon(polygon, layer_ids, project_id=None)
Returns data pertaining to a polygon coordinates.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
polygon
|
Polygon
|
The bounding points of an area for which data are requested. The first and last point MUST be the same, and the loop MUST be in a counterclockwise direction (i.e. on the left-hand side of an observer walking along the boundary). |
required |
layer_ids
|
List[str]
|
The identifiers of the types of data being requested. |
required |
project_id
|
Optional[str]
|
Idenitifier to differentiate projects using the API. |
None
|
get_polygon_stats(polygon, layer_ids, project_id=None)
Returns statistics about polygons using the given layer_ids
This is similar to the get_polygons method, but will only return statistics about the polygon, not the polygon itself. To see what statistics are returned, see the gRPC documentation
Parameters:
Name | Type | Description | Default |
---|---|---|---|
polygon
|
Polygon
|
The bounding points of an area for which data are requested. The first and last point MUST be the same, and the loop MUST be in a counterclockwise direction (i.e. on the left-hand side of an observer walking along the boundary). |
required |
layer_ids
|
List[str]
|
The identifiers of the types of data being requested. |
required |
project_id
|
Optional[str]
|
Idenitifier to differentiate projects using the API. |
None
|
GeoJSONClient(base_client)
dataclass
A client to fetch data from the fathom SDK using GeoJSON.
The geojson
input to the method parameters should be one of:
- An opened file object
- A string or bytes containing raw GeoJSON
- A PathLike object with the filepath to a geojson file
- A Python dictionary containing the GeoJSON
GeoJSON queries
from fathom.sdk.v2 import Client
client = Client(...)
layer_ids = [...]
# With an opened file
with open("/path/to/geo.json") as geojson_file:
polygon_resp = client.geojson.get_polygon_stats(geojson_file, layer_ids)
# With a geojson string
geojson_string = '{"type": ...}'
polygon_resp = client.geojson.get_polygon(geojson_string, layer_ids)
# With a Python dictionary
polygon_geojson = {
...
}
polygon_resp = client.geojson.get_polygon(polygon_geojson, layer_ids)
get_points(geojson, layer_ids, project_id=None)
Returns data pertaining to points encoded in GeoJSON.
get_polygon(geojson, layer_ids, project_id=None)
Returns data pertaining to a polygon coordinates encoded in GeoJSON.
get_polygon_stats(geojson, layer_ids, project_id=None)
Returns statistics about polygons using the given layer_ids
PortfolioClient(base_client)
dataclass
Sub-client for interacting with portfolios
Triggering large portfolio requests
import time
from fathom.api.v2 import portfolio_pb2
from fathom.sdk.v2 import Client
client = Client(...)
layer_ids = [...]
create_resp = client.portfolio.create_task(layer_ids)
client.portfolio.upload_portfolio_csv(create_resp.upload_url, "/path/to/input.csv")
for i in range(100):
time.sleep(10)
status = client.portfolio.task_status(create_resp.task_id)
if status.task_status == portfolio_pb2.TASK_STATUS_COMPLETE:
break
elif status.task_status == portfolio_pb2.TASK_STATUS_ERROR:
raise Exception(f"task failed: {status}")
else:
raise Exception("task was not ready in time")
num_bytes_read = client.portfolio.attempt_task_result_download(
create_resp.task_id, "/path/to/output.csv"
)
attempt_task_result_download(task_id, output_path, chunk_size=1000)
Attempts to download the result of a given task. Should only be called after a call to
task_status
has indicated that the task completed without errors, otherwise an
exception will be raised.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
task_id
|
str
|
ID of previously created portfolio task |
required |
output_path
|
PathOrString
|
Name of file to download output in to. It will be OVERWRITTEN if it already exists. |
required |
chunk_size
|
int
|
Override chunk size when downloading CSV |
1000
|
Returns:
Type | Description |
---|---|
int
|
Number of bytes downloaded |
Raises:
Type | Description |
---|---|
TaskNotCompleteException
|
Task was not ready or there were errors during processing |
create_task(layer_ids, project_id=None)
Create a new portfolio task
Parameters:
Name | Type | Description | Default |
---|---|---|---|
layer_ids
|
List[str]
|
Layer IDs to use for task |
required |
project_id
|
Optional[str]
|
Identifier to differentiate projects using the API. |
None
|
task_status(task_id)
Gets the status of an existing portfolio task
Parameters:
Name | Type | Description | Default |
---|---|---|---|
task_id
|
str
|
ID of previously created portfolio task |
required |
upload_portfolio_csv(upload_url, input_path, *, timeout=10)
staticmethod
Uploads the given portfolio CSV file for the portfolio task
Parameters:
Name | Type | Description | Default |
---|---|---|---|
upload_url
|
str
|
upload url from a previous CreatePortfolioTaskResponse |
required |
input_path
|
PathOrString
|
path to CSV file to upload |
required |
timeout
|
int
|
timeout on uploading CSV |
10
|
VectorFileClient(client)
dataclass
Sub-client for fetching data using polygons encoded in vector files.
Supported vector types:
- KML and KMZ files
- GeoJSON
- Shapefiles
- GeoPackage
Each file must contain exactly one polygon 'feature' which follows the rules for other polygon queries.
Additionally, GeoJSON files must follow the same rules as defined in the GeoJSON query documentation.
Vector file queries
from fathom.sdk.v2 import Client
client = Client(...)
layer_ids = [...]
polygon_resp = client.vector_file_name.get_polygon_stats("/path/to/file.kml", layer_ids)
# On Windows, use the 'r' prefix to the path:
# polygon_resp = client.vector_file_name.get_polygon_stats(r"C:\Users\MyUser\file.kml", layer_ids)
get_polygon(vector_file_name, layer_ids, project_id=None, *, correct_polygon_points_order=False)
Returns data pertaining to a polygon contained in the given vector file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
vector_file_name
|
Union[str, PathLike]
|
path to a vector file in one of the supported formats |
required |
layer_ids
|
List[str]
|
Layer IDs to use for task |
required |
project_id
|
Optional[str]
|
Identifier to differentiate projects using the API. |
None
|
correct_polygon_points_order
|
bool
|
If set to True, attempt to correct the order of polygon points. If the polygon contained in the given vector file has points in the incorrect order (counter-clockwise) this will be rejected by the API, Enabling this option reverses the points before sending it to the API. |
False
|
get_polygon_stats(vector_file_name, layer_ids, project_id=None, *, correct_polygon_points_order=False)
Returns stats pertaining to a polygon contained in the given vector file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
vector_file_name
|
Union[str, PathLike]
|
path to a vector file in one of the supported formats |
required |
layer_ids
|
List[str]
|
Layer IDs to use for task |
required |
project_id
|
Optional[str]
|
Identifier to differentiate projects using the API. |
None
|
correct_polygon_points_order
|
bool
|
If set to True, attempt to correct the order of polygon points. If the polygon contained in the given vector file has points in the incorrect order (counter-clockwise) this will be rejected by the API, Enabling this option reverses the points before sending it to the API. |
False
|
point(lat, lng)
Returns a Point object for use with Client.get_point().
polygon(points)
Returns a Polygon object for use with Client.get_polygon().
write_tiffs(response, output_dir, *, pattern='{layer_id}.tif')
Given a polygon data response, write polygon tiff data in the response to the output directory.
If any polygon result in the response was fully 'no data' (see key values documentation), the output tiff will not be written.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
response
|
GetPolygonDataResponse
|
A response from a |
required |
output_dir
|
PathOrString
|
the directory to write the tiff data to |
required |
pattern
|
str
|
The pattern to save the file as. Formatted using normal Python string formatting, with the only available key being : - 'layer_id': the layer id - 'sep': The os-specific directory separator |
'{layer_id}.tif'
|