Skip to content

Commit

Permalink
Updates to isgeo() to include checking for shape, and to documentatio…
Browse files Browse the repository at this point in the history
…n for equivalence
  • Loading branch information
natgeo-wong committed Sep 29, 2024
1 parent f1a2d2c commit cb64e2e
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ makedocs(;
"Project Setup" => "api/project.md",
"Tables" => "api/tables.md",
"Shape / Coordinates" => "api/shape.md",
"Is In/On?" => "api/isinonequal.md",
"Is In/On/Equal?" => "api/isinonequal.md",
],
"Ecosystem" => "ecosystem.md",
],
Expand Down
82 changes: 74 additions & 8 deletions docs/src/basics/using/isequal.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,80 @@
# Comparing GeoRegions

Now, suppose we have two different GeoRegions, we have constructed several different ways of defining equivalence:
Now, suppose we have two different GeoRegions, we have constructed several different ways of testing various forms of equivalence.

```@example equivalence
using GeoRegions
using DelimitedFiles
using CairoMakie
download("https://raw.githubusercontent.com/natgeo-wong/GeoPlottingData/main/coastline_resl.txt","coast.cst")
coast = readdlm("coast.cst",comments=true)
clon = coast[:,1]
clat = coast[:,2]
nothing
```

## 1. Are two GeoRegions Equivalent

If you want to check that two GeoRegions are equivalent, we can use the `==` or `isequal()` functions. For `==` or `isequal` to return true, the following conditions must be satisfied:
* The `ID` and `pID` fields are the same
* The `shape` fields define exactly the same geographic region as per the function `on()`
If you want to check that two GeoRegions are equivalent, we can use the `==` or `isequal()` functions.


### 1. Strict Equivalence

For `==` or `isequal(geo1,geo2,strict = true)` to return true, the following conditions must be satisfied:
* The `ID` and `pID` fields are the same
* The `shape` fields define exactly the same geographic region as per the function [`on()`](/basics/using/ison)
* The `GeoRegion` must be of the same `type` (i.e., a `RectRegion` will not considered to be equivalent to a `PolyRegion` even if they have the same shape)

Let us consider the following example. First, we load a `RectRegion` and extract its `lon` and `lat` coordinates

```@example equivalence
geo = GeoRegion("GF_SEA")
lon,lat = coordinates(geo)
nothing
```

We define `RectRegion`s that are of the same shape (note that because `save = false` that the same `ID` can be used to define these GeoRegions):
```@example equivalence
geo2 = RectRegion("GF_SEA","GLB","",geo.bounds) # Different name
geo3 = RectRegion("SEA","GLB",geo.name,geo.bounds) # Different ID
geo4 = PolyRegion("GF_SEA","GLB",geo.name,lon,lat) # Different ID
geo5 = PolyRegion("GF_SEA","GLB","",lon,lat) # Different ID
geo6 = PolyRegion("GF_SEA","GLB",geo.name,lon.+360,lat) # Shifted by 360º
```

And we perform the tests with `==`:

```@example equivalence
geo == geo2, # true, name is not a factor in considering equivalence
geo == geo3, # false, different ID
geo == geo4 # false, different GeoRegion type
```

See the API nfor `==` [here](/api/isinonequal#Base.==)

And we perform the tests with `isequal()`

```@example equivalence
isequal(geo,geo2), # true, name is not a factor in considering equivalence
isequal(geo,geo3), # false, different ID
isequal(geo,geo4) # false, different GeoRegion type
```

See the API nfor `isequal()` [here](/api/isinonequal#Base.isequal)

### 1.2 Non-Strict Equivalence

`isequal()` also has a `strict = false` option, where we do not care if the `GeoRegion`s being compared are of the same `type` (i.e., a `RectRegion` can be equivalent to a `PolyRegion` as long as the `ID`, `pID` and `shape` fields are equivalent).

So, we can see that

```@example equivalence
isequal(geo,geo4,strict=false), # true, the shape is the same even though the GeoRegions are of differen types
isequal(geo,geo5,strict=false), # false, the ID is different
isequal(geo,geo6,strict=false), # true, shape is same even tho shift is by 360º
```

## 2. Does there already exist a GeoRegion?

!!! tip "Equivalent Regions in GeoRegions.jl"
For regions to be equivalent to each other in GeoRegions.jl, they do not need to be defined exactly in the same way.
1. the regions can be offset by 360º
2. the coordinates can be a `circshift()` version of each other.
Sometimes, we want to figure out if there exists a `GeoRegion` `geo` in a project we have defined (for more information on how to use GeoRegions.jl in projects, see [here](/tutorials/projects)). We can use the function `isgeo()` to determine if this is the case.
15 changes: 15 additions & 0 deletions src/georegions/is.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ Keyword Arguments
- `path` : The path where the list of custom GeoRegions will be retrieved from.
Defaults to the directory `geo.path`.
- `strict` : If `true` (which is default), check to see if all fields are equivalent except for `name` and `path`.
- `shape` : If `true` (which is default), check to see if any existing GeoRegion in `path` has the same shape
- `throw` : If `true`, then throws an error if there is no `GeoRegion` defined in `path` with the same characteristics or field values as `geo`.
- `verbose` : Verbose logging for ease of monitoring? Default is `false`.
Expand All @@ -167,6 +168,7 @@ function isgeo(
geo :: GeoRegion;
path :: AbstractString = dirname(geo.path),
strict :: Bool = true,
shape :: Bool = true,
throw :: Bool = false,
verbose :: Bool = false
)
Expand All @@ -186,6 +188,19 @@ function isgeo(
end
end

elseif isgeoshape(geo,path,verbose=verbose)

# In this case, a GeoRegion of the same ID does not exist, but there already exists a GeoRegion with the same shape
ID = isgeoshape(geo,path,returnID=true,verbose=verbose)

if shape
if verbose; @info "$(modulelog()) - There exists a GeoRegion \"$ID\" that has the same shape as the GeoRegion \"$(geo.ID)\" that we have defined, and because `shape = true`, we have decided to treat this GeoRegion as equivalent to our user-defined GeoRegion \"$(geo.ID)\" to prevent redundancy." end
return true
else
@warn "$(modulelog()) - There exists a GeoRegion \"$ID\" that has the same shape as the GeoRegion \"$(geo.ID)\" that we have defined. However, because `shape = false`, we have decided that this does not matter and that no equivalent GeoRegion to our user-defined GeoRegion \"$(geo.ID)\" exists."
return false
end

else

return false
Expand Down

0 comments on commit cb64e2e

Please sign in to comment.