def geometric_carrier_trapping(eventIDs): filename = r"C:\Users\alexp\Documents\UW\Research\Selenium\aSe0vBB\particle\selenium-build\output\122_keV_testTuple.root" emfilename = r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize.txt" configfilename = r"./config.txt" settings = sc.readConfigFile(configfilename) newCollection = pd.gEventCollection(filename) newCollection.printInfo() bmap = brewer2mpl.get_map("Set2", "Qualitative", max(len(eventIDs) + 1, 3)).mpl_colors fig, ax = plt.subplots() for colorj, j in enumerate(eventIDs): settings["CARRIER_LIFETIME_GEOMETRIC"] = 1 event = newCollection.collection[j] # Iterate over many scenarios to watch fluctuations N = 30 qtot = 0 for i in range(N): print(i) t, q = pd.computeChargeSignal(event, emfilename, **settings) ax.plot(t, -q / 1.6e-19 * 0.05, color=bmap[colorj], alpha=0.3) qtot += q ax.plot( t, -qtot / N / 1.6e-19 * 0.05, color=bmap[colorj], linewidth=2, label="Noise, Event ID %i" % event.GetEventID(), ) ax.set_xlabel(r"Time ($\mu$s)", fontsize=14) ax.set_ylabel(r"Induced Charge (keV)", fontsize=14) ax.set_title( "Q(t), expressed as energy, on a Coplanar Detector (5 $\mu m$ thickness kapton, 280 V bias) \n with Carrier Trapping Fluctuation. Scaling", fontsize=16, ) settings["CARRIER_LIFETIME_GEOMETRIC"] = 0 t, q = pd.computeChargeSignal(event, emfilename, **settings) ax.plot(t, -q / 1.6e-19 * 0.05, color="black", linewidth=1, label="No Noise") ax.legend() return fig, ax
def noise_histogram_parallel(): configfilename = "/home/apiers/aSe0vBB/carrierproduction/config.txt" # configfilename = "/home/apiers/mnt/rocks/aSe0vBB/carrierproduction/localconfig.txt" settings = sc.readConfigFile(configfilename) filename = settings["PARTICLE_FILENAME"] emfilename = settings["EM_FILENAME"] # nEvents = pd.numberOfEvents(filename) nEvents = 10000.0 simObj = pd.CarrierSimulation(emfilename=emfilename, configfile=configfilename) filesize = settings["NEVENTS_PER_FILE"] outdir = settings["OUTPUT_DIR"] outfilename = settings["OUTPUT_FILE"] # Chunk event collection into smaller pieces if needed for j in range(int(np.ceil(nEvents / filesize))): indx = [] # Create new event collect with the smaller chunck size newEventCollection = pd.gEventCollection( filename, eventCounterRange=[j * filesize, (j + 1) * filesize - 1]) simObj.newEventCollection(newEventCollection) for i in range(len(newEventCollection.collection)): event = newEventCollection.collection[i] zmin = min(event.z) ymin = np.min(np.abs(event.y)) xmin = np.min(np.abs(event.x)) eevent = np.sum(event.energy) # if xmin < 1.9 and ymin < 1.9 and zmin > -0.1: if (xmin < settings["X_MAX"] and ymin < settings["Y_MAX"] and zmin > settings["Z_MIN"]): indx.append(i) simOutput = simObj.processMultipleEvents(indx, processes=int( settings["NPROCESSORS"])) simOutput.setGitInfo(settings["GIT_DIR"]) simObj.outputfile = outfilename % j simObj.outputdir = outdir simObj.savedata(simOutput) signal = 0
def __init__(self, emfilename=None, eventCollection=None, configfile=None): """ Initialize the class """ self.emfilname = emfilename self.configfile = configfile # Default work function of 0.05 keV/ehp self.symbolTable = cexprtk.Symbol_Table({"E": 10}, add_constants=True) self.wehpExpression = cexprtk.Expression("0.05", self.symbolTable) # Read and store settings print("Read config") if configfile: self.settings = sc.readConfigFile(configfile) else: self.settings = None warnings.warn( "No Settings File Read. Please read (or create) class settings and run applySettings()." ) return # Read and store particle data print("Read Geant4 Simulation Data") if type(eventCollection) is str: self.eventCollection = gEventCollection(eventCollection) else: self.eventCollection = eventCollection # Read and store emdata print("Read Comsol EM Data") if emfilename: self.newEmFile(emfilename) else: self.x = self.y = self.z = self.data = [] self.applySettings() if self.settings["SCALE_WEIGHTED_PHI"]: self.computeScaleFactor() else: self.scale = 1
def signalAnalysis(): filename = r"C:\Users\alexp\Documents\UW\Research\Selenium\aSe0vBB\particle\selenium-build\output\122_keV_testTuple.root" emfilename = [ r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_1um_spacing_fullsize.txt", r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_3um_spacing_fullsize.txt", r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize.txt", r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_8um_spacing_fullsize.txt", ] configfilename = r"./config.txt" print ("Read settings") settings = sc.readConfigFile(configfilename) print ("Read Geant4 Particle data") newCollection = pd.gEventCollection(filename) event = newCollection.collection[140] creatorProc = event.GetHits()[1]["creatorProcess"].split("\x00")[0] print ("Calculating induced charge signal") for file in emfilename: biasVoltIndex = [0, 1, 2, 3, 4] plt.rc("font", family="serif") fig, ax = plt.subplots() bmap = brewer2mpl.get_map("Set1", "Qualitative", 5).mpl_colors biasString = ["120 V", "160 V", "200 V", "240 V", "280 V"] for indx in biasVoltIndex: print (indx) settings["VOLTAGE_SWEEP_INDEX"] = indx time, q = pd.computeChargeSignal(event, file, **settings) ax.plot(time, -q, linewidth=2, color=bmap[indx], label=biasString[indx]) ax.set_xlabel(r"Time ($\mu s$)", fontsize=14) ax.set_ylabel(r"Induced Charge (C)", fontsize=14) ax.set_title( "Induced Charge Signal at Amplifier for %s Kapton layer" % file.split("\\")[-1].split("_")[3] ) ax.legend() return fig, ax
def testScaleFactor(): filename = r"C:\Users\alexp\Documents\UW\Research\Selenium\aSe0vBB\particle\selenium-build\output\122_keV_testTuple.root" emfilename = r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize.txt" gCollection = pd.gEventCollection(filename) event = gCollection.collection[146] configfilename = r"./config.txt" allhits = event.GetHits() etot = 0 for i in allhits: etot += i["energy"] print (etot) print (allhits[1]["y"]) event.plotH2() settings = sc.readConfigFile(configfilename) settings["SCALE_WEIGHTED_PHI"] = 1 t, q = pd.computeChargeSignal(event, emfilename, **settings) settings["SCALE_WEIGHTED_PHI"] = 0 tt, qq = pd.computeChargeSignal(event, emfilename, **settings) # fig, ax = plt.subplots() # ax.plot(t, -q, 'k', linewidth=3) # ax.plot(tt, -qq, '-b', linewidth=3) # ax.set_xlabel(r'Time ($\mu s$)', fontsize=14) # ax.set_ylabel(r'Induced Charge (C)', fontsize=14) # ax.legend(['Scaled', 'Not Scaled']) # return fig, ax return etot
def main(argv): """ Main program that acts as an entry point to the simulation """ # Set default values configfile = "./carrierproduction/config.txt" nEvents = 0 parser = argparse.ArgumentParser( description="Process command line arguments for Selena simulation" ) # Add arguments to the parsers parser.add_argument( "-c", "--configfile", nargs="?", default="./carrierproduction/config.txt" ) parser.add_argument("-n", "--number", nargs="?", default=0, type=int) parser.add_argument("-v", "--configvar") parser.add_argument("configvarValue", nargs="*", default=["None"]) commandArgs = parser.parse_args() # Assign command line variables configfile = commandArgs.configfile nEvents = commandArgs.number # Setup and run the simulation settings = sc.readConfigFile(configfile) particlefilename = settings["PARTICLE_FILENAME"] emfilename = settings["EM_FILENAME"] if nEvents <= 0: nEvents = pd.numberOfEvents(particlefilename) # Print simulation information print ("Config file is %s" % configfile) print ("Number of events is %i\n" % nEvents) simObj = pd.CarrierSimulation(emfilename=emfilename, configfile=configfile) # Iterate over the values passed to the config var value for val in commandArgs.configvarValue: filesize = settings["NEVENTS_PER_FILE"] outdir = settings["OUTPUT_DIR"] outfilename = settings["OUTPUT_FILE"] if val != "None": print ("\nConfig variable: " + commandArgs.configvar + " = " + val) outfilename = ( settings["OUTPUT_FILE"].split(".")[0] + "_" + commandArgs.configvar + "_" + val + "." + settings["OUTPUT_FILE"].split(".")[1] ) # Try to parse config value into double if that is the form of the command line arguments try: val = float(val) except ValueError: pass except Exception as e: print (str(e)) return # Change the configvar in the settings and apply simObj.settings[commandArgs.configvar] = val simObj.settings["OUTPUT_FILE"] = outfilename simObj.applySettings() # Chunk event collection into smaller pieces if needed for j in range(int(np.ceil(float(nEvents) / filesize))): indx = [] # Create new event collect with the smaller chunck size newEventCollection = pd.gEventCollection( particlefilename, eventCounterRange=[j * filesize, (j + 1) * filesize - 1], zoffset=settings["Z_OFFSET"], ) simObj.newEventCollection(newEventCollection) for i in range(len(newEventCollection.collection)): event = newEventCollection.collection[i] zr = np.max(np.abs(event.z)) yr = np.max(np.abs(event.y)) xr = np.max(np.abs(event.x)) eevent = np.sum(event.energy) zmean = np.sum(np.array(event.z) * np.array(event.energy)) / np.sum( event.energy ) if ( xr < settings["X_MAX"] and yr < settings["Y_MAX"] and zr < settings["Z_MAX"] # and zmean < 0.06 # and zmean > 0.01 # and eevent > 115 ): indx.append(i) simOutput = simObj.processMultipleEvents( indx, processes=int(settings["NPROCESSORS"]) ) # simOutput = simObj.processMultipleEvents( # [indx[50]], processes=int(settings["NPROCESSORS"]) # ) simOutput.setGitInfo(settings["GIT_DIR"]) simObj.outputfile = outfilename % j simObj.outputdir = outdir simObj.savedata(simOutput) return
def noise_histogram(): filename = r"C:\Users\alexp\Documents\UW\Research\Selenium\aSe0vBB\particle\selenium-build\output\122_keV_testTupleLarge.root" emfilename = r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize.txt" configfilename = r"./config.txt" settings = sc.readConfigFile(configfilename) # For planar detector settings["CHARGE_DIFFERENCE"] = 1 settings["VOLTAGE_SWEEP_INDEX"] = 4 settings["SCALE_WEIGHTED_PHI"] = 1 # color scheme bmap = brewer2mpl.get_map("Dark2", "Qualitative", 5).mpl_colors # Read event data collection = pd.gEventCollection(filename) event = collection.collection[125] N = 50 wehp = 0.05 # keV e = 1.6e-19 energy = [] charge = [] charge1usNoTrapping = [] charge20usNoTrapping = [] charge1usTrapping = [] charge20usTrapping = [] allfig = [] allax = [] for i in range(N): print(i) energy.append(sum(event.energy)) # nehp, nehpFluctuations, _, _ = event.createCarriers(**settings) # totalCharge = np.sum((nehp + nehpFluctuations) * wehp) # charge.append(totalCharge) # No Trapping settings["CARRIER_LIFETIME_GEOMETRIC"] = 0 t, qNo = pd.computeChargeSignal(event, emfilename, **settings) indx1us = np.where(t > 1)[0][0] indx20us = np.where(t > 20)[0][0] charge1usNoTrapping.append(-qNo[indx1us] / e * wehp) charge20usNoTrapping.append(-qNo[indx20us] / e * wehp) # Trapping settings["CARRIER_LIFETIME_GEOMETRIC"] = 1 t, qTrap = pd.computeChargeSignal(event, emfilename, **settings) indx1us = np.where(t > 0.5)[0][0] indx20us = np.where(t > 22)[0][0] charge1usTrapping.append(-qTrap[indx1us] / e * wehp) charge20usTrapping.append(-qTrap[indx20us] / e * wehp) fig, ax = plt.subplots() ax.plot(t, -qTrap) # Energy histogram fig, ax = plt.subplots() ax.hist(energy, bins=100, range=(100, 140), histtype="step", linewidth=2, color=bmap[0]) ax.set_title("Energy Deposited in Event %i" % event.GetEventID(), fontsize=16) ax.set_xlabel("Energy (keV)", fontsize=14) allfig.append(fig), allax.append(ax) # Charge creation histogram # fig, ax = plt.subplots() # ax.hist(charge, bins=100, range=(100,140), histtype='step', linewidth=2, color=bmap[0]) # ax.set_title('Charge Created with Poisson Fluctuations in Event %i' % event.GetEventID(), fontsize=16) # ax.set_xlabel('Energy (keV)', fontsize=14) # Induced charge, trapping fig, ax = plt.subplots() ax.hist( charge1usTrapping, bins=122, range=(0, 122), histtype="step", linewidth=2, color=bmap[0], label="1 $\mu s$", ) ax.hist( charge20usTrapping, bins=122, range=(0, 122), histtype="step", linewidth=2, color=bmap[1], label="20 $\mu s$", ) ax.set_title( "Charge Induced at Planar Detector (Poisson and Trapping Fluctuations) in Event %i" % event.GetEventID(), fontsize=16, ) ax.set_xlabel("Energy (keV)", fontsize=14) ax.legend() allfig.append(fig), allax.append(ax) # Induced charge, no trapping fig, ax = plt.subplots() ax.hist( charge1usNoTrapping, bins=122, range=(0, 122), histtype="step", linewidth=2, color=bmap[0], label="1 $\mu s$", ) ax.hist( charge20usNoTrapping, bins=122, range=(0, 122), histtype="step", linewidth=2, color=bmap[1], label="20 $\mu s$", ) ax.set_title( "Charge Induced at Planar Detector (Poisson and No Trapping Fluctuations) in Event %i" % event.GetEventID(), fontsize=16, ) ax.set_xlabel("Energy (keV)", fontsize=14) ax.legend() allfig.append(fig), allax.append(ax) return allfig, allax
def noise_histogram_multiple_events(): filename = r"C:\Users\alexp\Documents\UW\Research\Selenium\aSe0vBB\particle\selenium-build\output\122_keV_testTuple.root" emfilename = r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize.txt" configfilename = r"./config.txt" settings = sc.readConfigFile(configfilename) # manipulate settings eventCollection = pd.gEventCollection(filename) eventCollection.printInfo() wehp = 0.05 # keV e = 1.6e-19 bmap = brewer2mpl.get_map("Dark2", "Qualitative", 5).mpl_colors # data storage allfig = [] allax = [] # info for iterating over 3 cases emfilename = [ r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize_fine.txt", r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\kapton_layer_analysis_5um_spacing_fullsize_fine.txt", r"C:\Users\alexp\Documents\UW\Research\Selenium\Coplanar Detector\sim_data\real_electrode.txt", ] plotTitle = [ "Coplanar Detector No Scaling", "Coplanar Detector Scaling", "Planar Detector", ] chargediff = [1, 1, 0] voltageIndx = [4, 4, 0] scaleWeight = [0, 1, 0] neg = [-1, -1, 1] # iterate over each event. Pick 122 keV and do simulation on them for j in range(len(plotTitle)): charge1usNoTrapping = [] charge20usNoTrapping = [] charge1usTrapping = [] charge20usTrapping = [] settings["CHARGE_DIFFERENCE"] = chargediff[j] settings["VOLTAGE_SWEEP_INDEX"] = voltageIndx[j] settings["SCALE_WEIGHTED_PHI"] = scaleWeight[j] for i, event in enumerate(eventCollection.collection): etot = sum(event.energy) zmin = min(event.z) # if energy is 122 kev, we do the analysis if round(etot) == 122: if np.max(np.abs(event.y)) < 0.5 and zmin > -0.05: # No trapping settings["CARRIER_LIFETIME_GEOMETRIC"] = 0 # t, qNo = pd.computeChargeSignal(event, emfilename[j], **settings) # indx1us = np.where(t > 1)[0][0] # indx20us = t.size - 1 q1, q20 = charge_compute_wrapper(event, emfilename[j], e, wehp, neg[j], **settings) charge1usNoTrapping.append(q1) charge20usNoTrapping.append(q20) print("1 us. Event ID %i: %f" % (event.GetEventID(), q1)) print("20 us. Event ID %i: %f" % (event.GetEventID(), q20)) # Trapping # settings['CARRIER_LIFETIME_GEOMETRIC'] = 0 # t, qTrap = pd.computeChargeSignal(event, emfilename[j], **settings) # indx1us = np.where(t >1)[0][0] # indx20us = t.size - 1 # charge1usTrapping.append(neg[j]*qTrap[indx1us]/e * wehp) # charge20usTrapping.append(neg[j]*qTrap[indx20us]/e * wehp) # Induced charge, trapping # fig, ax = plt.subplots() # ax.hist(charge1usTrapping, bins=130, range=(0,130), histtype='step', linewidth=2, color=bmap[0], label='1 $\mu s$, mean=%.2f, rms=%.2f' %(np.mean(charge1usTrapping), np.std(charge1usTrapping))) # ax.hist(charge20usTrapping, bins=130, range=(0,130), histtype='step', linewidth=2, color=bmap[1], label='20 $\mu s$, mean=%.2f, rms=%.2f' %(np.mean(charge20usTrapping), np.std(charge20usTrapping))) # ax.set_title('Charge Induced at %s for Different 122 keV Events'%plotTitle[j], fontsize=16) # ax.set_xlabel('Energy (keV)', fontsize=14) # ax.legend(loc=2) # allfig.append(fig), allax.append(ax) # Induced charge, no trapping fig, ax = plt.subplots() ax.hist( charge1usNoTrapping, bins=130, range=(0, 130), histtype="step", linewidth=2, color=bmap[0], label="1.5 $\mu s$, mean=%.2f, rms=%.2f" % (np.mean(charge1usNoTrapping), np.std(charge1usNoTrapping)), ) ax.hist( charge20usNoTrapping, bins=130, range=(0, 130), histtype="step", linewidth=2, color=bmap[1], label="20 $\mu s$, mean=%.2f, rms=%.2f" % (np.mean(charge20usNoTrapping), np.std(charge20usNoTrapping)), ) ax.set_title( "Charge Induced at %s for Different 122 keV Events" % plotTitle[j], fontsize=16, ) ax.set_xlabel("Energy (keV)", fontsize=14) ax.legend(loc=2) allfig.append(fig), allax.append(ax) return allfig, allax
def newSettings(self, configfile): self.settings = sc.readConfigFile(configfile)
# Testing the operation of these objects import seleniumconfig as sc import particledata as pd # Create the data for the simulated pulse objects Load test particle data eventCol = pd.gEventCollection( "/home/apiers/mnt/rocks/selena/data/particle/pixel_sio2_122kev_12degBeam_100k.root", eventCounterRange=[0, 5], ) # Load config file config = sc.readConfigFile( "/home/apiers/mnt/rocks/aSe0vBB/carrierproduction/config.txt" ) # Create fake data n = 100 t = np.linspace(0, 10, n) s1 = t[0 : int(np.random.uniform(1, n))] * np.random.uniform(0, 1) s2 = t[0 : int(np.random.uniform(1, n))] * np.random.uniform(0, 1) signal = np.concatenate((s1, s1[-1] * np.ones(n - s1.size))) + np.concatenate( (s2, s2[-1] * np.ones(n - s2.size)) ) x, y, z = [1, 1, 1], [1, 2, 3], [5, 7, 7] energy = np.array([12, 10, 100]) wehp = np.array([0.04, 0.041, 0.042]) nehp = energy / wehp nehpf = np.random.poisson(nehp)