diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /pkg/images/imutil/src/imhistogram.x | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'pkg/images/imutil/src/imhistogram.x')
-rw-r--r-- | pkg/images/imutil/src/imhistogram.x | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/pkg/images/imutil/src/imhistogram.x b/pkg/images/imutil/src/imhistogram.x new file mode 100644 index 00000000..b62233b7 --- /dev/null +++ b/pkg/images/imutil/src/imhistogram.x @@ -0,0 +1,332 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <imhdr.h> +include <gset.h> + +define SZ_CHOICE 18 + +define HIST_TYPES "|normal|cumulative|difference|second_difference|" +define NORMAL 1 +define CUMULATIVE 2 +define DIFFERENCE 3 +define SECOND_DIFF 4 + +define PLOT_TYPES "|line|box|" +define LINE 1 +define BOX 2 + +define SZ_TITLE 512 # plot title buffer + +# IMHISTOGRAM -- Compute and plot the histogram of an image. + +procedure t_imhistogram() + +long v[IM_MAXDIM] +real z1, z2, dz, z1temp, z2temp, zstart +int npix, nbins, nbins1, nlevels, nwide, z1i, z2i, i, maxch, histtype +pointer gp, im, sp, hgm, hgmr, buf, image, device, str, title, op + +real clgetr() +pointer immap(), gopen() +int clgeti(), clgwrd() +int imgnlr(), imgnli() +bool clgetb(), fp_equalr() + +begin + call smark (sp) + call salloc (image, SZ_LINE, TY_CHAR) + call salloc (str, SZ_CHOICE, TY_CHAR) + + # Get the image name. + call clgstr ("image", Memc[image], SZ_LINE) + im = immap (Memc[image], READ_ONLY, 0) + npix = IM_LEN(im,1) + + # Get histogram range. + z1 = clgetr ("z1") + z2 = clgetr ("z2") + + if (IS_INDEFR(z1) || IS_INDEFR(z2)) { + + if (IM_LIMTIME(im) >= IM_MTIME(im)) { + z1temp = IM_MIN(im) + z2temp = IM_MAX(im) + } else + call im_minmax (im, z1temp, z2temp) + + if (IS_INDEFR(z1)) + z1 = z1temp + + if (IS_INDEFR(z2)) + z2 = z2temp + } + + if (z1 > z2) { + dz = z1; z1 = z2; z2 = dz + } + + # Get default histogram resolution. + dz = clgetr ("binwidth") + if (IS_INDEFR(dz)) + nbins = clgeti ("nbins") + else { + nbins = nint ((z2 - z1) / dz) + z2 = z1 + nbins * dz + } + + # Set the limits for integer images. + switch (IM_PIXTYPE(im)) { + case TY_SHORT, TY_USHORT, TY_INT, TY_LONG: + z1i = nint (z1) + z2i = nint (z2) + z1 = real (z1i) + z2 = real (z2i) + } + + # Adjust the resolution of the histogram and/or the data range + # so that an integral number of data values map into each + # histogram bin (to avoid aliasing effects). + + if (clgetb ("autoscale")) + switch (IM_PIXTYPE(im)) { + case TY_SHORT, TY_USHORT, TY_INT, TY_LONG: + nlevels = z2i - z1i + nwide = max (1, nint (real (nlevels) / real (nbins))) + nbins = max (1, nint (real (nlevels) / real (nwide))) + z2i = z1i + nbins * nwide + z2 = real (z2i) + } + + # The extra bin counts the pixels that equal z2 and shifts the + # remaining bins to evenly cover the interval [z1,z2]. + # Real numbers could be handled better - perhaps adjust z2 + # upward by ~ EPSILONR (in ahgm itself). + + nbins1 = nbins + 1 + + # Initialize the histogram buffer and image line vector. + call salloc (hgm, nbins1, TY_INT) + call aclri (Memi[hgm], nbins1) + call amovkl (long(1), v, IM_MAXDIM) + + # Read successive lines of the image and accumulate the histogram. + + switch (IM_PIXTYPE(im)) { + case TY_SHORT, TY_USHORT, TY_INT, TY_LONG: + # Test for constant valued image, which causes zero divide in ahgm. + if (z1i == z2i) { + call eprintf ("Warning: Image `%s' has no data range.\n") + call pargstr (Memc[image]) + call imunmap (im) + call sfree (sp) + return + } + + while (imgnli (im, buf, v) != EOF) + call ahgmi (Memi[buf], npix, Memi[hgm], nbins1, z1i, z2i) + + default: + # Test for constant valued image, which causes zero divide in ahgm. + if (fp_equalr (z1, z2)) { + call eprintf ("Warning: Image `%s' has no data range.\n") + call pargstr (Memc[image]) + call imunmap (im) + call sfree (sp) + return + } + + while (imgnlr (im, buf, v) != EOF) + call ahgmr (Memr[buf], npix, Memi[hgm], nbins1, z1, z2) + } + + # "Correct" the topmost bin for pixels that equal z2. Each + # histogram bin really wants to be half open. + + if (clgetb ("top_closed")) + Memi[hgm+nbins-1] = Memi[hgm+nbins-1] + Memi[hgm+nbins1-1] + + dz = (z2 - z1) / real (nbins) + + histtype = clgwrd ("hist_type", Memc[str], SZ_CHOICE, HIST_TYPES) + + switch (histtype) { + case NORMAL: + # do nothing + case CUMULATIVE: + call ih_acumi (Memi[hgm], Memi[hgm], nbins) + case DIFFERENCE: + call ih_amrgi (Memi[hgm], Memi[hgm], nbins) + z1 = z1 + dz / 2. + z2 = z2 - dz / 2. + nbins = nbins - 1 + case SECOND_DIFF: + call ih_amrgi (Memi[hgm], Memi[hgm], nbins) + call ih_amrgi (Memi[hgm], Memi[hgm], nbins-1) + z1 = z1 + dz + z2 = z2 - dz + nbins = nbins - 2 + default: + call error (1, "bad switch 1") + } + + # List or plot the histogram. In list format, the bin value is the + # z value of the left side (start) of the bin. + + if (clgetb ("listout")) { + zstart = z1 + dz / 2.0 + do i = 1, nbins { + call printf ("%g %d\n") + call pargr (zstart) + call pargi (Memi[hgm+i-1]) + zstart = zstart + dz + } + } else { + call salloc (device, SZ_FNAME, TY_CHAR) + call salloc (title, SZ_TITLE, TY_CHAR) + call salloc (hgmr, nbins, TY_REAL) + call achtir (Memi[hgm], Memr[hgmr], nbins) + + call clgstr ("device", Memc[device], SZ_FNAME) + gp = gopen (Memc[device], NEW_FILE, STDGRAPH) + if (clgetb ("logy")) + call gseti (gp, G_YTRAN, GW_LOG) + call gswind (gp, z1, z2, INDEF, INDEF) + call gascale (gp, Memr[hgmr], nbins, 2) + + # Format the plot title, starting with the system banner. + call sysid (Memc[title], SZ_TITLE) + for (op=title; Memc[op] != '\n' && Memc[op] != EOS; op=op+1) + ; + Memc[op] = '\n'; op = op + 1 + maxch = SZ_TITLE - (op - title) + + # Format the remainder of the plot title. + call sprintf (Memc[op], maxch, + "%s of %s = %s\nFrom z1=%g to z2=%g, nbins=%d, width=%g") + switch (histtype) { + case NORMAL: + call pargstr ("Histogram") + case CUMULATIVE: + call pargstr ("Cumulative histogram") + case DIFFERENCE: + call pargstr ("Difference histogram") + case SECOND_DIFF: + call pargstr ("Second difference histogram") + default: + call error (1, "bad switch 3") + } + + call pargstr (Memc[image]) + call pargstr (IM_TITLE(im)) + call pargr (z1) + call pargr (z2) + call pargi (nbins) + call pargr (dz) + + # Draw the plot. Center the bins for plot_type=line. + call glabax (gp, Memc[title], "", "") + + switch (clgwrd ("plot_type", Memc[str], SZ_LINE, PLOT_TYPES)) { + case LINE: + call gvline (gp, Memr[hgmr], nbins, z1 + dz/2., z2 - dz/2.) + case BOX: + call hgline (gp, Memr[hgmr], nbins, z1, z2) + default: + call error (1, "bad switch 2") + } + + call gclose (gp) + } + + call imunmap (im) + call sfree (sp) +end + + +# HGLINE -- Draw a stepped curve of the histogram data. + +procedure hgline (gp, ydata, npts, x1, x2) + +pointer gp # Graphics descriptor +real ydata[ARB] # Y coordinates of the line endpoints +int npts # Number of line endpoints +real x1, x2 + +int pixel +real x, y, dx + +begin + dx = (x2 - x1) / npts + + # Do the first horizontal line + x = x1 + y = ydata[1] + call gamove (gp, x, y) + x = x + dx + call gadraw (gp, x, y) + + do pixel = 2, npts { + x = x1 + dx * (pixel - 1) + y = ydata[pixel] + # vertical connection + call gadraw (gp, x, y) + # horizontal line + call gadraw (gp, x + dx, y) + } +end + + +# These two routines are intended to be generic vops routines. Only +# the integer versions are included since that's all that's used here. + +# <NOT IMPLEMENTED!> The operation is carried out in such a way that +# the result is the same whether or not the output vector overlaps +# (partially) the input vector. The routines WILL work in place! + +# ACUM -- Compute a cumulative vector (generic). Should b[1] be zero? + +procedure ih_acumi (a, b, npix) + +int a[ARB], b[ARB] +int npix, i + +# int npix, i, a_first, b_first + +begin +# call zlocva (a, a_first) +# call zlocva (b, b_first) +# +# if (b_first <= a_first) { + # Shouldn't use output arguments internally, + # but no reason to use this routine unsafely. + b[1] = a[1] + do i = 2, npix + b[i] = b[i-1] + a[i] +# } else { + # overlapping solution not implemented yet! +# } +end + + +# AMRG -- Compute a marginal (forward difference) vector (generic). + +procedure ih_amrgi (a, b, npix) + +int a[ARB], b[ARB] +int npix, i + +# int npix, i, a_first, b_first + +begin +# call zlocva (a, a_first) +# call zlocva (b, b_first) +# +# if (b_first <= a_first) { + do i = 1, npix-1 + b[i] = a[i+1] - a[i] + b[npix] = 0 +# } else { + # overlapping solution not implemented yet! +# } +end |