[ADMB Users] Using asin with df1b2variables
Ben Stevenson
bcs5 at st-andrews.ac.uk
Wed Oct 16 13:34:17 PDT 2013
Hi ADMBers,
A couple of points:
1)
I have discovered that the function asin does not work with df1b2variables,
despite appearing in src/df1b2separable/df1b2f26. I am not very familiar
with the ADMB source code (or with C++ for that matter), but I added asin
to df1b2fun.h, rebuilt the source and everything worked fine. Assuming I
did the right thing, could someone with write access make the same change
to the subversion repo? Note that atan does appear but acos does not.
2)
My reason for using asin was to calculate a bearing between two locations,
which are being treated as latent variables (and so modelled with a
random_effects_matrix). The model is an animal movement model, and it is
necessary to work out the direction the animal moved in from one time point
to the next. The problem for me was that the range of the function asin is
(-pi, pi) and obviously the range of the directions an animal can move is
(0, 2*pi). So it was necessary to translate from the first to the second,
but this depends on what quadrant the bearing belongs to (i.e., if the
animal moved northeast, southeast, southwest, or northwest). This is
because for each value returned in (-pi, pi) by asin, there are two
possible bearings in (0, 2*pi) that this could correspond to.
"x_diff" and "y_diff" are the differences between the current and previous
x and y-coordinates, and "dist" is the distance between the current and
previous locations. I wanted to write something like:
bearing = asin(x_diff/dist)
if (southeast) bearing += M_PI - 2*bearing;
if (southwest) bearing += M_PI - 2*bearing;
if (northwest) bearing += 2*M_PI;
But this would break all sorts of ADMB rules with the if statements.
In the end, I got around the problem by first emulating the performance of
R's sign() function (is there a way to do this in ADMB already??):
sign_x_diff = x_diff/fabs(x_diff);
sign_y_diff = y_diff/fabs(y_diff);
And then creating some dummy variables that indicated the animal's
direction:
se_dummy = (sign_x_diff - sign_y_diff)*(sign_x_diff +
square(sign_y_diff))/4;
nw_dummy = (sign_y_diff - sign_x_diff)*(sign_y_diff +
square(sign_x_diff))/4;
sw_dummy = (-sign_x_diff - sign_y_diff)*(square(sign_x_diff) -
sign_y_diff)/4;
Before using these instead of the if statements above to make the correct
adjustments to what was returned by asin:
bearing = asin(x_diff/dist);
bearing += se_dummy*M_PI - 2*bearing);
bearing += nw_dummy*2.0*M_PI;
bearing += sw_dummy*(M_PI - 2*bearing);
Everything worked fine once I did all this, but it was quite a big
procedure to do something quite simple, and I was wondering if I was
missing an obvious solution I could use in future instead of the mess that
I've tried to explain above.
Thanks in advance,
Ben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.admb-project.org/pipermail/users/attachments/20131016/2d403107/attachment.html>
More information about the Users
mailing list