############################################################################ # # File: flohisto.icn # # Subject: Program to display float histograms # # Author: Ralph E. Griswold # # Date: June 28, 2002 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program analyzes the floats in BLPs for drawdowns. # # The names of BLPs are given on the command line. The output images # are named _float.gif # ############################################################################ # # Requires: Version 9 graphics # ############################################################################ # # Links: link basename, numbers, options, wopen # ############################################################################ link basename link wopen link numbers link pattread $define FloatMax 15 $define Width 300 $define Gutter 20 $define Height 250 $define Delta 9 $define Gap 4 $define Xoff 20 $define Yoff 30 procedure main(args) local front, back, black, white, name, i, canvas local warp_front, warp_back, weft_front, weft_back, win, input every name := !args do { input := open(name) | stop("Cannot open ", name) front := pattread(input) close(input) back := copy(front) # 0 = black, 1 = white. every i := 1 to *back do back[i] := map(back[i], "10", "01") weft_front := analyze(front, "1") front := rot(front) warp_front := analyze(front, "0") weft_back := analyze(back, "1") back := rot(back) warp_back := analyze(back, "0") win := WOpen("size=" || (2 * Width + 2 * Gutter) || "," || (2 * Height + 2 * Gutter), "canvas=hidden") | stop("*** cannot open main window") CopyArea(plot(warp_front, "warp front"), win, , , , , 0, 0) CopyArea(plot(weft_front, "weft front"), win, , , , , Width + Gutter, 0) CopyArea(plot(warp_back, "warp back"), win, , , , , 0, Height + Gutter) CopyArea(plot(weft_back, "weft back"), win, , , , , Width + Gutter, Height + Gutter) WriteImage(win, basename(name, ".blp") || "_floats.gif") WClose(win) } end procedure analyze(rows, color) local counts, length, row, k, count_list counts := table(0) every row := !rows do { row ? { while tab(upto(color)) do { length := *tab(many(color)) if length > 1 then counts[length] +:= 1 } } } if *counts = 0 then fail # no floats count_list := list(FloatMax, 0) # list of counts every k := key(counts) do if k > FloatMax then count_list[FloatMax] +:= counts[k] else count_list[k - 1] := counts[k] return count_list end procedure plot(data, legend) local i, j, scale, maximum, y, width, win win := WOpen("size=" || Width || "," || Height, "font=times,10", "canvas=hidden") | stop("*** cannot open plotting window") WAttrib(win, "dx=" || Xoff) WAttrib(win, "dy=" || (Yoff + Gap)) DrawLine(win, 0, 0 - Gap, Width, 0 - Gap) DrawLine(win, 0, 0 - Gap, 0, Height - Gap) DrawString(win, -2, -(18 + Gap), legend) if /data then return win maximum := max ! data maximum := integer((maximum + 99.0) / 100) * 100 # get to next hundred width := real(Width - 2 * Xoff) scale := width / maximum every i := 0 to 4 do CenterString(win, (width / 4) * i, 18 - Yoff, (maximum / 4) * i) every j := 2 to FloatMax + 1 do { y := (j - 2) * (Delta + Gap) FillRectangle(win, 0, y, data[j - 1] * scale, Delta) if j > FloatMax then j := ">" RightString(win, 15 - Xoff, y + Gap, j) } return win end procedure win2rows(win) local width, height, row, rows, pixel, y width := WAttrib(win, "width") height := WAttrib(win, "height") rows := [] every y := 0 to height - 1 do { row := "" every pixel := Pixel(win, 0, y, width, 1) do row ||:= if pixel == "0,0,0" then "0" else "1" put(rows, row) } return rows end procedure rot(rows) local cols, row, grid, i cols := list(*rows[1], "") every row := !rows do { i := 0 every grid := !row do cols[i +:= 1] := grid || cols[i] } return cols end