I'm looking for an elegant way of useing ndgrid and interpn in a more "general" way - basically for any given size of input and not treat each rank in a separate case.
Given an N-D source data with matching N-D mesh given in a cell-array of 1D vectors for each coordinate Mesh={[x1]; [x2]; ...; [xn]} and the query/output coordinates given in the same way (QueryMesh), how do I generate the ndgrid matrices and use them in the interpn without setting a case for each dimension?
Also, if there is a better way the define the mesh - I am more than willing to change.
Here's a pretty obvious, conceptual (and NOT WORKING) schematic of what I want to get, if it wasn't clear
Mesh={linspace(0,1,10); linspace(0,4,20); ... linsapce(0,10,15)};
QueryMesh={linspace(0,1,20); linspace(0,4,40); ... linsapce(0,10,30)};
Data=... (whatever)
NewData=InterpolateGeneric(Mesh,QueryMesh,Data);
function NewData=InterpolateGeneric(Mesh,QueryMesh,Data)
InGrid=ndgrid(Mesh{:});
OutGrid=ndgrid(QueryMesh{:});
NewData=interpn(InGrid{:},Data,OutGrid{:},'linear',0.0)
end
I think what you are looking for is how to get multiple outputs from this line:
OutGrid = ndgrid(QueryMesh{:});
Since ndgrid produces as many output arrays as input arrays it receives, you can create an empty cell array in this way:
OutGrid = cell(size(QueryMesh));
Next, prove each of the elements of OutGrid as an output argument:
[OutGrid{:}] = ndgrid(QueryMesh{:});
Related
When using the MATLAB jsonencode function it seems very difficult to convert size 1 arrays into the correct JSON format i.e. [value]. For example if I do:
jsonencode(struct('words', [string('hello'), string('bye')]))
Then this produces:
{"words":["hello","bye"]}
which is correct. If however I do:
jsonencode(struct('words', [string('hello')]))
Then it produces:
{"words":"hello"}
losing the square brackets, which it needs because it is in general an array. The same happens when using a cell rather than an array, although using a cell does work if it's not inside a struct.
Any idea how I can work around this issue?
It seems this can be solved by using a cell rather than an array and then not creating the struct inline. Like
s.words = {'hello'};
jsonencode(s)
Output:
{"words":["hello"]}
I presume when created inline the cell functionality of matlab is actually trying to make multiple structs rather than multiple strings. Note that this still won't work with arrays as matlab treats a size one array as a scalar.
I noticed the following line in the transfer function block in the Modelica library (Modelica.Blocks.Continuous.TransferFunction):
parameter Real bb[:] = vector([zeros(max(0,na-nb),1);b]);
I don't understand what the "vector" function call does, and why it is even necessary. Wouldn't
parameter Real bb[:] = [zeros(max(0,na-nb),1);b];
lead to the same result?
I found the following explanation in the Modelica Language Specification 3.2, but it doesn't really help:
"vector(A) - Returns a 1-vector, if A is a scalar and otherwise returns a vector containing all the elements of the array, provided there is at most one dimension size > 1."
I assume the whole story is based on some difference between arrays and vectors in Modelica. I would be grateful if someone helped me sort it out.
Simple answer: A vector is a one-dimensional array.
Imagine we declared something like this:
Real x[1,5,1,1];
Not there are only 5 elements in this thing and they are all contained in the same dimension. So what if we wanted to convert this to a simple vector of 5 elements. We could do this:
Real y[5] = { x[1,i,1,1] for i in 1:5 };
But that gets tedious. The alternative is:
Real y[5] = vector(x);
The compiler looks at this and automatically finds the dimension that has a size>1 and then pulls all the elements out as a vector.
And just to address one point you brought up, this is not valid:
Real z[5] = [1,2,3,4,5];
Because the left hand side is a vector (one dimensional) and the right hand side is an array. Normally, if you wanted to use the right hand side, the left hand side would have to be:
Real z[1,5] = [1,2,3,4,5];
If you want to stuff it into a vector, you need to convert the right hand side from an array to a vector, i.e.,
Real z[5] = vector([1,2,3,4,5]);
Does that help?
Consider the three-dimensional arrays
A = rand(3,4,5);
B = rand(3,4,5);
plot(A(:,1,1),B(:,1,1))
plot(A(1,:,1),B(1,:,1))
This all works fine, however
>> plot(A(1,1,:),B(1,1,:))
Error using plot
Data may not have more than 2 dimension
Is there a quick way around this a way around this other than using reshape()?
you should use squeeze to remove singleton dimensions:
plot(squeeze(A(1,1,:)),squeeze(B(1,1,:)))
another option is to shift matrix dimensions using shiftdim
plot(shiftdim(A(1,1,:),1),shiftdim(B(1,1,:),1),'o')
I have a simple problem with structures.
Lets create:
x(1).a(:, :) = magic(2);
x(2).a(:, :) = magic(2)*2;
x(3).a(:, :) = magic(2)*3;
how to list a(1, 1) from all x-es?
i wanted to do it like:
x(1, :).a(1,1)
but there is an error "Scalar index required for this type of multi-level indexing."
How to approach it? I know I can do it with a loop, but that's probably the worst solution :)
Thanks!
This is not the best datastructure to use if this is the sort of query you'd like to make on it, precisely because this sort of indexing cannot be done directly.
However, here is one approach that works:
cellfun(#(X) X(1,1), {x.a})
The syntax {x.a} converts x from a 'struct array' into a cell array. Then we use cellfun to apply a function as a map over the cell array. The anonymous function #(X) X(1,1) takes one argument X and returns X(1,1).
You can also get your data in this way:
B = cat(3,x.a);
out = reshape(B(1,1,:),1,[]);
By the way, loops are not evil. Sometimes they are even faster than vectorized indexation. Try it both ways, see what suits you best in terms of:
Speed - use the profiler to check
Code clarity - depends on the context. Sometimes vectorized code looks better, sometimes the opposite.
Is there an elegant way to express
val a = Array.fill(2,10) {1}
def do_to_elt(i:Int,j:Int) {
if (a.isDefinedAt(i) && a(i).isDefinedAt(j)) f(a(i)(j))
}
in scala?
I recommend that you not use arrays of arrays for 2D arrays, for three main reasons. First, it allows inconsistency: not all columns (or rows, take your pick) need to be the same size. Second, it is inefficient--you have to follow two pointers instead of one. Third, very few library functions exist that work transparently and usefully on arrays of arrays as 2D arrays.
Given these things, you should either use a library that supports 2D arrays, like scalala, or you should write your own. If you do the latter, among other things, this problem magically goes away.
So in terms of elegance: no, there isn't a way. But beyond that, the path you're starting on contains lots of inelegance; you would probably do best to step off of it quickly.
You just need to check the array at index i with isDefinedAt if it exists:
def do_to_elt(i:Int, j:Int): Unit =
if (a.isDefinedAt(i) && a(i).isDefinedAt(j)) f(a(i)(j))
EDIT: Missed that part about the elegant solution as I focused on the error in the code before your edit.
Concerning elegance: no, per se there is no way to express it in a more elegant way. Some might tell you to use the pimp-my-library-Pattern to make it look more elegant but in fact it does not in this case.
If your only use case is to execute a function with an element of a multidimensional array when the indices are valid then this code does that and you should use it. You could generalize the method by changing the signature of to take the function to apply to the element and maybe a value if the indices are invalid like this:
def do_to_elt[A](i: Int, j: Int)(f: Int => A, g: => A = ()) =
if (a.isDefinedAt(i) && a(i).isDefinedAt(j)) f(a(i)(j)) else g
but I would not change anything beyond this. This also does not look more elegant but widens your use case.
(Also: If you are working with arrays you mostly do that for performance reasons and in that case it might even be better to not use isDefinedAt but perform validity checks based on the length of the arrays.)