> The code doesn't work for me. In fact, there are two cases where fwhm is set 
> to 0. With the previou code, I had the right fwhm. That's why I don't like a 
> very complex code, because it has strange behavious for ome cases.

I have tried many testing data and found no fail. If you think you have 
found data the routine does not work on, please show them.

BTW, your function fails for parabola-like functions, e.g.
        x=-20:1:20;
        y = x.*x;
        fwhm(x,y)
My code tests for this (maybe that's why you find it complicated)?

> here is the function I use. On it, I corrected the way to calculate
> fwhm, and with cos, it works now, try this line

I think we should stay with the original definition of FWHM, i.e. values 
taken at fmax*0.5, not at 0.5*(fmax+fmin). The "background" can be 
subtracted outside. Or even better, an option can be added. So you should 
use
  renorm = 0.5 * fmax;
instead of
  renorm = 0.5 * (fmax-fmin) + fmin;
and fix documentation in the header.

BTW: it is easily
 renorm = 0.5 * (fmax+fmin);

> I think matricial input are not needed. I really think that the most 
> important is to provide a simple function that return the fwhm of a 
> function and that's all. No need to return the fwhm in 5 dimensional space 
> with relativity corrections.

Well, the routine works on data, not on functions. Consider an experiment 
with measured 100 data sets put columnwise into a matrix y. Then max(y), 
min(y), mean(y), std(y), etc. give statistics for each data set at one call.
Therefore fwhm(y) should behave the same.

I'm enclosing an update for my previous routine fwhm.m that does work on 
matrix data, works on both potential definitions of fwhm, and passes all of 
the accompanying tests. I consider this being general and powerful enough 
for being enclosed into an octave's package.

---
PM
%% Compute full-width at half maximum (FWHM) for vector or matrix data y,
%% optionally sampled as y(x). If y is a matrix, return fwhm for each column
%% as a row vector.
%%      f = fwhm(y)
%%      f = fwhm(x, y)
%%      f = fwhm(x, y, 'zero')
%%      f = fwhm(x, y, 'min')
%%
%% The default option 'zero' computes fwhm at half maximum, i.e. 0.5*max(y). 
%% The option 'min' computes fwhm at the middle curve, i.e. 0.5*(min(y)+max(y)).
%%
%% Return 0 if FWHM does not exist (e.g. monotonous function or the function
%% does not cut horizontal line at 0.5*max(y) or 0.5(max(y)+min(y)),
%% respectively).
%%
%% Compatibility: Octave 3.x, Matlab
%% Author: Petr Mikulik
%% Version: 15. 7. 2009
%% This program is public domain.


function myfwhm = fwhm (x, y, opt)

    if nargin < 1 || nargin > 3
        error('1, 2 or 3 input arguments required');
    end
    if nargin==1
        y = x;
        x = 1:length(y);
        opt = 'zero';
    elseif nargin==2
        opt = 'zero';
    end

    if ~isstr(opt)
        error('opt must be "zero" or "min"');
    end
    if ~(strcmp(opt, 'zero') || strcmp(opt, 'min'))
        error('opt must be "zero" or "min"');
    end

    [nr, nc] = size(y);
    if (nr == 1 && nc > 1)
        y = y'; nr = nc; nc = 1;
    end

    if length(x) ~= nr
        error('dimension of input arguments do not match');
    end

    % Shift matrix columns so that y(+-xfwhm) = 0:
    if strcmp(opt, 'zero')
        % case: full-width at half maximum
        y = y - 0.5 * repmat(max(y), nr, 1);
    else
        % case: full-width above background
        y = y - 0.5 * repmat((max(y) + min(y)), nr, 1);
    end

    if 0 % Trying to do it via a "vectorizing" approach failed:
        myfwhm = zeros(1,nc); % default: 0 for fwhm undefined
        ind = find (y(1:end-1, :) .* y(2:end, :) <= 0);
        [r1,c1] = ind2sub(size(y), ind);
        % ... how to take min and max value in each column?
        % => need to do it column-by-column
    else % Analyze the matrix column by column
        myfwhm = zeros(1,nc); % default: 0 for fwhm undefined
        for n=1:nc
            yy = y(:, n);
            ind = find((yy(1:end-1) .* yy(2:end)) <= 0);
            if length(ind) >= 2 && yy(ind(1)) > 0 % must start ascending
                ind = ind(2:end);
            end
            [mx, imax] = max(yy); % protection against constant or (almost) 
monotonous functions
            if length(ind) >= 2 && imax > ind(1) && imax < ind(end)
                ind1 = ind(1);
                ind2 = ind1 + 1;
                xx1 = x(ind1) - yy(ind1) * (x(ind2) - x(ind1)) / (yy(ind2) - 
yy(ind1));
                ind1 = ind(end);
                ind2 = ind1 + 1;
                xx2 = x(ind1) - yy(ind1) * (x(ind2) - x(ind1)) / (yy(ind2) - 
yy(ind1));
                myfwhm(n) = xx2 - xx1;
            end
        end
    end

%!test
%! x=-pi:0.001:pi; y=cos(x);
%! assert( abs(fwhm(x, y) - 2*pi/3) < 0.01 );
%!
%!test
%! assert( fwhm(-10:10) == 0 );
%!
%!test
%! assert( fwhm(ones(1,50)) == 0 );
%!
%!test
%! x=-20:1:20;
%! y1=-4+zeros(size(x)); y1(4:10)=8;
%! y2=-2+zeros(size(x)); y2(4:11)=2;
%! y3= 2+zeros(size(x)); y3(5:13)=10;
%! assert( max(abs(fwhm(x, [y1;y2;y3]') - [20.0/3,7.5,9.25])) < 0.01 );
%!
%!test
%! x=-10:10; assert( fwhm(x.*x) == 0 );
%!
%!test
%! x=-5:5; assert( abs( fwhm(x, 18-x.*x, 'zero') - 6.0 ) < 0.01);
%!
%!test
%! x=-5:5; assert( abs( fwhm(x, 18-x.*x, 'min') - 7.0 ) < 0.01);
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to