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.10+
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.
Custom exceptions for the Fathom SDK.
AuthenticationError
Bases: FathomException
Could not create an authenticated connection to the API.
FathomException
Bases: Exception
A client exception.
GeoJSONError
Bases: FathomException
Invalid GeoJSON given.
InvalidCredentialsError
Bases: FathomException
Could not create an authenticated connection to the API.
KMLError
Bases: FathomException
Invalid KML/KMZ given.
PortfolioCSVError
Bases: FathomException
Error when uploading data for a large portfolio run.
TaskNotCompleteException
Bases: FathomException
Tried to download the result from a task that was not complete.
VectorFileError
Bases: FathomException
Invalid vector file given.
Utility functions
Common utility functions for the Fathom SDK.
check_polygon_order(geojson, correct_polygon_points_order=False)
Check if the polygon contained in the geojson is in the right order.
This function can only check the polygon order if there is exactly one Polygon at the top level of the GeoJSON. Some errors (e.g. nested polygons, invalid GeoJSON structure) may not be caught by this function and will only be detected by the server. If correct_polygon_points_order is True and the points in the given polygon are in the wrong order (clockwise instead of counter-clockwise), this function reverses the points in the GeoJSON in-place. If correct_polygon_points_order is False, it logs a warning instead.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geojson
|
Dict
|
The loaded GeoJSON |
required |
correct_polygon_points_order
|
bool
|
if True, and the points in the given polygon are in the wrong order (clockwise instead of counter-clockwise), reverse the points in the GeoJSON in place. If False, log a warning and continue. |
False
|
Raises:
Type | Description |
---|---|
GeoJSONError
|
If the GeoJSON is missing a geometry type. |
Note
This function modifies the input GeoJSON in-place.
Example
import json
from fathom.sdk.common import check_polygon_order
poly = json.loads('{"type": "Polygon", "coordinates": [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]]}')
check_polygon_order(poly)
write_tiff_data_to_file(geotiff_bytes, layer_id, output_dir, pattern, tiff_num)
Write GeoTIFF data to a file based on the provided pattern and parameters.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geotiff_bytes
|
bytes
|
The byte data of the GeoTIFF to be written. |
required |
layer_id
|
str
|
The identifier for the layer. |
required |
output_dir
|
PathOrString
|
The directory where the file will be saved. |
required |
pattern
|
str
|
The filename pattern to use, which can include placeholders for |
required |
tiff_num
|
int
|
The number of the TIFF file, used in the filename pattern. |
required |
Raises:
Type | Description |
---|---|
OSError
|
If there is an issue creating the directory or writing the file. |
V2 API
Functions for interacting with the V2 Fathom API.
Client(client_id, client_secret, api_address='api.fathom.global', msg_channel_size=FATHOM_GRPC_CHANNEL_MSG_SIZE, *, grpc_interceptors=None)
Fathom SDK v2 client.
Construct 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
|
grpc_interceptors
|
Optional[List[UnaryUnaryClientInterceptor]]
|
An optional list of grpc interceptors to add to the grpc channel, for logging or other purposes. |
None
|
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_large_polygon(polygon, layer_ids, project_id=None)
Return data pertaining to a large 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]
|
Identifier to differentiate projects using the API. |
None
|
Returns:
Type | Description |
---|---|
GetLargePolygonDataResponse
|
A GetLargePolygonDataResponse object containing the data for the large polygon. |
Fetching large polygon data
import requests
from fathom.api.v2 import fathom_pb2
from fathom.sdk.v2 import Client, point, polygon
client = Client(...)
layer_ids = [...]
# Define a polygon
poly = polygon([
point(51.50, -0.12),
point(51.51, -0.12),
point(51.51, -0.11),
point(51.50, -0.11),
point(51.50, -0.12),
])
# Request the large polygon data
large_poly_resp = client.geo.get_large_polygon(poly, layer_ids)
# Print the result codes for each layer
print("Result codes per layer:")
for layer_id, result_code in large_poly_resp.result_codes.items():
# Map the integer result code to its string name
result_code_name = fathom_pb2.PolygonResultCode.Name(result_code)
print(f" {layer_id}: {result_code_name}")
# Download the data using the provided URL
download_url = large_poly_resp.download_url
print(f"Downloading data from: {download_url}")
response = requests.get(download_url)
response.raise_for_status() # Raise an exception for bad status codes
# Process the downloaded data (e.g., save to a file)
with open("large_polygon_data.zip", "wb") as f:
f.write(response.content)
get_points(points, layer_ids, project_id=None)
Return 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
|
Returns:
Type | Description |
---|---|
GetPointsDataResponse
|
A GetPointsDataResponse object containing the data for the points. |
get_polygon(polygon, layer_ids, project_id=None)
Return 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]
|
Identifier to differentiate projects using the API. |
None
|
Returns:
Type | Description |
---|---|
GetPolygonDataResponse
|
A GetPolygonDataResponse object containing the data for the polygon. |
get_polygon_stats(polygon, layer_ids, project_id=None)
Return 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]
|
Identifier to differentiate projects using the API. |
None
|
Returns:
Type | Description |
---|---|
GetPolygonStatsResponse
|
A GetPolygonStatsResponse object containing the statistics for the polygon. |
quote_points(points, layer_ids)
Quote the cost to get points data.
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 |
Returns:
Type | Description |
---|---|
QuotePointsResponse
|
A QuotePointsResponse object containing the quote for the points data. |
quote_polygon(polygon, layer_ids)
Quote the cost to get polygon data.
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 |
Returns:
Type | Description |
---|---|
QuotePolygonResponse
|
A QuotePolygonResponse object containing the quote for the polygon data. |
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_large_polygon(geojson, layer_ids, project_id=None)
Return data pertaining to a large polygon encoded in GeoJSON.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geojson
|
Union[PathLike, str, bytes, bytearray, BufferedIOBase, TextIOBase, Dict]
|
The GeoJSON data representing the polygon. - 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 |
required |
layer_ids
|
List[str]
|
Layer IDs to use for task |
required |
project_id
|
Optional[str]
|
Identifier to differentiate projects using the API. |
None
|
Returns:
Type | Description |
---|---|
GetLargePolygonDataResponse
|
A GetLargePolygonDataResponse object containing the data for the large polygon. |
get_points(geojson, layer_ids, project_id=None)
Return data pertaining to points encoded in GeoJSON.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geojson
|
Union[PathLike, str, bytes, bytearray, BufferedIOBase, TextIOBase, Dict]
|
The GeoJSON data representing the points. - 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 |
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
|
Returns:
Type | Description |
---|---|
GetPointsDataResponse
|
A GetPointsDataResponse object containing the data for the points. |
get_polygon(geojson, layer_ids, project_id=None)
Return data pertaining to a polygon encoded in GeoJSON.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geojson
|
Union[PathLike, str, bytes, bytearray, BufferedIOBase, TextIOBase, Dict]
|
The GeoJSON data representing the polygon. - 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 |
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
|
Returns:
Type | Description |
---|---|
GetPolygonDataResponse
|
A GetPolygonDataResponse object containing the data for the polygon. |
get_polygon_stats(geojson, layer_ids, project_id=None)
Return statistics about a polygon encoded in GeoJSON.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
geojson
|
Union[PathLike, str, bytes, bytearray, BufferedIOBase, TextIOBase, Dict]
|
The GeoJSON data representing the polygon. - 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 |
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
|
Returns:
Type | Description |
---|---|
GetPolygonStatsResponse
|
A GetPolygonStatsResponse object containing the statistics for the polygon. |
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)
Attempt 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
|
Returns:
Type | Description |
---|---|
CreatePortfolioTaskResponse
|
A CreatePortfolioTaskResponse object containing the task details. |
task_status(task_id)
Get the status of an existing portfolio task.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
task_id
|
str
|
ID of previously created portfolio task |
required |
Returns:
Type | Description |
---|---|
GetPortfolioTaskStatusResponse
|
A GetPortfolioTaskStatusResponse object containing the task status. |
upload_portfolio_csv(upload_url, input_path, *, timeout=10)
staticmethod
Upload 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_large_polygon(vector_file_name, layer_ids, project_id=None, *, correct_polygon_points_order=False)
Return data pertaining to a large 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
|
Returns:
Type | Description |
---|---|
GetLargePolygonDataResponse
|
A GetLargePolygonDataResponse object containing the data for the large polygon. |
get_polygon(vector_file_name, layer_ids, project_id=None, *, correct_polygon_points_order=False)
Return 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
|
Returns:
Type | Description |
---|---|
GetPolygonDataResponse
|
A GetPolygonDataResponse object containing the data for the polygon. |
get_polygon_stats(vector_file_name, layer_ids, project_id=None, *, correct_polygon_points_order=False)
Return 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
|
Returns:
Type | Description |
---|---|
GetPolygonStatsResponse
|
A GetPolygonStatsResponse object containing the statistics for the polygon. |
point(lat, lng)
Return a Point object for use with Client.get_point().
Parameters:
Name | Type | Description | Default |
---|---|---|---|
lat
|
float
|
The latitude of the point. |
required |
lng
|
float
|
The longitude of the point. |
required |
Returns:
Type | Description |
---|---|
Point
|
A Point object. |
polygon(points)
Return a Polygon object for use with Client.get_polygon().
Parameters:
Name | Type | Description | Default |
---|---|---|---|
points
|
List[Point]
|
A list of Point objects defining the polygon boundary. |
required |
Returns:
Type | Description |
---|---|
Polygon
|
A Polygon object. |
write_tiffs(response, output_dir, *, pattern='{layer_id}.tif')
Write polygon tiff data from a 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'
|