X-Git-Url: https://zdv2.bktei.com/gitweb/BK-2020-03.git/blobdiff_plain/b914c4010b87ea0f988556d3f9bd982ba28a43d4..6d44d2ad506f4107fd410ef4be6f93b8c5a9dfbb:/unitproc/python/sleepRand.py?ds=inline diff --git a/unitproc/python/sleepRand.py b/unitproc/python/sleepRand.py index 27e98d7..016e9f3 100755 --- a/unitproc/python/sleepRand.py +++ b/unitproc/python/sleepRand.py @@ -1,21 +1,66 @@ #!/usr/bin/env python3 # Desc: Pauses a random amount of time. Random distribution is inverse gaussian. -# Version: 0.0.2 +# Version: 0.0.6 # Depends: python 3.7.3 -# Usage: ./sleepRand.py arg1 -# Input: arg1: float seconds (mean of inverse gaussian distribution) -# Example: python3 sleepRand.py 4.0 +# Usage: ./sleepRand.py [-v] [-p P] SECONDS +# Input: SECONDS: float seconds (mean of inverse gaussian distribution) +# P: precision (lambda of inverse gaussian distribution) +# Example: python3 sleepRand.py -vv -p 8.0 60.0 -import math, time, random, sys +import argparse; +import math, time, random, sys; +import logging; + +# Set up argument parser (see https://docs.python.org/3.7/library/argparse.html ) +parser = argparse.ArgumentParser( + description='Delay activity for a random number of seconds. Delays sampled from an inverse gaussian distribution.', + epilog="Author: Steven Baltakatei Sandoval. License: GPLv3+"); +parser.add_argument('-v','--verbose', + action='count', + dest='verbosity', + default=0, + help='Verbose output. (repeat for increased verbosity)'); +parser.add_argument('mean', + action='store', + metavar='SECONDS', + nargs=1, + default=1, + type=float, + help='Mean seconds of delay. Is the mean of the inverse gaussian distribution.'); +parser.add_argument('--precision','-p', + action='store', + metavar='P', + nargs=1, + default=[4.0], + type=float, + help='How concentrated delays are around the mean (default: 4.0). Must be a positive integer or floating point value. Is the lambda factor in the inverse gaussian distribution. High values (e.g. > 10.0) cause random delays to rarely stray far from MEAN. Small values (e.g. < 0.10) result in many small delays plus occasional long delays.'); +parser.add_argument('--upper','-u', + action='store', + metavar='U', + nargs=1, + default=[None], + type=float, + help='Upper bound for possible delays (default: no bound). Without bound, extremely high delays are unlikely but possible.'); +args = parser.parse_args(); # Define functions +def setup_logging(verbosity): + '''Sets up logging''' + # Depends: module: argparse + # Ref/Attrib: Haas, Florian; Configure logging with argparse; https://xahteiwi.eu/resources/hints-and-kinks/python-cli-logging-options/ + base_loglevel = 30; + verbosity = min(verbosity, 2); + loglevel = base_loglevel - (verbosity * 10); + logging.basicConfig(level=loglevel, + format='%(message)s'); + def randInvGau(mu, lam): """Returns random variate of inverse gaussian distribution""" # input: mu: mean of inverse gaussian distribution # lam: shape parameter # output: float sampled from inv. gaus. with range 0 to infinity, mean mu # example: sample = float(randInvGau(1.0,4.0)); - # Ref/Attrib: doi:10.1080/00031305.1976.10479147 + # Ref/Attrib: Michael, John R. "Generating Random Variates Using Transformations with Multiple Roots" https://doi.org/10.2307/2683801 nu = random.gauss(0,1); y = nu ** 2; xTerm1 = mu; @@ -28,16 +73,52 @@ def randInvGau(mu, lam): else: return (mu ** 2 / x); -# Check input (TODO) -arg1 = float(sys.argv[1]); # first argument -desMean = arg1; +# Process input +## Start up logger +setup_logging(args.verbosity); +logging.debug('DEBUG:Debug logging output enabled.'); +logging.debug('DEBUG:args.verbosity:' + str(args.verbosity)); +logging.debug('DEBUG:args:' + str(args)); -# Configure -lambdaFactor = 4; # spread factor; inversely proportional to variance +## Receive input arguments +try: + ### Get desired mean + desMean = args.mean[0]; + logging.debug('DEBUG:Desired mean:' + str(desMean)); + + ### Get lambda precision factor + lambdaFactor = args.precision[0]; + logging.debug('DEBUG:Lambda precision factor:' + str(lambdaFactor)); + + ### Get upper bound + if isinstance(args.upper[0], float): + logging.debug('DEBUG:args.upper[0] is float:' + str(args.upper[0])); + upperBound = args.upper[0]; + elif args.upper[0] is None: + logging.debug('DEBUG:args.upper[0] is None:' + str(args.upper[0])); + upperBound = None; + else: + raise TypeError('Upper bound not set correctly.'); + logging.debug('DEBUG:Upper bound:' + str(upperBound)); + + ### Reject negative floats. + if desMean < 0: + logging.error('ERROR:Desired mean is negative:' + str(desMean)); + raise ValueError('Negative number error.'); + if lambdaFactor < 0: + logging.error('ERROR:Lambda precision factor is negative:' + str(lambdaFactor)); + raise ValueError('Negative number error.'); +except ValueError: + sys.exit(1); # Calculate delay -delay = randInvGau(desMean, desMean * lambdaFactor); -#print('DEBUG:delay:' + str(float(delay))); +rawDelay = randInvGau(desMean, desMean * lambdaFactor); +logging.debug('DEBUG:rawDelay(seconds):' + str(rawDelay)); +if isinstance(upperBound,float): + delay = min(upperBound, rawDelay); +elif upperBound is None: + delay = rawDelay; +logging.debug('DEBUG:delay(seconds) :' + str(delay)); # Sleep time.sleep(float(delay));