Skip to content

Commit

Permalink
Merge pull request #10 from danforthcenter/add_transform_points
Browse files Browse the repository at this point in the history
Add transform points
  • Loading branch information
k034b363 authored Aug 27, 2024
2 parents 8dea687 + 17cd6f4 commit e82daa2
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 2 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ All notable changes to this project will be documented below.
#### geospatial.read_geotif

* v0.1dev: spectral = **geospatial.read_geotif**(*filename, bands="B,G,R"*)

#### geospatial.transform_points

* v0.1dev: coord = **geospatial.transform_points**(*img, geojson*)
29 changes: 29 additions & 0 deletions docs/transform_points.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Transform Points

Transform the points from a georeferenced shapefile/GeoJSON based on an image size.

**plantcv.geospatial.transform_points**(*img, geojson*)

**returns** list of transformed coordinates

- **Parameters:**
- img - Spectral image object, likely read in with [`geo.read_geotif`](read_geotif.md)
- geojson - Path to the shapefile/GeoJSON containing the points. Can be Point or MultiPoint geometry.

- **Context:**
- Transformed points can be used downstream for Python analysis, such as defining ROIs.
- **Example use:**
- below to define plot boundaries


```python
import plantcv.geospatial as geo

# Read geotif in
spectral = geo.read_geotif(filename="./data/example_img.tif", bands="b,g,r,RE,NIR")
coords = geo.transform_points(img=spectral, geojson="./experimental_bounds_2024.shp")
roi_objects = pcv.roi.custom(img=spectral.pseudo_rgb, vertices=coords)

```

**Source Code:** [Here](https://github.com/danforthcenter/plantcv-geospatial/blob/main/plantcv/geospatial/transform_points.py)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ nav:
- 'PlantCV Namespace':
- 'Geopspatial Tools':
- Read Geo-tif Data: read_geotif.md
- Transform coordinate points: transform_points.md
markdown_extensions:
- toc:
permalink: True
Expand Down
4 changes: 3 additions & 1 deletion plantcv/geospatial/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from importlib.metadata import version
from plantcv.geospatial.read_geotif import read_geotif
from plantcv.geospatial.transform_points import transform_points

# Auto versioning
__version__ = version("plantcv-geospatial")

__all__ = [
"read_geotif"
"read_geotif",
"transform_points"
]
30 changes: 30 additions & 0 deletions plantcv/geospatial/transform_points.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Transform georeferenced GeoJSON/shapefile points into python coordinates
import fiona


def transform_points(img, geojson):
"""Takes a points-type shapefile/GeoJSON and transforms to numpy coordinates
Inputs:
img: A spectral object from read_geotif.
geojson: Path to the shape file containing the points.
Returns:
coord: Transformed points as a list of numpy coordinates
:param img: [spectral object]
:param geojson: str
:return coord: list
"""
geo_transform = img.geo_transform

coord = []
with fiona.open(geojson, 'r') as shapefile:
for i, _ in enumerate(shapefile):
if type((shapefile[i].geometry["coordinates"])) is list:
pixel_point = ~(geo_transform) * (shapefile[i].geometry["coordinates"][0])
if type((shapefile[i].geometry["coordinates"])) is tuple:
pixel_point = ~(geo_transform) * (shapefile[i].geometry["coordinates"])
rounded = (int(pixel_point[0]), int(pixel_point[1]))
coord.append(rounded)

return coord
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ dependencies = [
"rasterio",
"fiona",
"shapely",

]
requires-python = ">=3.6"
authors = [
Expand Down
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def __init__(self):
self.empty_tif = os.path.join(self.datadir, "cropped_empty.tif")
# rgb image
self.rgb_tif = os.path.join(self.datadir, "rgb.tif")
# multiPoints shapefilex
self.pts_geojson = os.path.join(self.datadir, "test_pts.geojson")
# points shapefilex
self.single_pts_geojson = os.path.join(self.datadir, "single_test_pts.geojson")
# polygon shapefile
self.square_crop = os.path.join(self.datadir, "square_crop.geojson")
# points shapefile
Expand Down
19 changes: 19 additions & 0 deletions tests/test_geospatial_transform_points.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Tests for geospatial.readd_geotif."""

from plantcv.geospatial import read_geotif, transform_points


def test_geospatial_transform_points(test_data):
"""Test for plantcv-geospatial."""
# read in small 5-band tif image
img = read_geotif(filename=test_data.rgb_tif, bands="B,G,R")
coords = transform_points(img=img, geojson=test_data.pts_geojson)
assert len(coords) == 4


def test_geospatial_transform_single_points(test_data):
"""Test for plantcv-geospatial."""
# read in small 5-band tif image
img = read_geotif(filename=test_data.rgb_tif, bands="B,G,R")
coords = transform_points(img=img, geojson=test_data.single_pts_geojson)
assert len(coords) == 8
15 changes: 15 additions & 0 deletions tests/testdata/single_test_pts.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"type": "FeatureCollection",
"name": "single_test_pts",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::32615" } },
"features": [
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720201.455548222991638, 4302929.009466916322708 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720200.939437506720424, 4302928.515762113966048 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720200.359096014057286, 4302927.93337285425514 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720199.889628155739047, 4302927.349608448334038 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720199.406284277676605, 4302926.797856044024229 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720198.922733629238792, 4302926.185171222314239 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720198.442067798110656, 4302925.539512793533504 ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "Point", "coordinates": [ 720197.996919097611681, 4302925.057554029859602 ] } }
]
}
11 changes: 11 additions & 0 deletions tests/testdata/test_pts.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"type": "FeatureCollection",
"name": "test_pts",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::32615" } },
"features": [
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 720198.48000389453955, 4302927.004775654524565 ] ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 720199.890186188276857, 4302928.102779876440763 ] ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 720200.501309029874392, 4302929.21947811357677 ] ] } },
{ "type": "Feature", "properties": { "id": null }, "geometry": { "type": "MultiPoint", "coordinates": [ [ 720197.757872894289903, 4302926.144173440523446 ] ] } }
]
}

0 comments on commit e82daa2

Please sign in to comment.