# Using RegionTrees adaptivesampling! with MappedArrays

I’m playing around with RegionTrees and am trying to write a refinery that makes an octree given a bunch of points. The twist being my points are in a MappedArray. I can populate an initial `Cell` with the `MappedArray` data playload successfully, but then when I try to build a refinery like in the demo it fails.

The stacktrace points to a convert method issue, but it seems strange to me that I can even create the root `Cell` in the first place. What is the missing definition that I would need to define to make this work?

MWE:

``````#set up
using MappedArrays, RegionTrees, StaticArrays
import RegionTrees: AbstractRefinery, needs_refinement, refine_data

a = [rand(100000:200000,3) for i in 1:100]

f = (x -> x * 0.1)
f_inv = (x -> x / 0.1)

m1 = mappedarray(f, f_inv, a)

xmin = minimum(getindex.(m1,1))
ymin = minimum(getindex.(m1,2))
zmin = minimum(getindex.(m1,3))
xmax = maximum(getindex.(m1,1))
ymax = maximum(getindex.(m1,2))
zmax = maximum(getindex.(m1,3))

#this works
root = Cell(SVector(xmin, ymin, zmin), SVector((xmax - xmin), (ymax - ymin), (zmax - zmin)), m1)

#double check to see what it looks like
root.data

#split until each cell contains less than some number of records
struct MyRefinery <: AbstractRefinery
pointcount::Int64
end

# These two methods are all we need to implement
function needs_refinement(r::MyRefinery, cell)
length(cell.data) > r.pointcount
end

function refine_data(r::MyRefinery, cell::Cell, indices)
boundary = child_boundary(cell, indices)
cell.data[cell.data .< Ref(boundary.widths)]
end

r = MyRefinery(10)

#this errors

ERROR: MethodError: Cannot `convert` an object of type
Cell{Vector{Vector{Float64}},3,Float64{},8} to an object of type
Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"},3,Float64{},8}
Closest candidates are:
convert(::Type{T}, ::T) where T at essentials.jl:205
Cell{Data, N, T, L}(::Any, ::Any, ::Any, ::Any, ::Any) where {Data, N, T, L} at /home/crgxcf/.julia/packages/RegionTrees/rosFd/src/cell.jl:2
Stacktrace:
[1] cvt1
@ ./essentials.jl:322 [inlined]
[2] macro expansion
@ ./ntuple.jl:74 [inlined]
[3] ntuple
@ ./ntuple.jl:69 [inlined]
[4] convert(#unused#::Type{NTuple{8, Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}}}, x::NTuple{8, Cell{Vector{Vector{Float64}}, 3, Float64, 8}})
@ Base ./essentials.jl:323
[5] RegionTrees.TwosArray{3, Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, 8}(data::NTuple{8, Cell{Vector{Vector{Float64}}, 3, Float64, 8}})
@ RegionTrees ~/.julia/packages/RegionTrees/rosFd/src/twosarray.jl:8
[6] convert
@ ~/.julia/packages/StaticArrays/rdb0l/src/convert.jl:10 [inlined]
[7] convert(#unused#::Type{Union{Nothing, RegionTrees.TwosArray{3, Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, 8}}}, x::RegionTrees.TwosArray{3, Cell{Vector{Vector{Float64}}, 3, Float64, 8}, 8})
@ Base ./some.jl:36
[8] setproperty!(x::Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, f::Symbol, v::RegionTrees.TwosArray{3, Cell{Vector{Vector{Float64}}, 3, Float64, 8}, 8})
@ Base ./Base.jl:34
[9] macro expansion
@ ~/.julia/packages/RegionTrees/rosFd/src/cell.jl:77 [inlined]
[10] split!(cell::Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, child_data::RegionTrees.TwosArray{3, Vector{Vector{Float64}}, 8})
@ RegionTrees ~/.julia/packages/RegionTrees/rosFd/src/cell.jl:65
[11] split!(cell::Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, child_data_function::Function)
@ RegionTrees ~/.julia/packages/RegionTrees/rosFd/src/cell.jl:69
[12] adaptivesampling!(root::Cell{MappedArray{Vector{Float64}, 1, Vector{Vector{Int64}}, var"#3#4", var"#5#6"}, 3, Float64, 8}, refinery::MyRefinery)
[13] top-level scope
@ REPL[28]:1

``````

I am able to get around this if I first `collect` the array but then I lose my transform information.

``````m2 = collect(m1)
root2 = Cell(SVector(xmin, ymin, zmin), SVector((xmax - xmin), (ymax - ymin), (zmax - zmin)), m2)
#this works