From ded9bd1e238f169549024797e8346f619ee8c65b Mon Sep 17 00:00:00 2001 From: avik-pal Date: Sat, 1 Aug 2020 09:35:11 -0400 Subject: [PATCH 1/2] Format the code using JuliaFormatter.jl --- benchmarks/plot.jl | 2 +- benchmarks/transforms.jl | 100 +++--- benchmarks/triangle_mesh.jl | 6 +- bors.toml | 3 - docs/make.jl | 24 +- examples/dgcnn_classification.jl | 70 ++-- examples/fit_mesh.jl | 31 +- examples/pointnet_classification.jl | 70 ++-- src/Flux3D.jl | 22 +- src/datasets/Dataset.jl | 2 +- src/datasets/custom.jl | 6 +- src/datasets/modelnet10/mn10.jl | 64 +++- src/datasets/modelnet10/mn10_pcloud.jl | 56 ++- src/datasets/modelnet40/mn40.jl | 174 ++++++++-- src/datasets/modelnet40/mn40_pcloud.jl | 62 +++- src/datasets/utils.jl | 12 +- src/metrics/mesh.jl | 16 +- src/metrics/pcloud.jl | 42 ++- src/models/dgcnn.jl | 116 +++---- src/models/pointnet.jl | 42 +-- src/models/utils.jl | 12 +- src/rep/mesh.jl | 2 +- src/rep/pcloud.jl | 24 +- src/rep/utils.jl | 90 ++--- src/transforms/mesh_func.jl | 8 +- src/transforms/pcloud_func.jl | 40 ++- src/transforms/utils.jl | 2 +- src/visualize.jl | 16 +- test/cuda/metrics.jl | 133 +++---- test/cuda/rep.jl | 448 ++++++++++++++---------- test/cuda/transforms.jl | 108 ++++-- test/dataset.jl | 80 +++-- test/metrics.jl | 102 +++--- test/models.jl | 8 +- test/rep.jl | 463 +++++++++++++++---------- test/transforms/mesh_func.jl | 17 +- test/transforms/transforms.jl | 91 +++-- test/utils.jl | 11 +- 38 files changed, 1577 insertions(+), 998 deletions(-) delete mode 100644 bors.toml diff --git a/benchmarks/plot.jl b/benchmarks/plot.jl index b8edc9d..b0e33d2 100644 --- a/benchmarks/plot.jl +++ b/benchmarks/plot.jl @@ -10,7 +10,7 @@ function read_benchmarks(fname, framework) ) for line in eachline(fname) raw = split(line) - push!(data,(raw[1], raw[2], parse(Int, raw[3]), parse(Float64, raw[4]))) + push!(data, (raw[1], raw[2], parse(Int, raw[3]), parse(Float64, raw[4]))) end data[!, :framework] .= framework return data diff --git a/benchmarks/transforms.jl b/benchmarks/transforms.jl index cc057ba..6524076 100644 --- a/benchmarks/transforms.jl +++ b/benchmarks/transforms.jl @@ -1,7 +1,7 @@ using Flux3D, BenchmarkTools, Printf function setup_benchmark_record(names) - benchmarks = Dict{String, Vector{Float64}}() + benchmarks = Dict{String,Vector{Float64}}() for name in names benchmarks[name] = [] end @@ -31,9 +31,11 @@ function realign_point_cloud(npoints) return rot(pc) end -ROT_MATRIX = [1.0 2.0 3.0 - 0.2 0.5 0.9 - 3.0 2.0 1.0] +ROT_MATRIX = [ + 1.0 2.0 3.0 + 0.2 0.5 0.9 + 3.0 2.0 1.0 +] npoint_arr = 2 .^ [12, 14, 16, 18, 20] @@ -45,15 +47,22 @@ cpu_benchmarks = setup_benchmark_record(names) println("DEVICE: CPU") for _npoints in npoint_arr arr = [ - (ScalePointCloud(0.5; inplace=false), "ScalePointCloud"), - (RotatePointCloud(ROT_MATRIX; inplace=false), "RotatePointCloud"), - (ReAlignPointCloud(realign_point_cloud(_npoints); inplace=false), "RealignPointCloud"), - (NormalizePointCloud(inplace=false), "NormalizePointCloud"), - (Chain( - ScalePointCloud(0.5; inplace=false), - RotatePointCloud(ROT_MATRIX; inplace=false), - ReAlignPointCloud(realign_point_cloud(_npoints); inplace=false), - NormalizePointCloud()), "Chain") + (ScalePointCloud(0.5; inplace = false), "ScalePointCloud"), + (RotatePointCloud(ROT_MATRIX; inplace = false), "RotatePointCloud"), + ( + ReAlignPointCloud(realign_point_cloud(_npoints); inplace = false), + "RealignPointCloud", + ), + (NormalizePointCloud(inplace = false), "NormalizePointCloud"), + ( + Chain( + ScalePointCloud(0.5; inplace = false), + RotatePointCloud(ROT_MATRIX; inplace = false), + ReAlignPointCloud(realign_point_cloud(_npoints); inplace = false), + NormalizePointCloud(), + ), + "Chain", + ), ] println("Running benchmarks for npoints = $_npoints") @@ -70,39 +79,52 @@ if has_cuda() println("DEVICE: GPU") for _npoints in npoint_arr arr = [ - (ScalePointCloud(0.5; inplace=false), "ScalePointCloud"), - (RotatePointCloud(ROT_MATRIX; inplace=false), "RotatePointCloud"), - (ReAlignPointCloud(realign_point_cloud(_npoints); inplace=false), "RealignPointCloud"), - (NormalizePointCloud(inplace=false), "NormalizePointCloud"), - (Chain( - ScalePointCloud(0.5; inplace=false), - RotatePointCloud(ROT_MATRIX; inplace=false), - ReAlignPointCloud(realign_point_cloud(_npoints); inplace=false), - NormalizePointCloud(inplace=false)), "Chain") - ] + (ScalePointCloud(0.5; inplace = false), "ScalePointCloud"), + (RotatePointCloud(ROT_MATRIX; inplace = false), "RotatePointCloud"), + ( + ReAlignPointCloud(realign_point_cloud(_npoints); inplace = false), + "RealignPointCloud", + ), + (NormalizePointCloud(inplace = false), "NormalizePointCloud"), + ( + Chain( + ScalePointCloud(0.5; inplace = false), + RotatePointCloud(ROT_MATRIX; inplace = false), + ReAlignPointCloud(realign_point_cloud(_npoints); inplace = false), + NormalizePointCloud(inplace = false), + ), + "Chain", + ), + ] println("Running benchmarks for npoints = $_npoints") - run_benchmarks!(gpu_benchmarks, arr, _npoints, (op, pc) -> (CuArrays.@sync op(pc)), gpu) + run_benchmarks!( + gpu_benchmarks, + arr, + _npoints, + (op, pc) -> (CuArrays.@sync op(pc)), + gpu, + ) println() end end function save_bm(fname, cpu_benchmarks, gpu_benchmarks) - open(fname, "w") do io - device = "cpu" - for (key, values) in cpu_benchmarks - for (p,v) in zip(npoint_arr, values) - Printf.@printf(io, "%s %s %d %f ms\n",device, key, p, v) - end - end - - device = "gpu" - for (key, values) in gpu_benchmarks - for (p,v) in zip(npoint_arr, values) - Printf.@printf(io, "%s %s %d %f ms\n",device, key, p, v) - end - end - end + open(fname, "w") do io + device = "cpu" + for (key, values) in cpu_benchmarks + for (p, v) in zip(npoint_arr, values) + Printf.@printf(io, "%s %s %d %f ms\n", device, key, p, v) + end + end + + device = "gpu" + for (key, values) in gpu_benchmarks + for (p, v) in zip(npoint_arr, values) + Printf.@printf(io, "%s %s %d %f ms\n", device, key, p, v) + end + end + end end fname = joinpath(@__DIR__, "bm_flux3d.txt") diff --git a/benchmarks/triangle_mesh.jl b/benchmarks/triangle_mesh.jl index 1be7bf6..4204de2 100644 --- a/benchmarks/triangle_mesh.jl +++ b/benchmarks/triangle_mesh.jl @@ -3,13 +3,13 @@ using Flux3D, BenchmarkTools # mesh = load_trimesh(joinpath(@__DIR__, "../test/meshes/teapot.obj")) mesh = load_trimesh("./test/meshes/teapot.obj") -trail = @benchmark $get_edges_packed($mesh; refresh=true) +trail = @benchmark $get_edges_packed($mesh; refresh = true) minimum(trail.times) * 1.0e-6 -trail = @benchmark $get_faces_to_edges_packed($mesh; refresh=true) +trail = @benchmark $get_faces_to_edges_packed($mesh; refresh = true) minimum(trail.times) * 1.0e-6 -trail = @benchmark $get_laplacian_packed($mesh; refresh=true) +trail = @benchmark $get_laplacian_packed($mesh; refresh = true) minimum(trail.times) * 1.0e-6 trail = @benchmark $compute_verts_normals_packed($mesh) diff --git a/bors.toml b/bors.toml deleted file mode 100644 index 26df435..0000000 --- a/bors.toml +++ /dev/null @@ -1,3 +0,0 @@ -status = [ - "ci/gitlab/%" -] \ No newline at end of file diff --git a/docs/make.jl b/docs/make.jl index f452f01..2604a78 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,20 +2,16 @@ using Flux3D using Documenter makedocs(; - modules=[Flux3D], - authors="Nirmal P. Suthar ", - repo="https://github.com/nirmal-suthar/Flux3D.jl/blob/{commit}{path}#L{line}", - sitename="Flux3D.jl", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", "false") == "true", - canonical="https://nirmal-suthar.github.io/Flux3D.jl", - assets=String[], + modules = [Flux3D], + authors = "Nirmal P. Suthar ", + repo = "https://github.com/nirmal-suthar/Flux3D.jl/blob/{commit}{path}#L{line}", + sitename = "Flux3D.jl", + format = Documenter.HTML(; + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://nirmal-suthar.github.io/Flux3D.jl", + assets = String[], ), - pages=[ - "Home" => "index.md", - ], + pages = ["Home" => "index.md"], ) -deploydocs(; - repo="github.com/nirmal-suthar/Flux3D.jl.git", -) +deploydocs(; repo = "github.com/nirmal-suthar/Flux3D.jl.git") diff --git a/examples/dgcnn_classification.jl b/examples/dgcnn_classification.jl index 38ce206..ec18986 100644 --- a/examples/dgcnn_classification.jl +++ b/examples/dgcnn_classification.jl @@ -25,33 +25,56 @@ end function get_processed_data(args) # Fetching the train and validation data and getting them into proper shape if args.num_classes == 10 - dset = ModelNet10.dataset(;mode=:pointcloud, npoints=args.npoints, transform=NormalizePointCloud()) + dset = ModelNet10.dataset(; + mode = :pointcloud, + npoints = args.npoints, + transform = NormalizePointCloud(), + ) elseif args.num_classes == 40 - dset = ModelNet40.dataset(;mode=:pointcloud, npoints=args.npoints, transform=NormalizePointCloud()) + dset = ModelNet40.dataset(; + mode = :pointcloud, + npoints = args.npoints, + transform = NormalizePointCloud(), + ) else error("ModelNet dataset with $(args.num_classes) is not supported. Currently supported num_classes for ModelNet dataset is {10,40}") end - data = [dset[i].data.points for i in 1:length(dset)] - labels = onehotbatch([dset[i].ground_truth for i in 1:length(dset)],1:args.num_classes) + data = [dset[i].data.points for i = 1:length(dset)] + labels = onehotbatch([dset[i].ground_truth for i = 1:length(dset)], 1:args.num_classes) #onehot encode labels of batch - train = [(cat(data[i]..., dims = 3), labels[:,i]) for i in partition(1:length(data), args.batch_size)] .|> args.device - + train = + [ + (cat(data[i]..., dims = 3), labels[:, i]) + for i in partition(1:length(data), args.batch_size) + ] .|> args.device + if args.num_classes == 10 - VAL = ModelNet10.dataset(;mode=:pointcloud, train=false, npoints=args.npoints, transform=NormalizePointCloud()) + VAL = ModelNet10.dataset(; + mode = :pointcloud, + train = false, + npoints = args.npoints, + transform = NormalizePointCloud(), + ) elseif args.num_classes == 40 - VAL = ModelNet40.dataset(;mode=:pointcloud, train=false, npoints=args.npoints, transform=NormalizePointCloud()) + VAL = ModelNet40.dataset(; + mode = :pointcloud, + train = false, + npoints = args.npoints, + transform = NormalizePointCloud(), + ) else error("ModelNet dataset with $(args.num_classes) is not supported. Currently supported num_classes for ModelNet dataset is {10,40}") end - valX = cat([VAL[i].data.points for i in 1:length(VAL)]..., dims=3) |> args.device - valY = onehotbatch([VAL[i].ground_truth for i in 1:length(VAL)], 1:args.num_classes) |> args.device + valX = cat([VAL[i].data.points for i = 1:length(VAL)]..., dims = 3) |> args.device + valY = + onehotbatch([VAL[i].ground_truth for i = 1:length(VAL)], 1:args.num_classes) |> args.device - val = (valX,valY) + val = (valX, valY) return train, val end @@ -67,17 +90,18 @@ function train(; kwargs...) args.device = cpu @info("Training on CPU") end - + @info("Loading Data...") # Load the train, validation data - train,val = get_processed_data(args) + train, val = get_processed_data(args) - @info("Initializing Model...") + @info("Initializing Model...") # Defining the loss and accuracy functions m = DGCNN(args.num_classes, args.K, args.npoints) |> args.device loss(x, y) = crossentropy(m(x), y) - accuracy(x, y) = mean(onecold(cpu(m(x)), 1:args.num_classes) .== onecold(cpu(y), 1:args.num_classes)) + accuracy(x, y) = + mean(onecold(cpu(m(x)), 1:args.num_classes) .== onecold(cpu(y), 1:args.num_classes)) ## Training opt = ADAM(args.lr) @@ -90,18 +114,18 @@ end function custom_train!(loss, ps, data, opt, epochs, (valX, valY), accuracy) ps = Zygote.Params(ps) - for epoch in 1:epochs + for epoch = 1:epochs running_loss = 0 for d in data - gs = gradient(ps) do - training_loss = loss(d...) - running_loss += training_loss - return training_loss - end - Flux.update!(opt, ps, gs) + gs = gradient(ps) do + training_loss = loss(d...) + running_loss += training_loss + return training_loss + end + Flux.update!(opt, ps, gs) end print("Epoch: $(epoch), epoch_loss: $(running_loss), accuracy: $(accuracy(valX, valY))\n") end end -m = train() \ No newline at end of file +m = train() diff --git a/examples/fit_mesh.jl b/examples/fit_mesh.jl index 10e2fdb..1c9e77d 100644 --- a/examples/fit_mesh.jl +++ b/examples/fit_mesh.jl @@ -1,15 +1,19 @@ using Flux3D, Statistics, FileIO, Zygote, Flux -mkpath(joinpath(@__DIR__,"assets")) -mkpath(joinpath(@__DIR__,"results")) +mkpath(joinpath(@__DIR__, "assets")) +mkpath(joinpath(@__DIR__, "results")) -download("https://github.com/nirmalsuthar/public_files/raw/master/dolphin.obj", - joinpath(@__DIR__,"assets/dolphin.obj")) -download("https://github.com/nirmalsuthar/public_files/raw/master/sphere.obj", - joinpath(@__DIR__,"assets/sphere.obj")) +download( + "https://github.com/nirmalsuthar/public_files/raw/master/dolphin.obj", + joinpath(@__DIR__, "assets/dolphin.obj"), +) +download( + "https://github.com/nirmalsuthar/public_files/raw/master/sphere.obj", + joinpath(@__DIR__, "assets/sphere.obj"), +) -dolphin = load_trimesh(joinpath(@__DIR__,"assets/dolphin.obj")) -src = load_trimesh(joinpath(@__DIR__,"assets/sphere.obj")) +dolphin = load_trimesh(joinpath(@__DIR__, "assets/dolphin.obj")) +src = load_trimesh(joinpath(@__DIR__, "assets/sphere.obj")) tgt = deepcopy(dolphin) tgt = Flux3D.normalize!(tgt) @@ -22,7 +26,7 @@ function loss_dolphin(x::Array, src::TriMesh, tgt::TriMesh) loss1 = chamfer_distance(src, tgt, 5000)#; w1=1., w2=0.2) loss2 = laplacian_loss(src) loss3 = edge_loss(src) - return (loss1) + (0.1*loss2) + (loss3) + return (loss1) + (0.1 * loss2) + (loss3) end lr = 1.0 @@ -30,13 +34,16 @@ opt = Flux.Optimise.Momentum(lr, 0.9) function customtrain(_offset) θ = Zygote.Params([_offset]) - for itr in 1:2000 + for itr = 1:2000 gs = gradient(θ) do loss_dolphin(_offset, src, tgt) end Flux.update!(opt, _offset, gs[_offset]) - if (itr%100 == 0) - save(joinpath(@__DIR__, "results", "src_$(itr).png"), visualize(Flux3D.offset(src, off))) + if (itr % 100 == 0) + save( + joinpath(@__DIR__, "results", "src_$(itr).png"), + visualize(Flux3D.offset(src, off)), + ) end end return _offset diff --git a/examples/pointnet_classification.jl b/examples/pointnet_classification.jl index 2f83872..9cfdd71 100644 --- a/examples/pointnet_classification.jl +++ b/examples/pointnet_classification.jl @@ -25,33 +25,56 @@ end function get_processed_data(args) # Fetching the train and validation data and getting them into proper shape if args.num_classes == 10 - dset = ModelNet10.dataset(;mode=:pointcloud, npoints=args.npoints, transforms=NormalizePointCloud()) + dset = ModelNet10.dataset(; + mode = :pointcloud, + npoints = args.npoints, + transforms = NormalizePointCloud(), + ) elseif args.num_classes == 40 - dset = ModelNet40.dataset(;mode=:pointcloud, npoints=args.npoints, transforms=NormalizePointCloud()) + dset = ModelNet40.dataset(; + mode = :pointcloud, + npoints = args.npoints, + transforms = NormalizePointCloud(), + ) else error("ModelNet dataset with $(args.num_classes) is not supported. Currently supported num_classes for ModelNet dataset is {10,40}") end - data = [dset[i].data.points for i in 1:length(dset)] - labels = onehotbatch([dset[i].ground_truth for i in 1:length(dset)],1:args.num_classes) + data = [dset[i].data.points for i = 1:length(dset)] + labels = onehotbatch([dset[i].ground_truth for i = 1:length(dset)], 1:args.num_classes) #onehot encode labels of batch - train = [(cat(data[i]..., dims = 3), labels[:,i]) for i in partition(1:length(data), args.batch_size)] .|> args.device - + train = + [ + (cat(data[i]..., dims = 3), labels[:, i]) + for i in partition(1:length(data), args.batch_size) + ] .|> args.device + if args.num_classes == 10 - VAL = ModelNet10.dataset(;mode=:pointcloud, train=false, npoints=args.npoints, transforms=NormalizePointCloud()) + VAL = ModelNet10.dataset(; + mode = :pointcloud, + train = false, + npoints = args.npoints, + transforms = NormalizePointCloud(), + ) elseif args.num_classes == 40 - VAL = ModelNet40.dataset(;mode=:pointcloud, train=false, npoints=args.npoints, transforms=NormalizePointCloud()) + VAL = ModelNet40.dataset(; + mode = :pointcloud, + train = false, + npoints = args.npoints, + transforms = NormalizePointCloud(), + ) else error("ModelNet dataset with $(args.num_classes) is not supported. Currently supported num_classes for ModelNet dataset is {10,40}") end - valX = cat([VAL[i].data.points for i in 1:length(VAL)]..., dims=3) |> args.device - valY = onehotbatch([VAL[i].ground_truth for i in 1:length(VAL)], 1:num_classes) |> args.device + valX = cat([VAL[i].data.points for i = 1:length(VAL)]..., dims = 3) |> args.device + valY = + onehotbatch([VAL[i].ground_truth for i = 1:length(VAL)], 1:num_classes) |> args.device - val = (valX,valY) + val = (valX, valY) return train, val end @@ -67,17 +90,18 @@ function train(; kwargs...) args.device = cpu @info("Training on CPU") end - + @info("Loading Data...") # Load the train, validation data - train,val = get_processed_data(args) + train, val = get_processed_data(args) - @info("Initializing Model...") + @info("Initializing Model...") # Defining the loss and accuracy functions m = PointNet(args.num_classes) |> args.device loss(x, y) = crossentropy(m(x), y) - accuracy(x, y) = mean(onecold(cpu(m(x)), 1:args.num_classes) .== onecold(cpu(y), 1:args.num_classes)) + accuracy(x, y) = + mean(onecold(cpu(m(x)), 1:args.num_classes) .== onecold(cpu(y), 1:args.num_classes)) ## Training opt = ADAM(args.lr) @@ -90,18 +114,18 @@ end function custom_train!(loss, ps, data, opt, epochs, (valX, valY), accuracy) ps = Zygote.Params(ps) - for epoch in 1:epochs + for epoch = 1:epochs running_loss = 0 for d in data - gs = gradient(ps) do - training_loss = loss(d...) - running_loss += training_loss - return training_loss - end - Flux.update!(opt, ps, gs) + gs = gradient(ps) do + training_loss = loss(d...) + running_loss += training_loss + return training_loss + end + Flux.update!(opt, ps, gs) end print("Epoch: $(epoch), epoch_loss: $(running_loss), accuracy: $(accuracy(valX, valY))\n") end end -m = train() \ No newline at end of file +m = train() diff --git a/src/Flux3D.jl b/src/Flux3D.jl index 880085b..870f9c1 100644 --- a/src/Flux3D.jl +++ b/src/Flux3D.jl @@ -1,6 +1,14 @@ module Flux3D -using Flux, Zygote, NearestNeighbors, LinearAlgebra, Statistics, CUDA, FileIO, SparseArrays, Requires +using Flux, + Zygote, + NearestNeighbors, + LinearAlgebra, + Statistics, + CUDA, + FileIO, + SparseArrays, + Requires using Base: tail import Zygote: @nograd, @ignore import GeometryBasics @@ -11,12 +19,12 @@ export gpu, cpu, Chain # borowed from Flux.jl const use_cuda = Ref(false) function __init__() - use_cuda[] = CUDA.functional() # Can be overridden after load with `Flux.use_cuda[] = false` - if CUDA.functional() - if !CUDA.has_cudnn() - @warn "CUDA.jl found cuda, but did not find libcudnn. Some functionality will not be available." + use_cuda[] = CUDA.functional() # Can be overridden after load with `Flux.use_cuda[] = false` + if CUDA.functional() + if !CUDA.has_cudnn() + @warn "CUDA.jl found cuda, but did not find libcudnn. Some functionality will not be available." + end end - end end # representation @@ -40,7 +48,7 @@ using .Dataset export CustomDataset, ModelNet10, ModelNet40 # visualization -@init @require Makie="ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" include("visualize.jl") +@init @require Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" include("visualize.jl") # models include("models/utils.jl") diff --git a/src/datasets/Dataset.jl b/src/datasets/Dataset.jl index 20c9185..43fecce 100644 --- a/src/datasets/Dataset.jl +++ b/src/datasets/Dataset.jl @@ -13,4 +13,4 @@ include("modelnet40/mn40.jl") # (m::Module)(kwargs...) = m.dataset(kwargs...) -end # module \ No newline at end of file +end # module diff --git a/src/datasets/custom.jl b/src/datasets/custom.jl index ea29aa3..559531c 100644 --- a/src/datasets/custom.jl +++ b/src/datasets/custom.jl @@ -28,7 +28,7 @@ struct CustomDataset <: AbstractDataset getdata::Function end -CustomDataset(;length::Int, getdata::Function) = CustomDataset(length, getdata) +CustomDataset(; length::Int, getdata::Function) = CustomDataset(length, getdata) Base.size(d::CustomDataset) = (d.length,) Base.length(d::CustomDataset) = d.length @@ -40,5 +40,5 @@ Base.getindex(d::CustomDataset, idx::Int) = d.getdata(idx) Base.getindex(d::CustomDataset, r::AbstractArray{<:Any,1}) = [d[ri] for ri in r] #TODO: revise this Base.getindex(d::CustomDataset, c::Colon) = d[1:length(d)] -Base.show(io::IO, d::CustomDataset) = - print(io, "CustomDataset(length=$(d.length), getdata=$(d.getdata))") \ No newline at end of file +Base.show(io::IO, d::CustomDataset) = + print(io, "CustomDataset(length=$(d.length), getdata=$(d.getdata))") diff --git a/src/datasets/modelnet10/mn10.jl b/src/datasets/modelnet10/mn10.jl index 3b0cb55..0089a66 100644 --- a/src/datasets/modelnet10/mn10.jl +++ b/src/datasets/modelnet10/mn10.jl @@ -30,9 +30,9 @@ julia> dset = ModelNet10.dataset(;mode=:pointcloud, train=false) julia> typeof(dset[1].data) == PointCloud ``` """ -function dataset(;mode=:pointcloud, kwargs...) +function dataset(; mode = :pointcloud, kwargs...) if mode == :pointcloud - return ModelNet10PCloud(;kwargs...) + return ModelNet10PCloud(; kwargs...) else error("selected mode: $(mode) is not supported (Currently supported mode are {:pointcloud}).") end @@ -46,19 +46,51 @@ end const default_root = normpath(@__DIR__, "../../../datasets/modelnet") -const MN10_classes_to_idx = Dict{String, UInt8}([("bathtub",1), ("bed",2), ("chair",3), ("desk",4), ("dresser",5), - ("monitor",6), ("night_stand",7), ("sofa",8), ("table",9), ("toilet",10)]) - -const MN10_idx_to_classes = Dict{UInt8, String}([(1,"bathtub"), (2,"bed"), (3,"chair"), (4,"desk"), (5,"dresser"), - (6,"monitor"), (7,"night_stand"), (8,"sofa"), (9,"table"), (10,"toilet")]) - -const MN10_classes = ["bathtub", "bed", "chair", "desk", "dresser", - "monitor", "night_stand", "sofa", "table", "toilet"] - -Base.show(io::IO, p::MN10DataPoint) = - print(io, "idx: $(p.idx), data: $(typeof(p.data)), ground_truth: $(p.ground_truth) ($(MN10_idx_to_classes[p.ground_truth]))") - -Base.show(io::IO, ::MIME"text/plain", p::MN10DataPoint) = +const MN10_classes_to_idx = Dict{String,UInt8}([ + ("bathtub", 1), + ("bed", 2), + ("chair", 3), + ("desk", 4), + ("dresser", 5), + ("monitor", 6), + ("night_stand", 7), + ("sofa", 8), + ("table", 9), + ("toilet", 10), +]) + +const MN10_idx_to_classes = Dict{UInt8,String}([ + (1, "bathtub"), + (2, "bed"), + (3, "chair"), + (4, "desk"), + (5, "dresser"), + (6, "monitor"), + (7, "night_stand"), + (8, "sofa"), + (9, "table"), + (10, "toilet"), +]) + +const MN10_classes = [ + "bathtub", + "bed", + "chair", + "desk", + "dresser", + "monitor", + "night_stand", + "sofa", + "table", + "toilet", +] + +Base.show(io::IO, p::MN10DataPoint) = print( + io, + "idx: $(p.idx), data: $(typeof(p.data)), ground_truth: $(p.ground_truth) ($(MN10_idx_to_classes[p.ground_truth]))", +) + +Base.show(io::IO, ::MIME"text/plain", p::MN10DataPoint) = print(io, "ModelNet10 DataPoint:\n ", p) -end # module \ No newline at end of file +end # module diff --git a/src/datasets/modelnet10/mn10_pcloud.jl b/src/datasets/modelnet10/mn10_pcloud.jl index 5424b09..1209577 100644 --- a/src/datasets/modelnet10/mn10_pcloud.jl +++ b/src/datasets/modelnet10/mn10_pcloud.jl @@ -4,10 +4,14 @@ function pcloud_load(root::String = default_root) local_path = joinpath(root, "modelnet40_normal_resampled.zip") hash = "d64e9c5cfc479bac3260b164ae3c75ba83e94a1d216fbcd3f59ce2a9686d3762" - if(!isdir(local_dir)) - if(!isfile(local_path)) + if (!isdir(local_dir)) + if (!isfile(local_path)) # dataset prepared by authors of pointnet2 - download_and_verify("https://shapenet.cs.stanford.edu/media/modelnet40_normal_resampled.zip", local_path, hash) + download_and_verify( + "https://shapenet.cs.stanford.edu/media/modelnet40_normal_resampled.zip", + local_path, + hash, + ) end run(`unzip -q $local_path -d $root`) end @@ -34,15 +38,15 @@ PointCloud version of ModelNet10 dataset. """ struct ModelNet10PCloud <: AbstractDataset - root::String + root::String path::String train::Bool length::Int datapaths::Array npoints::Int - transform::Union{Flux3D.AbstractTransform, Nothing} - sampling #TODO Add type-assertion accordingly to include two possible option {"top", "uniform"} - classes_to_idx::Dict{String, UInt8} + transform::Union{Flux3D.AbstractTransform,Nothing} + sampling::Any #TODO Add type-assertion accordingly to include two possible option {"top", "uniform"} + classes_to_idx::Dict{String,UInt8} classes::Array{String,1} end @@ -51,22 +55,42 @@ function pcloud_extract(datapath, npoints) pset = Array{Float32}(undef, npoints, 3) nset = Array{Float32}(undef, npoints, 3) stream = open(datapath[2], "r") - for i in 1:npoints - tmp = map((x->parse(Float32, x)), split(readline(stream, keep=false), ",")) + for i = 1:npoints + tmp = map((x -> parse(Float32, x)), split(readline(stream, keep = false), ",")) pset[i, :] = tmp[1:3] nset[i, :] = tmp[4:6] end return (pset, nset, cls) end -function ModelNet10PCloud(;root::String=default_root, train::Bool=true, npoints::Int=1024, transform=nothing, sampling=nothing) +function ModelNet10PCloud(; + root::String = default_root, + train::Bool = true, + npoints::Int = 1024, + transform = nothing, + sampling = nothing, +) _path = pcloud_load(root) - train ? _split="train" : _split="test" + train ? _split = "train" : _split = "test" shapeids = [line for line in readlines(joinpath(_path, "modelnet10_$(_split).txt"))] - shape_names = [join(split(shapeids[i], "_")[1:end-1], "_") for i in 1:length(shapeids)] - datapaths = [(shape_names[i], joinpath(_path, shape_names[i], (shapeids[i])*".txt")) for i in 1:length(shapeids)] + shape_names = [join(split(shapeids[i], "_")[1:end-1], "_") for i = 1:length(shapeids)] + datapaths = [ + (shape_names[i], joinpath(_path, shape_names[i], (shapeids[i]) * ".txt")) + for i = 1:length(shapeids) + ] _length = length(datapaths) - ModelNet10PCloud(root, _path, train, _length, datapaths, npoints, transform, sampling, MN10_classes_to_idx, MN10_classes) + ModelNet10PCloud( + root, + _path, + train, + _length, + datapaths, + npoints, + transform, + sampling, + MN10_classes_to_idx, + MN10_classes, + ) end function Base.getindex(v::ModelNet10PCloud, idx::Int) @@ -82,7 +106,7 @@ end Base.size(v::ModelNet10PCloud) = (v.length,) Base.length(v::ModelNet10PCloud) = v.length -function Base.show(io::IO, dset::ModelNet10PCloud) +function Base.show(io::IO, dset::ModelNet10PCloud) print(io, "ModelNet10(") print("mode = point_cloud, ") print("root = $(dset.root), ") @@ -90,4 +114,4 @@ function Base.show(io::IO, dset::ModelNet10PCloud) print("length = $(dset.length), ") print("npoints = $(dset.npoints), ") print("transform = $(typeof(dset.transform))(...))") -end \ No newline at end of file +end diff --git a/src/datasets/modelnet40/mn40.jl b/src/datasets/modelnet40/mn40.jl index fac73c1..664a373 100644 --- a/src/datasets/modelnet40/mn40.jl +++ b/src/datasets/modelnet40/mn40.jl @@ -30,9 +30,9 @@ julia> dset = ModelNet40.dataset(;mode=:pointcloud, train=false) julia> typeof(dset[1].data) == PointCloud ``` """ -function dataset(;mode=:pointcloud, kwargs...) +function dataset(; mode = :pointcloud, kwargs...) if mode == :pointcloud - return ModelNet40PCloud(;kwargs...) + return ModelNet40PCloud(; kwargs...) else error("selected mode: $(mode) is not supported (Currently supported mode are {:pointcloud}).") end @@ -46,39 +46,141 @@ end const default_root = normpath(@__DIR__, "../../../datasets/modelnet") -const MN40_classes_to_idx = - Dict{String, UInt8}([("airplane",1), ("bathtub",2), ("bed",3), ("bench",4), ("bookshelf",5), - ("bottle",6), ("bowl",7), ("car",8), ("chair",9), ("cone",10), - ("cup",11), ("curtain",12), ("desk",13), ("door",14), ("dresser",15), - ("flower_pot",16), ("glass_box",17), ("guitar",18), ("keyboard",19), ("lamp",20), - ("laptop",21), ("mantel",22), ("monitor",23), ("night_stand",24), ("person",25), - ("piano",26), ("plant",27), ("radio",28), ("range_hood",29), ("sink",30), - ("sofa",31), ("stairs",32), ("stool",33), ("table",34), ("tent",35), - ("toilet",36), ("tv_stand",37), ("vase",38), ("wardrobe",39), ("xbox",40)]) - -const MN40_idx_to_classes = - Dict{UInt8, String}([(1,"airplane"), (2,"bathtub"), (3,"bed"), (4,"bench"), (5,"bookshelf"), - (6,"bottle"), (7,"bowl"), (8,"car"), (9,"chair"), (10,"cone"), - (11,"cup"), (12,"curtain"), (13,"desk"), (14,"door"), (15,"dresser"), - (16,"flower_pot"), (17,"glass_box"), (18,"guitar"), (19,"keyboard"), (20,"lamp"), - (21,"laptop"), (22,"mantel"), (23,"monitor"), (24,"night_stand"), (25,"person"), - (26,"piano"), (27,"plant"), (28,"radio"), (29,"range_hood"), (30,"sink"), - (31,"sofa"), (32,"stairs"), (33,"stool"), (34,"table"), (35,"tent"), - (36,"toilet"), (37,"tv_stand"), (38,"vase"), (39,"wardrobe"), (40,"xbox")]) - -const MN40_classes = ["airplane", "bathtub", "bed", "bench", "bookshelf", - "bottle", "bowl", "car", "chair", "cone", - "cup", "curtain", "desk", "door", "dresser", - "flower_pot", "glass_box", "guitar", "keyboard", "lamp", - "laptop", "mantel", "monitor", "night_stand", "person", - "piano", "plant", "radio", "range_hood", "sink", - "sofa", "stairs", "stool", "table", "tent", - "toilet", "tv_stand", "vase", "wardrobe", "xbox"] - -Base.show(io::IO, p::MN40DataPoint) = - print(io, "idx: $(p.idx), data: $(typeof(p.data)), ground_truth: $(p.ground_truth) ($(MN40_idx_to_classes[p.ground_truth]))") - -Base.show(io::IO, ::MIME"text/plain", p::MN40DataPoint) = +const MN40_classes_to_idx = Dict{String,UInt8}([ + ("airplane", 1), + ("bathtub", 2), + ("bed", 3), + ("bench", 4), + ("bookshelf", 5), + ("bottle", 6), + ("bowl", 7), + ("car", 8), + ("chair", 9), + ("cone", 10), + ("cup", 11), + ("curtain", 12), + ("desk", 13), + ("door", 14), + ("dresser", 15), + ("flower_pot", 16), + ("glass_box", 17), + ("guitar", 18), + ("keyboard", 19), + ("lamp", 20), + ("laptop", 21), + ("mantel", 22), + ("monitor", 23), + ("night_stand", 24), + ("person", 25), + ("piano", 26), + ("plant", 27), + ("radio", 28), + ("range_hood", 29), + ("sink", 30), + ("sofa", 31), + ("stairs", 32), + ("stool", 33), + ("table", 34), + ("tent", 35), + ("toilet", 36), + ("tv_stand", 37), + ("vase", 38), + ("wardrobe", 39), + ("xbox", 40), +]) + +const MN40_idx_to_classes = Dict{UInt8,String}([ + (1, "airplane"), + (2, "bathtub"), + (3, "bed"), + (4, "bench"), + (5, "bookshelf"), + (6, "bottle"), + (7, "bowl"), + (8, "car"), + (9, "chair"), + (10, "cone"), + (11, "cup"), + (12, "curtain"), + (13, "desk"), + (14, "door"), + (15, "dresser"), + (16, "flower_pot"), + (17, "glass_box"), + (18, "guitar"), + (19, "keyboard"), + (20, "lamp"), + (21, "laptop"), + (22, "mantel"), + (23, "monitor"), + (24, "night_stand"), + (25, "person"), + (26, "piano"), + (27, "plant"), + (28, "radio"), + (29, "range_hood"), + (30, "sink"), + (31, "sofa"), + (32, "stairs"), + (33, "stool"), + (34, "table"), + (35, "tent"), + (36, "toilet"), + (37, "tv_stand"), + (38, "vase"), + (39, "wardrobe"), + (40, "xbox"), +]) + +const MN40_classes = [ + "airplane", + "bathtub", + "bed", + "bench", + "bookshelf", + "bottle", + "bowl", + "car", + "chair", + "cone", + "cup", + "curtain", + "desk", + "door", + "dresser", + "flower_pot", + "glass_box", + "guitar", + "keyboard", + "lamp", + "laptop", + "mantel", + "monitor", + "night_stand", + "person", + "piano", + "plant", + "radio", + "range_hood", + "sink", + "sofa", + "stairs", + "stool", + "table", + "tent", + "toilet", + "tv_stand", + "vase", + "wardrobe", + "xbox", +] + +Base.show(io::IO, p::MN40DataPoint) = print( + io, + "idx: $(p.idx), data: $(typeof(p.data)), ground_truth: $(p.ground_truth) ($(MN40_idx_to_classes[p.ground_truth]))", +) + +Base.show(io::IO, ::MIME"text/plain", p::MN40DataPoint) = print(io, "ModelNet40 DataPoint:\n ", p) -end # module \ No newline at end of file +end # module diff --git a/src/datasets/modelnet40/mn40_pcloud.jl b/src/datasets/modelnet40/mn40_pcloud.jl index a40c4ad..39a5092 100644 --- a/src/datasets/modelnet40/mn40_pcloud.jl +++ b/src/datasets/modelnet40/mn40_pcloud.jl @@ -4,10 +4,14 @@ function pcloud_load(root::String = default_root) local_path = joinpath(root, "modelnet40_normal_resampled.zip") hash = "d64e9c5cfc479bac3260b164ae3c75ba83e94a1d216fbcd3f59ce2a9686d3762" - if(!isdir(local_dir)) - if(!isfile(local_path)) + if (!isdir(local_dir)) + if (!isfile(local_path)) # dataset prepared by authors of pointnet2 - download_and_verify("https://shapenet.cs.stanford.edu/media/modelnet40_normal_resampled.zip", local_path, hash) + download_and_verify( + "https://shapenet.cs.stanford.edu/media/modelnet40_normal_resampled.zip", + local_path, + hash, + ) end run(`unzip -q $local_path -d $root`) end @@ -34,15 +38,15 @@ PointCloud version of ModelNet40 dataset. """ struct ModelNet40PCloud <: AbstractDataset - root::String + root::String path::String train::Bool length::Int datapaths::Array #TODO add detailed type assertion npoints::Int - transform::Union{Flux3D.AbstractTransform, Nothing} - sampling #TODO Add type-assertion accordingly to include two possible option {"top", "uniform"} - classes_to_idx::Dict{String, UInt8} + transform::Union{Flux3D.AbstractTransform,Nothing} + sampling::Any #TODO Add type-assertion accordingly to include two possible option {"top", "uniform"} + classes_to_idx::Dict{String,UInt8} classes::Array{String,1} end @@ -50,22 +54,42 @@ function pcloud_extract(path, npoints) pset = Array{Float32}(undef, npoints, 3) nset = Array{Float32}(undef, npoints, 3) stream = open(path, "r") - for i in 1:npoints - tmp = map((x->parse(Float32, x)), split(readline(stream, keep=false), ",")) - pset[i,:] = tmp[1:3] - nset[i,:] = tmp[4:6] + for i = 1:npoints + tmp = map((x -> parse(Float32, x)), split(readline(stream, keep = false), ",")) + pset[i, :] = tmp[1:3] + nset[i, :] = tmp[4:6] end - return (pset,nset) + return (pset, nset) end -function ModelNet40PCloud(;root::String=default_root, train::Bool=true, npoints::Int=1024, transform=nothing, sampling=nothing) +function ModelNet40PCloud(; + root::String = default_root, + train::Bool = true, + npoints::Int = 1024, + transform = nothing, + sampling = nothing, +) _path = pcloud_load(root) - train ? _split="train" : _split="test" + train ? _split = "train" : _split = "test" shapeids = [line for line in readlines(joinpath(_path, "modelnet40_$(_split).txt"))] - shape_names = [join(split(shapeids[i], "_")[1:end-1], "_") for i in 1:length(shapeids)] - datapaths = [(shape_names[i], joinpath(_path, shape_names[i], (shapeids[i])*".txt")) for i in 1:length(shapeids)] + shape_names = [join(split(shapeids[i], "_")[1:end-1], "_") for i = 1:length(shapeids)] + datapaths = [ + (shape_names[i], joinpath(_path, shape_names[i], (shapeids[i]) * ".txt")) + for i = 1:length(shapeids) + ] _length = length(datapaths) - ModelNet40PCloud(root, _path, train, _length, datapaths, npoints, transform, sampling, MN40_classes_to_idx, MN40_classes) + ModelNet40PCloud( + root, + _path, + train, + _length, + datapaths, + npoints, + transform, + sampling, + MN40_classes_to_idx, + MN40_classes, + ) end function Base.getindex(v::ModelNet40PCloud, idx::Int) @@ -82,10 +106,10 @@ end Base.size(v::ModelNet40PCloud) = (v.length,) Base.length(v::ModelNet40PCloud) = v.length -function Base.show(io::IO, dset::ModelNet40PCloud) +function Base.show(io::IO, dset::ModelNet40PCloud) print(io, "ModelNet40(") print("mode = point_cloud, ") print("root = $(dset.root), ") print("train = $(dset.train), ") print("length = $(dset.length))") -end \ No newline at end of file +end diff --git a/src/datasets/utils.jl b/src/datasets/utils.jl index dcd61a6..e35b69c 100644 --- a/src/datasets/utils.jl +++ b/src/datasets/utils.jl @@ -8,26 +8,26 @@ function download_and_verify(url, path, hash) bytes2hex(SHA.sha256(f)) end if hash_download !== hash - msg = "Hash Mismatch!\n" + msg = "Hash Mismatch!\n" msg *= " Expected sha256: $hash\n" msg *= " Calculated sha256: $hash_download" error(msg) end - mv(tmppath, path; force=true) + mv(tmppath, path; force = true) end Base.size(d::AbstractDataset) = error("define Base.size of dataset type: $(typeof(d)).") Base.length(d::AbstractDataset) = error("define Base.length of dataset type: $(typeof(d)).") -Base.show(io::IO, p::AbstractDataPoint) = +Base.show(io::IO, p::AbstractDataPoint) = print(io, "idx: $(p.idx), data: $(typeof(p.data))") -Base.show(io::IO, ::MIME"text/plain", p::AbstractDataPoint) = +Base.show(io::IO, ::MIME"text/plain", p::AbstractDataPoint) = print(io, "DataPoint:\n ", p) -function Base.show(io::IO, dset::AbstractDataset) +function Base.show(io::IO, dset::AbstractDataset) print(io, "Dataset(") print("root = $(dset.root), ") print("train = $(dset.train), ") print("length = $(dset.length))") -end \ No newline at end of file +end diff --git a/src/metrics/mesh.jl b/src/metrics/mesh.jl index d3592f1..4d2ae5a 100644 --- a/src/metrics/mesh.jl +++ b/src/metrics/mesh.jl @@ -8,17 +8,23 @@ function laplacian_loss(m::TriMesh) return mean(L) end -function edge_loss(m::TriMesh, target_length::Number=0.0) +function edge_loss(m::TriMesh, target_length::Number = 0.0) verts = get_verts_packed(m) edges = @ignore get_edges_packed(m) - v1 = verts[:, edges[:,1]] - v2 = verts[:, edges[:,2]] - el = (_norm(v1-v2; dims=1) .- Float32(target_length)) .^ 2 + v1 = verts[:, edges[:, 1]] + v2 = verts[:, edges[:, 2]] + el = (_norm(v1 - v2; dims = 1) .- Float32(target_length)) .^ 2 loss = mean(el) return loss end -function chamfer_distance(m1::TriMesh, m2::TriMesh, num_samples::Int = 5000; w1::Number=1.0, w2::Number=1.0) +function chamfer_distance( + m1::TriMesh, + m2::TriMesh, + num_samples::Int = 5000; + w1::Number = 1.0, + w2::Number = 1.0, +) A = sample_points(m1, num_samples) B = sample_points(m2, num_samples) return _chamfer_distance(A, B, Float32(w1), Float32(w2)) diff --git a/src/metrics/pcloud.jl b/src/metrics/pcloud.jl index 592979e..ca54512 100644 --- a/src/metrics/pcloud.jl +++ b/src/metrics/pcloud.jl @@ -4,36 +4,50 @@ export chamfer_distance # chamfer_distance(A::PointCloud, B::PointCloud; w1::Number=1.0, w2::Number=1.0) = # _chamfer_distance(A.points, B.points, Float32(w1), Float32(w2)) -chamfer_distance(A::AbstractArray{<:Number}, B::AbstractArray{<:Number}; w1::Number=1.0, w2::Number=1.0) = - _chamfer_distance(Float32.(A), Float32.(B), Float32(w1), Float32(w2)) +chamfer_distance( + A::AbstractArray{<:Number}, + B::AbstractArray{<:Number}; + w1::Number = 1.0, + w2::Number = 1.0, +) = _chamfer_distance(Float32.(A), Float32.(B), Float32(w1), Float32(w2)) -function _chamfer_distance(A::AbstractArray{Float32, 2}, B::AbstractArray{Float32, 2}, w1::Float32=1.0, w2::Float32=1.0) +function _chamfer_distance( + A::AbstractArray{Float32,2}, + B::AbstractArray{Float32,2}, + w1::Float32 = 1.0, + w2::Float32 = 1.0, +) A = reshape(A, size(A)..., 1) B = reshape(B, size(B)..., 1) - return _chamfer_distance(A,B,w1,w2) + return _chamfer_distance(A, B, w1, w2) end -function _chamfer_distance(A::AbstractArray{Float32, 3}, B::AbstractArray{Float32, 3}, w1::Float32=1.0, w2::Float32=1.0) +function _chamfer_distance( + A::AbstractArray{Float32,3}, + B::AbstractArray{Float32,3}, + w1::Float32 = 1.0, + w2::Float32 = 1.0, +) nn_for_A, nn_for_B = _nearest_neighbors(A, B) # pcloud Batch reduction - nn_for_A = mean(nn_for_A; dims=2) - nn_for_B = mean(nn_for_B; dims=2) + nn_for_A = mean(nn_for_A; dims = 2) + nn_for_B = mean(nn_for_B; dims = 2) # pcloud mean reduction dist_to_B = mean(nn_for_A) dist_to_A = mean(nn_for_B) - distance = (Float32(w1)*dist_to_B) + (Float32(w2)*dist_to_A) + distance = (Float32(w1) * dist_to_B) + (Float32(w2) * dist_to_A) return distance end -function _nearest_neighbors(x::AbstractArray{Float32,3},y::AbstractArray{Float32,3}) - xx = sum(x .^ 2, dims=1) - yy = sum(y .^ 2, dims=1) - zz = Flux.batched_mul(permutedims(x, (2,1,3)), y) +function _nearest_neighbors(x::AbstractArray{Float32,3}, y::AbstractArray{Float32,3}) + xx = sum(x .^ 2, dims = 1) + yy = sum(y .^ 2, dims = 1) + zz = Flux.batched_mul(permutedims(x, (2, 1, 3)), y) rx = reshape(xx, size(xx, 2), 1, :) ry = reshape(yy, 1, size(yy, 2), :) P = (rx .+ ry) .- (2 .* zz) - nn_for_x = minimum(P; dims=2) - nn_for_y = minimum(P; dims=1) + nn_for_x = minimum(P; dims = 2) + nn_for_y = minimum(P; dims = 1) return nn_for_x, nn_for_y end diff --git a/src/models/dgcnn.jl b/src/models/dgcnn.jl index 7e8de0b..3883f6f 100644 --- a/src/models/dgcnn.jl +++ b/src/models/dgcnn.jl @@ -3,7 +3,7 @@ export DGCNN, EdgeConv function CreateSingleKNNGraph(X::AbstractArray, K::Int) F, N = size(X) kdtree = KDTree(X) - cat([X[:,(knn(kdtree, X[:,i], K+1, true)[1][2:K+1])] for i in 1:N]..., dims=3) + cat([X[:, (knn(kdtree, X[:, i], K + 1, true)[1][2:K+1])] for i = 1:N]..., dims = 3) end @nograd CreateSingleKNNGraph @@ -11,62 +11,62 @@ end struct EdgeConv layers::AbstractArray K::Int - mlp - maxpool_K + mlp::Any + maxpool_K::Any end function EdgeConv(layers::AbstractArray, K::Int) m = [] - for i in 1:(length(layers)-1) + for i = 1:(length(layers)-1) if i == 1 - push!(m, conv_bn_block(2*layers[i], layers[i+1], (1,))) + push!(m, conv_bn_block(2 * layers[i], layers[i+1], (1,))) else push!(m, conv_bn_block(layers[i], layers[i+1], (1,))) end end - + EdgeConv(layers, K, Chain(m...), MaxPool((K,))) end function (m::EdgeConv)(X) F, N, B = size(X) # X: [F, N, B] - - KNNGraph = cat([CreateSingleKNNGraph(X[:,:,i], m.K) for i in 1:B]..., dims=4) + + KNNGraph = cat([CreateSingleKNNGraph(X[:, :, i], m.K) for i = 1:B]..., dims = 4) # KNNGraph: [F, K, N, B] - + X = reshape(X, F, 1, N, B) # X: [F, 1, N, B] - - X = cat([X for i in 1:m.K]...,dims=2) + + X = cat([X for i = 1:m.K]..., dims = 2) # X: [F, K, N, B] - - X = cat(X, KNNGraph-X, dims=1) + + X = cat(X, KNNGraph - X, dims = 1) # X: [2*F, K, N, B] - - X = PermutedDimsArray(X, (2,3,1,4)) + + X = PermutedDimsArray(X, (2, 3, 1, 4)) # X: [K, N, 2*F, B] - - X = reshape(X, N*m.K, 2*F,B) + + X = reshape(X, N * m.K, 2 * F, B) # X: [K*N, 2*F, B] - + X = m.mlp(X) # X: [K*N, an, B] - + an = size(X)[2] - X = reshape(X, m.K, an*N, B) + X = reshape(X, m.K, an * N, B) # X: [K, N*an, B] - + X = m.maxpool_K(X) # X: [1, N*an, B] - + X = reshape(X, N, an, B) # X: [N, an, B] - - X = PermutedDimsArray(X, (2,1,3)) + + X = PermutedDimsArray(X, (2, 1, 3)) # X: [an, N, B] - + return X end @@ -75,63 +75,63 @@ end struct DGCNN EdgeConv1::EdgeConv EdgeConv2::EdgeConv - conv_3 - maxpool_3 - fc_4 - drop_4 - fc_5 - drop_5 - fc_6 -end - -function DGCNN(num_classes::Int=10, K::Int=10, npoints::Int=1024) + conv_3::Any + maxpool_3::Any + fc_4::Any + drop_4::Any + fc_5::Any + drop_5::Any + fc_6::Any +end + +function DGCNN(num_classes::Int = 10, K::Int = 10, npoints::Int = 1024) DGCNN( - EdgeConv([3,32,64,64], K), - EdgeConv([64,128,256], K), - conv_bn_block(256,1024,(1,)), + EdgeConv([3, 32, 64, 64], K), + EdgeConv([64, 128, 256], K), + conv_bn_block(256, 1024, (1,)), MaxPool((npoints,)), - fc_bn_block(1024,512), + fc_bn_block(1024, 512), Dropout(0.5), - fc_bn_block(512,256), + fc_bn_block(512, 256), Dropout(0.5), - Dense(256,num_classes) - ) + Dense(256, num_classes), + ) end function (m::DGCNN)(X) - + # X: [3, N, B] - - C,N,B = size(X) + + C, N, B = size(X) X = m.EdgeConv1(X) # X: [64, N, B] - + X = m.EdgeConv2(X) # X: [128, N, B] - - X = PermutedDimsArray(X, (2,1,3)) + + X = PermutedDimsArray(X, (2, 1, 3)) # X: [N, 128, B] - + X = m.conv_3(X) # X: [N, 1024, B] - + X = m.maxpool_3(X) # X: [1, 1024, B] - + X = reshape(X, :, B) # X: [1024, B] - + X = m.drop_4(m.fc_4(X)) # X: [512, B] - + X = m.drop_5(m.fc_5(X)) # X: [256, B] - + X = m.fc_6(X) # X: [num_classes, B] - - return softmax(X, dims=1) - + + return softmax(X, dims = 1) + end -@functor DGCNN \ No newline at end of file +@functor DGCNN diff --git a/src/models/pointnet.jl b/src/models/pointnet.jl index 931eade..de1a0b8 100644 --- a/src/models/pointnet.jl +++ b/src/models/pointnet.jl @@ -1,58 +1,58 @@ export stnKD, PointNet stnKD(K::Int) = Chain( - Conv((1,), K=>64, relu), + Conv((1,), K => 64, relu), BatchNorm(64), - Conv((1,), 64=>128, relu), + Conv((1,), 64 => 128, relu), BatchNorm(128), - Conv((1,), 128=>1024, relu), + Conv((1,), 128 => 1024, relu), BatchNorm(1024), - x -> maximum(x, dims=1), + x -> maximum(x, dims = 1), x -> reshape(x, :, size(x, 3)), Dense(1024, 512, relu), -# BatchNorm(512), + # BatchNorm(512), Dense(512, 256, relu), BatchNorm(256), - Dense(256,K*K), + Dense(256, K * K), x -> reshape(x, K, K, size(x, 2)), x -> x .+ reshape(Matrix{Float64}(I, K, K), K, K, 1), - x -> PermutedDimsArray(x, (2,1,3)), + x -> PermutedDimsArray(x, (2, 1, 3)), ) struct PointNet - stn - fstn - conv_block1 - feat - cls + stn::Any + fstn::Any + conv_block1::Any + feat::Any + cls::Any end -function PointNet(num_classes::Int=10, K::Int=64) +function PointNet(num_classes::Int = 10, K::Int = 64) stn = stnKD(3) fstn = stnKD(K) conv_block1 = conv_bn_block(3, 64, (1,)) feat = Chain( - Conv((1,), 64=>128, relu), + Conv((1,), 64 => 128, relu), BatchNorm(128), - Conv((1,), 128=>1024), + Conv((1,), 128 => 1024), BatchNorm(1024), - x -> maximum(x, dims=1), + x -> maximum(x, dims = 1), x -> reshape(x, 1024, :), Dense(1024, 512, relu), BatchNorm(512), Dense(512, 256, relu), Dropout(0.4), BatchNorm(256), - ) + ) cls = Dense(256, num_classes, relu) - PointNet(stn,fstn, conv_block1, feat, cls) + PointNet(stn, fstn, conv_block1, feat, cls) end function (m::PointNet)(X) # X: [3, N, B] - X = permutedims(X, (2,1,3)) + X = permutedims(X, (2, 1, 3)) # X: [N, 3, B] X = batched_mul(X, m.stn(X)) @@ -70,7 +70,7 @@ function (m::PointNet)(X) X = m.cls(X) # X: [num_classes, B] - return softmax(X, dims=1) + return softmax(X, dims = 1) end -@functor PointNet \ No newline at end of file +@functor PointNet diff --git a/src/models/utils.jl b/src/models/utils.jl index 939f6a0..f21feee 100644 --- a/src/models/utils.jl +++ b/src/models/utils.jl @@ -1,13 +1,7 @@ function conv_bn_block(input, output, kernel_size) - return Chain( - Conv((kernel_size...,), input=>output), - BatchNorm(output), - x -> relu.(x)) + return Chain(Conv((kernel_size...,), input => output), BatchNorm(output), x -> relu.(x)) end function fc_bn_block(input, output) - return Chain( - Dense(input,output), - BatchNorm(output), - x -> relu.(x)) -end \ No newline at end of file + return Chain(Dense(input, output), BatchNorm(output), x -> relu.(x)) +end diff --git a/src/rep/mesh.jl b/src/rep/mesh.jl index f673b4f..b16ddaa 100644 --- a/src/rep/mesh.jl +++ b/src/rep/mesh.jl @@ -200,7 +200,7 @@ function Base.show(io::IO, m::TriMesh{T,R,S}) where {T,R,S} "\n offset: ", m.offset, "\n Storage type: ", - S + S, ) end diff --git a/src/rep/pcloud.jl b/src/rep/pcloud.jl index ab47549..5d506ab 100644 --- a/src/rep/pcloud.jl +++ b/src/rep/pcloud.jl @@ -24,21 +24,25 @@ should match with the `N` and `B` of `points` and `D`=2 or `D`=3 """ mutable struct PointCloud{T<:Float32} <: AbstractObject points::AbstractArray{T,3} - normals::Union{AbstractArray{T,3}, Nothing} + normals::Union{AbstractArray{T,3},Nothing} end -function PointCloud(points::AbstractArray{Float32,2}, normals::Union{AbstractArray{Float32,2}, Nothing}=nothing) - points = reshape(points, size(points)...,1) +function PointCloud( + points::AbstractArray{Float32,2}, + normals::Union{AbstractArray{Float32,2},Nothing} = nothing, +) + points = reshape(points, size(points)..., 1) if !(normals isa Nothing) - size(points,2) == size(normals,2) || error("number of points and normals must match in PointCloud.") - normals = reshape(normals, size(normals)...,1); + size(points, 2) == size(normals, 2) || + error("number of points and normals must match in PointCloud.") + normals = reshape(normals, size(normals)..., 1) end return PointCloud(points, normals) end -function PointCloud(points::AbstractArray, normals::Union{AbstractArray, Nothing}=nothing) +function PointCloud(points::AbstractArray, normals::Union{AbstractArray,Nothing} = nothing) points = Float32.(points) if normals !== nothing normals = Float32.(normals) @@ -46,7 +50,7 @@ function PointCloud(points::AbstractArray, normals::Union{AbstractArray, Nothing return PointCloud(points, normals) end -PointCloud(;points, normals=nothing)= PointCloud(points, normals) +PointCloud(; points, normals = nothing) = PointCloud(points, normals) PointCloud(pcloud::PointCloud) = PointCloud(pcloud.points, pcloud.normals) @@ -54,9 +58,9 @@ PointCloud(pcloud::PointCloud) = PointCloud(pcloud.points, pcloud.normals) # deepcopy generate error when using on PointCloud with parent field of points not Nothing Base.deepcopy_internal(x::PointCloud, dict::IdDict) = - PointCloud(copy(x.points), (x.normals===nothing ? nothing : copy(x.normals))) + PointCloud(copy(x.points), (x.normals === nothing ? nothing : copy(x.normals))) -Base.getindex(p::PointCloud, index::Number) = p.points[:,:,index] +Base.getindex(p::PointCloud, index::Number) = p.points[:, :, index] function Base.show(io::IO, p::PointCloud) if p.normals isa Nothing @@ -74,4 +78,4 @@ Base.show(io::IO, ::MIME"text/plain", p::PointCloud) = Returns the size of PointCloud. """ -npoints(p::PointCloud) = size(p.points,2) +npoints(p::PointCloud) = size(p.points, 2) diff --git a/src/rep/utils.jl b/src/rep/utils.jl index 7e4060e..9de750d 100644 --- a/src/rep/utils.jl +++ b/src/rep/utils.jl @@ -7,30 +7,32 @@ function _lg_cross(A::AbstractArray, B::AbstractArray) end a1, a2, a3 = A[1, :], A[2, :], A[3, :] b1, b2, b3 = B[1, :], B[2, :], B[3, :] - return vcat(reshape.([(a2 .* b3) - (a3 .* b2), (a3 .* b1) - (a1 .* b3), (a1 .* b2) - (a2 .* b1)], 1,:)...) + return vcat(reshape.( + [(a2 .* b3) - (a3 .* b2), (a3 .* b1) - (a1 .* b3), (a1 .* b2) - (a2 .* b1)], + 1, + :, + )...) end function _normalize(A::AbstractArray{T,2}; eps::Number = 1e-6, dims::Int = 2) where {T} eps = T.(eps) - norm = max.(_norm(A; dims=dims), eps) + norm = max.(_norm(A; dims = dims), eps) return (A ./ norm) end _norm(A::AbstractArray; dims::Int = 2) = sqrt.(sum(A .^ 2; dims = dims)) -function _auxiliary_mesh( - list::Vector{<:AbstractArray{T, 2}} -) where {T<:Number} +function _auxiliary_mesh(list::Vector{<:AbstractArray{T,2}}) where {T<:Number} all(ndims.(list) .== 2) || error("only 2d arrays are supported") _N = length(list) items_len = Array{Int,1}(undef, _N) packed_first_idx = Array{Int,1}(undef, _N) - packed_to_list_idx = Array{Int,1}(undef, sum(size.(list,2))) + packed_to_list_idx = Array{Int,1}(undef, sum(size.(list, 2))) cur_idx = 1 - for (i,x) in enumerate(list) + for (i, x) in enumerate(list) _len = size(x, 2) items_len[i] = _len packed_first_idx[i] = cur_idx @@ -41,19 +43,19 @@ function _auxiliary_mesh( end function _list_to_padded( - list::Vector{<:AbstractArray{T, 2}}, + list::Vector{<:AbstractArray{T,2}}, pad_value::Number, - pad_size::Union{Nothing, Tuple}=nothing; - is_similar::Bool = false -) where {T<:Number} + pad_size::Union{Nothing,Tuple} = nothing; + is_similar::Bool = false, +) where {T<:Number} all(ndims.(list) .== 2) || error("only 2d arrays are supported") if is_similar - return Flux.stack(list, ndims(list[1])+1) + return Flux.stack(list, ndims(list[1]) + 1) end if pad_size isa Nothing - pad_size = (maximum(size.(list,1)), maximum(size.(list, 2))) + pad_size = (maximum(size.(list, 1)), maximum(size.(list, 2))) else length(pad_size) == 2 || error("pad_size should be a tuple of length 2") end @@ -61,16 +63,14 @@ function _list_to_padded( padded = @ignore fill!(similar(list[1], pad_size..., length(list)), T.(pad_value)) padded = Zygote.bufferfrom(padded) - for (i,x) in enumerate(list) - padded[1:size(x,1), 1:size(x,2),i] = x + for (i, x) in enumerate(list) + padded[1:size(x, 1), 1:size(x, 2), i] = x end return copy(padded) end -function _list_to_packed( - list::Vector{<:AbstractArray{T, 2}} -) where {T<:Number} +function _list_to_packed(list::Vector{<:AbstractArray{T,2}}) where {T<:Number} all(ndims.(list) .== 2) || error("only 2d arrays are supported") packed = hcat(list...) @@ -84,20 +84,20 @@ packed (sum(Mi),3) padded (N, max(Mi), 3) """ function _packed_to_padded( - packed::AbstractArray{T, 2}, - items_len::AbstractArray{<:Number, 1}, + packed::AbstractArray{T,2}, + items_len::AbstractArray{<:Number,1}, pad_value::Number, -) where {T<:Number} +) where {T<:Number} ndims(packed) == 2 || error("only 2d arrays are supported") _N = length(items_len) _M = maximum(items_len) - padded = @ignore fill!(similar(packed, size(packed,1), _M, _N), T.(pad_value)) + padded = @ignore fill!(similar(packed, size(packed, 1), _M, _N), T.(pad_value)) padded = Zygote.bufferfrom(padded) cur_idx = 1 - for (i,_len) in enumerate(items_len) - padded[:,1:_len,i] = packed[:,cur_idx:cur_idx+_len-1] + for (i, _len) in enumerate(items_len) + padded[:, 1:_len, i] = packed[:, cur_idx:cur_idx+_len-1] cur_idx += _len end @@ -105,9 +105,9 @@ function _packed_to_padded( end function _packed_to_list( - packed::AbstractArray{T, 2}, - items_len::AbstractArray{<:Number, 1} -) where {T<:Number} + packed::AbstractArray{T,2}, + items_len::AbstractArray{<:Number,1}, +) where {T<:Number} ndims(packed) == 2 || error("only 2d arrays are supported") @@ -115,8 +115,8 @@ function _packed_to_list( _M = maximum(items_len) list = @ignore typeof(similar(packed))[] list = Zygote.bufferfrom(list) - cur_idx=1 - for (i,_len) in enumerate(items_len) + cur_idx = 1 + for (i, _len) in enumerate(items_len) push!(list, packed[:, cur_idx:cur_idx+_len-1]) cur_idx += _len end @@ -125,26 +125,31 @@ end function _padded_to_packed( padded::AbstractArray{T,3}, - items_len::Union{Nothing, AbstractArray{<:Number, 1}}=nothing, - pad_value::Union{Nothing, Number}=nothing -) where{T<:Number} + items_len::Union{Nothing,AbstractArray{<:Number,1}} = nothing, + pad_value::Union{Nothing,Number} = nothing, +) where {T<:Number} ndims(padded) == 3 || error("padded should be 3 dimension array") - (pad_value == nothing || items_len == nothing) || error("pad_value and items_len both should not be given") + (pad_value == nothing || items_len == nothing) || + error("pad_value and items_len both should not be given") - packed = reshape(padded, size(padded,1), :) + packed = reshape(padded, size(padded, 1), :) _N = length(items_len) _M = size(padded, 2) - _N == size(padded, 3) || error("items_len length should match the last dimension of padded array") - _mask = @ignore reduce(vcat, [collect(1:_len) .+ ((i-1)*_M) for (i,_len) in enumerate(items_len)]) + _N == size(padded, 3) || + error("items_len length should match the last dimension of padded array") + _mask = @ignore reduce( + vcat, + [collect(1:_len) .+ ((i - 1) * _M) for (i, _len) in enumerate(items_len)], + ) return packed[:, _mask] end function _padded_to_list( padded::AbstractArray{T,3}, - items_len::Union{Nothing, AbstractArray{<:Number, 1}} -) where {T<:Number} + items_len::Union{Nothing,AbstractArray{<:Number,1}}, +) where {T<:Number} ndims(padded) == 3 || error("padded should be 3 dimension array") @@ -153,13 +158,14 @@ function _padded_to_list( end _N = length(items_len) - _N == size(padded, 3) || error("items_len length should match the last dimension of padded array") + _N == size(padded, 3) || + error("items_len length should match the last dimension of padded array") - list = @ignore typeof(similar(padded,1,1))[] + list = @ignore typeof(similar(padded, 1, 1))[] list = Zygote.bufferfrom(list) - for (i,_len) in enumerate(items_len) - push!(list, padded[:,1:_len,i]) + for (i, _len) in enumerate(items_len) + push!(list, padded[:, 1:_len, i]) end return copy(list) diff --git a/src/transforms/mesh_func.jl b/src/transforms/mesh_func.jl index 0844898..57af1be 100644 --- a/src/transforms/mesh_func.jl +++ b/src/transforms/mesh_func.jl @@ -40,8 +40,12 @@ function sample_points( dist = Distributions.Categorical(probvec) sample_faces_idx = @ignore rand(dist, num_samples) sample_faces = faces_padded[:, sample_faces_idx, i] - samples[:, :, i] = - _sample_points(S,verts_padded[:,1:m._verts_len[i],i], sample_faces, num_samples) + samples[:, :, i] = _sample_points( + S, + verts_padded[:, 1:m._verts_len[i], i], + sample_faces, + num_samples, + ) end return copy(samples) diff --git a/src/transforms/pcloud_func.jl b/src/transforms/pcloud_func.jl index 9965701..1c2f1c9 100644 --- a/src/transforms/pcloud_func.jl +++ b/src/transforms/pcloud_func.jl @@ -15,7 +15,9 @@ julia> normalize!(p) """ function normalize!(pcloud::PointCloud) centroid = mean(pcloud.points, dims = 2) - pcloud.points = (pcloud.points .- centroid) ./ (std(pcloud.points, mean = centroid, dims = 2) .+ EPS) + pcloud.points = + (pcloud.points .- centroid) ./ + (std(pcloud.points, mean = centroid, dims = 2) .+ EPS) return pcloud end @@ -104,7 +106,8 @@ julia> rotate!(p, rotmat) ``` """ function rotate!(pcloud::PointCloud, rotmat::AbstractArray{Float32,2}) - size(rotmat) == (3, 3) || error("rotmat must be (3, 3) array, but instead got $(size(rotmat)) array") + size(rotmat) == (3, 3) || + error("rotmat must be (3, 3) array, but instead got $(size(rotmat)) array") size(pcloud.points, 1) == 3 || error("dimension of points in PointCloud must be 3") points_packed = transpose(rotmat) * reshape(pcloud.points, 3, :) pcloud.points = reshape(points_packed, size(pcloud.points)...) @@ -136,7 +139,8 @@ function rotate(pcloud::PointCloud, rotmat::AbstractArray{Float32,2}) return p end -rotate(pcloud::PointCloud, rotmat::AbstractArray{Number,2}) = rotate(pcloud, Float32.(rotmat)) +rotate(pcloud::PointCloud, rotmat::AbstractArray{Number,2}) = + rotate(pcloud, Float32.(rotmat)) """ realign!(src::PointCloud, tgt::PointCloud) @@ -156,18 +160,28 @@ julia> tgt = PointCloud(rand(1024,3)) julia> realign!(src, tgt) ``` """ -function realign!(src::PointCloud, tgt_min::AbstractArray{Float32,2}, tgt_max::AbstractArray{Float32,2}) - size(src.points, 1) == size(tgt_max, 1) || error("source and target pointcloud dimension mismatch") +function realign!( + src::PointCloud, + tgt_min::AbstractArray{Float32,2}, + tgt_max::AbstractArray{Float32,2}, +) + size(src.points, 1) == size(tgt_max, 1) || + error("source and target pointcloud dimension mismatch") src_min = minimum(src.points, dims = 2) src_max = maximum(src.points, dims = 2) - src.points = ((src.points .- src_min) ./ (src_max - src_min .+ EPS)) .* (tgt_max - tgt_min) .+ tgt_min + src.points = + ((src.points .- src_min) ./ (src_max - src_min .+ EPS)) .* (tgt_max - tgt_min) .+ + tgt_min return src end -realign!(src::PointCloud, tgt_min::AbstractArray{<:Number,2}, tgt_max::AbstractArray{<:Number,2}) = - realign!(src, Float32.(tgt_min), Float32.(tgt_max)) +realign!( + src::PointCloud, + tgt_min::AbstractArray{<:Number,2}, + tgt_max::AbstractArray{<:Number,2}, +) = realign!(src, Float32.(tgt_min), Float32.(tgt_max)) -function realign!(src::PointCloud, tgt::PointCloud, index::Number=1) +function realign!(src::PointCloud, tgt::PointCloud, index::Number = 1) points = tgt[index] tgt_min = minimum(points, dims = 2) tgt_max = maximum(points, dims = 2) @@ -192,13 +206,17 @@ julia> tgt = PointCloud(rand(1024,3)) julia> src = realign!(src, tgt) ``` """ -function realign(src::PointCloud, tgt_min::AbstractArray{<:Number,2}, tgt_max::AbstractArray{<:Number,2}) +function realign( + src::PointCloud, + tgt_min::AbstractArray{<:Number,2}, + tgt_max::AbstractArray{<:Number,2}, +) p = deepcopy(src) realign!(p, tgt_min, tgt_max) return p end -function realign(src::PointCloud, tgt::PointCloud, index::Number=1) +function realign(src::PointCloud, tgt::PointCloud, index::Number = 1) p = deepcopy(src) realign!(p, tgt, index) return p diff --git a/src/transforms/utils.jl b/src/transforms/utils.jl index ffaf23e..6217b77 100644 --- a/src/transforms/utils.jl +++ b/src/transforms/utils.jl @@ -9,4 +9,4 @@ function Base.show(io::IO, c::AbstractCompose) print(io, ")") end -Base.show(io::IO, t::AbstractTransform) = print(io, "$(typeof(t))(...)") \ No newline at end of file +Base.show(io::IO, t::AbstractTransform) = print(io, "$(typeof(t))(...)") diff --git a/src/visualize.jl b/src/visualize.jl index c497f96..90f06f2 100644 --- a/src/visualize.jl +++ b/src/visualize.jl @@ -13,16 +13,15 @@ Dimension of points in PointCloud `pcloud` must be 3. - color (Symbol) - Color of the marker, default `:blue` - markersize (Number) - Size of the marker, default `0.02*npoints(pcloud)/1024` """ -function visualize(v::PointCloud, index::Number=1; kwargs...) - points = v[index] - size(points,1)==3 || error("dimension of points in PointCloud must be 3.") +function visualize(v::PointCloud, index::Number = 1; kwargs...) + points = v[index] + size(points, 1) == 3 || error("dimension of points in PointCloud must be 3.") kwargs = convert(Dict{Symbol,Any}, kwargs) get!(kwargs, :color, :blue) get!(kwargs, :markersize, 40 / npoints(v)) - AbstractPlotting.meshscatter(v.points[:, 1], v.points[:, 2],v.points[:, 3]; - kwargs...) + AbstractPlotting.meshscatter(v.points[:, 1], v.points[:, 2], v.points[:, 3]; kwargs...) end """ @@ -34,17 +33,16 @@ Visualize mesh at `index` in TriMesh `m`. ### Optional Arguments: """ -function visualize(m::GeometryBasics.Mesh; kwargs...) where{T,R} +function visualize(m::GeometryBasics.Mesh; kwargs...) where {T,R} kwargs = convert(Dict{Symbol,Any}, kwargs) get!(kwargs, :color, :red) AbstractPlotting.mesh(GeometryBasics.normal_mesh(m); kwargs...) end -visualize(m::TriMesh, index::Int=1; kwargs...) = visualize(GBMesh(m, index); kwargs...) +visualize(m::TriMesh, index::Int = 1; kwargs...) = visualize(GBMesh(m, index); kwargs...) -visualize(v::Dataset.AbstractDataPoint; kwargs...) = - visualize(v.data; kwargs...) +visualize(v::Dataset.AbstractDataPoint; kwargs...) = visualize(v.data; kwargs...) visualize(v::AbstractCustomObject; kwargs...) = error("Define visualize function for custom type: $(typeof(v)). diff --git a/test/cuda/metrics.jl b/test/cuda/metrics.jl index 21327f7..cb77b8e 100644 --- a/test/cuda/metrics.jl +++ b/test/cuda/metrics.jl @@ -1,57 +1,68 @@ @info "Testing Metrics..." @testset "TriMesh Metrics" begin - _mesh = load_trimesh([ - joinpath(@__DIR__, "../meshes/teapot.obj"), - joinpath(@__DIR__, "../meshes/sphere.obj"), - ]) |> gpu + _mesh = + load_trimesh([ + joinpath(@__DIR__, "../meshes/teapot.obj"), + joinpath(@__DIR__, "../meshes/sphere.obj"), + ]) |> gpu @testset "Laplacian loss" begin - verts1 = [0.1 0.3 0.5; - 0.5 0.2 0.1; - 0.6 0.8 0.7] - verts2 = [0.1 0.3 0.3; - 0.6 0.7 0.8; - 0.2 0.3 0.4; - 0.1 0.5 0.3] - verts3 = [0.7 0.3 0.6; - 0.2 0.4 0.8; - 0.9 0.5 0.2; - 0.2 0.3 0.4; - 0.9 0.3 0.8] + verts1 = [ + 0.1 0.3 0.5 + 0.5 0.2 0.1 + 0.6 0.8 0.7 + ] + verts2 = [ + 0.1 0.3 0.3 + 0.6 0.7 0.8 + 0.2 0.3 0.4 + 0.1 0.5 0.3 + ] + verts3 = [ + 0.7 0.3 0.6 + 0.2 0.4 0.8 + 0.9 0.5 0.2 + 0.2 0.3 0.4 + 0.9 0.3 0.8 + ] faces1 = [1 2 3] - faces2 = [1 2 3; - 2 3 4] - faces3 = [2 3 1; - 1 2 4; - 3 4 2; - 5 4 3; - 5 1 2; - 5 4 2; - 5 3 2] + faces2 = [ + 1 2 3 + 2 3 4 + ] + faces3 = [ + 2 3 1 + 1 2 4 + 3 4 2 + 5 4 3 + 5 1 2 + 5 4 2 + 5 3 2 + ] - T,R = Float32, UInt32 + T, R = Float32, UInt32 verts_list = [T.(verts1'), T.(verts2'), T.(verts3')] faces_list = [R.(faces1'), R.(faces2'), R.(faces3')] m = TriMesh(verts_list, faces_list) |> gpu _edges = get_edges_packed(m) V = size(get_verts_packed(m), 2) - L = zeros(V,V) - deg = zeros(V,V) - for i in 1:size(_edges, 1) - L[_edges[i,1], _edges[i,2]] = 1 - L[_edges[i,2], _edges[i,1]] = 1 + L = zeros(V, V) + deg = zeros(V, V) + for i = 1:size(_edges, 1) + L[_edges[i, 1], _edges[i, 2]] = 1 + L[_edges[i, 2], _edges[i, 1]] = 1 end deg = sum(L; dims = 2) deg = map(x -> (x > 0 ? 1 / x : x), deg) - for i=1:V, j=1:V - if i==j - L[i,j] = -1 - elseif L[i,j]==1 - L[i,j] = deg[i] + for i = 1:V, j = 1:V + if i == j + L[i, j] = -1 + elseif L[i, j] == 1 + L[i, j] = deg[i] end end @@ -59,56 +70,52 @@ L = L * transpose(verts) L = Flux3D._norm(L; dims = 2) @test isapprox(mean(L), laplacian_loss(m)) - @test gradient(x->laplacian_loss(x), m) isa Tuple + @test gradient(x -> laplacian_loss(x), m) isa Tuple end @testset "Edge Loss" begin m = deepcopy(_mesh) verts = get_verts_packed(m) edges = get_edges_packed(m) - v1 = verts[:, edges[:,1]] - v2 = verts[:, edges[:,2]] - loss = mean((Flux3D._norm(v1-v2; dims=1)) .^ 2) + v1 = verts[:, edges[:, 1]] + v2 = verts[:, edges[:, 2]] + loss = mean((Flux3D._norm(v1 - v2; dims = 1)) .^ 2) @test edge_loss(m) == loss - @test gradient(x->edge_loss(x), m) isa Tuple + @test gradient(x -> edge_loss(x), m) isa Tuple end @testset "sample_points" begin - m = load_trimesh([ - joinpath(@__DIR__, "../meshes/sphere.obj"), - joinpath(@__DIR__, "../meshes/sphere.obj"), - ]) |> gpu + m = + load_trimesh([ + joinpath(@__DIR__, "../meshes/sphere.obj"), + joinpath(@__DIR__, "../meshes/sphere.obj"), + ]) |> gpu samples = sample_points(m, 1000) - _radius = sqrt.(sum(samples.^2; dims=1)) - @test samples isa CuArray{Float32, 3} - @test all(isapprox.( - cpu(_radius), - 1.0, - rtol = 1e-2, - atol = 1e-5, - )) - @test gradient(x->sum(sample_points(x,1000)),m) isa Tuple + _radius = sqrt.(sum(samples .^ 2; dims = 1)) + @test samples isa CuArray{Float32,3} + @test all(isapprox.(cpu(_radius), 1.0, rtol = 1e-2, atol = 1e-5)) + @test gradient(x -> sum(sample_points(x, 1000)), m) isa Tuple end @testset "Chamfer Loss" begin m = deepcopy(_mesh) - loss = chamfer_distance(m,m) + loss = chamfer_distance(m, m) @test all(isapprox.(loss, 0, rtol = 1e-5, atol = 1e-2)) - @test gradient(x->chamfer_distance(x, x), m) isa Tuple + @test gradient(x -> chamfer_distance(x, x), m) isa Tuple # naive chamfer distance - x = rand(3,1000) |> gpu - y = rand(3,500) |> gpu - xx = sum(x .^ 2, dims=1) - yy = sum(y .^ 2, dims=1) + x = rand(3, 1000) |> gpu + y = rand(3, 500) |> gpu + xx = sum(x .^ 2, dims = 1) + yy = sum(y .^ 2, dims = 1) zz = x' * y rx = reshape(xx, size(xx, 2), 1) ry = reshape(yy, 1, size(yy, 2)) P = (rx .+ ry) .- (2 .* zz) - distA = minimum(P; dims=2) - distB = minimum(P; dims=1) + distA = minimum(P; dims = 2) + distB = minimum(P; dims = 1) loss = mean(distA) + mean(distB) - @test isapprox(chamfer_distance(x,y), loss) + @test isapprox(chamfer_distance(x, y), loss) end end diff --git a/test/cuda/rep.jl b/test/cuda/rep.jl index 9ca1abd..f84f0b1 100644 --- a/test/cuda/rep.jl +++ b/test/cuda/rep.jl @@ -1,7 +1,7 @@ @testset "Representation" begin - for T = [Float32,Float64], _N = [true, false] - points = rand(T,3,16,4) - _normals = rand(T,3,16,4) + for T in [Float32, Float64], _N in [true, false] + points = rand(T, 3, 16, 4) + _normals = rand(T, 3, 16, 4) if _N normals = _normals else @@ -16,7 +16,7 @@ @test size(crep.normals) == size(_normals) @test crep.normals isa CuArray{Float32,3} end - @test npoints(crep) == size(points,2) + @test npoints(crep) == size(points, 2) @test size(crep.points) == size(points) @test crep.points isa CuArray{Float32,3} end @@ -25,32 +25,42 @@ end @info "Testing TriMesh..." @testset "TriMesh rep" begin - T,R = (Float32, Int64) - verts1 = [0.1 0.3 0.5; - 0.5 0.2 0.1; - 0.6 0.8 0.7] - verts2 = [0.1 0.3 0.3; - 0.6 0.7 0.8; - 0.2 0.3 0.4; - 0.1 0.5 0.3] - verts3 = [0.7 0.3 0.6; - 0.2 0.4 0.8; - 0.9 0.5 0.2; - 0.2 0.3 0.4; - 0.9 0.3 0.8] + T, R = (Float32, Int64) + verts1 = [ + 0.1 0.3 0.5 + 0.5 0.2 0.1 + 0.6 0.8 0.7 + ] + verts2 = [ + 0.1 0.3 0.3 + 0.6 0.7 0.8 + 0.2 0.3 0.4 + 0.1 0.5 0.3 + ] + verts3 = [ + 0.7 0.3 0.6 + 0.2 0.4 0.8 + 0.9 0.5 0.2 + 0.2 0.3 0.4 + 0.9 0.3 0.8 + ] verts_list = [T.(verts1'), T.(verts2'), T.(verts3')] faces1 = [1 2 3] - faces2 = [1 2 3; - 2 3 4] - faces3 = [2 3 1; - 1 2 4; - 3 4 2; - 5 4 3; - 5 1 2; - 5 4 2; - 5 3 2] + faces2 = [ + 1 2 3 + 2 3 4 + ] + faces3 = [ + 2 3 1 + 1 2 4 + 3 4 2 + 5 4 3 + 5 1 2 + 5 4 2 + 5 3 2 + ] faces_list = [R.(faces1'), R.(faces2'), R.(faces3')] m = TriMesh(verts_list, faces_list) @@ -71,36 +81,36 @@ end gm_list = get_verts_list(gm) gm_packed = get_verts_packed(gm) gm_padded = get_verts_padded(gm) - @test gm_list isa Vector{<:CuArray{Float32, 2}} - @test gm_packed isa CuArray{Float32, 2} - @test gm_padded isa CuArray{Float32, 3} + @test gm_list isa Vector{<:CuArray{Float32,2}} + @test gm_packed isa CuArray{Float32,2} + @test gm_padded isa CuArray{Float32,3} @test all(verts_list .== cpu(gm_list)) _padded = cpu(gm_padded) - @test cat(verts_list...; dims=2) == cpu(gm_packed) - for (i,v) in enumerate(verts_list) - @test _padded[:, 1:size(v,2),i] == v - @test all(_padded[:, size(v,2)+1:end,i] .== 0) + @test cat(verts_list...; dims = 2) == cpu(gm_packed) + for (i, v) in enumerate(verts_list) + @test _padded[:, 1:size(v, 2), i] == v + @test all(_padded[:, size(v, 2)+1:end, i] .== 0) end gm_list = get_faces_list(gm) gm_packed = get_faces_packed(gm) gm_padded = get_faces_padded(gm) - @test gm_list isa Vector{<:Array{<:Integer, 2}} - @test gm_packed isa Array{<:Integer, 2} - @test gm_padded isa Array{<:Integer, 3} + @test gm_list isa Vector{<:Array{<:Integer,2}} + @test gm_packed isa Array{<:Integer,2} + @test gm_padded isa Array{<:Integer,3} @test all(faces_list .== gm_list) _cur_idx = 1 _offset = 0 _packed = gm_packed - for (i,f) in enumerate(faces_list) - @test _packed[:, _cur_idx:_cur_idx+size(f,2)-1] == (f .+ _offset) - _cur_idx += size(f,2) - _offset += size(verts_list[i],2) + for (i, f) in enumerate(faces_list) + @test _packed[:, _cur_idx:_cur_idx+size(f, 2)-1] == (f .+ _offset) + _cur_idx += size(f, 2) + _offset += size(verts_list[i], 2) end _padded = gm_padded - for (i,v) in enumerate(faces_list) - @test _padded[:, 1:size(v,2),i] == v - @test all(_padded[:, size(v,2)+1:end,i] .== 0) + for (i, v) in enumerate(faces_list) + @test _padded[:, 1:size(v, 2), i] == v + @test all(_padded[:, size(v, 2)+1:end, i] .== 0) end _packed = get_faces_packed(m) @@ -109,105 +119,123 @@ end e31 = cat(_packed[3, :], _packed[1, :], dims = 2) edges = cat(e12, e23, e31, dims = 1) edges = sort(edges, dims = 2) - edges = sortslices(edges; dims=1) + edges = sortslices(edges; dims = 1) edges = unique(edges; dims = 1) @test edges == get_edges_packed(m) _dict = get_edges_to_key(m) - for i in 1:size(edges,1) - @test i == _dict[Tuple(edges[i,:])] + for i = 1:size(edges, 1) + @test i == _dict[Tuple(edges[i, :])] end _f_edges = get_faces_to_edges_packed(m) _packed = get_faces_packed(m) - for i in 1:size(_f_edges,1) - @test edges[_f_edges[i,1],:] == sort(_packed[[2,3], i]) - @test edges[_f_edges[i,2],:] == sort(_packed[[1,3], i]) - @test edges[_f_edges[i,3],:] == sort(_packed[[1,2], i]) + for i = 1:size(_f_edges, 1) + @test edges[_f_edges[i, 1], :] == sort(_packed[[2, 3], i]) + @test edges[_f_edges[i, 2], :] == sort(_packed[[1, 3], i]) + @test edges[_f_edges[i, 3], :] == sort(_packed[[1, 2], i]) end _edges = get_edges_packed(m) V = size(get_verts_packed(m), 2) - L = zeros(V,V) - deg = zeros(V,V) - for i in 1:size(_edges, 1) - L[_edges[i,1], _edges[i,2]] = 1 - L[_edges[i,2], _edges[i,1]] = 1 + L = zeros(V, V) + deg = zeros(V, V) + for i = 1:size(_edges, 1) + L[_edges[i, 1], _edges[i, 2]] = 1 + L[_edges[i, 2], _edges[i, 1]] = 1 end deg = sum(L; dims = 2) deg = map(x -> (x > 0 ? 1 / x : x), deg) - for i=1:V, j=1:V - if i==j - L[i,j] = -1 - elseif L[i,j]==1 - L[i,j] = deg[i] + for i = 1:V, j = 1:V + if i == j + L[i, j] = -1 + elseif L[i, j] == 1 + L[i, j] = deg[i] end end @test all(isapprox.(L, Array(get_laplacian_packed(m)), rtol = 1e-5, atol = 1e-5)) # verts_normals, faces_normals, faces_areas - verts1 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.6 0.8 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7; - 0.5 0.0 0.2; - 0.6 0.0 0.5; - 0.8 0.0 0.7; - 0.0 0.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0] - - verts2 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.6 0.8 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7] - - verts2 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7] - - - faces1 = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12] - - faces2 = [1 2 3; - 3 4 5] - - - _normal1 = [0.0 0.0 1.0; - 0.0 0.0 1.0; - 0.0 0.0 1.0; - -1.0 0.0 0.0; - -1.0 0.0 0.0; - -1.0 0.0 0.0; - 0.0 1.0 0.0; - 0.0 1.0 0.0; - 0.0 1.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0] - - _normal2 = [-0.2408 -0.9631 -0.1204; - -0.2408 -0.9631 -0.1204; - -0.9389 -0.3414 -0.0427; - -1.0000 0.0000 0.0000; - -1.0000 0.0000 0.0000] - - _fnormal1 = [-0.0 0.0 1.0; - -1.0 0.0 0.0; - 0.0 1.0 0.0; - 0.0 0.0 0.0] - - _fnormal2 = [-0.2408 -0.9631 -0.1204; - -1.0000 0.0000 0.0000;] + verts1 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.6 0.8 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + 0.5 0.0 0.2 + 0.6 0.0 0.5 + 0.8 0.0 0.7 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + ] + + verts2 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.6 0.8 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + ] + + verts2 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + ] + + + faces1 = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + ] + + faces2 = [ + 1 2 3 + 3 4 5 + ] + + + _normal1 = [ + 0.0 0.0 1.0 + 0.0 0.0 1.0 + 0.0 0.0 1.0 + -1.0 0.0 0.0 + -1.0 0.0 0.0 + -1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 1.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + ] + + _normal2 = [ + -0.2408 -0.9631 -0.1204 + -0.2408 -0.9631 -0.1204 + -0.9389 -0.3414 -0.0427 + -1.0000 0.0000 0.0000 + -1.0000 0.0000 0.0000 + ] + + _fnormal1 = [ + -0.0 0.0 1.0 + -1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 0.0 + ] + + _fnormal2 = [ + -0.2408 -0.9631 -0.1204 + -1.0000 0.0000 0.0000 + ] _farea1 = [0.125, 0.1, 0.02, 0.0] _farea2 = [0.0415, 0.1] @@ -232,12 +260,27 @@ end @test compute_verts_normals_packed(gm) isa CuArray{T,2} @test compute_verts_normals_padded(gm) isa CuArray{T,3} @test compute_verts_normals_list(gm) isa Array{<:CuArray{T,2},1} - @test all(isapprox.(cat(_normal1,_normal2; dims=2), normals_packed, rtol = 1e-4, atol = 1e-4)) + @test all(isapprox.( + cat(_normal1, _normal2; dims = 2), + normals_packed, + rtol = 1e-4, + atol = 1e-4, + )) @test all(isapprox.([_normal1, _normal2], normals_list, rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_normal1, normals_padded[:,1:size(_normal1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_normal2, normals_padded[:,1:size(_normal2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(normals_padded[:,size(_normal1,2)+1:end,1] .== 0) - @test all(normals_padded[:,size(_normal2,2)+1:end,2] .== 0) + @test all(isapprox.( + _normal1, + normals_padded[:, 1:size(_normal1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _normal2, + normals_padded[:, 1:size(_normal2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(normals_padded[:, size(_normal1, 2)+1:end, 1] .== 0) + @test all(normals_padded[:, size(_normal2, 2)+1:end, 2] .== 0) normals_packed = cpu(compute_faces_normals_packed(gm)) normals_padded = cpu(compute_faces_normals_padded(gm)) @@ -245,12 +288,27 @@ end @test compute_faces_normals_packed(gm) isa CuArray{T,2} @test compute_faces_normals_padded(gm) isa CuArray{T,3} @test compute_faces_normals_list(gm) isa Array{<:CuArray{T,2},1} - @test all(isapprox.(cat(_fnormal1,_fnormal2; dims=2), normals_packed, rtol = 1e-4, atol = 1e-4)) + @test all(isapprox.( + cat(_fnormal1, _fnormal2; dims = 2), + normals_packed, + rtol = 1e-4, + atol = 1e-4, + )) @test all(isapprox.([_fnormal1, _fnormal2], normals_list, rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_fnormal1, normals_padded[:,1:size(_fnormal1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_fnormal2, normals_padded[:,1:size(_fnormal2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(normals_padded[:,size(_fnormal1,2)+1:end,1] .== 0) - @test all(normals_padded[:,size(_fnormal2,2)+1:end,2] .== 0) + @test all(isapprox.( + _fnormal1, + normals_padded[:, 1:size(_fnormal1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _fnormal2, + normals_padded[:, 1:size(_fnormal2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(normals_padded[:, size(_fnormal1, 2)+1:end, 1] .== 0) + @test all(normals_padded[:, size(_fnormal2, 2)+1:end, 2] .== 0) areas_packed = cpu(compute_faces_areas_packed(gm)) areas_padded = cpu(compute_faces_areas_padded(gm)) @@ -258,97 +316,127 @@ end @test compute_faces_areas_packed(gm) isa CuArray{T,1} @test compute_faces_areas_padded(gm) isa CuArray{T,3} @test compute_faces_areas_list(gm) isa Array{<:CuArray{T,2},1} - @test all(isapprox.(reshape(cat(_farea1,_farea2; dims=2),:), areas_packed, rtol = 1e-4, atol = 1e-4)) + @test all(isapprox.( + reshape(cat(_farea1, _farea2; dims = 2), :), + areas_packed, + rtol = 1e-4, + atol = 1e-4, + )) @test all(isapprox.([_farea1, _farea2], areas_list, rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_farea1, areas_padded[:,1:size(_farea1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_farea2, areas_padded[:,1:size(_farea2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(areas_padded[:,size(_farea1,2)+1:end,1] .== 0) - @test all(areas_padded[:,size(_farea2,2)+1:end,2] .== 0) + @test all(isapprox.( + _farea1, + areas_padded[:, 1:size(_farea1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _farea2, + areas_padded[:, 1:size(_farea2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(areas_padded[:, size(_farea1, 2)+1:end, 1] .== 0) + @test all(areas_padded[:, size(_farea2, 2)+1:end, 2] .== 0) end end # testset TriMesh @info "Testing Rep Utils..." @testset "Rep Utils" begin for T in [Float32] - a1 = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12] - - a2 = [13 14 15; - 16 17 18] - - a3 = [19 20 21; - 22 23 24; - 25 26 27] + a1 = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + ] + + a2 = [ + 13 14 15 + 16 17 18 + ] + + a3 = [ + 19 20 21 + 22 23 24 + 25 26 27 + ] a1 = T.(a1') a2 = T.(a2') a3 = T.(a3') - _list = [a1,a2,a3] |> gpu - - _packed = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12; - 13 14 15; - 16 17 18; - 19 20 21; - 22 23 24; - 25 26 27] + _list = [a1, a2, a3] |> gpu + + _packed = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + 13 14 15 + 16 17 18 + 19 20 21 + 22 23 24 + 25 26 27 + ] _packed = T.(_packed') |> gpu _padded = zeros(3, 4, 3) - _padded[:, 1:size(a1,2),1] = a1 - _padded[:, 1:size(a2,2),2] = a2 - _padded[:,1:size(a3,2),3] = a3 + _padded[:, 1:size(a1, 2), 1] = a1 + _padded[:, 1:size(a2, 2), 2] = a2 + _padded[:, 1:size(a3, 2), 3] = a3 _padded = T.(_padded) |> gpu - items_len, packed_first_idx, packed_to_list_idx = - Flux3D._auxiliary_mesh(_list) + items_len, packed_first_idx, packed_to_list_idx = Flux3D._auxiliary_mesh(_list) - @test items_len == [4,2,3] - @test packed_first_idx == [1,5,7] + @test items_len == [4, 2, 3] + @test packed_first_idx == [1, 5, 7] @test all(packed_to_list_idx[1:4] .== 1) @test all(packed_to_list_idx[5:6] .== 2) @test all(packed_to_list_idx[7:9] .== 3) @test Flux3D._list_to_padded(_list, 0) == _padded @test Flux3D._list_to_padded(_list, 0) isa CuArray{T,3} - @test gradient(x-> 0.5 .* sum(Flux3D._list_to_padded(x, 0) .^ 2), _list)[1] == _list + @test gradient(x -> 0.5 .* sum(Flux3D._list_to_padded(x, 0) .^ 2), _list)[1] == + _list @test Flux3D._list_to_packed(_list) == _packed @test Flux3D._list_to_packed(_list) isa CuArray{T,2} - @test gradient(x->.5 .* sum(Flux3D._list_to_packed(x) .^ 2), _list)[1] == Tuple(_list) + @test gradient(x -> 0.5 .* sum(Flux3D._list_to_packed(x) .^ 2), _list)[1] == + Tuple(_list) @test Flux3D._packed_to_padded(_packed, items_len, 0) == _padded @test Flux3D._packed_to_padded(_packed, items_len, 0) isa CuArray{T,3} - @test gradient(x-> .5 .* sum(Flux3D._packed_to_padded(x, items_len, 0) .^ 2), _packed)[1] == _packed + @test gradient( + x -> 0.5 .* sum(Flux3D._packed_to_padded(x, items_len, 0) .^ 2), + _packed, + )[1] == _packed @test Flux3D._packed_to_list(_packed, items_len) == _list @test Flux3D._packed_to_list(_packed, items_len) isa Array{<:CuArray{T,2},1} gs = gradient(_packed) do x - loss = 0 - for x in Flux3D._packed_to_list(x, items_len) - loss += sum(x .^ 2) - end - return 0.5*loss + loss = 0 + for x in Flux3D._packed_to_list(x, items_len) + loss += sum(x .^ 2) end + return 0.5 * loss + end @test gs[1] == _packed @test Flux3D._padded_to_list(_padded, items_len) == _list @test Flux3D._padded_to_list(_padded, items_len) isa Array{<:CuArray{T,2},1} gs = gradient(_padded) do x - loss = 0 - for x in Flux3D._padded_to_list(x, items_len) - loss += sum(x .^ 2) - end - return 0.5*loss + loss = 0 + for x in Flux3D._padded_to_list(x, items_len) + loss += sum(x .^ 2) end + return 0.5 * loss + end @test gs[1] == _padded @test Flux3D._padded_to_packed(_padded, items_len) == _packed @test Flux3D._padded_to_packed(_padded, items_len) isa CuArray{T,2} - @test gradient(x->sum(.5 .* sum(Flux3D._padded_to_packed(x, items_len) .^2 )), _padded)[1] == _padded + @test gradient( + x -> sum(0.5 .* sum(Flux3D._padded_to_packed(x, items_len) .^ 2)), + _padded, + )[1] == _padded end end diff --git a/test/cuda/transforms.jl b/test/cuda/transforms.jl index 0c4bb68..a94512d 100644 --- a/test/cuda/transforms.jl +++ b/test/cuda/transforms.jl @@ -46,10 +46,10 @@ # Transformed PointCloud should be inside the bounding box defined by `tgt` PointCloud @test all( - reshape(maximum( - Array(tgt.points), dims = 2), (:, 1)) .>= - Array(src_1.points) .>= - reshape(minimum(Array(tgt.points), dims = 2), (:, 1))) + reshape(maximum(Array(tgt.points), dims = 2), (:, 1)) .>= + Array(src_1.points) .>= + reshape(minimum(Array(tgt.points), dims = 2), (:, 1)), + ) end end @@ -61,31 +61,47 @@ pc2 = t(pc1) |> gpu @test pc1.points isa CuArray @test pc2.points isa CuArray - @test all(isapprox.(mean(Array(pc2.points);dims = 2), 0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(Array(pc2.points);dims = 2), 1, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.( + mean(Array(pc2.points); dims = 2), + 0, + rtol = 1e-5, + atol = 1e-5, + )) + @test all(isapprox.( + std(Array(pc2.points); dims = 2), + 1, + rtol = 1e-5, + atol = 1e-5, + )) end end @testset "Chain" begin p = rand(Float32, 3, 8, 2) - t = Chain(ScalePointCloud(0.5), RotatePointCloud(rand(3,3)), NormalizePointCloud()) |> gpu + t = + Chain( + ScalePointCloud(0.5), + RotatePointCloud(rand(3, 3)), + NormalizePointCloud(), + ) |> gpu pc1 = PointCloud(p) |> gpu pc1 = t(pc1) @test pc1.points isa CuArray - @test all(isapprox.(mean(Array(pc1.points);dims = 2), 0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(Array(pc1.points);dims = 2), 1, rtol = 1e-5, atol = 1e-4)) + @test all(isapprox.(mean(Array(pc1.points); dims = 2), 0, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.(std(Array(pc1.points); dims = 2), 1, rtol = 1e-5, atol = 1e-4)) end - _mesh = load_trimesh([ - joinpath(@__DIR__, "../meshes/teapot.obj"), - joinpath(@__DIR__, "../meshes/sphere.obj"), - ]) |> gpu + _mesh = + load_trimesh([ + joinpath(@__DIR__, "../meshes/teapot.obj"), + joinpath(@__DIR__, "../meshes/sphere.obj"), + ]) |> gpu for inplace in [true, false] @testset "ScaleTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t1 = ScaleTriMesh(2.0; inplace=inplace) |> gpu - t2 = ScaleTriMesh(0.5; inplace=inplace) |> gpu + t1 = ScaleTriMesh(2.0; inplace = inplace) |> gpu + t2 = ScaleTriMesh(0.5; inplace = inplace) |> gpu m2 = t2(t1(m)) if inplace @@ -93,13 +109,13 @@ else @test m2 !== m end - @test get_verts_packed(m2) isa CuArray{Float32, 2} + @test get_verts_packed(m2) isa CuArray{Float32,2} @test all(isapprox.( cpu(get_verts_packed(_mesh)), cpu(get_verts_packed(m2)), rtol = 1e-5, atol = 1e-5, - )) + )) end end @@ -108,15 +124,15 @@ m = deepcopy(_mesh) rotmat = 2 .* one(rand(Float32, 3, 3)) rotmat_inv = inv(rotmat) - t1 = RotateTriMesh(rotmat; inplace=inplace) |> gpu - t2 = RotateTriMesh(rotmat_inv; inplace=inplace) |> gpu + t1 = RotateTriMesh(rotmat; inplace = inplace) |> gpu + t2 = RotateTriMesh(rotmat_inv; inplace = inplace) |> gpu m2 = t2(t1(m)) if inplace @test m2 === m else @test m2 !== m end - @test get_verts_packed(m2) isa CuArray{Float32, 2} + @test get_verts_packed(m2) isa CuArray{Float32,2} @test all(isapprox.( cpu(get_verts_packed(_mesh)), cpu(get_verts_packed(m2)), @@ -131,23 +147,23 @@ m = deepcopy(_mesh) src = Flux3D.scale(m, 2.0) tgt = Flux3D.scale(m, 1.0) - t = ReAlignTriMesh(tgt, 1; inplace=inplace) |> gpu + t = ReAlignTriMesh(tgt, 1; inplace = inplace) |> gpu src_1 = t(src) if inplace @test src === src_1 else @test src !== src_1 end - @test get_verts_packed(src_1) isa CuArray{Float32, 2} + @test get_verts_packed(src_1) isa CuArray{Float32,2} @test all( maximum(get_verts_list(_mesh)[1]; dims = 2) .>= get_verts_list(src_1)[1] .>= - minimum(get_verts_list(_mesh)[1]; dims = 2) + minimum(get_verts_list(_mesh)[1]; dims = 2), ) @test all( maximum(get_verts_list(_mesh)[1]; dims = 2) .>= get_verts_list(src_1)[2] .>= - minimum(get_verts_list(_mesh)[1]; dims = 2) + minimum(get_verts_list(_mesh)[1]; dims = 2), ) end end @@ -155,33 +171,53 @@ for inplace in [true, false] @testset "NormalizeTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t = NormalizeTriMesh(; inplace=inplace) |> gpu + t = NormalizeTriMesh(; inplace = inplace) |> gpu m2 = t(m) if inplace @test m2 === m else @test m2 !== m end - @test get_verts_packed(m2) isa CuArray{Float32, 2} - @test all(isapprox.(mean(cpu(get_verts_list(m2))[1]; dims = 2), 0.0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(cpu(get_verts_list(m2))[1]; dims = 2), 1.0, rtol = 1e-4, atol = 1e-5)) - @test all(isapprox.(mean(cpu(get_verts_list(m2))[2]; dims = 2), 0.0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(cpu(get_verts_list(m2))[2]; dims = 2), 1.0, rtol = 1e-4, atol = 1e-5)) + @test get_verts_packed(m2) isa CuArray{Float32,2} + @test all(isapprox.( + mean(cpu(get_verts_list(m2))[1]; dims = 2), + 0.0, + rtol = 1e-5, + atol = 1e-5, + )) + @test all(isapprox.( + std(cpu(get_verts_list(m2))[1]; dims = 2), + 1.0, + rtol = 1e-4, + atol = 1e-5, + )) + @test all(isapprox.( + mean(cpu(get_verts_list(m2))[2]; dims = 2), + 0.0, + rtol = 1e-5, + atol = 1e-5, + )) + @test all(isapprox.( + std(cpu(get_verts_list(m2))[2]; dims = 2), + 1.0, + rtol = 1e-4, + atol = 1e-5, + )) end end for inplace in [true, false] @testset "TranslateTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t1 = TranslateTriMesh(1.0; inplace=inplace) |> gpu - t2 = TranslateTriMesh(-1.0; inplace=inplace) |> gpu + t1 = TranslateTriMesh(1.0; inplace = inplace) |> gpu + t2 = TranslateTriMesh(-1.0; inplace = inplace) |> gpu m2 = t2(t1(m)) if inplace @test m2 === m else @test m2 !== m end - @test get_verts_packed(m2) isa CuArray{Float32, 2} + @test get_verts_packed(m2) isa CuArray{Float32,2} @test all(isapprox.( cpu(get_verts_packed(_mesh)), cpu(get_verts_packed(m2)), @@ -195,8 +231,8 @@ @testset "OffsetTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) _offset = ones(size(get_verts_packed(m))) - t1 = OffsetTriMesh(_offset; inplace=inplace) |> gpu - t2 = OffsetTriMesh(_offset .* -1; inplace=inplace) |> gpu + t1 = OffsetTriMesh(_offset; inplace = inplace) |> gpu + t2 = OffsetTriMesh(_offset .* -1; inplace = inplace) |> gpu m2 = t2(t1(m)) if inplace @@ -204,7 +240,7 @@ else @test m2 !== m end - @test get_verts_packed(m2) isa CuArray{Float32, 2} + @test get_verts_packed(m2) isa CuArray{Float32,2} @test all(isapprox.( cpu(get_verts_packed(_mesh)), cpu(get_verts_packed(m2)), diff --git a/test/dataset.jl b/test/dataset.jl index 3bcaaf8..526b970 100644 --- a/test/dataset.jl +++ b/test/dataset.jl @@ -1,36 +1,33 @@ @info "Testing CustomDataset..." @testset "CustomDataset" begin - x = rand(100,8) - getdata(idx) = x[idx,:] - dset = CustomDataset(size(x,1), getdata) + x = rand(100, 8) + getdata(idx) = x[idx, :] + dset = CustomDataset(size(x, 1), getdata) - @test size(dset) == (size(x,1),) - @test length(dset) == size(x,1) + @test size(dset) == (size(x, 1),) + @test length(dset) == size(x, 1) @test firstindex(dset) == 1 - @test lastindex(dset) == size(x,1) - @test lastindex(dset) == size(x,1) - @test dset[1] == x[1,:] - @test dset[3:8] == [x[i,:] for i in 3:8] - @test dset[:] == [x[i,:] for i in 1:size(x,1)] + @test lastindex(dset) == size(x, 1) + @test lastindex(dset) == size(x, 1) + @test dset[1] == x[1, :] + @test dset[3:8] == [x[i, :] for i = 3:8] + @test dset[:] == [x[i, :] for i = 1:size(x, 1)] end @info "Testing ModelNet..." @testset "ModelNet10 PointCloud dataset" begin - for (split, train) in [ - ("train", true), - ("test", false) - ] - - npoints=32 - dset = ModelNet10.dataset(;mode=:pointcloud, train=train, npoints=npoints) + for (split, train) in [("train", true), ("test", false)] + npoints = 32 + dset = ModelNet10.dataset(; mode = :pointcloud, train = train, npoints = npoints) print(@__DIR__) @test dset isa Flux3D.Dataset.AbstractDataset @test dset.root == normpath(@__DIR__, "../datasets/modelnet") - @test dset.path == normpath(@__DIR__, "../datasets/modelnet/modelnet40_normal_resampled") + @test dset.path == + normpath(@__DIR__, "../datasets/modelnet/modelnet40_normal_resampled") @test dset.train == train @test dset.npoints == npoints @test dset.sampling isa Nothing #TODO: add appropriate test - @test dset.transform isa Nothing + @test dset.transform isa Nothing @test dset.datapaths isa AbstractArray if train @@ -42,36 +39,43 @@ end @test size(dset) == (908,) @test length(dset) == 908 end - + dpoint1 = dset[1] @test dpoint1 isa Flux3D.Dataset.AbstractDataPoint @test dpoint1 isa ModelNet10.MN10DataPoint @test dpoint1.data isa PointCloud t = Compose(ScalePointCloud(2)) - dset = ModelNet10.dataset(;mode=:pointcloud, train=train, npoints=npoints, transform = t) + dset = ModelNet10.dataset(; + mode = :pointcloud, + train = train, + npoints = npoints, + transform = t, + ) @test dset.transform isa Compose dpoint2 = dset[1] @test dpoint2 isa Flux3D.Dataset.AbstractDataPoint @test dpoint2 isa ModelNet10.MN10DataPoint @test dpoint2.data isa PointCloud - @test all(isapprox.(2 .* dpoint1.data.points, dpoint2.data.points, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.( + 2 .* dpoint1.data.points, + dpoint2.data.points, + rtol = 1e-5, + atol = 1e-5, + )) end end @testset "ModelNet40 PointCloud dataset" begin - for (split, train) in [ - ("train", true), - ("test", false) - ] - - npoints=32 - dset = ModelNet40.dataset(;mode=:pointcloud, train=train, npoints=npoints) + for (split, train) in [("train", true), ("test", false)] + npoints = 32 + dset = ModelNet40.dataset(; mode = :pointcloud, train = train, npoints = npoints) @test dset isa Flux3D.Dataset.AbstractDataset @test dset.root == normpath(@__DIR__, "../datasets/modelnet") - @test dset.path == normpath(@__DIR__, "../datasets/modelnet/modelnet40_normal_resampled") + @test dset.path == + normpath(@__DIR__, "../datasets/modelnet/modelnet40_normal_resampled") @test dset.train == train @test dset.npoints == npoints @test dset.sampling isa Nothing #TODO: add appropriate test @@ -94,13 +98,23 @@ end @test dpoint1.data isa PointCloud t = Compose(ScalePointCloud(2)) - dset = ModelNet40.dataset(;mode=:pointcloud, train=train, npoints=npoints, transform = t) + dset = ModelNet40.dataset(; + mode = :pointcloud, + train = train, + npoints = npoints, + transform = t, + ) @test dset.transform isa Compose dpoint2 = dset[1] @test dpoint2 isa Flux3D.Dataset.AbstractDataPoint @test dpoint2 isa ModelNet40.MN40DataPoint @test dpoint2.data isa PointCloud - @test all(isapprox.(2 .* dpoint1.data.points, dpoint2.data.points, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.( + 2 .* dpoint1.data.points, + dpoint2.data.points, + rtol = 1e-5, + atol = 1e-5, + )) end -end \ No newline at end of file +end diff --git a/test/metrics.jl b/test/metrics.jl index 5950aad..c9fed2b 100644 --- a/test/metrics.jl +++ b/test/metrics.jl @@ -7,51 +7,61 @@ @testset "Laplacian loss" begin - verts1 = [0.1 0.3 0.5; - 0.5 0.2 0.1; - 0.6 0.8 0.7] - verts2 = [0.1 0.3 0.3; - 0.6 0.7 0.8; - 0.2 0.3 0.4; - 0.1 0.5 0.3] - verts3 = [0.7 0.3 0.6; - 0.2 0.4 0.8; - 0.9 0.5 0.2; - 0.2 0.3 0.4; - 0.9 0.3 0.8] + verts1 = [ + 0.1 0.3 0.5 + 0.5 0.2 0.1 + 0.6 0.8 0.7 + ] + verts2 = [ + 0.1 0.3 0.3 + 0.6 0.7 0.8 + 0.2 0.3 0.4 + 0.1 0.5 0.3 + ] + verts3 = [ + 0.7 0.3 0.6 + 0.2 0.4 0.8 + 0.9 0.5 0.2 + 0.2 0.3 0.4 + 0.9 0.3 0.8 + ] faces1 = [1 2 3] - faces2 = [1 2 3; - 2 3 4] - faces3 = [2 3 1; - 1 2 4; - 3 4 2; - 5 4 3; - 5 1 2; - 5 4 2; - 5 3 2] + faces2 = [ + 1 2 3 + 2 3 4 + ] + faces3 = [ + 2 3 1 + 1 2 4 + 3 4 2 + 5 4 3 + 5 1 2 + 5 4 2 + 5 3 2 + ] - T,R = Float32, UInt32 + T, R = Float32, UInt32 verts_list = [T.(verts1'), T.(verts2'), T.(verts3')] faces_list = [R.(faces1'), R.(faces2'), R.(faces3')] m = TriMesh(verts_list, faces_list) _edges = get_edges_packed(m) V = size(get_verts_packed(m), 2) - L = zeros(V,V) - deg = zeros(V,V) - for i in 1:size(_edges, 1) - L[_edges[i,1], _edges[i,2]] = 1 - L[_edges[i,2], _edges[i,1]] = 1 + L = zeros(V, V) + deg = zeros(V, V) + for i = 1:size(_edges, 1) + L[_edges[i, 1], _edges[i, 2]] = 1 + L[_edges[i, 2], _edges[i, 1]] = 1 end deg = sum(L; dims = 2) deg = map(x -> (x > 0 ? 1 / x : x), deg) - for i=1:V, j=1:V - if i==j - L[i,j] = -1 - elseif L[i,j]==1 - L[i,j] = deg[i] + for i = 1:V, j = 1:V + if i == j + L[i, j] = -1 + elseif L[i, j] == 1 + L[i, j] = deg[i] end end @@ -59,38 +69,38 @@ L = L * transpose(verts) L = Flux3D._norm(L; dims = 2) @test isapprox(mean(L), laplacian_loss(m)) - @test gradient(x->laplacian_loss(x), m) isa Tuple + @test gradient(x -> laplacian_loss(x), m) isa Tuple end @testset "Edge Loss" begin m = deepcopy(_mesh) verts = get_verts_packed(m) edges = get_edges_packed(m) - v1 = verts[:, edges[:,1]] - v2 = verts[:, edges[:,2]] - loss = mean((Flux3D._norm(v1-v2; dims=1)) .^ 2) + v1 = verts[:, edges[:, 1]] + v2 = verts[:, edges[:, 2]] + loss = mean((Flux3D._norm(v1 - v2; dims = 1)) .^ 2) @test edge_loss(m) == loss - @test gradient(x->edge_loss(x), m) isa Tuple + @test gradient(x -> edge_loss(x), m) isa Tuple end @testset "Chamfer Loss" begin m = deepcopy(_mesh) - loss = chamfer_distance(m,m) + loss = chamfer_distance(m, m) @test all(isapprox.(loss, 0, rtol = 1e-5, atol = 1e-2)) - @test gradient(x->chamfer_distance(x, x), m) isa Tuple + @test gradient(x -> chamfer_distance(x, x), m) isa Tuple # naive chamfer distance - x = rand(3,1000) - y = rand(3,500) - xx = sum(x .^ 2, dims=1) - yy = sum(y .^ 2, dims=1) + x = rand(3, 1000) + y = rand(3, 500) + xx = sum(x .^ 2, dims = 1) + yy = sum(y .^ 2, dims = 1) zz = x' * y rx = reshape(xx, size(xx, 2), 1) ry = reshape(yy, 1, size(yy, 2)) P = (rx .+ ry) .- (2 .* zz) - distA = minimum(P; dims=2) - distB = minimum(P; dims=1) + distA = minimum(P; dims = 2) + distB = minimum(P; dims = 1) loss = mean(distA) + mean(distB) - @test isapprox(chamfer_distance(x,y), loss) + @test isapprox(chamfer_distance(x, y), loss) end end diff --git a/test/models.jl b/test/models.jl index fd0372d..21ae983 100644 --- a/test/models.jl +++ b/test/models.jl @@ -1,6 +1,6 @@ @testset "PointCloud Model tests" begin x_test = rand(Float32, 3, 64, 2) - _dims = size(x_test,2) + _dims = size(x_test, 2) @testset "PointNet Model tests" begin MODEL = PointNet @@ -13,7 +13,7 @@ # Testing Forward Propagation @test y_test isa AbstractArray - @test size(y_test) == (num_classes,size(x_test,3)) + @test size(y_test) == (num_classes, size(x_test, 3)) # Testing Backward Propagation # @test gradtest(x_test -> model(x_test), x_test) @@ -26,13 +26,13 @@ @info "Testing $(MODEL)..." for num_classes in [10, 40] @testset "DGCNN num_classes: $(num_classes)" begin - model = MODEL(num_classes,10,_dims) + model = MODEL(num_classes, 10, _dims) y_test = model(x_test) # Testing Forward Propagation @test y_test isa AbstractArray - @test size(y_test) == (num_classes,size(x_test,3)) + @test size(y_test) == (num_classes, size(x_test, 3)) # Testing Backward Propagation # @test gradtest(x_test -> model(x_test), x_test) diff --git a/test/rep.jl b/test/rep.jl index d1ba419..49569b7 100644 --- a/test/rep.jl +++ b/test/rep.jl @@ -1,8 +1,8 @@ @info "Testing PointCloud..." @testset "PointCloud" begin - for T = [Float32,Float64], _N = [true, false] - points = rand(T,3,16,4) - _normals = rand(T,3,16,4) + for T in [Float32, Float64], _N in [true, false] + points = rand(T, 3, 16, 4) + _normals = rand(T, 3, 16, 4) if _N normals = _normals else @@ -15,16 +15,16 @@ @test size(rep.normals) == size(_normals) @test rep.normals isa Array{Float32,3} end - @test npoints(rep) == size(points,2) + @test npoints(rep) == size(points, 2) @test size(rep.points) == size(points) @test rep.points isa Array{Float32,3} - for i in 1:size(points,3) - @test all(isapprox.(rep[i], points[:,:,i])) + for i = 1:size(points, 3) + @test all(isapprox.(rep[i], points[:, :, i])) end # using other contructor - rep1 = PointCloud(points=points, normals=normals) + rep1 = PointCloud(points = points, normals = normals) rep2 = PointCloud(rep) @test rep.points == rep1.points @test rep.points == rep2.points @@ -36,32 +36,42 @@ end @info "Testing TriMesh..." @testset "TriMesh" begin - T,R = (Float32, Int64) - verts1 = [0.1 0.3 0.5; - 0.5 0.2 0.1; - 0.6 0.8 0.7] - verts2 = [0.1 0.3 0.3; - 0.6 0.7 0.8; - 0.2 0.3 0.4; - 0.1 0.5 0.3] - verts3 = [0.7 0.3 0.6; - 0.2 0.4 0.8; - 0.9 0.5 0.2; - 0.2 0.3 0.4; - 0.9 0.3 0.8] + T, R = (Float32, Int64) + verts1 = [ + 0.1 0.3 0.5 + 0.5 0.2 0.1 + 0.6 0.8 0.7 + ] + verts2 = [ + 0.1 0.3 0.3 + 0.6 0.7 0.8 + 0.2 0.3 0.4 + 0.1 0.5 0.3 + ] + verts3 = [ + 0.7 0.3 0.6 + 0.2 0.4 0.8 + 0.9 0.5 0.2 + 0.2 0.3 0.4 + 0.9 0.3 0.8 + ] verts_list = [T.(verts1'), T.(verts2'), T.(verts3')] faces1 = [1 2 3] - faces2 = [1 2 3; - 2 3 4] - faces3 = [2 3 1; - 1 2 4; - 3 4 2; - 5 4 3; - 5 1 2; - 5 4 2; - 5 3 2] + faces2 = [ + 1 2 3 + 2 3 4 + ] + faces3 = [ + 2 3 1 + 1 2 4 + 3 4 2 + 5 4 3 + 5 1 2 + 5 4 2 + 5 3 2 + ] faces_list = [R.(faces1'), R.(faces2'), R.(faces3')] m = TriMesh(verts_list, faces_list) @@ -79,26 +89,26 @@ end end @test all(verts_list .== get_verts_list(m)) - @test cat(verts_list...; dims=2) == get_verts_packed(m) + @test cat(verts_list...; dims = 2) == get_verts_packed(m) _padded = get_verts_padded(m) - for (i,v) in enumerate(verts_list) - @test _padded[:, 1:size(v,2),i] == v - @test all(_padded[:, size(v,2)+1:end,i] .== 0) + for (i, v) in enumerate(verts_list) + @test _padded[:, 1:size(v, 2), i] == v + @test all(_padded[:, size(v, 2)+1:end, i] .== 0) end @test all(faces_list .== get_faces_list(m)) _packed = get_faces_packed(m) _cur_idx = 1 _offset = 0 - for (i,f) in enumerate(faces_list) - @test _packed[:, _cur_idx:_cur_idx+size(f,2)-1] == (f .+ _offset) - _cur_idx += size(f,2) - _offset += size(verts_list[i],2) + for (i, f) in enumerate(faces_list) + @test _packed[:, _cur_idx:_cur_idx+size(f, 2)-1] == (f .+ _offset) + _cur_idx += size(f, 2) + _offset += size(verts_list[i], 2) end _padded = get_faces_padded(m) - for (i,v) in enumerate(faces_list) - @test _padded[:, 1:size(v,2),i] == v - @test all(_padded[:, size(v,2)+1:end,i] .== 0) + for (i, v) in enumerate(faces_list) + @test _padded[:, 1:size(v, 2), i] == v + @test all(_padded[:, size(v, 2)+1:end, i] .== 0) end _packed = get_faces_packed(m) @@ -107,105 +117,123 @@ end e31 = cat(_packed[3, :], _packed[1, :], dims = 2) edges = cat(e12, e23, e31, dims = 1) edges = sort(edges, dims = 2) - edges = sortslices(edges; dims=1) + edges = sortslices(edges; dims = 1) edges = unique(edges; dims = 1) @test edges == get_edges_packed(m) _dict = get_edges_to_key(m) - for i in 1:size(edges,1) - @test i == _dict[Tuple(edges[i,:])] + for i = 1:size(edges, 1) + @test i == _dict[Tuple(edges[i, :])] end _f_edges = get_faces_to_edges_packed(m) _packed = get_faces_packed(m) - for i in 1:size(_f_edges,1) - @test edges[_f_edges[i,1],:] == sort(_packed[[2,3], i]) - @test edges[_f_edges[i,2],:] == sort(_packed[[1,3], i]) - @test edges[_f_edges[i,3],:] == sort(_packed[[1,2], i]) + for i = 1:size(_f_edges, 1) + @test edges[_f_edges[i, 1], :] == sort(_packed[[2, 3], i]) + @test edges[_f_edges[i, 2], :] == sort(_packed[[1, 3], i]) + @test edges[_f_edges[i, 3], :] == sort(_packed[[1, 2], i]) end _edges = get_edges_packed(m) V = size(get_verts_packed(m), 2) - L = zeros(V,V) - deg = zeros(V,V) - for i in 1:size(_edges, 1) - L[_edges[i,1], _edges[i,2]] = 1 - L[_edges[i,2], _edges[i,1]] = 1 + L = zeros(V, V) + deg = zeros(V, V) + for i = 1:size(_edges, 1) + L[_edges[i, 1], _edges[i, 2]] = 1 + L[_edges[i, 2], _edges[i, 1]] = 1 end deg = sum(L; dims = 2) deg = map(x -> (x > 0 ? 1 / x : x), deg) - for i=1:V, j=1:V - if i==j - L[i,j] = -1 - elseif L[i,j]==1 - L[i,j] = deg[i] + for i = 1:V, j = 1:V + if i == j + L[i, j] = -1 + elseif L[i, j] == 1 + L[i, j] = deg[i] end end @test all(isapprox.(L, Array(get_laplacian_packed(m)), rtol = 1e-5, atol = 1e-5)) # verts_normals, faces_normals, faces_areas - verts1 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.6 0.8 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7; - 0.5 0.0 0.2; - 0.6 0.0 0.5; - 0.8 0.0 0.7; - 0.0 0.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0] - - verts2 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.6 0.8 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7] - - verts2 = [0.1 0.3 0.0; - 0.5 0.2 0.0; - 0.0 0.3 0.2; - 0.0 0.2 0.5; - 0.0 0.8 0.7] - - - faces1 = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12] - - faces2 = [1 2 3; - 3 4 5] - - - _normal1 = [0.0 0.0 1.0; - 0.0 0.0 1.0; - 0.0 0.0 1.0; - -1.0 0.0 0.0; - -1.0 0.0 0.0; - -1.0 0.0 0.0; - 0.0 1.0 0.0; - 0.0 1.0 0.0; - 0.0 1.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0; - 0.0 0.0 0.0] - - _normal2 = [-0.2408 -0.9631 -0.1204; - -0.2408 -0.9631 -0.1204; - -0.9389 -0.3414 -0.0427; - -1.0000 0.0000 0.0000; - -1.0000 0.0000 0.0000] - - _fnormal1 = [-0.0 0.0 1.0; - -1.0 0.0 0.0; - 0.0 1.0 0.0; - 0.0 0.0 0.0] - - _fnormal2 = [-0.2408 -0.9631 -0.1204; - -1.0000 0.0000 0.0000;] + verts1 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.6 0.8 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + 0.5 0.0 0.2 + 0.6 0.0 0.5 + 0.8 0.0 0.7 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + ] + + verts2 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.6 0.8 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + ] + + verts2 = [ + 0.1 0.3 0.0 + 0.5 0.2 0.0 + 0.0 0.3 0.2 + 0.0 0.2 0.5 + 0.0 0.8 0.7 + ] + + + faces1 = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + ] + + faces2 = [ + 1 2 3 + 3 4 5 + ] + + + _normal1 = [ + 0.0 0.0 1.0 + 0.0 0.0 1.0 + 0.0 0.0 1.0 + -1.0 0.0 0.0 + -1.0 0.0 0.0 + -1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 1.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + 0.0 0.0 0.0 + ] + + _normal2 = [ + -0.2408 -0.9631 -0.1204 + -0.2408 -0.9631 -0.1204 + -0.9389 -0.3414 -0.0427 + -1.0000 0.0000 0.0000 + -1.0000 0.0000 0.0000 + ] + + _fnormal1 = [ + -0.0 0.0 1.0 + -1.0 0.0 0.0 + 0.0 1.0 0.0 + 0.0 0.0 0.0 + ] + + _fnormal2 = [ + -0.2408 -0.9631 -0.1204 + -1.0000 0.0000 0.0000 + ] _farea1 = [0.125, 0.1, 0.02, 0.0] _farea2 = [0.0415, 0.1] @@ -226,117 +254,192 @@ end @test compute_verts_normals_packed(m) isa Array{T,2} @test compute_verts_normals_padded(m) isa Array{T,3} @test compute_verts_normals_list(m) isa Array{Array{T,2},1} - @test all(isapprox.(cat(_normal1,_normal2; dims=2), compute_verts_normals_packed(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.([_normal1, _normal2], compute_verts_normals_list(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_normal1, compute_verts_normals_padded(m)[:,1:size(_normal1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_normal2, compute_verts_normals_padded(m)[:,1:size(_normal2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(compute_verts_normals_padded(m)[:,size(_normal1,2)+1:end,1] .== 0) - @test all(compute_verts_normals_padded(m)[:,size(_normal2,2)+1:end,2] .== 0) + @test all(isapprox.( + cat(_normal1, _normal2; dims = 2), + compute_verts_normals_packed(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + [_normal1, _normal2], + compute_verts_normals_list(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _normal1, + compute_verts_normals_padded(m)[:, 1:size(_normal1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _normal2, + compute_verts_normals_padded(m)[:, 1:size(_normal2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(compute_verts_normals_padded(m)[:, size(_normal1, 2)+1:end, 1] .== 0) + @test all(compute_verts_normals_padded(m)[:, size(_normal2, 2)+1:end, 2] .== 0) @test compute_faces_normals_packed(m) isa Array{T,2} @test compute_faces_normals_padded(m) isa Array{T,3} @test compute_faces_normals_list(m) isa Array{Array{T,2},1} - @test all(isapprox.(cat(_fnormal1,_fnormal2; dims=2), compute_faces_normals_packed(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.([_fnormal1, _fnormal2], compute_faces_normals_list(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_fnormal1, compute_faces_normals_padded(m)[:,1:size(_fnormal1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_fnormal2, compute_faces_normals_padded(m)[:,1:size(_fnormal2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(compute_faces_normals_padded(m)[:,size(_fnormal1,2)+1:end,1] .== 0) - @test all(compute_faces_normals_padded(m)[:,size(_fnormal2,2)+1:end,2] .== 0) + @test all(isapprox.( + cat(_fnormal1, _fnormal2; dims = 2), + compute_faces_normals_packed(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + [_fnormal1, _fnormal2], + compute_faces_normals_list(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _fnormal1, + compute_faces_normals_padded(m)[:, 1:size(_fnormal1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _fnormal2, + compute_faces_normals_padded(m)[:, 1:size(_fnormal2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(compute_faces_normals_padded(m)[:, size(_fnormal1, 2)+1:end, 1] .== 0) + @test all(compute_faces_normals_padded(m)[:, size(_fnormal2, 2)+1:end, 2] .== 0) @test compute_faces_areas_packed(m) isa Array{T,1} @test compute_faces_areas_padded(m) isa Array{T,3} @test compute_faces_areas_list(m) isa Array{Array{T,2},1} - @test all(isapprox.(reshape(cat(_farea1,_farea2; dims=2),:), compute_faces_areas_packed(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.([_farea1, _farea2], compute_faces_areas_list(m), rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_farea1, compute_faces_areas_padded(m)[:,1:size(_farea1,2),1], rtol = 1e-4, atol = 1e-4)) - @test all(isapprox.(_farea2, compute_faces_areas_padded(m)[:,1:size(_farea2,2),2], rtol = 1e-4, atol = 1e-4)) - @test all(compute_faces_areas_padded(m)[:,size(_farea1,2)+1:end,1] .== 0) - @test all(compute_faces_areas_padded(m)[:,size(_farea2,2)+1:end,2] .== 0) + @test all(isapprox.( + reshape(cat(_farea1, _farea2; dims = 2), :), + compute_faces_areas_packed(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + [_farea1, _farea2], + compute_faces_areas_list(m), + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _farea1, + compute_faces_areas_padded(m)[:, 1:size(_farea1, 2), 1], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(isapprox.( + _farea2, + compute_faces_areas_padded(m)[:, 1:size(_farea2, 2), 2], + rtol = 1e-4, + atol = 1e-4, + )) + @test all(compute_faces_areas_padded(m)[:, size(_farea1, 2)+1:end, 1] .== 0) + @test all(compute_faces_areas_padded(m)[:, size(_farea2, 2)+1:end, 2] .== 0) end end @info "Testing Rep Utils..." @testset "Rep Utils" begin for T in [Float64, Float32, Int64, UInt32] - a1 = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12] - - a2 = [13 14 15; - 16 17 18] - - a3 = [19 20 21; - 22 23 24; - 25 26 27] + a1 = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + ] + + a2 = [ + 13 14 15 + 16 17 18 + ] + + a3 = [ + 19 20 21 + 22 23 24 + 25 26 27 + ] a1 = T.(a1') a2 = T.(a2') a3 = T.(a3') - _list = [a1,a2,a3] - - _packed = [1 2 3; - 4 5 6; - 7 8 9; - 10 11 12; - 13 14 15; - 16 17 18; - 19 20 21; - 22 23 24; - 25 26 27] + _list = [a1, a2, a3] + + _packed = [ + 1 2 3 + 4 5 6 + 7 8 9 + 10 11 12 + 13 14 15 + 16 17 18 + 19 20 21 + 22 23 24 + 25 26 27 + ] _packed = T.(_packed') _padded = zeros(3, 4, 3) - _padded[:, 1:size(a1,2),1] = a1 - _padded[:, 1:size(a2,2),2] = a2 - _padded[:,1:size(a3,2),3] = a3 + _padded[:, 1:size(a1, 2), 1] = a1 + _padded[:, 1:size(a2, 2), 2] = a2 + _padded[:, 1:size(a3, 2), 3] = a3 _padded = T.(_padded) - items_len, packed_first_idx, packed_to_list_idx = - Flux3D._auxiliary_mesh(_list) + items_len, packed_first_idx, packed_to_list_idx = Flux3D._auxiliary_mesh(_list) - @test items_len == [4,2,3] - @test packed_first_idx == [1,5,7] + @test items_len == [4, 2, 3] + @test packed_first_idx == [1, 5, 7] @test all(packed_to_list_idx[1:4] .== 1) @test all(packed_to_list_idx[5:6] .== 2) @test all(packed_to_list_idx[7:9] .== 3) @test Flux3D._list_to_padded(_list, 0) == _padded @test Flux3D._list_to_padded(_list, 0) isa Array{T,3} - @test gradient(x-> 0.5 .* sum(Flux3D._list_to_padded(x, 0) .^ 2), _list)[1] == _list + @test gradient(x -> 0.5 .* sum(Flux3D._list_to_padded(x, 0) .^ 2), _list)[1] == + _list @test Flux3D._list_to_packed(_list) == _packed @test Flux3D._list_to_packed(_list) isa Array{T,2} - @test gradient(x->.5 .* sum(Flux3D._list_to_packed(x) .^ 2), _list)[1] == Tuple(_list) + @test gradient(x -> 0.5 .* sum(Flux3D._list_to_packed(x) .^ 2), _list)[1] == + Tuple(_list) @test Flux3D._packed_to_padded(_packed, items_len, 0) == _padded @test Flux3D._packed_to_padded(_packed, items_len, 0) isa Array{T,3} - @test gradient(x-> .5 .* sum(Flux3D._packed_to_padded(x, items_len, 0) .^ 2), _packed)[1] == _packed + @test gradient( + x -> 0.5 .* sum(Flux3D._packed_to_padded(x, items_len, 0) .^ 2), + _packed, + )[1] == _packed @test Flux3D._packed_to_list(_packed, items_len) == _list @test Flux3D._packed_to_list(_packed, items_len) isa Array{Array{T,2},1} gs = gradient(_packed) do x - loss = 0 - for x in Flux3D._packed_to_list(x, items_len) - loss += sum(x .^ 2) - end - return 0.5*loss + loss = 0 + for x in Flux3D._packed_to_list(x, items_len) + loss += sum(x .^ 2) end + return 0.5 * loss + end @test gs[1] == _packed @test Flux3D._padded_to_list(_padded, items_len) == _list @test Flux3D._padded_to_list(_padded, items_len) isa Array{Array{T,2},1} gs = gradient(_padded) do x - loss = 0 - for x in Flux3D._padded_to_list(x, items_len) - loss += sum(x .^ 2) - end - return 0.5*loss + loss = 0 + for x in Flux3D._padded_to_list(x, items_len) + loss += sum(x .^ 2) end + return 0.5 * loss + end @test gs[1] == _padded @test Flux3D._padded_to_packed(_padded, items_len) == _packed @test Flux3D._padded_to_packed(_padded, items_len) isa Array{T,2} - @test gradient(x->sum(.5 .* sum(Flux3D._padded_to_packed(x, items_len) .^2 )), _padded)[1] == _padded + @test gradient( + x -> sum(0.5 .* sum(Flux3D._padded_to_packed(x, items_len) .^ 2)), + _padded, + )[1] == _padded end end diff --git a/test/transforms/mesh_func.jl b/test/transforms/mesh_func.jl index 9654a7a..52331f9 100644 --- a/test/transforms/mesh_func.jl +++ b/test/transforms/mesh_func.jl @@ -8,14 +8,9 @@ ]) samples = sample_points(m, 1000) - _radius = sqrt.(sum(samples.^2; dims=1)) - @test all(isapprox.( - _radius, - 1.0, - rtol = 1e-2, - atol = 1e-5, - )) - @test gradient(x->sum(sample_points(x, 1000)), m) isa Tuple + _radius = sqrt.(sum(samples .^ 2; dims = 1)) + @test all(isapprox.(_radius, 1.0, rtol = 1e-2, atol = 1e-5)) + @test gradient(x -> sum(sample_points(x, 1000)), m) isa Tuple end _mesh = load_trimesh([ @@ -112,13 +107,13 @@ @test all( maximum(get_verts_list(_mesh)[1]; dims = 2) .>= get_verts_list(src_1)[1] .>= - minimum(get_verts_list(_mesh)[1]; dims = 2) + minimum(get_verts_list(_mesh)[1]; dims = 2), ) src_1 = FUNC(src, tgt, 2) @test all( maximum(get_verts_list(_mesh)[2]; dims = 2) .>= get_verts_list(src_1)[1] .>= - minimum(get_verts_list(_mesh)[2]; dims = 2) + minimum(get_verts_list(_mesh)[2]; dims = 2), ) end end @@ -145,7 +140,7 @@ @testset "$(FUNC)" begin m = deepcopy(_mesh) _offset = ones(size(get_verts_packed(m))) - m2 = FUNC(FUNC(m, _offset), (_offset.*-1)) + m2 = FUNC(FUNC(m, _offset), (_offset .* -1)) if inplace @test m2 === m else diff --git a/test/transforms/transforms.jl b/test/transforms/transforms.jl index c38b0f1..3087fbf 100644 --- a/test/transforms/transforms.jl +++ b/test/transforms/transforms.jl @@ -2,9 +2,9 @@ for inplace in [true, false] @testset "ScalePointCloud inplace=$(inplace)" begin - p = rand(Float32,3,8,2) - t1 = ScalePointCloud(2.0; inplace=inplace) - t2 = ScalePointCloud(0.5; inplace=inplace) + p = rand(Float32, 3, 8, 2) + t1 = ScalePointCloud(2.0; inplace = inplace) + t2 = ScalePointCloud(0.5; inplace = inplace) pc1 = PointCloud(p) pc2 = t2(t1(pc1)) if inplace @@ -18,12 +18,12 @@ for inplace in [true, false] @testset "RotatePointCloud inplace=$(inplace)" begin - p = rand(Float32,3,8,2) - rotmat = 2 .* one(rand(Float32,3,3)) + p = rand(Float32, 3, 8, 2) + rotmat = 2 .* one(rand(Float32, 3, 3)) rotmat_inv = inv(rotmat) - t1 = RotatePointCloud(rotmat; inplace=inplace) - t2 = RotatePointCloud(rotmat_inv; inplace=inplace) + t1 = RotatePointCloud(rotmat; inplace = inplace) + t2 = RotatePointCloud(rotmat_inv; inplace = inplace) pc1 = PointCloud(p) pc2 = t2(t1(pc1)) if inplace @@ -37,11 +37,11 @@ for inplace in [true, false] @testset "ReAlignPointCloud inplace=$(inplace)" begin - p1 = rand(Float32,3,8,2) - p2 = rand(Float32,3,8,1) + p1 = rand(Float32, 3, 8, 2) + p2 = rand(Float32, 3, 8, 1) src = PointCloud(p1) tgt = PointCloud(p2) - t = ReAlignPointCloud(tgt; inplace=inplace) + t = ReAlignPointCloud(tgt; inplace = inplace) src_1 = t(src) if inplace @test src == src_1 @@ -50,14 +50,17 @@ end # Transformed PointCloud should be inside the bounding box defined by `tgt` PointCloud @test all( - reshape(maximum(tgt.points, dims=2), (:,1)) .>= src_1.points .>= reshape(minimum(tgt.points, dims=2), (:,1))) + reshape(maximum(tgt.points, dims = 2), (:, 1)) .>= + src_1.points .>= + reshape(minimum(tgt.points, dims = 2), (:, 1)), + ) end end for inplace in [true, false] @testset "NormalizePointCloud inplace=$(inplace)" begin - p = rand(Float32,3,8,2) - t = NormalizePointCloud(; inplace=inplace) + p = rand(Float32, 3, 8, 2) + t = NormalizePointCloud(; inplace = inplace) pc1 = PointCloud(p) pc2 = t(pc1) if inplace @@ -65,19 +68,19 @@ else @test pc1 != pc2 end - @test all(isapprox.(mean(pc2.points;dims=2), 0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(pc2.points;dims=2), 1, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.(mean(pc2.points; dims = 2), 0, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.(std(pc2.points; dims = 2), 1, rtol = 1e-5, atol = 1e-5)) end end @testset "Chain" begin p = rand(Float32, 3, 8, 2) - t = Chain(ScalePointCloud(0.5), RotatePointCloud(rand(3,3)), NormalizePointCloud()) + t = Chain(ScalePointCloud(0.5), RotatePointCloud(rand(3, 3)), NormalizePointCloud()) pc1 = PointCloud(p) pc1 = t(pc1) @test pc1.points isa Array - @test all(isapprox.(mean(pc1.points;dims=2), 0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(pc1.points;dims=2), 1, rtol = 1e-5, atol = 1e-4)) + @test all(isapprox.(mean(pc1.points; dims = 2), 0, rtol = 1e-5, atol = 1e-5)) + @test all(isapprox.(std(pc1.points; dims = 2), 1, rtol = 1e-5, atol = 1e-4)) end _mesh = load_trimesh([ @@ -88,8 +91,8 @@ for inplace in [true, false] @testset "ScaleTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t1 = ScaleTriMesh(2.0; inplace=inplace) - t2 = ScaleTriMesh(0.5; inplace=inplace) + t1 = ScaleTriMesh(2.0; inplace = inplace) + t2 = ScaleTriMesh(0.5; inplace = inplace) m2 = t2(t1(m)) if inplace @@ -111,8 +114,8 @@ m = deepcopy(_mesh) rotmat = 2 .* one(rand(Float32, 3, 3)) rotmat_inv = inv(rotmat) - t1 = RotateTriMesh(rotmat; inplace=inplace) - t2 = RotateTriMesh(rotmat_inv; inplace=inplace) + t1 = RotateTriMesh(rotmat; inplace = inplace) + t2 = RotateTriMesh(rotmat_inv; inplace = inplace) m2 = t2(t1(m)) if inplace @test m2 === m @@ -133,7 +136,7 @@ m = deepcopy(_mesh) src = Flux3D.scale(m, 2.0) tgt = Flux3D.scale(m, 1.0) - t = ReAlignTriMesh(tgt, 1; inplace=inplace) + t = ReAlignTriMesh(tgt, 1; inplace = inplace) src_1 = t(src) if inplace @test src === src_1 @@ -144,12 +147,12 @@ @test all( maximum(get_verts_list(_mesh)[1]; dims = 2) .>= get_verts_list(src_1)[1] .>= - minimum(get_verts_list(_mesh)[1]; dims = 2) + minimum(get_verts_list(_mesh)[1]; dims = 2), ) @test all( maximum(get_verts_list(_mesh)[1]; dims = 2) .>= get_verts_list(src_1)[2] .>= - minimum(get_verts_list(_mesh)[1]; dims = 2) + minimum(get_verts_list(_mesh)[1]; dims = 2), ) end end @@ -157,25 +160,45 @@ for inplace in [true, false] @testset "NormalizeTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t = NormalizeTriMesh(; inplace=inplace) + t = NormalizeTriMesh(; inplace = inplace) m2 = t(m) if inplace @test m2 === m else @test m2 !== m end - @test all(isapprox.(mean(get_verts_list(m2)[1]; dims = 2), 0.0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(get_verts_list(m2)[1]; dims = 2), 1.0, rtol = 1e-4, atol = 1e-5)) - @test all(isapprox.(mean(get_verts_list(m2)[2]; dims = 2), 0.0, rtol = 1e-5, atol = 1e-5)) - @test all(isapprox.(std(get_verts_list(m2)[2]; dims = 2), 1.0, rtol = 1e-4, atol = 1e-5)) + @test all(isapprox.( + mean(get_verts_list(m2)[1]; dims = 2), + 0.0, + rtol = 1e-5, + atol = 1e-5, + )) + @test all(isapprox.( + std(get_verts_list(m2)[1]; dims = 2), + 1.0, + rtol = 1e-4, + atol = 1e-5, + )) + @test all(isapprox.( + mean(get_verts_list(m2)[2]; dims = 2), + 0.0, + rtol = 1e-5, + atol = 1e-5, + )) + @test all(isapprox.( + std(get_verts_list(m2)[2]; dims = 2), + 1.0, + rtol = 1e-4, + atol = 1e-5, + )) end end for inplace in [true, false] @testset "TranslateTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) - t1 = TranslateTriMesh(1.0; inplace=inplace) - t2 = TranslateTriMesh(-1.0; inplace=inplace) + t1 = TranslateTriMesh(1.0; inplace = inplace) + t2 = TranslateTriMesh(-1.0; inplace = inplace) m2 = t2(t1(m)) if inplace @test m2 === m @@ -195,8 +218,8 @@ @testset "OffsetTriMesh inplace=$(inplace)" begin m = deepcopy(_mesh) _offset = ones(size(get_verts_packed(m))) - t1 = OffsetTriMesh(_offset; inplace=inplace) - t2 = OffsetTriMesh(_offset .* -1; inplace=inplace) + t1 = OffsetTriMesh(_offset; inplace = inplace) + t2 = OffsetTriMesh(_offset .* -1; inplace = inplace) m2 = t2(t1(m)) if inplace diff --git a/test/utils.jl b/test/utils.jl index 8b54039..a1549a3 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -1,22 +1,21 @@ # Borrowed from Zygote tests function ngradient(f, xs::AbstractArray...) grads = zero.(xs) - for (x, Δ) in zip(xs, grads), i in 1:length(x) + for (x, Δ) in zip(xs, grads), i = 1:length(x) δ = sqrt(eps()) tmp = x[i] - x[i] = tmp - δ/2 + x[i] = tmp - δ / 2 y1 = f(xs...) - x[i] = tmp + δ/2 + x[i] = tmp + δ / 2 y2 = f(xs...) x[i] = tmp - Δ[i] = (y2-y1)/δ + Δ[i] = (y2 - y1) / δ end return grads end gradcheck(f, xs...) = - all(isapprox.(ngradient(f, xs...), - gradient(f, xs...), rtol = 1e-5, atol = 1e-5)) + all(isapprox.(ngradient(f, xs...), gradient(f, xs...), rtol = 1e-5, atol = 1e-5)) gradtest(f, xs::AbstractArray...) = gradcheck((xs...) -> sum(sin.(f(xs...))), xs...) gradtest(f, dims...) = gradtest(f, rand.(Float64, dims)...) From 05578ac3abdde464d8ab582eff97a0eba4cc88e0 Mon Sep 17 00:00:00 2001 From: avik-pal Date: Sat, 1 Aug 2020 09:36:36 -0400 Subject: [PATCH 2/2] Add format PR action --- .github/workflows/format_pr.yml | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/format_pr.yml diff --git a/.github/workflows/format_pr.yml b/.github/workflows/format_pr.yml new file mode 100644 index 0000000..eade2e8 --- /dev/null +++ b/.github/workflows/format_pr.yml @@ -0,0 +1,36 @@ +name: format-pr + +on: + schedule: + - cron: '0 0 * * *' +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1.4.2] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - uses: actions/checkout@v2 + - name: Install JuliaFormatter and format + run: | + julia -e 'import Pkg; Pkg.add("JuliaFormatter")' + julia -e 'using JuliaFormatter; format(".")' + # https://github.com/marketplace/actions/create-pull-request + - name: Create Pull Request + uses: peter-evans/create-pull-request@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Format .jl files + title: 'Automatic JuliaFormatter.jl run' + branch: auto-juliaformatter-pr + labels: formatting, automated pr, no changelog + - name: Check outputs + run: | + echo 'Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}' + echo 'Pull Request Number - ${{ steps.cpr.outputs.pr_number }}'