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.properties
file 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.