Is there some nice solution for vertically concatenating arrays into one matrix, and then “unconcatenate” a similar matrix to equally sized arrays as we started with?

Background: I have a Dict{String, Matrix{Float}} (the dimensions of all the arrays are n × 2) of pixel coordinates of a tracked animal. I need to calibrate these coordinates to real world values. The calibration of the camera that recorded the trajectories of the animals was done a la calibration toolbox in matlab (waving a checkerboard in front of the camera).

Currently there is no equivalent auto-detection of the checkerboards in Julia, so I’m forced to use matlab. But because it’s matlab I kind of want to work with a single large matrix (and not multiple small matrices) for speed. Once matlab is done converting the coordinates from pixels to real-world, I want to redistribute the now calibrated coordinates back to the Dict. So I need to divide the large matrix I got back from matlab into the same shapes of small matrices I had before. The way I’m doing this now is by saving a vector of tuples with three indices: the key to the dictionary, the row index in the small matrix, the row index in the large matrix.

How about the below… It’s perhaps similar to the approach you’re currently using. I wouldn’t expect there to be a much easier solution, since the presence of a dictionary makes your problem quite specific.

function package(dict)
rows = 1
order = [(s = size(v,1); (k, s, (rows+=s)-s)) for (k,v) = dict]
data = similar(first(values(d)), rows-1, 2)
for (k,s,r) = order
data[r:r+s-1,:] .= dict[k]
end
order,data
end
function update!(dict, order, data)
for (k,s,r) = order
dict[k] .= data[r:r+s-1,:]
end
end
function convert!(data)
data .= sin.(data)
end
dict = Dict("a" => rand(3,2), "b" => rand(1,2), "c" => rand(5, 2))
display(dict)
order,data = package(dict)
convert!(data)
update!(dict, order, data)
display(dict)

Yap, that’s more or less what I’m doing now. OK, I kind of hoped there would be a super-duper awesome way to do this. No worries, I got it working, but I can’t do it with out saving a collection of indices that help convert the large matrix to the small ones.

Or a regular for loop with a pre-allocated array for much better performance (at the cost of more code):

function fast_vcat(M)
n = mapreduce(x -> size(x,1), +, M)
V = similar(M[1], n, 2)
r = 1
for m = M
s = size(m,1)
@inbounds for j=1:2, i=1:s
V[r+i-1,j] = m[i,j]
end
r += s
end
V
end

(This version is hard-coded to two columns, which gives a small performance boost.) Test:

Very nice. Yea, while speed is always welcomed, I was hoping there would be some macro or package out there that does the unconcatenation. I can’t seem to see how SplitApplyCombine.jl would do the trick because there is no way for the combine part to know to which indices the parts belong (the same kind of information dim1Dist,...,dimNDist convey in matlab’s mat2cell).