def measure_deviations(electron): """ Measure angular deviation vs. radial distance. Input is a geant4 matrix from geant.separateElectrons. """ if electron.shape[0] == 0: return None, None # column indices ind_trackID = 0 ind_parentID = 1 ind_stepnum = 2 ind_charge = 3 ind_initpos = range(4, 7) ind_finalpos = range(7, 10) ind_tracklen = 10 ind_steplen = 11 ind_final_E = 12 ind_dE = 13 energy_keV = geant.measureEnergyKev(electron) # tabata_range_um = tabata.extrapolatedRangeSi(energy_keV) trackID = electron[:, ind_trackID].astype(int) parentID, charge = geant.constructParticleTable(electron, ind_trackID, ind_parentID, ind_charge) # (copied from geant.measureExtrapolatedRangeX) # exclude electrons induced by secondary photons # (e.g. bremsstrahlung) # i.e., only include particles with a pure electron ancestry # start from all electrons, and remove any with photon ancestors. is_valid = charge == -1 was_valid = np.ones(len(is_valid)) > 0 # is there a better way to make a boolean array? while any(np.logical_xor(is_valid, was_valid)): was_valid = is_valid is_valid = np.logical_and( is_valid, np.logical_or(is_valid[parentID], parentID == 0)) is_valid_step = is_valid[trackID] first_step = list(electron[is_valid_step, ind_stepnum]).index(1) initial_pos = electron[first_step, ind_initpos] # assume initial direction is along x-axis offset_vector_mm = (electron[is_valid_step, :][:, ind_finalpos] - initial_pos) radial_distance_mm = np.sqrt(offset_vector_mm[:, 0]**2 + offset_vector_mm[:, 1]**2 + offset_vector_mm[:, 2]**2) atan_y = np.sqrt(offset_vector_mm[:, 1]**2 + offset_vector_mm[:, 2]**2) atan_x = offset_vector_mm[:, 0] deviation_deg = np.arctan2(atan_y, atan_x) return radial_distance_mm, deviation_deg
def run_file(filename, savename): """ Load a geant data file, measure deviations, save to file. """ electrons = geant.separateElectrons(geant.loadG4Data(filename)) energy_keV = [geant.measureEnergyKev(e) for e in electrons] radial_distance_mm = [[] for i in xrange(len(electrons))] deviation_deg = [[] for i in xrange(len(electrons))] for i in xrange(len(electrons)): radial_distance_mm[i], deviation_deg[i] = ( measure_deviations(electrons[i])) np.savez(savename, energy_keV=energy_keV, radial_distance_mm=radial_distance_mm, deviation_deg=deviation_deg)
def run_file(filename, savename): """ Load a geant data file, measure deviations, save to file. """ electrons = geant.separateElectrons(geant.loadG4Data(filename)) energy_keV = [geant.measureEnergyKev(e) for e in electrons] radial_distance_mm = [[] for i in xrange(len(electrons))] deviation_deg = [[] for i in xrange(len(electrons))] for i in xrange(len(electrons)): radial_distance_mm[i], deviation_deg[i] = (measure_deviations( electrons[i])) np.savez(savename, energy_keV=energy_keV, radial_distance_mm=radial_distance_mm, deviation_deg=deviation_deg)
def measure_deviations(electron): """ Measure angular deviation vs. radial distance. Input is a geant4 matrix from geant.separateElectrons. """ if electron.shape[0] == 0: return None, None # column indices ind_trackID = 0 ind_parentID = 1 ind_stepnum = 2 ind_charge = 3 ind_initpos = range(4, 7) ind_finalpos = range(7, 10) ind_tracklen = 10 ind_steplen = 11 ind_final_E = 12 ind_dE = 13 energy_keV = geant.measureEnergyKev(electron) # tabata_range_um = tabata.extrapolatedRangeSi(energy_keV) trackID = electron[:, ind_trackID].astype(int) parentID, charge = geant.constructParticleTable( electron, ind_trackID, ind_parentID, ind_charge) # (copied from geant.measureExtrapolatedRangeX) # exclude electrons induced by secondary photons # (e.g. bremsstrahlung) # i.e., only include particles with a pure electron ancestry # start from all electrons, and remove any with photon ancestors. is_valid = charge == -1 was_valid = np.ones(len(is_valid)) > 0 # is there a better way to make a boolean array? while any(np.logical_xor(is_valid, was_valid)): was_valid = is_valid is_valid = np.logical_and( is_valid, np.logical_or(is_valid[parentID], parentID == 0)) is_valid_step = is_valid[trackID] first_step = list(electron[is_valid_step, ind_stepnum]).index(1) initial_pos = electron[first_step, ind_initpos] # assume initial direction is along x-axis offset_vector_mm = (electron[is_valid_step, :][:, ind_finalpos] - initial_pos) radial_distance_mm = np.sqrt( offset_vector_mm[:, 0]**2 + offset_vector_mm[:, 1]**2 + offset_vector_mm[:, 2]**2) atan_y = np.sqrt( offset_vector_mm[:, 1]**2 + offset_vector_mm[:, 2]**2) atan_x = offset_vector_mm[:, 0] deviation_deg = np.arctan2(atan_y, atan_x) return radial_distance_mm, deviation_deg