2

I have been unable to find anything close to this with Google, so I'm afraid that my question itself may be flawed... None the less, here goes:

I wish to display a matrix of values (Z) at various fixed dynamic ranges. In this case, fixed at 0dB, 10dB, ..., 40dB.

My current approach is to find Zmag = abs(Z).^2, Zn = normalized(Zmag), Zdb = 10*log10(1+Zn)

In order to view a different dynamic range (say, 10dB) I would include 'Zn(Zn<0.1)=0.1' before finding Zdb. For 20dB I do the same, except the value of interest changes to 0.01.

Then I do a color mesh plot of Zn and view the XY (top, from 3D perspective) plot to see something similar to what imagesc(Zn) would give. The intent is that as I increase the dynamic range, I should see a more detailed plot (with more colors between the maximum and minimum, in this case).

My current method is performing as (I think) it should for 10dB: 10dB dynamic range mesh Compared to 40dB: 40dB dynamic range mesh plot

However, I can't see a difference between my 0,20,30, and 40dB plots. I would expect there to be a gradual increase in values from 0dB to 40dB.

-Dylan

EDIT: Here is some sample code. It is a snippit of the real code, but should still run:

%% Constants
fnum = 1;
Fc = 1/16;
taup = 128;
taumin = 1;
taumax = 512;
taux = taumin:taumax;

%% Signal
l = 1:16; %Signal length
s = sin(2*pi*Fc*l); %Original Signal
sig = zeros([1 taup+512]);
sig(taup:taup+size(l,2)-1) = s;

[mfr,fdy] = MatchedFilterResponse(sig,taup,l);
Z = mfr;

slices = true;
%full dynamic range
name = 'Short Tone Ping results with 0dB range';
Zmag = abs(Z).^2;
Zn = normalizeMat(Zmag);
Zdb = 10*log10(1+Zn);
fnum = plotSurfaces(taux,fdy,Zdb,fnum,name,slices);

slices = false;
%40dB dynamic range
name = 'Short Tone Ping results with 40dB range';
Z40mag = Zmag;
Z40n = normalizeMat(Z40mag);
Z40n(Z40n<0.0001) = 0.0001;
Z40db = 10*log10(1+Z40n);
fnum = plotSurfaces(taux,fdy,Z40db,fnum,name,slices);

function [mfr,fdy] = MatchedFilterResponse(sig,taup,l)
    Fdmin = -1/16;
    Fdmax = 1/16;
    Fdinc = (0.125)/(255);
    fdy = linspace(Fdmin,Fdmax,256);
    i = 0;
    for tau = 1:512
        i = i+1;
        j = 0;
        for Fd = Fdmin:Fdinc:Fdmax
            j = j+1;
            a = sig(l+taup-1);
            b = sig(l+tau).*exp(1i*2*pi*Fd*l);
            mfr(j,i) = sum(a.*b);
        end
    end
return
end

function [fnum] = plotSurfaces(taux,fdy,z,fnum,name,slices)
    fid = figure(fnum);
    axes1 = axes('Parent',fid);
    grid(axes1,'on');
    hold(axes1,'all');
    msh = mesh(taux,fdy,z,'Parent',axes1);
    xlabel ('Delay - seconds');
    ylabel ('Frequency offset from center frequency - Cycles/sample');
    zlabel ('Ambiguity function (Normalized Magnitude-Squared)','Visible','off');
    fname = strcat(name,' (Ambiguity Function z(\tau;F_d))');
    title(fname);
    ax = axis;
    axis([50 200 ax(3) ax(4)])
    cb = colorbar('peer',axes1);
    set(get(cb,'ylabel'),'String','Magnitude-Squared (dB)');
    hold off;
    fnum = fnum + 1;
    return
end
Dylan
  • 63
  • 1
  • 4
  • 9

1 Answers1

1

There are a few methods of compressing/expanding the dynamic range, and thresholding from below is just one. You could threshold from above, or you could do a 'softer' compression of the dynamic range, by using a smoother function.

The gradual increase you expect to see depends on the distribution of values of Zn, and without an example of data and the code you use, it's hard to find the cause or problem in code (if it is a bug at all).

Anyway if your aim is to display the data (as opposed to any further analysis you might want to do), I suggest you compress the dynamic range of the colormap, and not of the data itself. The fastest way to do it is to right-click the colorbar and choosing 'Interactive Colormap Shift', which enables you to use the mouse directly on the colrbar in order to change the dynamic range.

If you want to do it programatically, create a few custom colormaps according to the distribution of your values. For example (I am using only red values, for the sake of simplicity)

data = 10 .^ randn(100,100);                      % large dynamic range data
ncols = 128;                                      % number of colors in the colormap
R1 = [linspace(0,1, 10)'; ones(ncols - 10, 1); ]; % colormap for the small values
R2 = [zeros(ncols - 10, 1); linspace(0,1,10)'];   % colormap for the large values
G = zeros(ncols, 1);
B = zeros(ncols, 1);
cmap1 = [R1, G, B];
cmap2 = [R2, G, B];

figure
subplot(1,2,1)
rgbplot(cmap1) % plot the colormap values
subplot(1,2,2)
imagesc (data) % plot the data
colormap(cmap1)
colorbar

figure
subplot(1,2,1)
rgbplot(cmap2)
subplot(1,2,2)
imagesc (data)
colormap(cmap2)
colorbar
Itamar Katz
  • 9,544
  • 5
  • 42
  • 74
  • Sample code was added to the question. I tried out what you have posted here and it seems to work how I would expect it to, but I would like to have the ranges at exactly 0dB,10dB,etc ranges instead of arbitrary. – Dylan Nov 01 '11 at 08:56
  • Since the colormap is a linear map (values->map index), you have to find the index to the limiting value in your sorted Zn values, and use it to find the index in the colormap from which to start the linear change. For example, for 10dB, Zlim=0.1, so if you have 100 data values, the 50th value (in sorted data) is 0.1, and 128 colors, then 50 / 100 * 128 = 64, so the index to start the nonzero values of the colormap is 64. – Itamar Katz Nov 01 '11 at 09:02
  • I am having trouble going from what you are saying here to code. I have a 128x256 matrix of values. To get the number of values below 0.1 I use: totsz = prod(size(Zn)); Zlim = 0.01; threshsz = size(Zn(Zn – Dylan Nov 01 '11 at 11:17