summaryrefslogtreecommitdiff
path: root/likelihood.py
diff options
context:
space:
mode:
authorStan Seibert <stan@mtrr.org>2011-09-16 14:27:46 -0400
committerStan Seibert <stan@mtrr.org>2011-09-16 14:27:46 -0400
commit084dfd08b714faefaea77cb7dc04d2e93dc04b1d (patch)
tree5be8c1f1d30dc52d74c70c4964ec54f66294c265 /likelihood.py
parentcfecff941fc619eb7269128afc62d9c11ae78aff (diff)
downloadchroma-084dfd08b714faefaea77cb7dc04d2e93dc04b1d.tar.gz
chroma-084dfd08b714faefaea77cb7dc04d2e93dc04b1d.tar.bz2
chroma-084dfd08b714faefaea77cb7dc04d2e93dc04b1d.zip
File reorganization to move toward standard python package layout
Diffstat (limited to 'likelihood.py')
-rw-r--r--likelihood.py131
1 files changed, 0 insertions, 131 deletions
diff --git a/likelihood.py b/likelihood.py
deleted file mode 100644
index 0e378b1..0000000
--- a/likelihood.py
+++ /dev/null
@@ -1,131 +0,0 @@
-import numpy as np
-from histogram import HistogramDD
-from uncertainties import ufloat, umath, unumpy
-from math import sqrt
-from itertools import islice, izip, compress, repeat
-from chroma.tools import profile_if_possible
-
-class Likelihood(object):
- "Class to evaluate likelihoods for detector events."
- def __init__(self, sim, event=None, tbins=100, trange=(-0.5e-9, 999.5e-9),
- qbins=10, qrange=(-0.5, 9.5), time_only=True):
- """
- Args:
- - sim: chroma.sim.Simulation
- The simulation object used to simulate events and build pdfs.
- - event: chroma.event.Event, *optional*
- The detector event being reconstructed. If None, you must call
- set_event() before eval().
- - tbins: int, *optional*
- Number of time bins in PDF
- - trange: tuple of 2 floats, *optional*
- Min and max time to include in PDF
- - qbins: int, *optional*
- Number of charge bins in PDF
- - qrange: tuple of 2 floats, *optional*
- Min and max charge to include in PDF
- - time_only: bool, *optional*
- Only use time observable (instead of time and charge) in computing
- likelihood. Defaults to True.
- """
- self.sim = sim
- self.tbins = tbins
- self.trange = trange
- self.qbins = qbins
- self.qrange = qrange
- self.time_only = time_only
-
- if event is not None:
- self.set_event(event)
-
- def set_event(self, event):
- "Set the detector event being reconstructed."
- self.event = event
-
- @profile_if_possible
- def eval(self, vertex_generator, nevals, nreps=16, ndaq=50):
- """
- Return the negative log likelihood that the detector event set in the
- constructor or by set_event() was the result of a particle generated
- by `vertex_generator`. If `nreps` set to > 1, each set of photon
- vertices will be propagated `nreps` times.
- """
- ntotal = nevals * nreps * ndaq
-
- vertex_generator = islice(vertex_generator, nevals)
-
- hitcount, pdf_prob, pdf_prob_uncert = \
- self.sim.eval_pdf(self.event.channels,
- vertex_generator,
- 0.1e-9, self.trange,
- 1, self.qrange,
- nreps=nreps,
- ndaq=ndaq,
- time_only=self.time_only)
-
- # Normalize probabilities and put a floor to keep the log finite
- hit_prob = hitcount.astype(np.float32) / ntotal
- hit_prob = np.maximum(hit_prob, 0.5 / ntotal)
-
- # Set all zero or nan probabilities to limiting PDF value
- bad_value = (pdf_prob <= 0.0) | np.isnan(pdf_prob)
- if self.time_only:
- pdf_floor = 1.0 / (self.trange[1] - self.trange[0])
- else:
- pdf_floor = 1.0 / (self.trange[1] - self.trange[0]) / (self.qrange[1] - self.qrange[0])
- pdf_prob[bad_value] = pdf_floor
- pdf_prob_uncert[bad_value] = pdf_floor
-
- print 'channels with no data:', (bad_value & self.event.channels.hit).astype(int).sum()
-
- # NLL calculation: note that negation is at the end
- # Start with the probabilties of hitting (or not) the channels
- hit_channel_prob = np.log(hit_prob[self.event.channels.hit]).sum() + np.log(1.0-hit_prob[~self.event.channels.hit]).sum()
- hit_channel_prob_uncert = ( (ntotal * hit_prob * (1.0 - hit_prob)) / hit_prob**2 ).sum()**0.5
- log_likelihood = ufloat((hit_channel_prob, 0.0))
-
- # Then include the probability densities of the observed
- # charges and times.
- hit_pdf_ufloat = unumpy.uarray((pdf_prob[self.event.channels.hit],
- pdf_prob_uncert[self.event.channels.hit]))
- log_likelihood += unumpy.log(hit_pdf_ufloat).sum()
-
- return -log_likelihood
-
-if __name__ == '__main__':
- from chroma import detectors
- from chroma.sim import Simulation
- from chroma.optics import water
- from chroma.generator import constant_particle_gun
- from chroma import tools
- import time
-
- tools.enable_debug_on_crash()
-
- detector = detectors.find('lbne')
- sim = Simulation(detector, seed=0)
-
- event = sim.simulate(islice(constant_particle_gun('e-',(0,0,0),(1,0,0),100.0), 1)).next()
-
- print 'nhit = %i' % np.count_nonzero(event.channels.hit)
-
- likelihood = Likelihood(sim, event)
-
- x = np.linspace(-10.0, 10.0, 100)
- l = []
-
- for pos in izip(x, repeat(0), repeat(0)):
- t0 = time.time()
- ev_vertex_iter = constant_particle_gun('e-',pos,(1,0,0),100.0)
- l.append(likelihood.eval(ev_vertex_iter, 1000))
- elapsed = time.time() - t0
-
- print '(%.1f, %.1f, %.1f), %s (%1.1f sec)' % \
- (pos[0], pos[1], pos[2], tools.ufloat_to_str(l[-1]), elapsed)
-
- import matplotlib.pyplot as plt
-
- plt.errorbar(x, [v.nominal_value for v in l], [v.std_dev() for v in l])
- plt.xlabel('X Position (m)')
- plt.ylabel('Negative Log Likelihood')
- plt.show()