Image Mosaic¶
from pathlib import Path
from geoserver import GeoServer
GeoServer Connection¶
Connect to the running GeoServer instance and create a workspace and a store.
# Setup the geoserver instance
geoserver = GeoServer(
service_url="http://localhost:8080/geoserver",
username="admin",
password="geoserver",
)
Let's clean up the workspace and remove created data.
if geoserver.workspace_exists("demo"):
geoserver.delete_workspace("demo", recurse=True)
geoserver.create_workspace_from_name("demo")
'Created'
Config¶
We'll set up the configuration for the notebook:
# Directory containing sample data
DATA_DIR = Path("../tests/data")
assert DATA_DIR.exists(), f"The directory {DATA_DIR} does not exist."
Uploading a new image mosaic¶
Upload a ZIP file containing a mosaic definition and granule(s).
file_path = DATA_DIR / "mosaics" / "polyphemus.zip"
assert file_path.exists(), f"File not found: {file_path.as_posix()!r}"
# If the store already exists, it will be overwritten
geoserver.upload_coverage_store(file=file_path, format="imagemosaic", workspace="demo", name="polyphemus")
'Created'
Updating an image mosaic contents¶
Harvest (or reharvest) a single file into the mosaic and update the mosaic index.
geoserver.upload_coverage_store(
file="file:/path/to/the/file/polyphemus_20130302.nc",
format="imagemosaic",
workspace="demo",
name="poly-incremental",
)
Harvest (or reharvest) a whole directory into the mosaic and update the mosaic index.
geoserver.upload_coverage_store(
file="file:/path/to/the/mosaic/folder",
format="imagemosaic",
workspace="demo",
name="poly-incremental",
)
Listing image mosaic details¶
Retrieve the image mosaic index structure.
xml = geoserver.get_coverages(workspace="demo", store="polyphemus", format="xml")
print(xml)
<coverages>
<coverage>
<name>O3</name>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/demo/coveragestores/polyphemus/coverages/O3.xml" type="application/atom+xml"/>
</coverage>
</coverages>
xml = geoserver.get_coverage(name="O3", workspace="demo", store="polyphemus", format="xml")
print(xml)
<coverage>
<name>O3</name>
<nativeName>O3</nativeName>
<namespace>
<name>demo</name>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/namespaces/demo.xml" type="application/xml"/>
</namespace>
<title>O3</title>
<description>Generated from ImageMosaic</description>
<keywords>
<string>O3</string>
<string>WCS</string>
<string>ImageMosaic</string>
</keywords>
<nativeCRS>GEOGCS["WGS 84",
DATUM["World Geodetic System 1984",
SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]],
UNIT["degree", 0.017453292519943295],
AXIS["Geodetic longitude", EAST],
AXIS["Geodetic latitude", NORTH],
AUTHORITY["EPSG","4326"]]</nativeCRS>
<srs>EPSG:4326</srs>
<nativeBoundingBox>
<minx>4.9375</minx>
<maxx>14.9375</maxx>
<miny>44.96875</miny>
<maxy>50.96875</maxy>
<crs>EPSG:4326</crs>
</nativeBoundingBox>
<latLonBoundingBox>
<minx>4.9375</minx>
<maxx>14.9375</maxx>
<miny>44.96875</miny>
<maxy>50.96875</maxy>
<crs>EPSG:4326</crs>
</latLonBoundingBox>
<projectionPolicy>REPROJECT_TO_DECLARED</projectionPolicy>
<enabled>true</enabled>
<metadata>
<entry key="dirName">polyphemus_null</entry>
</metadata>
<store class="coverageStore">
<name>demo:polyphemus</name>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/demo/coveragestores/polyphemus.xml" type="application/xml"/>
</store>
<serviceConfiguration>false</serviceConfiguration>
<simpleConversionEnabled>false</simpleConversionEnabled>
<nativeFormat>ImageMosaic</nativeFormat>
<grid dimension="2">
<range>
<low>0 0</low>
<high>80 96</high>
</range>
<transform>
<scaleX>0.125</scaleX>
<scaleY>-0.0625</scaleY>
<shearX>0.0</shearX>
<shearY>0.0</shearY>
<translateX>5.0</translateX>
<translateY>50.9375</translateY>
</transform>
<crs>EPSG:4326</crs>
</grid>
<supportedFormats>
<string>GIF</string>
<string>PNG</string>
<string>JPEG</string>
<string>TIFF</string>
<string>NetCDF</string>
<string>EHdr</string>
<string>VRT</string>
<string>GEOTIFF</string>
<string>DTED</string>
<string>ArcGrid</string>
<string>RST</string>
<string>GeoPackage (mosaic)</string>
<string>ImageMosaic</string>
<string>SRP</string>
<string>ENVIHdr</string>
<string>ERDASImg</string>
<string>ImagePyramid</string>
<string>AIG</string>
<string>RPFTOC</string>
<string>NITF</string>
</supportedFormats>
<interpolationMethods>
<string>nearest neighbor</string>
<string>bilinear</string>
<string>bicubic</string>
</interpolationMethods>
<defaultInterpolationMethod>nearest neighbor</defaultInterpolationMethod>
<dimensions>
<coverageDimension>
<name>GRAY_INDEX</name>
<description>GridSampleDimension[-Infinity,Infinity]</description>
<range>
<min>-inf</min>
<max>inf</max>
</range>
<dimensionType>
<name>REAL_32BITS</name>
</dimensionType>
</coverageDimension>
</dimensions>
<requestSRS>
<string>EPSG:4326</string>
</requestSRS>
<responseSRS>
<string>EPSG:4326</string>
</responseSRS>
<parameters>
<entry>
<string>BackgroundValues</string>
<string></string>
</entry>
<entry>
<string>OVERVIEW_POLICY</string>
<string>QUALITY</string>
</entry>
<entry>
<string>MergeBehavior</string>
<string>FLAT</string>
</entry>
<entry>
<string>AllowMultithreading</string>
<string>false</string>
</entry>
<entry>
<string>MaxAllowedTiles</string>
<string>-1</string>
</entry>
<entry>
<string>ExcessGranuleRemoval</string>
<string>NONE</string>
</entry>
<entry>
<string>OutputTransparentColor</string>
<string></string>
</entry>
<entry>
<string>USE_JAI_IMAGEREAD</string>
<string>true</string>
</entry>
<entry>
<string>Bands</string>
<string></string>
</entry>
<entry>
<string>RescalePixels</string>
<string>true</string>
</entry>
<entry>
<string>Filter</string>
<string></string>
</entry>
<entry>
<string>InputTransparentColor</string>
<string></string>
</entry>
<entry>
<string>SUGGESTED_TILE_SIZE</string>
<string>512,512</string>
</entry>
<entry>
<string>Accurate resolution computation</string>
<string>false</string>
</entry>
<entry>
<string>SORTING</string>
<string></string>
</entry>
<entry>
<string>FootprintBehavior</string>
<string>None</string>
</entry>
</parameters>
<nativeCoverageName>O3</nativeCoverageName>
</coverage>
xml = geoserver.get_coverage_index(name="O3", workspace="demo", store="polyphemus", format="xml")
print(xml)
<Schema>
<attributes>
<Attribute>
<name>the_geom</name>
<minOccurs>0</minOccurs>
<maxOccurs>1</maxOccurs>
<nillable>true</nillable>
<binding>org.locationtech.jts.geom.Polygon</binding>
</Attribute>
<Attribute>
<name>location</name>
<minOccurs>0</minOccurs>
<maxOccurs>1</maxOccurs>
<nillable>true</nillable>
<binding>java.lang.String</binding>
</Attribute>
<Attribute>
<name>imageindex</name>
<minOccurs>0</minOccurs>
<maxOccurs>1</maxOccurs>
<nillable>true</nillable>
<binding>java.lang.Integer</binding>
</Attribute>
<Attribute>
<name>time</name>
<minOccurs>0</minOccurs>
<maxOccurs>1</maxOccurs>
<nillable>true</nillable>
<binding>java.sql.Timestamp</binding>
</Attribute>
</attributes>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="alternate" href="http://localhost:8080/geoserver/rest/workspaces/demo/coveragestores/polyphemus/coverages/O3/index/granules.xml" type="application/xml"/>
</Schema>
Retrieve the existing granule information:
xml = geoserver.get_coverage_granules(name="O3", workspace="demo", store="polyphemus", format="xml")
print(xml)
<?xml version="1.0" encoding="UTF-8"?><wfs:FeatureCollection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gf="http://www.geoserver.org/rest/granules" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coord> <gml:X>4.9375</gml:X> <gml:Y>44.96875</gml:Y> </gml:coord> <gml:coord> <gml:X>14.9375</gml:X> <gml:Y>50.96875</gml:Y> </gml:coord> </gml:Box> </gml:boundedBy> <gml:featureMember> <gf:O3 fid="O3.1"> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coordinates>4.9375,44.96875 14.9375,50.96875</gml:coordinates> </gml:Box> </gml:boundedBy> <gf:the_geom> <gml:Polygon srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:outerBoundaryIs> <gml:LinearRing> <gml:coordinates>4.9375,44.96875 4.9375,50.96875 14.9375,50.96875 14.9375,44.96875 4.9375,44.96875</gml:coordinates> </gml:LinearRing> </gml:outerBoundaryIs> </gml:Polygon> </gf:the_geom> <gf:location>polyphemus_20130301_test.nc</gf:location> <gf:imageindex>0</gf:imageindex> <gf:time>2013-03-01T00:00:00Z</gf:time> </gf:O3> </gml:featureMember> <gml:featureMember> <gf:O3 fid="O3.2"> <gml:boundedBy> <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:coordinates>4.9375,44.96875 14.9375,50.96875</gml:coordinates> </gml:Box> </gml:boundedBy> <gf:the_geom> <gml:Polygon srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> <gml:outerBoundaryIs> <gml:LinearRing> <gml:coordinates>4.9375,44.96875 4.9375,50.96875 14.9375,50.96875 14.9375,44.96875 4.9375,44.96875</gml:coordinates> </gml:LinearRing> </gml:outerBoundaryIs> </gml:Polygon> </gf:the_geom> <gf:location>polyphemus_20130301_test.nc</gf:location> <gf:imageindex>1</gf:imageindex> <gf:time>2013-03-01T01:00:00Z</gf:time> </gf:O3> </gml:featureMember> </wfs:FeatureCollection>
Removing image mosaic granules¶
Remove all the granules originating from a particular file.
geoserver.delete_coverage_granules(name="O3", workspace="demo", store="polyphemus", filter="location='polyphemus_20130301.nc'")
'Deleted'
Uploading an empty mosaic¶
Upload an archive with the definition of an mosaic, but with no granules.
Given a empty.zip file containing:
datastore.properties(PostGIS connection parameters)indexer.xml(Mosaic indexer; note the CanBeEmpty=true parameter)polyphemus-test.xml(Auxiliary file used by the NetCDF reader to parse schemas and tables)
Warning:
Make sure to update thedatastore.propertiesfile with your connection parameters and refresh the ZIP before uploading it.
file_path = EXAMPLES_DIR / "mosaics" / "empty.zip"
assert file_path.exists(), f"File not found: {file_path.as_posix()!r}"
geoserver.upload_coverage_store(file=file_path, format="imagemosaic", workspace="demo", store="empty", configure="none")
Note:
Theconfigure="none"parameter allows for future configuration after harvesting
Note:
When specifying only the coverage name, the coverage will be automatically configured.