aboutsummaryrefslogtreecommitdiffstats
path: root/golemflavor/misc.py
diff options
context:
space:
mode:
Diffstat (limited to 'golemflavor/misc.py')
-rw-r--r--golemflavor/misc.py226
1 files changed, 226 insertions, 0 deletions
diff --git a/golemflavor/misc.py b/golemflavor/misc.py
new file mode 100644
index 0000000..4974775
--- /dev/null
+++ b/golemflavor/misc.py
@@ -0,0 +1,226 @@
+# author : S. Mandalia
+# s.p.mandalia@qmul.ac.uk
+#
+# date : March 17, 2018
+
+"""
+Misc functions for the BSM flavour ratio analysis
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import os
+import errno
+import multiprocessing
+from fractions import gcd
+
+import argparse
+from operator import attrgetter
+
+import numpy as np
+
+from golemflavor.enums import str_enum
+from golemflavor.enums import DataType, Likelihood, Texture
+
+
+class SortingHelpFormatter(argparse.HelpFormatter):
+ """Sort argparse help options alphabetically."""
+ def add_arguments(self, actions):
+ actions = sorted(actions, key=attrgetter('option_strings'))
+ super(SortingHelpFormatter, self).add_arguments(actions)
+
+
+def solve_ratio(fr):
+ denominator = reduce(gcd, fr)
+ f = [int(x/denominator) for x in fr]
+ allow = (1, 2, 0)
+ if f[0] not in allow or f[1] not in allow or f[2] not in allow:
+ return '{0:.2f}_{1:.2f}_{2:.2f}'.format(fr[0], fr[1], fr[2])
+ else:
+ return '{0}_{1}_{2}'.format(f[0], f[1], f[2])
+
+
+def gen_identifier(args):
+ f = '_DIM{0}'.format(args.dimension)
+ f += '_sfr_' + solve_ratio(args.source_ratio)
+ if args.data in [DataType.ASIMOV, DataType.REALISATION]:
+ f += '_mfr_' + solve_ratio(args.injected_ratio)
+ if args.texture is not Texture.NONE:
+ f += '_{0}'.format(str_enum(args.texture))
+ return f
+
+
+def gen_outfile_name(args):
+ """Generate a name for the output file based on the input args.
+
+ Parameters
+ ----------
+ args : argparse
+ argparse object to print
+
+ """
+ return args.outfile + gen_identifier(args)
+
+
+def parse_bool(s):
+ """Parse a string to a boolean.
+
+ Parameters
+ ----------
+ s : str
+ String to parse
+
+ Returns
+ ----------
+ bool
+
+ Examples
+ ----------
+ >>> from misc import parse_bool
+ >>> print parse_bool('true')
+ True
+
+ """
+ if s.lower() == 'true':
+ return True
+ elif s.lower() == 'false':
+ return False
+ else:
+ raise ValueError
+
+
+def parse_enum(e):
+ return '{0}'.format(e).split('.')[1].lower()
+
+
+def print_args(args):
+ """Print the input arguments.
+
+ Parameters
+ ----------
+ args : argparse
+ argparse object to print
+
+ """
+ arg_vars = vars(args)
+ for key in sorted(arg_vars):
+ print('== {0:<25} = {1}'.format(key, arg_vars[key]))
+
+
+def enum_parse(s, c):
+ return c[s.upper()]
+
+
+def make_dir(outfile):
+ try:
+ os.makedirs(outfile[:-len(os.path.basename(outfile))])
+ except OSError as exc: # Python >2.5
+ if exc.errno == errno.EEXIST and os.path.isdir(outfile[:-len(os.path.basename(outfile))]):
+ pass
+ else:
+ raise
+
+
+def remove_option(parser, arg):
+ for action in parser._actions:
+ if (vars(action)['option_strings']
+ and vars(action)['option_strings'][0] == arg) \
+ or vars(action)['dest'] == arg:
+ parser._remove_action(action)
+
+ for action in parser._action_groups:
+ vars_action = vars(action)
+ var_group_actions = vars_action['_group_actions']
+ for x in var_group_actions:
+ if x.dest == arg:
+ var_group_actions.remove(x)
+ return
+
+
+def seed_parse(s):
+ if s.lower() == 'none':
+ return None
+ else:
+ return int(s)
+
+
+def thread_type(t):
+ if t.lower() == 'max':
+ return multiprocessing.cpu_count()
+ else:
+ return int(t)
+
+
+def thread_factors(t):
+ for x in reversed(range(int(np.ceil(np.sqrt(t)))+1)):
+ if t%x == 0:
+ return (x, int(t/x))
+
+
+def centers(x):
+ return (x[:-1]+x[1:])*0.5
+
+
+def get_units(dimension):
+ if dimension == 3: return r' / \:{\rm GeV}'
+ if dimension == 4: return r''
+ if dimension == 5: return r' / \:{\rm GeV}^{-1}'
+ if dimension == 6: return r' / \:{\rm GeV}^{-2}'
+ if dimension == 7: return r' / \:{\rm GeV}^{-3}'
+ if dimension == 8: return r' / \:{\rm GeV}^{-4}'
+
+
+def calc_nbins(x):
+ n = (np.max(x) - np.min(x)) / (2 * len(x)**(-1./3) * (np.percentile(x, 75) - np.percentile(x, 25)))
+ return np.floor(n)
+
+
+def calc_bins(x):
+ nbins = calc_nbins(x)
+ return np.linspace(np.min(x), np.max(x)+2, num=nbins+1)
+
+
+def most_likely(arr):
+ """Return the densest region given a 1D array of data."""
+ binning = calc_bins(arr)
+ harr = np.histogram(arr, binning)[0]
+ return centers(binning)[np.argmax(harr)]
+
+
+def interval(arr, percentile=68.):
+ """Returns the *percentile* shortest interval around the mode."""
+ center = most_likely(arr)
+ sarr = sorted(arr)
+ delta = np.abs(sarr - center)
+ curr_low = np.argmin(delta)
+ curr_up = curr_low
+ npoints = len(sarr)
+ while curr_up - curr_low < percentile/100.*npoints:
+ if curr_low == 0:
+ curr_up += 1
+ elif curr_up == npoints-1:
+ curr_low -= 1
+ elif sarr[curr_up]-sarr[curr_low-1] < sarr[curr_up+1]-sarr[curr_low]:
+ curr_low -= 1
+ elif sarr[curr_up]-sarr[curr_low-1] > sarr[curr_up+1]-sarr[curr_low]:
+ curr_up += 1
+ elif (curr_up - curr_low) % 2:
+ # they are equal so step half of the time up and down
+ curr_low -= 1
+ else:
+ curr_up += 1
+ return sarr[curr_low], center, sarr[curr_up]
+
+
+def flat_angles_to_u(x):
+ """Convert from angles to mixing elements."""
+ return abs(angles_to_u(x)).astype(np.float32).flatten().tolist()
+
+
+def myround(x, base=2, up=False, down=False):
+ if up == down and up is True: assert 0
+ if up: return int(base * np.round(float(x)/base-0.5))
+ elif down: return int(base * np.round(float(x)/base+0.5))
+ else: int(base * np.round(float(x)/base))
+
+