Mapping a function across an array of structures

조회 수: 4 (최근 30일)
Andrew
Andrew 2011년 5월 8일
Hi,
I have created an array of structures for the x, y, and z coordinates of particles at time t. For example, suppose I have 3 particles and monitor the positions of the particles at five different times:
s(1).x=1.1:0.1:1.5;
s(1).y=2.1:0.1:2.5;
s(1).z=3.1:0.1:3.5;
s(2).x=4.1:0.1:4.5;
s(2).y=5.1:0.1:5.5;
s(2).z=6.1:0.1:6.5;
s(3).x=7.1:0.1:7.5;
s(3).y=8.1:0.1:8.5;
s(3).z=9.1:0.1:9.5;
For the purpose of this example, I have just made up the x, y, and z coordinates of the three particles at the five times. (My actual data is much more extensive; it contains information about 254 atoms at 2001 different times, but my structure organization is the same.)
Now suppose that I want to find the displacement of the ith particle at time t relative to its position at the first time. For this, I have written a function called delta:
function result = delta(i,t,structureName)
xvalinitial=structureName(i).x(1);
yvalinitial=structureName(i).y(1);
zvalinitial=structureName(i).z(1);
xval=structureName(i).x(t);
yval=structureName(i).y(t);
zval=structureName(i).z(t);
result=[xval-xvalinitial yval-yvalinitial zval-zvalinitial];
So if I call for example delta(1,2,s), I get the displacement of atom 1 at time 2, relative to atom 1's initial position:
>> delta(1,2,s)
ans =
0.1000 0.1000 0.1000
But, now, what if I wanted to vectorize my function delta? What if I wanted to be able to "map" delta across a vector. For example, ideally, I would like to be able to type:
delta([1 2 3],2,s)
and obtain a list of the displacements of atoms 1, 2, AND 3 at time 2 relative to the initial time, time 1.
Or, I might want to be able to type:
delta(1,[2 3],s)
and obtain a list of the displacement of atom 1 at the time 2 AND at the time 3, relative to the initial time, time 1.
(By "list," I guess I really mean "matrix" or "array", where each row contains x, y, and z coordinates for the delta of the atom(s) at the time(s).)
Can you please help me see how I might be able to write the delta function so that I am able to do this? Should I be using the built-in Matlab command structfun? I tried this, but I have not had success so far. Is there any other way that I can "map" my delta function across vectors?
Thanks in advance. Andrew DeYoung Carnegie Mellon University

채택된 답변

Walter Roberson
Walter Roberson 2011년 5월 9일
EDITED: corrected to "arrayfun"
selectx = @(i,t) cell2mat(arrayfun(@(S) {S.x([1 t])}, structureName(i)));
Likewise for y and z.
The resulting arrays will have one row per value of i, and the columns will be x(1) followed by one column per x(t). Take the first column and repmat() it to the width of the remaining columns and subtract that from the remaining columns in order to get your delta values.

추가 답변 (2개)

Andrew
Andrew 2011년 5월 9일
I am sorry, this does not appear to be working. Should I place the selectx function inside my delta function definition? When I do this, using the following:
function result = delta(i,t,structureName)
selectx = @(i,t) cell2mat(arrayfunc(@(s) {s.x([1 t])}, structureName(i)));
xvalinitial=structureName(i).x(1);
yvalinitial=structureName(i).y(1);
zvalinitial=structureName(i).z(1);
xval=structureName(i).x(t);
yval=structureName(i).y(t);
zval=structureName(i).z(t);
result=selectx(i,t);
I get an error message when I make the call delta(2,[1 2],s) in Matlab:
??? Undefined function or method 'arrayfunc' for input arguments of type
'function_handle'.
Error in ==> delta>@(i,t)cell2mat(arrayfunc(@(s){s.x([1,t])},structureName(i)))
Error in ==> delta at 13
result=selectx(i,t);
Can you help me see what I should do differently? Thanks in advance.
  댓글 수: 2
Matt Fig
Matt Fig 2011년 5월 9일
Walter made a typo. It should be arrayfun, not arrayfunc. After you make that change, read his further comments again...
Andrew
Andrew 2011년 5월 9일
Thank you!

댓글을 달려면 로그인하십시오.


Andrew
Andrew 2011년 5월 9일
Hi,
May I ask you a related question? What if I want to map a function across each row in an array. For example, the built-in Matlab function norm computes the norm of a vector. Suppose I had an array like the following:
>> A=[1 0 0; 2 1 0; 0 0 3]
A =
1 0 0
2 1 0
0 0 3
and I want to obtain the following vector:
1.0000 2.2361 3.0000
where these are the norms of the three rows of A, respectively. Effectively, this is just entering:
[norm(A(1,:)) norm(A(2,:)) norm(A(3,:))]
but I would like Matlab to do it automatically. Is there any way to do this, perhaps using arrayfun, and without using a for loop?
Thank you kindly!
  댓글 수: 3
Walter Roberson
Walter Roberson 2011년 5월 9일
New question would have been better.
Walter Roberson
Walter Roberson 2011년 5월 9일
You can hide the "for" loop, but for "norm" you cannot really replace it.
arrayfun(@(K) norm(A(K,:)), 1:size(A,1))
If you want to do this kind of thing repeatedly then,
maprows = @(f,A) arrayfun(@(K) f(A(K,:)), 1:size(A,1))
then
maprows(@norm, A)

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by