Hi Aivar,<br><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

The mapping of values to histogram bins counts values that are less than the min in the first bin and values that are greater than the max in the last bin.  <b><i>Is this really desirable behavior?</i></b></blockquote><div>

<b><i><br></i></b>The most flexible way of doing it would be to bin such values to special "under" and "over" bins that are not part of the histogram proper, but whose counts can be requested via the histogram API. In this way, downstream code can decide how to consume it. Sound good?</div>

<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">I haven't actually worked with any histograms of integral valued images but I thought they should work the same way as floating point, that is you could count a range of values in a single histogram bin.  </span><i style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><b>Is there any reason bins and values should always be 1:1 for integral valued images?</b></i></blockquote>

<div><br></div><div>Good point. We should *not* assume 1:1. Using the histogram code to resample the lifetime bins would be valuable, I think. This would always be limited to a "nearest neighbor" style resampling of course, which I think is for the best.</div>

<div><br></div><div>That said, we need to make sure such flexibility does not complexify the common 1:1 case. The API should provide shortcuts for that.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<br><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)">If we specify min/max as centers some values slightly below minimum and slightly above maximum will map to the first and last histogram bins respectively.  </span><i style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:rgb(255,255,255)"><b>Do we need to specify min/max as bin center values?</b></i></blockquote>

<div><br></div><div>From a mathematical standpoint, the two are totally interchangeable—it is just a pain to convert between them. So the question comes down to which is more intuitive. Personally I agree with you and find the "min as absolute min" / "max as absolute max" more intuitive, rather than them being bin centers. So let's go with that unless someone else has an objection. (At worst, if there is disagreement, we can always add multiple API signatures and/or a state flag to toggle the behavior.)</div>

<div><br></div><div>Regards,</div><div>Curtis</div><div><br><br><div class="gmail_quote">On Fri, Aug 10, 2012 at 6:13 PM, Aivar Grislis <span dir="ltr"><<a href="mailto:grislis@wisc.edu" target="_blank">grislis@wisc.edu</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <div><div class="im">>The mapping of values to histogram
      bins counts values that are less than the min in the first bin and
      values that are greater than the max in the last bin.  <b><i>Is
          this really desirable behavior?</i> </b> In my usage of
      histograms I specifically don't want to count under- and
      over-range values.  Similarly when using a LUT I like under- and
      over-range values to appear black.  Of course if we need it work
      both ways we can provide a switch.<br>
      <br></div>
      I totally forgot, actually thats how IJ1 works: it does assign
      under-range values to the first color and over-range values to the
      last color.<br>
      <br>
      For my purposes, I had to kludge up the first and last colors of
      the LUT to be black and fiddle with the min/max values to make it
      all work.<div><div class="h5"><br>
      <br>
      On 8/10/12 5:11 PM, Aivar Grislis wrote:<br>
    </div></div></div>
    <blockquote type="cite"><div><div class="h5">
      
      <div>Here is a discussion of changes I
        propose for dealing with histograms in IJ2.  Sorry it's so
        length, let me know if something is unclear and please comment
        if you have an interest in histograms; I do have some specific
        questions for the group (<b><i>in bold italics</i></b>):<br>
        <br>
        <br>
        1)  First of all I would create some helper methods like the
        following (could just be static methods somewhere)...<br>
        <br>
        // maps a value to a bin index, given the range min...max and
        the number of bins<br>
        int valueToBin(int bins, double min, double max, double value);<br>
        <br>
        // returns array of edge values<br>
        double[] getEdgeValues(int bins, double min, double max);<br>
        <br>
        // returns array of center values<br>
        double[] getCenterValues(int bins, double min, double max);<br>
        <br>
        ...and equivalent set for integer values.<br>
        <br>
        Note that these methods would be used for both computing
        histograms and assigning colors from a LUT.  It's nice to use
        exactly the same code for both.  You can characterize a
        histogram bin or LUT color by the starting or edge value or by
        the center value, I've seen it both ways so I included both
        flavors.<br>
        <br>
        Having these common methods would also avoid bugs:<br>
        <br>
        i) One bug I saw in several places is to compute (value - min) /
        (max - min) and get a value from 0.0 to 1.0, but multiply that
        by 255.  The problem with that is the only way you get bin 255
        is if value == min.  Ideally each bin should represent a range
        of values; if the data set is uniformly distributed the size of
        the range of values per bin would be about the same.<br>
        <br>
        ii) Another bug was to compute width = max - min + 1.  That's
        certainly the way you do it for integer arithmetic but it
        doesn't work in floating point!<br>
        <br>
        I'd rather fix these bugs by refactoring to call the common
        helper methods.<br>
        <br>
        <br>
        2)  Regarding the "ImageStatistics" class idea that Curtis
        mentioned:<br>
        <br>
        For example it might include methods:<br>
        <br>
        // request certain things ahead of time<br>
        doMinMax();<br>
        doHistogram(int bins);<br>
        doHistogram(int bins, double min, double max);<br>
        doMean();<br>
        <br>
        // do minimal number of passes through the image<br>
        process();<br>
        <br>
        // get accumulated results<br>
        double[] getMinMax();<br>
        long[] getHistogram();<br>
        double getMean;<br>
        <br>
        Here if you don't specify a min/max for doHistogram the code has
        to take an initial pass to get min/max then another to build the
        histogram using that min/max.<br>
        <br>
        <br>
        3) Discussion of  net.imglib2.script.analysis.Histogram:<br>
        <br>
        Both of these ImgLib2 histogram methods combine a single pass
        through the image with generating histogram statistics.<br>
        <br>
        This code exhibits bug (i).<br>
        <br>
        I'm not sure that this handles integral values as well as
        floating point.<br>
        <br>
        The mapping of values to histogram bins counts values that are
        less than the min in the first bin and values that are greater
        than the max in the last bin.  <b><i>Is this really desirable
            behavior?</i> </b> In my usage of histograms I specifically
        don't want to count under- and over-range values.  Similarly
        when using a LUT I like under- and over-range values to appear
        black.  Of course if we need it work both ways we can provide a
        switch.<br>
        <br>
        The output of this code is actually a JFreeChart image, there's
        no way to get the raw histogram count array.<br>
        <br>
        FYI, uses TreeMap<Double, Long> as an internal
        representation of the histogram count array.  Note that this
        combines what I am calling the edge values with the histogram
        counts.<br>
        <br>
        <br>
        4) Discussion of net.imglib2.algorithm.stats.Histogram:<br>
        <br>
        This has a HistogramBinMapper base class with RealBinMapper and
        IntBinMapper so it's meant to handle real and integral values. 
        The mapper is passed in as a parameter; I think it could be
        inferred from the cursor type T.<br>
        <br>
        Here the RealBinMapper class exhibits bug (ii) when calculating
        binWidth in the constructor.<br>
        <br>
        IntBinMapper doesn't let you specify a bin count, but assumes
        numBins = max - min + 1.  In other words, each bin will track a
        given integer value.  I haven't actually worked with any
        histograms of integral valued images but I thought they should
        work the same way as floating point, that is you could count a
        range of values in a single histogram bin.  <i><b>Is there any
            reason bins and values should always be 1:1 for integral
            valued images?</b></i>  This is so in IJ1 for 8-bit and RGB
        images.<br>
        <br>
        You pass in the minimum and maximum values when you create a
        HistogramBinMapper, but these are described as bin center
        values.  My concept of the minimum and maximum values has been
        the minimum is the lowest value that maps to the first histogram
        bin and the maximum is the highest value that maps to the last
        histogram bin.  If we specify min/max as centers some values
        slightly below minimum and slightly above maximum will map to
        the first and last histogram bins respectively.  <i><b>Do we
            need to specify min/max as bin center values?</b></i><br>
        <br>
        <br>
        Thanks!<br>
        Aivar<br>
        <br>
        <br>
        On 8/10/12 2:44 PM, Curtis Rueden wrote:<br>
      </div>
      <blockquote type="cite">Hi all,
        <div><br>
        </div>
        <div>Aivar & I also discussed histograms, and our plan for
          those is a bit more nebulous. Aivar is going to investigate
          improving Larry's histogram API in
          net.imglib2.algorithms.stats.</div>
        <div> <br>
        </div>
        <div>The general idea is that computing min/max, computing
          histograms, and computing other statistics are intrinsically
          related, and for performance reasons it is nice to minimize
          the number of passes through the image when computing these.
          So we would like to create a unified ImageStatistics class
          (sound familiar? ;-) that can compute one or more of these in
          an intelligent way, then return the results on demand.</div>
        <div><br>
        </div>
        <div>None of this is reconciled with the
          net.imglib2.script.analysis package (Histogram, ImgMax,
          ImgMean, etc.), but perhaps in the future the
          net.imglib2.script stuff can take more direct advantage of it.</div>
        <div><br>
        </div>
        <div>Regards,</div>
        <div>Curtis</div>
        <div><br>
          <br>
          <div class="gmail_quote">On Tue, Aug 7, 2012 at 4:45 PM, Aivar
            Grislis <span dir="ltr"><<a href="mailto:grislis@wisc.edu" target="_blank">grislis@wisc.edu</a>></span>
            wrote:<br>
            <blockquote class="gmail_quote">I'd also be interested in
              working on the histogram code.  Mostly the code that
              generates histogram data, also their display, perhaps the
              histogram tool itself.<br>
              <br>
              SLIM Plugin uses histograms in a very dynamic way, as they
              are updated periodically during the fit process.  You can
              change the minimum and maximum values interactively.  So I
              might be an interested consumer of any common histogram
              code.<br>
              <br>
              (I looked at the histogram code in the AutoContrast
              plugin, net.imglib2.algorithm.stats.Histogram, and
              net.imglib2.script.analysis.Histogram and found bugs in
              all of them when binning up the histogram values.)<span><br>
                <br>
                Aivar<br>
                <br>
              </span></blockquote>
          </div>
          <br>
        </div>
      </blockquote>
      <br>
      <br>
      <fieldset></fieldset>
      <br>
      </div></div><pre>_______________________________________________
ImageJ-devel mailing list
<a href="mailto:ImageJ-devel@imagej.net" target="_blank">ImageJ-devel@imagej.net</a>
<a href="http://imagej.net/mailman/listinfo/imagej-devel" target="_blank">http://imagej.net/mailman/listinfo/imagej-devel</a>
</pre>
    </blockquote>
    <br>
  </div>

<br>_______________________________________________<br>
ImageJ-devel mailing list<br>
<a href="mailto:ImageJ-devel@imagej.net">ImageJ-devel@imagej.net</a><br>
<a href="http://imagej.net/mailman/listinfo/imagej-devel" target="_blank">http://imagej.net/mailman/listinfo/imagej-devel</a><br>
<br></blockquote></div><br></div>