def digitize(self, point): """ Digitize a hit on a plane of the MRPC. """ x = random.gauss(point.x(), MRPC_LONGITUDINAL_SIGMA) y = int(point.y() / MRPC_STRIP_PITCH + 0.5) * MRPC_STRIP_PITCH z = point.z() return E3Point(x, y, z)
def randomPoint(self, plane=2): """ """ x = random.uniform(MRPC_X_MIN, MRPC_X_MAX) y = random.uniform(MRPC_Y_MIN, MRPC_Y_MAX) z = self.z(plane) return E3Point(x, y, z)
def test(): """ """ fitTool = E3FittingTool2dWeighted() # Real event from FRAS-02-2014-10-30-00018_dst.root (11878) # Processed with e3pipe 2.1.0 gives: # root [4] Events.Scan("XDir:YDir:ZDir:ChiSquare", "EventNumber==11878") # ************************************************************ # * Row * XDir * YDir * ZDir * ChiSquare * # ************************************************************ # * 11878 * -0.050563 * 0.1976770 * 0.9789620 * 1.6044100 * # ************************************************************ hits = [E3Point(79.229, 38.400, 0.000), E3Point(82.742, 32.000, 40.000), E3Point(83.922, 22.400, 80.000) ] fitTool.run(hits) print fitTool.track()
def readEvent(self, event, refit=False, verbose=True): """ Read all the event information and store it in memory. """ self.__CurrentHits = [] self.__CurrentTrack = None self.GetEntry(event) x = self.value('PosXBot') y = self.value('PosYBot') z = self.__Z[0] self.__CurrentHits.append(E3Point(x, y, z)) x = self.value('PosXMid') y = self.value('PosYMid') z = self.__Z[1] self.__CurrentHits.append(E3Point(x, y, z)) x = self.value('PosXTop') y = self.value('PosYTop') z = self.__Z[2] self.__CurrentHits.append(E3Point(x, y, z)) if refit: self.__CurrentTrack = self.refitTrack(verbose) else: x0 = self.value('IntersectXMid') y0 = self.value('IntersectYMid') # Note there is apparently a bug where IntersectZMid is always # 80 and cannot be used here. z0 = self.__Z[1] origin = E3Point(x0, y0, z0) xdir = self.value('XDir') ydir = self.value('YDir') zdir = self.value('ZDir') directionRot = E3Vector(xdir, ydir, zdir) # Remember: in the DST we store the direction referred to the # north, and we do have to transform back into instrument # coordinates. direction = directionRot.rotatez(-self.__PhiNorth, deg=True) self.__CurrentTrack = E3Track(origin, direction) chi2 = self.value('ChiSquare') self.__CurrentTrack.setChi2(chi2) if verbose: self.__printEventInfo(event)
class E3FittingToolBase: DEFAULT_TRACK = E3Track(E3Point(-1., -1., -1), E3Vector(-1., -1., -1.), -1.) """ Base class for track fitting. """ def __init__(self): """ Constructor. """ logger.info('Initializing fitting tool %s...' %\ (self.__class__.__name__)) self.clear() def track(self): """ Return the best-fit track. """ return self.__Track def setTrack(self, track): """ Set the best-fit track. """ self.__Track = track def clear(self): """ Reset the best-fit track. """ self.setTrack(self.DEFAULT_TRACK) def __str__(self): """ String formatting. """ return '%s' % self.__Track def fitTrack(self, hits): """ Do-nothing hook. The actual fitting code is implemented in the actual sub-classes. """ return self.DEFAULT_TRACK def run(self, hits): """ Run the fit. """ self.clear() if len(hits) < 2: return self.setTrack(self.fitTrack(hits))
def extrapolate(self, z): """ """ x = self.x0() + (z - self.z0()) * self.xdir() / self.zdir() y = self.y0() + (z - self.z0()) * self.ydir() / self.zdir() return E3Point(x, y, z)
""" """ return self.__Direction.theta() def phi(self): """ """ return self.__Direction.phi() def extrapolate(self, z): """ """ x = self.x0() + (z - self.z0()) * self.xdir() / self.zdir() y = self.y0() + (z - self.z0()) * self.ydir() / self.zdir() return E3Point(x, y, z) def __str__(self): """ String formatting """ return '%s -> %s (chi2 = %.3f)' %\ (self.origin(), self.direction(), self.chi2()) if __name__ == '__main__': p = E3Point(50., 50., 100) v = E3Vector(0, 0, 1) t = E3Track(p, v) print t print t.phi(), t.theta() print t.extrapolate(0)
def fitTrack(self, hits): """ Run the track fitting. """ # Initialize some variables for the fit. n = 0 sx = 0. sx_z = 0. sx_zz = 0. sx_x = 0. sx_zx = 0. sy = 0. sy_z = 0. sy_zz = 0. sy_y = 0. sy_zy = 0. # Loop over the points. # Note that, since the weights correspond to errors in the x and y # directions, the two views are fitted in the z-x and z-y (as opposed to # x-z and y-z) planes (i.e. z acts as the abscissa in both cases). This # also turns out to be handy since we measure the theta angle # (i.e. zdir) from the z axis, rather than the x-y plane. for hit in hits: n += 1 sy += self.__Wy sy_z += hit.z() * self.__Wy sy_zz += hit.z() * hit.z() * self.__Wy sy_y += hit.y() * self.__Wy sy_zy += hit.z() * hit.y() * self.__Wy sx += self.__Wx sx_z += hit.z() * self.__Wx sx_zz += hit.z() * hit.z() * self.__Wx sx_x += hit.x() * self.__Wx sx_zx += hit.z() * hit.x() * self.__Wx # Go ahead with the fit parameters, i.e. the slopes in the two views. zxslope = (sx_zx * sx - sx_z * sx_x) / (sx_zz * sx - sx_z * sx_z) zyslope = (sy_zy * sy - sy_z * sy_y) / (sy_zz * sy - sy_z * sy_z) zxintercept = (sx_x * sx_zz - sx_zx * sx_z) / (sx_zz * sx - sx_z * sx_z) zyintercept = (sy_y * sy_zz - sy_zy * sy_z) / (sy_zz * sy - sy_z * sy_z) # Convert from the slope/intercept representation to the director # cosines. denom = math.sqrt(1 + zxslope * zxslope + zyslope * zyslope) xdir = zxslope / denom ydir = zyslope / denom zdir = 1. / denom v0 = E3Vector(xdir, ydir, zdir) # Refer the centroid to a common z0 value (e.g., the z of the # mid hit) z0 = hits[1].z() x0 = zxintercept + z0 * zxslope y0 = zyintercept + z0 * zyslope p0 = E3Point(x0, y0, z0) track = E3Track(p0, v0) # Need a final loop to calculate the chisquare, here. chi2 = 0. for hit in hits: extr = track.extrapolate(hit.z()) resx = (hit.x() - extr.x()) / self.__Wx resy = (hit.y() - extr.y()) / self.__Wy chi2 += (resx**2 + resy**2) track.setChi2(chi2) return track
def fitTrack(self, hits): """ Run the track fitting. This is a stripped-down version of the code in the Analyzer, with the variable names being the same to facilitate a direct comparison. """ # Initialize the hits. xxB = hits[0].x() yyB = hits[0].y() zzB = hits[0].z() xxM = hits[1].x() yyM = hits[1].y() zzM = hits[1].z() xxT = hits[2].x() yyT = hits[2].y() zzT = hits[2].z() #---------------------------------------------------------------------- sumX = xxB + xxM + xxT sumY = yyB + yyM + yyT sumZ = zzB + zzM + zzT sXZ = xxB*zzB + xxM*zzM + xxT*zzT sYZ = yyB*zzB + yyM*zzM + yyT*zzT sX2 = xxB*xxB + xxM*xxM + xxT*xxT sY2 = yyB*yyB + yyM*yyM + yyT*yyT sZ2 = zzB*zzB + zzM*zzM + zzT*zzT sumZ2 = sumZ*sumZ # Fit procedure in the 3D-space p0 = (3.*sXZ - sumX*sumZ) / (3.*sZ2 - sumZ2) p1 = (sumX - p0*sumZ) / 3. p2 = (3.*sYZ - sumY*sumZ) / (3.*sZ2 - sumZ2) p3 = (sumY - p2*sumZ) / 3. n0 = p0 / math.sqrt(1. + p0*p0 + p2*p2) n1 = p2 / math.sqrt(1. + p0*p0 + p2*p2) n2 = 1. / math.sqrt(1. + p0*p0 + p2*p2) zzz = n0*n0 + n1*n1 + n2*n2 # Evaluation of distances between points and line in 3D-space. dd = math.sqrt(zzz) axB = n2*(yyB - p3) - n1*zzB ayB = -1 * n2 * (xxB - p1) + n0 * zzB azB = n1 * (xxB - p1) - n0*(yyB - p3) distB = math.sqrt((axB)**2. + (ayB)**2. + (azB)**2.) / dd axM = n2*(yyM - p3) - n1*zzM ayM = -1 * n2 * (xxM - p1) + n0 * zzM azM = n1 * (xxM - p1) - n0*(yyM - p3) distM = math.sqrt((axM)**2. + (ayM)**2. + (azM)**2.) / dd axT = n2*(yyT - p3) - n1*zzT ayT = -1 * n2 * (xxT - p1) + n0 * zzT azT = n1 * (xxT - p1) - n0*(yyT - p3) distT = math.sqrt((axT)**2. + (ayT)**2. + (azT)**2.) / dd chi2 = math.sqrt(distB**2. + distM**2. + distT**2.) #---------------------------------------------------------------------- # Build the best-fit track object. # Note that, in order to recover the track origin, I add back the # original hit coordinates to the distances calculated into the # chisquare loop (wow!) p0 = E3Point(xxM + axM, yyM + ayM, zzM) v0 = E3Vector(n0, n1, n2) track = E3Track(p0, v0) track.setChi2(chi2) return track
def withinActiveArea(self, x, y): """ Return whether a given (x, y) two-dimensional point is within the active area. """ return x >= 0 and x <= MRPC_LENGTH and y >= 0 and y <= MRPC_WIDTH def digitize(self, point): """ Digitize a hit on a plane of the MRPC. """ x = random.gauss(point.x(), MRPC_LONGITUDINAL_SIGMA) y = int(point.y() / MRPC_STRIP_PITCH + 0.5) * MRPC_STRIP_PITCH z = point.z() return E3Point(x, y, z) def __str__(self): """ String formatting. """ return '%s: z = %s, phi to N = %.3f' %\ (self.name(), self.__Z, self.phiNorth()) if __name__ == '__main__': telescope = E3TelescopeBase() print telescope p = telescope.randomPoint(2) print p, telescope.digitize(p) ztop = telescope.ztop() p = E3Point(10, 1.7, ztop) print p, telescope.digitize(p)