Skip to content

Commit b7457a4

Browse files
authored
Merge pull request #4 from Circuitscape/vl/dev
LightGraphs interface fixes, add more tests
2 parents aa24584 + 9673132 commit b7457a4

8 files changed

+198
-13
lines changed

src/graph_interface.jl

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import LightGraphs:
55
inneighbors, outneighbors, is_directed, add_edge!
66

77
import SimpleWeightedGraphs:
8-
add_edge!, get_weight
8+
add_edge!, get_weight, add_vertex!, vertices
99

10-
import Base:
11-
eltype, zero
10+
import Base: zero
1211

1312
### LightGraphs interface
1413
nv(g::AbstractSpatialGraph) = nv(g.graph)
@@ -22,8 +21,31 @@ has_vertex(g::AbstractSpatialGraph, v) = has_vertex(g.graph, v)
2221
inneighbors(g::AbstractSpatialGraph, v) = inneighbors(g.graph, v)
2322
outneighbors(g::AbstractSpatialGraph, v) = outneighbors(g.graph, v)
2423
is_directed(g::AbstractSpatialGraph) = is_directed(g.graph)
25-
zero(g::AbstractSpatialGraph) = zero(g.graph)
24+
function Base.zero(g::AbstractRasterGraph)
25+
if g.graph isa SimpleGraph
26+
SimpleRasterGraph(
27+
zero(typeof(g.graph)),
28+
g.vertex_raster
29+
)
30+
elseif g.graph isa SimpleDiGraph
31+
SimpleRasterDiGraph(
32+
zero(typeof(g.graph)),
33+
g.vertex_raster
34+
)
35+
elseif g.graph isa SimpleWeightedGraph
36+
WeightedRasterGraph(
37+
SimpleWeightedGraph{eltype(g.graph), weighttype(g.graph)}(),
38+
g.vertex_raster
39+
)
40+
elseif g.graph isa SimpleWeightedDiGraph
41+
WeightedRasterDiGraph(
42+
SimpleWeightedDiGraph{eltype(g.graph), weighttype(g.graph)}(),
43+
g.vertex_raster
44+
)
45+
end
46+
end
2647
add_edge!(g::AbstractSpatialGraph, a::Integer, b::Integer, c::Number) = add_edge!(g.graph, a, b, c)
48+
add_vertex!(g::AbstractSpatialGraph) = add_vertex!(g.graph)
2749

2850
### SimpleWeightedGraphs
2951
get_weight(g::WeightedRasterGraph, a::Integer, b::Integer) = get_weight(g.graph, a, b)

src/rastergraphs.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,16 @@ function make_raster_graph(
396396

397397
sources = Vector{Int64}()
398398
destinations = Vector{Int64}()
399-
weighted && (node_weights = Vector{Float64}())
399+
400+
weighted && (weight_type = eltype(raster))
401+
402+
if weighted && (weight_type <: Integer)
403+
@info ("weight_raster eltype is $(weight_type). " *
404+
"Promoting to Float64.")
405+
weight_type = Float64
406+
end
407+
408+
weighted && (node_weights = Vector{weight_type}())
400409

401410
# Add the edges
402411
# Only need to do neighbors down or to the right for undirected graphs

test/lg_interface.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using SpatialGraphs, Test, GeoData, LightGraphs, SimpleWeightedGraphs
2+
## This script tests methods for the LightGraph interface that aren't already
3+
## used in other tests
4+
5+
A_array = Array{Float32}(undef, (3, 4, 1))
6+
A_array[:,:,:] = [1, 3, 2, 0.5, 10, 8, 5, -9999, 3, 1, 2, 6]
7+
x = X(1:4)
8+
y = Y(1:3)
9+
band = Band(1:1)
10+
11+
weight_raster = GeoArray(A_array, (y, x, band), missingval = -9999)
12+
rasgraph = weightedrastergraph(weight_raster)
13+
14+
@test nv(rasgraph) == maximum(rasgraph.vertex_raster)
15+
num_edge = ne(rasgraph)
16+
@test vertices(rasgraph) == 1:maximum(rasgraph.vertex_raster)
17+
@test eltype(rasgraph) == Int # Should always be Int64 (or int32 on 32-bit)
18+
@test edgetype(rasgraph) == SimpleWeightedEdge{eltype(rasgraph), eltype(A_array)}
19+
20+
for i in 1:maximum(rasgraph.vertex_raster)
21+
@test has_vertex(rasgraph, i)
22+
end
23+
24+
# In undirected graph incoming neighbors should equal outgoing
25+
@test inneighbors(rasgraph, 1) == outneighbors(rasgraph, 1)
26+
27+
empty = zero(rasgraph)
28+
29+
add_vertices!(empty, maximum(rasgraph.vertex_raster))
30+
add_edge!(empty, 1, 4, Float32(0.5))
31+
32+
@test nv(empty) == maximum(rasgraph.vertex_raster)
33+
@test has_edge(empty, 1, 4)
34+
@test get_weight(empty, 1, 4) == Float32(0.5)

test/runtests.jl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
using Test, SpatialGraphs
1+
using GeoData, LightGraphs, SimpleWeightedGraphs, SpatialGraphs, Test
2+
3+
@testset "Simple Raster Graph Construction" begin
4+
include("simplerastergraphs.jl")
5+
end
26

37
@testset "Weighted Raster Graph Construction" begin
48
include("weightedrastergraphs.jl")
@@ -10,4 +14,21 @@ end
1014

1115
@testset "Weighted Raster DiGraph Construction" begin
1216
include("weightedrasterdigraphs.jl")
13-
end
17+
end
18+
19+
@testset "LightGraphs Interface" begin
20+
include("lg_interface.jl")
21+
end
22+
23+
printstyled("Checking that Base.show works...\n", bold = true)
24+
25+
A_array = Array{Float64}(undef, (3, 4, 1))
26+
A_array[:,:,:] = [1, 3, 2, 0.5, 10, 8, 5, -9999, 3, 1, 2, 6]
27+
x = X(1:4)
28+
y = Y(1:3)
29+
band = Band(1:1)
30+
31+
weight_raster = GeoArray(A_array, (y, x, band), missingval = -9999)
32+
rasgraph = weightedrastergraph(weight_raster)
33+
show(rasgraph);print("\n")
34+

test/simplerasterdigraphs.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using GeoData, LightGraphs, SimpleWeightedGraphs, SpatialGraphs, Test
22

33
condition_array = Array{Float64}(undef, (3, 4, 1))
4-
condition_array[:,:,:] = [1, 3, 5, 2, 4, 8, 5, -9999, 2, 3, 6, 7]
4+
condition_array[:,:,:] = [1, 0.5, 5, 2, 4, 8, 5, -9999, 2, 3, 6, 7]
55

66
x = X(1:4)
77
y = Y(1:3)
@@ -52,3 +52,6 @@ for i in 1:length(graph_edges)
5252
col_diff = abs(source_coords[2] - dest_coords[2])
5353
@test col_diff <= 1
5454
end
55+
56+
@test is_directed(rasgraph)
57+
@test zero(rasgraph).vertex_raster == rasgraph.vertex_raster

test/simplerastergraphs.jl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using GeoData, LightGraphs, SimpleWeightedGraphs, SpatialGraphs, Test
2+
3+
array = Array{Int}(undef, (3, 4, 1))
4+
array[:,:,:] = [1, 1, 1, 1, 2, 2, 2, -9999, 2, 3, 3, 3]
5+
6+
x = X(1:4)
7+
y = Y(1:3)
8+
band = Band(1:1)
9+
10+
raster = GeoArray(array, (y, x, band), missingval = -9999)
11+
12+
compare = ==
13+
rasgraph = simplerastergraph(
14+
raster,
15+
directed = false,
16+
condition = compare
17+
)
18+
19+
# no vertices in NoData pixels?
20+
@test (rasgraph.vertex_raster .== 0) ==
21+
((raster .== raster.missingval) .|
22+
isnan.(raster))
23+
24+
# Is the number of of vertices correct, and is the range of values correct?
25+
@test sort(collect(rasgraph.vertex_raster[rasgraph.vertex_raster .!= 0])) ==
26+
collect(1:sum(
27+
(raster .!= raster.missingval) .&
28+
(!).(isnan.(raster))
29+
))
30+
31+
graph_edges = collect(edges(rasgraph))
32+
33+
# Test that the edges are correct and have proper weights
34+
for i in 1:length(graph_edges)
35+
source_i = src(graph_edges[i])
36+
dest_i = dst(graph_edges[i])
37+
38+
source_coords = findall(rasgraph.vertex_raster .== source_i)[1]
39+
dest_coords = findall(rasgraph.vertex_raster .== dest_i)[1]
40+
41+
# Check that condition is met
42+
@test compare(
43+
raster[source_coords],
44+
raster[dest_coords]
45+
)
46+
47+
# Test that source row is within 1 step of dest row
48+
row_diff = abs(source_coords[1] - dest_coords[1])
49+
@test row_diff <= 1
50+
51+
# Test that source column is within 1 step of dest row
52+
col_diff = abs(source_coords[2] - dest_coords[2])
53+
@test col_diff <= 1
54+
end
55+
56+
@test is_directed(rasgraph) == false
57+
@test zero(rasgraph).vertex_raster == rasgraph.vertex_raster

test/weightedrasterdigraphs.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ A_array = Array{Float64}(undef, (3, 4, 1))
33
A_array[:,:,:] = [1, 3, 2, 0.5, 10, 8, 5, -9999, 3, 1, 2, 6]
44

55
condition_array = Array{Float64}(undef, (3, 4, 1))
6-
condition_array[:,:,:] = [1, 3, 5, 2, 4, 8, 5, -9999, 2, 3, 6, 7]
6+
condition_array[:,:,:] = [1, 0.5, 5, 2, 4, 8, 5, -9999, 2, 3, 6, 7]
77

88
x = X(1:4)
99
y = Y(1:3)
@@ -68,3 +68,6 @@ for i in 1:length(graph_edges)
6868
weight_raster[dest_coords])
6969
end
7070
end
71+
72+
@test is_directed(rasgraph)
73+
@test zero(rasgraph).vertex_raster == rasgraph.vertex_raster

test/weightedrastergraphs.jl

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ band = Band(1:1)
88

99
weight_raster = GeoArray(A_array, (y, x, band), missingval = -9999)
1010
weight_raster2d = GeoArray(A_array[:, :, 1], (y, x), missingval = -9999)
11-
rasgraph2d = weightedrastergraph(weight_raster2d)
12-
rasgraph = weightedrastergraph(weight_raster)
11+
rasgraph2d = weightedrastergraph(
12+
weight_raster2d,
13+
connect_using_avg_weights = false
14+
)
15+
rasgraph = weightedrastergraph(weight_raster, connect_using_avg_weights = false)
1316

1417
# Test that graphs are the same regardless of whether weight_raster has Band dim
1518
@test rasgraph2d.graph == rasgraph.graph
@@ -48,11 +51,44 @@ for i in 1:length(graph_edges)
4851
# Test that the weight is what it should be (assumes connect_using_avg_weights = true in graph construction)
4952
if (row_diff == 1 && col_diff == 1) # get diagonal average
5053
@test weight_i ==
51-
SpatialGraphs.res_diagonal_avg(weight_raster[source_coords],
54+
SpatialGraphs.cond_diagonal_avg(weight_raster[source_coords],
5255
weight_raster[dest_coords])
5356
else
5457
@test weight_i ==
55-
SpatialGraphs.res_cardinal_avg(weight_raster[source_coords],
58+
SpatialGraphs.cond_cardinal_avg(weight_raster[source_coords],
5659
weight_raster[dest_coords])
5760
end
5861
end
62+
63+
# check that no edges exist that shouldn't
64+
vertex_raster = rasgraph.vertex_raster
65+
for src_row in 1:size(vertex_raster)[1]
66+
for src_col in 1:size(vertex_raster)[2]
67+
for dst_row in 1:size(vertex_raster)[1]
68+
for dst_col in 1:size(vertex_raster)[2]
69+
if ((vertex_raster[src_row, src_col] == 0) |
70+
(vertex_raster[dst_row, dst_col] == 0))
71+
continue
72+
elseif ((abs(src_row - dst_row) <= 1) &
73+
(abs(src_col - dst_col) <= 1)) & (
74+
(abs(src_row - dst_row) > 0) |
75+
(abs(src_col - dst_col) > 0))
76+
@test has_edge(
77+
rasgraph,
78+
vertex_raster[src_row, src_col],
79+
vertex_raster[dst_row, dst_col]
80+
) == true
81+
else
82+
@test (has_edge(
83+
rasgraph,
84+
vertex_raster[src_row, src_col],
85+
vertex_raster[dst_row, dst_col]
86+
) == false)
87+
end
88+
end
89+
end
90+
end
91+
end
92+
93+
@test is_directed(rasgraph) == false
94+
@test zero(rasgraph).vertex_raster == rasgraph.vertex_raster

0 commit comments

Comments
 (0)