Commit 563201b4380d431d6797efba6143c41bc9781b59
1 parent
211b3d95
add options and cumulative histogram
Showing
1 changed file
with
168 additions
and
38 deletions
examples/show_ts_distribution.py
| 1 | #! /usr/bin/env python | 1 | #! /usr/bin/env python |
| 2 | # ========================================================================== | 2 | # ========================================================================== |
| 3 | -# This script displays pull histograms that have been generated using the | ||
| 4 | -# cspull script. The pull is defined by | ||
| 5 | -# | ||
| 6 | -# (fitted value - simulated value) / estimated error | ||
| 7 | -# | ||
| 8 | -# and the pull histogram allows to assess possible biases in the fit | ||
| 9 | -# parameters and errors. | 3 | +# This script displays the TS distribution values generated using cstsdist. |
| 10 | # | 4 | # |
| 11 | # Required 3rd party modules: | 5 | # Required 3rd party modules: |
| 12 | # - matplotlib | 6 | # - matplotlib |
| @@ -39,9 +33,9 @@ import math | @@ -39,9 +33,9 @@ import math | ||
| 39 | # ==================== # | 33 | # ==================== # |
| 40 | # Read TS distribution # | 34 | # Read TS distribution # |
| 41 | # ==================== # | 35 | # ==================== # |
| 42 | -def read_ts(filename): | 36 | +def read_ts(filename, tsname="TS"): |
| 43 | """ | 37 | """ |
| 44 | - Read TS distribution. | 38 | + Read TS distribution values from CSV file. |
| 45 | """ | 39 | """ |
| 46 | # Initialise list | 40 | # Initialise list |
| 47 | values = [] | 41 | values = [] |
| @@ -57,9 +51,10 @@ def read_ts(filename): | @@ -57,9 +51,10 @@ def read_ts(filename): | ||
| 57 | # Get column index if first row | 51 | # Get column index if first row |
| 58 | if first: | 52 | if first: |
| 59 | try: | 53 | try: |
| 60 | - index = row.index("TS") | 54 | + index = row.index(tsname) |
| 61 | except: | 55 | except: |
| 62 | print 'ERROR: Column "TS" not found in file' | 56 | print 'ERROR: Column "TS" not found in file' |
| 57 | + print row | ||
| 63 | raise NameError("TS") | 58 | raise NameError("TS") |
| 64 | #print index | 59 | #print index |
| 65 | 60 | ||
| @@ -72,39 +67,108 @@ def read_ts(filename): | @@ -72,39 +67,108 @@ def read_ts(filename): | ||
| 72 | 67 | ||
| 73 | # Create numpy array | 68 | # Create numpy array |
| 74 | a = np.array(values) | 69 | a = np.array(values) |
| 75 | - #print a | ||
| 76 | 70 | ||
| 77 | # Return array | 71 | # Return array |
| 78 | return a | 72 | return a |
| 79 | 73 | ||
| 80 | 74 | ||
| 81 | -# ======================== # | ||
| 82 | -# Main routine entry point # | ||
| 83 | -# ======================== # | ||
| 84 | -if __name__ == '__main__': | 75 | +# =========== # |
| 76 | +# Compute erf # | ||
| 77 | +# =========== # | ||
| 78 | +def erf(x): | ||
| 85 | """ | 79 | """ |
| 86 | - Display pull histogram generated by cspull using matplotlib. | 80 | + Compute error function. |
| 87 | """ | 81 | """ |
| 88 | - # Print usage information | ||
| 89 | - usage = "Usage: show_ts_distribution filename [bins]" | ||
| 90 | - if len(sys.argv) < 2: | ||
| 91 | - print usage | ||
| 92 | - sys.exit() | 82 | + # save the sign of x |
| 83 | + sign = 1 | ||
| 84 | + if x < 0: | ||
| 85 | + sign = -1 | ||
| 86 | + x = abs(x) | ||
| 93 | 87 | ||
| 94 | - # Extract parameters | ||
| 95 | - filename = sys.argv[1] | ||
| 96 | - if len(sys.argv) == 3: | ||
| 97 | - nbins = int(sys.argv[2]) | ||
| 98 | - else: | ||
| 99 | - nbins = 30 | 88 | + # constants |
| 89 | + a1 = 0.254829592 | ||
| 90 | + a2 = -0.284496736 | ||
| 91 | + a3 = 1.421413741 | ||
| 92 | + a4 = -1.453152027 | ||
| 93 | + a5 = 1.061405429 | ||
| 94 | + p = 0.3275911 | ||
| 100 | 95 | ||
| 101 | - # Set lin/log | ||
| 102 | - log = True | 96 | + # A&S formula 7.1.26 |
| 97 | + t = 1.0/(1.0 + p*x) | ||
| 98 | + y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*math.exp(-x*x) | ||
| 103 | 99 | ||
| 104 | - # Read values from CSV file | ||
| 105 | - values = read_ts(filename) | ||
| 106 | - print len(values), "values read." | 100 | + # Return result |
| 101 | + return sign*y # erf(-x) = -erf(x) | ||
| 102 | + | ||
| 103 | + | ||
| 104 | +# =============================== # | ||
| 105 | +# Display cumulative distribution # | ||
| 106 | +# =============================== # | ||
| 107 | +def dist_cdf(values, nbins, title): | ||
| 108 | + """ | ||
| 109 | + Displays cumulative TS distribution and overplots expectation. | ||
| 110 | + """ | ||
| 111 | + # Set range and adapt number of bins. We make sure that we have a | ||
| 112 | + # histogram bin centred on 0 that will capture the TS=0 part. | ||
| 113 | + max_value = max(values) | ||
| 114 | + binsize = max_value/nbins | ||
| 115 | + min_value = 0.5*binsize | ||
| 116 | + while min_value > min(values): | ||
| 117 | + min_value -= binsize | ||
| 118 | + nbins += 1 | ||
| 119 | + | ||
| 120 | + # Create histogram | ||
| 121 | + hist_x = [] | ||
| 122 | + hist_y = [] | ||
| 123 | + hist_expect = [] | ||
| 124 | + norm = 0.5*len(values) | ||
| 125 | + for i in range(nbins): | ||
| 126 | + x_min = min_value+i*binsize | ||
| 127 | + x_max = min_value+(i+1)*binsize | ||
| 128 | + x_val = 0.5*(x_min+x_max) | ||
| 129 | + y_val = 0.0 | ||
| 130 | + for ts in values: | ||
| 131 | + if ts > x_min: | ||
| 132 | + y_val += 1.0 | ||
| 133 | + hist_x.append(x_min) | ||
| 134 | + hist_y.append(y_val) | ||
| 135 | + hist_x.append(x_max) | ||
| 136 | + hist_y.append(y_val) | ||
| 137 | + if x_min > 0.0: | ||
| 138 | + value = norm*erf(math.sqrt(0.5*x_min)) + norm | ||
| 139 | + hist_expect.append(len(values)-value) | ||
| 140 | + hist_expect.append(len(values)-value) | ||
| 141 | + else: | ||
| 142 | + hist_expect.append(norm) | ||
| 143 | + hist_expect.append(norm) | ||
| 144 | + | ||
| 145 | + # Show expected distribution (half) | ||
| 146 | + l = plt.semilogy(hist_x, hist_y, 'r-', linewidth=2, label="simulations") | ||
| 147 | + l = plt.semilogy(hist_x, hist_expect, 'k-', linewidth=2, label="expectation") | ||
| 148 | + l = plt.semilogy(hist_x, hist_y, 'r-', linewidth=2) | ||
| 149 | + | ||
| 150 | + # Set plot | ||
| 151 | + plt.xlabel('TS') | ||
| 152 | + plt.ylabel('Number of trials > TS') | ||
| 153 | + plt.title(title) | ||
| 154 | + plt.grid(True) | ||
| 155 | + plt.legend(loc="upper right") | ||
| 156 | + | ||
| 157 | + # Show histogram | ||
| 158 | + plt.show() | ||
| 107 | 159 | ||
| 160 | + # Return | ||
| 161 | + return | ||
| 162 | + | ||
| 163 | + | ||
| 164 | +# ======================================== # | ||
| 165 | +# Display probability density distribution # | ||
| 166 | +# ======================================== # | ||
| 167 | +def dist_pdf(values, nbins, title): | ||
| 168 | + """ | ||
| 169 | + Display probability density TS distribution and overplots | ||
| 170 | + expectation. | ||
| 171 | + """ | ||
| 108 | # Set range and adapt number of bins. We make sure that we have a | 172 | # Set range and adapt number of bins. We make sure that we have a |
| 109 | # histogram bin centred on 0 that will capture the TS=0 part. | 173 | # histogram bin centred on 0 that will capture the TS=0 part. |
| 110 | max_value = max(values) | 174 | max_value = max(values) |
| @@ -117,7 +181,7 @@ if __name__ == '__main__': | @@ -117,7 +181,7 @@ if __name__ == '__main__': | ||
| 117 | # Create histogram | 181 | # Create histogram |
| 118 | n, bins, patches = plt.hist(values, nbins, range=[min_value, max_value], \ | 182 | n, bins, patches = plt.hist(values, nbins, range=[min_value, max_value], \ |
| 119 | align='mid', facecolor='green', \ | 183 | align='mid', facecolor='green', \ |
| 120 | - log=log) | 184 | + log=True, label="simulations") |
| 121 | 185 | ||
| 122 | # Create expected distribution (onyl for positive TS). We compute the | 186 | # Create expected distribution (onyl for positive TS). We compute the |
| 123 | # full and half of the distribution, as for positively constrained | 187 | # full and half of the distribution, as for positively constrained |
| @@ -139,17 +203,83 @@ if __name__ == '__main__': | @@ -139,17 +203,83 @@ if __name__ == '__main__': | ||
| 139 | y_half.append(0.5*y) | 203 | y_half.append(0.5*y) |
| 140 | 204 | ||
| 141 | # Show expected distribution (half) | 205 | # Show expected distribution (half) |
| 142 | - if log: | ||
| 143 | - l = plt.semilogy(x, y_half, 'ro', linewidth=2) | ||
| 144 | - else: | ||
| 145 | - l = plt.plot(x, y_half, 'r-', linewidth=2) | 206 | + l = plt.semilogy(x, y_half, 'ro', linewidth=2, label="expectation") |
| 146 | 207 | ||
| 147 | # Set plot | 208 | # Set plot |
| 148 | plt.xlabel('TS') | 209 | plt.xlabel('TS') |
| 149 | plt.ylabel('Number of trials') | 210 | plt.ylabel('Number of trials') |
| 150 | - plt.title('TS distribution ('+filename+')') | 211 | + plt.title(title) |
| 151 | plt.grid(True) | 212 | plt.grid(True) |
| 213 | + plt.legend(loc="upper right") | ||
| 152 | 214 | ||
| 153 | # Show histogram | 215 | # Show histogram |
| 154 | plt.show() | 216 | plt.show() |
| 217 | + | ||
| 218 | + | ||
| 219 | +# ======================== # | ||
| 220 | +# Main routine entry point # | ||
| 221 | +# ======================== # | ||
| 222 | +if __name__ == '__main__': | ||
| 223 | + """ | ||
| 224 | + Display TS distribution generated using cstsdist using matplotlib. | ||
| 225 | + """ | ||
| 226 | + # Print usage information | ||
| 227 | + usage = "Usage: show_ts_distribution filename" \ | ||
| 228 | + " [-n bins] [-c column] [-t title] [-p plot]" | ||
| 229 | + if len(sys.argv) < 2: | ||
| 230 | + print usage | ||
| 231 | + sys.exit() | ||
| 232 | + | ||
| 233 | + # Extract parameters | ||
| 234 | + filename = sys.argv[1] | ||
| 235 | + | ||
| 236 | + # Set default parameters | ||
| 237 | + nbins = 30 | ||
| 238 | + tsname = "TS" | ||
| 239 | + title = "TS distribution" | ||
| 240 | + plot = "pdf" | ||
| 241 | + | ||
| 242 | + # Parameter dictionnary | ||
| 243 | + pars = [{'option': '-n', 'value': nbins}, \ | ||
| 244 | + {'option': '-c', 'value': tsname}, \ | ||
| 245 | + {'option': '-t', 'value': title}, \ | ||
| 246 | + {'option': '-p', 'value': plot}] | ||
| 247 | + | ||
| 248 | + # Gather parameters from command line | ||
| 249 | + i = 2 | ||
| 250 | + while i < len(sys.argv): | ||
| 251 | + | ||
| 252 | + # Search for options | ||
| 253 | + for par in pars: | ||
| 254 | + if sys.argv[i] == par['option']: | ||
| 255 | + if len(sys.argv) > i+1: | ||
| 256 | + i += 1 | ||
| 257 | + try: | ||
| 258 | + par['value'] = sys.argv[i] | ||
| 259 | + except: | ||
| 260 | + print usage | ||
| 261 | + sys.exit() | ||
| 262 | + else: | ||
| 263 | + print usage | ||
| 264 | + sys.exit() | ||
| 265 | + | ||
| 266 | + # Next item | ||
| 267 | + i += 1 | ||
| 268 | + | ||
| 269 | + # Recover parameters | ||
| 270 | + nbins = int(pars[0]['value']) | ||
| 271 | + tsname = pars[1]['value'] | ||
| 272 | + title = pars[2]['value'] | ||
| 273 | + plot = pars[3]['value'] | ||
| 274 | + | ||
| 275 | + # Read values from CSV file | ||
| 276 | + values = read_ts(filename, tsname=tsname) | ||
| 277 | + print len(values), "values read." | ||
| 278 | + | ||
| 279 | + # Show histogram | ||
| 280 | + if plot == "pdf": | ||
| 281 | + dist_pdf(values, nbins, title) | ||
| 282 | + else: | ||
| 283 | + dist_cdf(values, nbins, title) | ||
| 284 | + | ||
| 155 | 285 | ||
| 156 | \ No newline at end of file | 286 | \ No newline at end of file |