# shell archive created by dwjones on Tue 04 May 2021 04:23:56 PM CDT # To install this software on a UNIX compatable system (Linux or MacOS): # 1) create a directory (e.g. with the shell command mkdir project) # 2) change to that directory (e.g. with the command cd project), # 3) direct the remainder of this text to sh (e.g. sh < ../thisfile). # This will make sh create files in the new directory; it will do # nothing else (if you're paranoid, you should scan the following text # to verify this before you follow these directions). Then read README # in the new directory for additional instructions. # On other systems, extract files from this file using a text editor. # Each file is bracketed between two lines of xxxx. # The first line of xxxx contains a cat command giving the file name. cat > README <<\xxxxxxxxxx LOG NORMAL DISTRIBUTION PLOTTING TOOL ===================================== Author: Douglas W. Jones Version: May 4, 2021 This little program and makefile serves only one purpose, to help people experiment with what log-normal distributions look like by plotting the distribution. Files ----- This directory contains the following source files for the epidemic simulator: * README this file * LogNormal.java the main program, outputs a CSV file of the histogram * Makefile instructions for building and running the code * PlotScript instructions for Gnuplot to graph the output System Requirements ------------------- This code assumes you have the following: * A Java compiler and run-time system, version SE7 or higher * GNUplot, a widely available open-source plotting utility * Some command-line interface With the above, you can compile the program and direct its output into Gnuplot by hand. You may need to edit PlotScript to make it output the plot to a file you can display. If you have the following, you can automate building and running the code: * A window manager GNUplot can automatically find to display the plot. * A UNIX shell such as sh or bash. On Windows systems, wsl or Git Bash. * Some version of make, the most widely available version is GNU make. Windows users may need to do some tinkering with file name extensions. Instructions ------------ To compile the Java code, use this shell command make To clean up files that were created by make make clean To plot a log-normal distribution make plot # for one particular demo distribution make demo median=10 scatter=4 # for any median and scatter License ------- This code is hardly worth licensing, but just to make things clear, code in this distribution is released to the world under GPLv3, the GNU General Public License version 3, documented at -- http://www.gnu.org/licenses/gpl-3.0.html Warranty -------- You get what you pay for. This is free software, it seems to work, but the author does not accept responsibility for the consequences of relying on this code to do anything of consequence. The author may be contacted by e-mail at: -- douglas-w-jones@uiowa.edu xxxxxxxxxx cat > LogNormal.java <<\xxxxxxxxxx /* LogNormal.java * Demonstration of how to generate a log-normal probability distribution. * The histogram is binned so that (0.0-1.0] go in bin 1, (1.0-2.0] in bin 2. * This reads the median, scatter, bins and trials as command line * arguments. Examples: * java LogNormal 10 3 # plot with median 10.0, scatter 3.0 * java LogNormal 10 3 20 # plot as above, with 20 bins * java LogNormal 10 3 20 500 # plot as above, with 500 trials * * The default number of bins is median plus 3 times the scatter; * The default number of trials is 10 times the number of bins * * Author Douglas W. Jones * Version May 4, 2021 */ import java.util.Random; import java.lang.Math; import java.lang.NumberFormatException; class LogNormal { public static void main( String arg[] ) { Random rand = new Random(); // a source of random numbers double median = 0.0; // the median of the log normal distr double scatter = 0.0; // the scatter of the distribution int bins = 0; // histogram from 0 to bins int trials = 0; // how many trials // get median and scatter from the command line if (arg.length < 2) { System.err.println( "2 arguments required -- median and scatter" ); System.exit( 1 ); } else try { median = Double.parseDouble( arg[0] ); if (median <= 0.0) { // legitimacy check System.err.println( "Java LogNormal " + arg[0] + " " + arg[1] + ": Median must be positive" ); System.exit( 1 ); } scatter = Double.parseDouble( arg[1] ); if (scatter < 0.0) { // legitimacy check System.err.println( "Java LogNormal " + arg[0] + " " + arg[1] + ": Scatter must be non negative" ); System.exit( 1 ); } } catch (NumberFormatException e) { System.err.println( "java LogNormal " + arg[0] + " " + arg[1] + ": Non numeric command line argument" ); System.exit( 1 ); } if (arg.length < 3) { // default bins = (int)Math.round( median + 3*scatter ) + 1; } else try { bins = Integer.parseInt( arg[2] ); if (bins <= Math.round( median )) { // check legitimacy System.err.println( "Java LogNormal " + arg[0] + " " + arg[1] + " " + arg[2] + ": bins must exceed the median" ); System.exit( 1 ); } } catch (NumberFormatException e) { System.err.println( "java LogNormal " + arg[0] + " " + arg[1] + " " + arg[2] + ": Non numeric command line argument" ); System.exit( 1 ); } if (arg.length < 4) { // default trials = 10 * bins; } else try { trials = Integer.parseInt( arg[3] ); if (trials <= 0) { System.err.println( "Java LogNormal " + arg[0] + " " + arg[1] + " " + arg[2] + " " + arg[3] + ": must do at least one trial" ); System.exit( 1 ); } } catch (NumberFormatException e) { System.err.println( "java LogNormal " + arg[0] + " " + arg[1] + " " + arg[2] + " " + arg[3] + ": Non numeric command line argument" ); System.exit( 1 ); } // all command line arguments now known and values are sensible // the histogram accumulator int [] histogram = new int[bins + 1]; // sigma is the standard deviation of the underlying normal distribution // this needs to be computed just once no matter how // many numbers are drawn from the distribution. double sigma = Math.log( (scatter + median) / median ); // do the experiment to generate the histogram for (int i = 0; i < trials; i++) { // draw a random number from a log normal distribution double lognormal = Math.exp( sigma * rand.nextGaussian() ) * median; // find what bin of the histogram it goes in and increment that bin int bin = (int)Math.ceil( lognormal ); if (bin <= 0) bin = 0; if (bin > bins) bin = bins; histogram[bin]++; } // print the histogram (minus the overflow bin) for (int i = 0; i < bins; i++) { System.out.printf( "%d,%d\n", i, histogram[i] ); } } } xxxxxxxxxx cat > Makefile <<\xxxxxxxxxx # Makefile - Tool for experimenting with log-normal distribution # Author: Douglas W. Jones # Date: May 4, 2021 # make -- same as make LogNormal.class # make LogNormal.class -- compile LogNormal.java # make plot -- same as make plot median=12 scatter=4 # make plot median=a scatter=b # make clean -- clean up created files # make shar -- make shell archive median = 12 scatter = 4 LogNormal.class: LogNormal.java javac LogNormal.java plot: LogNormal.class java LogNormal $(median) $(scatter)\ | gnuplot -p -e "TITLE='Median=$(median) Scatter=$(scatter)'" PlotScript clean: rm -f *.class shar: README LogNormal.java Makefile PlotScript shar README LogNormal.java Makefile PlotScript > shar xxxxxxxxxx cat > PlotScript <<\xxxxxxxxxx # PlotScript -- tell gnuplot to plot histogram of csv data from a pipe # Author: Douglas W. Jones # Version: May. 4, 2021 # Use: from the shell, # dataSource | gnuplot -p PlotScript # dataSource | gnuplot -p -e "TITLE='text'" PlotScript # how to read a CSV file set datafile separator ',' # Commas separate values # how to make a histogram nice looking set boxwidth 0.5 relative set style fill solid set xrange [0:*] set nokey if (exists("TITLE")) set title TITLE # plot the data plot '< cat -' using 1:2 with boxes # alternative plot commands # if the histogram gets muddy from too many data points, just do a line graph # plot '< cat -' using 1:2 with lines # if you need to plot from some file instead of plotting from stdin # plot 'filename.csv' using 1:2 with lines xxxxxxxxxx