Logical Indexing with Complex Numbers

6 views (last 30 days)
So I have a data set of coefficients which are calculated from a Laplace expansion into spherical harmonics. The resulting coefficients can be either real or complex. When I'm working though the data, there are times all (or a lot) the imaginary components have values << eps i.e the numerical accuracy (so in one dataset of 100,000 or so coefficents, the max imaginary component is 2e-17 compared to a max coefficient of 120).
For the purposes of my work, the presence of the imaginary numbers is bad for both clarity and computational time.
For a variable A;
I can use the code
A(A<=eps)=0
to zero the effectively zero real components however the logical '<' ignores imaginary numbers. I did a lot of searching and can't seem to find a method to do the same with the imaginary component.
I believe it maybe possible to break up the matrix using real and imag, set the zeros and then reassign the initial matrix with the new imaginary components, howver I'm unsure of a consise way to do this and I would imagine the 4 lines of code I can write would become cumbersome when I'm working with lots of data and loops etc
Any ideas or suggestions would be much appreicated
  1 Comment
ADSW121365
ADSW121365 on 9 May 2019
Further to this, in the code mentioned previously, were the array A to have both positive and negative values, I would use;
A(abs(A)<=eps)=0
This stops it zeroing all the negative values in the array. However as you would imagine, the abs for an imaginary array removes all the complex components meaning I lose some of my data and hence the final set of coefficents end up wrong.

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 9 May 2019
The only approach I can suggest is:
A = rand(5) + 1j*(rand(5)*eps + rand(5).*(rand(5)>0.5)); % Create ‘A’
Ar = real(A);
Ai = imag(A);
ix = Ai<=eps;
Ai(ix) = 0;
Anew = Ar + 1j*Ai;
The problem with dealing with logical indices is that it can be difficult to retain the matrix orientation. Logical references can result in creating column vectors from matrices, frequently not the desired outcome. This approach avoids that, at the expense of a bit of inefficiency in creating separate real and imaginary component matrices of ‘A’.
  1 Comment
Steven Lord
Steven Lord on 9 May 2019
There's no need to rebuild the whole matrix.
A = rand(5) + 1j*(rand(5)*eps + rand(5).*(rand(5)>0.5)); % Create ‘A’
Ar = real(A);
Ai = imag(A);
ix = abs(Ai)<=eps; % Small imaginary parts
I'm going to make a copy of A so that you can keep the original A around for comparison; in real code you'd probably change A in place.
Anew = A;
Anew(ix) = Ar(ix); % Replace the complex number with its real part
% Display both matrices
A
Anew
Alternately if you don't want to create all of real(A), you can substitute additional indexing.
A = rand(5) + 1j*(rand(5)*eps + rand(5).*(rand(5)>0.5)); % Create ‘A’
Ai = imag(A);
ix = abs(Ai)<=eps; % Small imaginary parts
Anew2 = A;
Anew2(ix) = real(Anew2(ix));
% Display both matrices
A
Anew2
howver I'm unsure of a consise way to do this and I would imagine the 4 lines of code I can write would become cumbersome when I'm working with lots of data and loops etc
That makes this a prime candidate for making a small function. Tuck the four lines of code into a function (with a descriptive name, maybe something like trimSmallImagPart) and use one line to call that function with different arrays wherever needed in your code.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!