def main(config, ForceIntLEDLoad=True): # Construct a main "ADC Calibtation" Object, which we will return and manipulate # later using a GUI.... Calibration = ADCCalibration() # Load the status object to determine the state # of the calibration: Calibration.status = FECalibrationUtils.LoadCalibrationStatus(config["path"]) #Try to load an existing calibration: try: Calibration.FEChannels = FECalibrationUtils.LoadFEChannelList(os.path.join(config["path"],config["FECalibrations"])) print ("Loaded existing FECalibrations %s"%config["FECalibrations"]) except: Calibration.FEChannels = FECalibrationUtils.GenerateFEChannelList() print ("No existing FECalibrations found... Generated some empty data") # Applying Bias voltages (non-essensial step): if not ("BiasStored" in Calibration.status) or ( Calibration.status["BiasStored"] == False): # Load and apply bias settings: try: bias_path = os.path.join(config["path"], config["Biases_Filename"]) FECalibrationUtils.ApplyBiasData(Calibration.FEChannels, bias_path) Calibration.status["BiasStored"] = True print ("Loaded Biases from file: %s"%bias_path) except: print ("Failed to load Biases, no problem, igonoring.") # Apply bad channels list to the data: if not ("BadFE" in Calibration.status) or ( Calibration.status["BadFE"] == False): try: badfe_filename = os.path.join(config["path"], config["BadFE_Filename"]) FECalibrationUtils.ApplyBadChannels(Calibration.FEChannels, badfe_filename) Calibration.status["BadFE"] = True print ("Loaded Bad FE channels from: %s"%badfe_filename) except: print ("Failed to Bad FE channels, no problem, igonoring.") # Apply tracker mapping to data: if not ("Mapped" in Calibration.status) or (Calibration.status["Mapped"] == False): try: mapping_filename = os.path.join(config["path"], config["Mapping_Filename"]) TrackerMap = FECalibrationUtils.LoadMappingFile (mapping_filename) FECalibrationUtils.UpdateTrackerMapping(Calibration.FEChannels, TrackerMap) Calibration.status["Mapped"] = True print ("Loaded Mapping from: %s"%mapping_filename) except: print "Failed to load Mapping file, essensial, terminating." raise # Disable external LED processing: # WARNING: Remove in final version. Calibration.status["ExternalLED"] = True # Now try to load some of the external LED Data, and process: if not ("ExternalLED" in Calibration.status) or (Calibration.status["ExternalLED"] == False): try: print ("Attempting to load external led files ...") # Load the external LED list: leds_dict = config["ExternalLED"] for d in leds_dict: d["filepath"] = os.path.join(config["DataPath"],d["filename"]) # Load the files: external_files = [d for d in leds_dict if d["led"]] Calibration.ExtLEDHist = TrDAQReader.TrMultiDAQRead(external_files , "ExternalLED") notexternal_files = [d for d in leds_dict if not d["led"]] Calibration.ExtNoLEDHist = TrDAQReader.TrMultiDAQRead(notexternal_files , "ExternalNoLED") print ("... done loading external files") # Use the files to generate an LYE calibration: for FEChannel in Calibration.FEChannels: # Channel to process: ChannelUID = FEChannel.ChannelUID # Get single channel hisrogram, and nuke all channels below 15, # to stop peaks being found there in the event there is hits there. PedHist_LED = Calibration.ExtLEDHist.ProjectionY("th1d_led",ChannelUID+1,ChannelUID+1,"") for i in range (15): PedHist_LED.SetBinContent(i, 0.0) # Check for data, if no data then flag it in the "Issues" array. if (PedHist_LED.GetEntries() < 1): FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":10,\ "Issue":"ExternalLED","Comment":"Missing external LED data"}) continue # Data Available, do the fitting processes: # Run std processing on the pedestal histagram. LightYield_LED = LightYieldEstimator() LightYield_LED.process(PedHist_LED) # Check the state of the output: if LightYield_LED.ChannelState != "PEPeaks": FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":4,\ "Issue":"ExternalLED","Comment":"Failed to find LED Peaks"}) continue # Fit each peak, and try to improve location: for p in range(len(LightYield_LED.Peaks)): PeakFitResults = LightYield_LED.fitPeak(PedHist_LED, p) # Check each result, and copy only if good: if (abs(PeakFitResults[1] - LightYield_LED.Peaks[p]) < 3.0) \ and (not math.isnan(PeakFitResults[1])): LightYield_LED.Peaks[p] = PeakFitResults[1] else: print "Warning - Bad LED Fit..." # Compute the gain from the peaks, and store object to # main FE channel Data structure... LightYield_LED.gain = LightYield_LED.gainEstimator() FEChannel.ADC_Pedestal = LightYield_LED.offset FEChannel.ADC_Gain = LightYield_LED.gain std_peaks = [LightYield_LED.offset + i*LightYield_LED.gain for i in range(5)] LightYield_LED.peakIntegrals(PedHist_LED, std_peaks) FEChannel.LightYieldExtLED = LightYield_LED.getMap() # Generate and process the NOLED Data: PedHist_NoLED = Calibration.ExtNoLEDHist.ProjectionY("th1d_noled",ChannelUID+1,ChannelUID+1,"") for i in range (15): PedHist_NoLED.SetBinContent(i, 0.0) # Check for data, if no data then flag it in the "Issues" array. if (PedHist_NoLED.GetEntries() < 1): FEChannel.Issues.append("Missing external NoLED data") continue LightYield_NoLED = LightYieldEstimator() LightYield_NoLED.process(PedHist_NoLED, LightYield_LED) # Finally generate some estimates on noises: # note that the peaks are generated from the calibration for # consistency. LightYield_NoLED.peakIntegrals(PedHist_NoLED, std_peaks) # Done - save map! FEChannel.LightYieldExtNoLED = LightYield_NoLED.getMap() # Finally compare two histograms to identify defunct channels # (ie. those not connected). p_value = PedHist_NoLED.Chi2Test(PedHist_LED, "UUP") # Done with external LED, update statuses: Calibration.status["ExternalLED"] = True except: raise # Next task, process internal LED: if not ("InternalLED" in Calibration.status) or (Calibration.status["InternalLED"] == False)\ or ForceIntLEDLoad: try: print ("Attempting to load internal led files ...") if len(config["InternalLED"]) == 0: raise ("No Files to load!") elif "pedcalib" in config["InternalLED"][0]: Calibration.IntNoLEDHist, Calibration.IntLEDHist =\ FECalibrationUtils.LoadPedCalib(os.path.join(config["DataPath"],config["InternalLED"][0]["pedcalib"])) else: # Load the external LED list: leds_dict = config["InternalLED"] for d in leds_dict: d["filepath"] = os.path.join(config["DataPath"],d["filename"]) # Load the files: internal_files = [d for d in leds_dict if d["led"]] Calibration.IntLEDHist = TrDAQReader.TrMultiDAQRead(internal_files , "InternalLED") notinternal_files = [d for d in leds_dict if not d["led"]] Calibration.IntNoLEDHist = TrDAQReader.TrMultiDAQRead(notinternal_files , "InternalNoLED") if ( Calibration.IntNoLEDHist is None ) or ( Calibration.IntLEDHist is None): print ("error loading internal led files") else: print ("... done loading external files") except: raise # Next task, process internal LED: if not ("InternalLED" in Calibration.status) or (Calibration.status["InternalLED"] == False): # Use the files to generate an LYE calibration: poisson_ipar = None for FEChannel in Calibration.FEChannels: # Channel to process: ChannelUID = FEChannel.ChannelUID print "Processing channel: ", ChannelUID # Wrap in a try loop to catch and skip errors... try: # Get single channel hisrogram, and nuke all channels below 15, # to stop peaks being found there in the event there is hits there. PedHist_LED = Calibration.IntLEDHist.ProjectionY("th1d_led",ChannelUID+1,ChannelUID+1,"") for i in range (10): PedHist_LED.SetBinContent(i, 0.0) # Check for data, if no data then flag it in the "Issues" array. if (PedHist_LED.GetEntries() < 1): FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":4,\ "Issue":"InternalLED","Comment":"Failed to find LED Data"}) continue # Generate and process the NOLED Data: PedHist_NoLED = Calibration.IntNoLEDHist.ProjectionY("th1d_noled",ChannelUID+1,ChannelUID+1,"") for i in range (15): PedHist_NoLED.SetBinContent(i, 0.0) # Check for data, if no data then flag it in the "Issues" array. if (PedHist_NoLED.GetEntries() < 1): FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":4,\ "Issue":"InternalLED","Comment":"Missing internal NoLED data"}) continue LightYield_LED = LightYieldEstimator() LightYield_NoLED = LightYieldEstimator() # Attempt Poisson fitting of data: dopoissonfit = True poissonfit = None if dopoissonfit: #Do the fit: poissonfit = PoissonPeakFitter.combinedfit(PedHist_NoLED, PedHist_LED, poisson_ipar) #PoissonPeakFitter.drawfits(poissonfit["fit"], PedHist_NoLED, PedHist_LED) poissonfit["fit"].Result().Print(ROOT.cout,True) # Check the status of the result if poissonfit["fit"].Result().Status() == 0: # Sotore and check fit result, only update ipar if chisq looks good. FEChannel.InternalPoissonFitResult = poissonfit["fitpar"] if FEChannel.InternalPoissonFitResult["ndf"] > 0: chi_ndf = FEChannel.InternalPoissonFitResult["chisq"]/FEChannel.InternalPoissonFitResult["ndf"] else: chi_ndf = 100 if chi_ndf> 5.0: FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":6,\ "Issue":"PoissonFit","Comment":"high chisquare/ndf for fit: %i"% chi_ndf}) else: poisson_ipar = [poissonfit["fit"].Result().Parameter(i) for i in range(8)] else: FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":7,\ "Issue":"PoissonFit","Comment":"Failed to Fit LED Data, status: %i"% poissonfit["fit"].Result().Status()}) poissonfit = None # Data Available, do the fitting processes: # Run std processing on the pedestal histagram. # Use the poisson result(if available), and skip peak finding. LightYield_LED.process(PedHist_LED, poissonfit=poissonfit) # Fit each peak, and try to improve location: if poissonfit is None: for p in range(len(LightYield_LED.Peaks)): PeakFitResults = LightYield_LED.fitPeak(PedHist_LED, p) # Check each result, and copy only if good: if (abs(PeakFitResults[1] - LightYield_LED.Peaks[p]) < 3.0) \ and (not math.isnan(PeakFitResults[1])): LightYield_LED.Peaks[p] = PeakFitResults[1] else: print "Warning - Bad LED Fit..." # Check the state of the output: if LightYield_LED.ChannelState != "PEPeaks": FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":4,\ "Issue":"InternalLED","Comment":"Failed to find LED Peaks"}) continue # Compute the gain from the peaks, and store object to # main FE channel Data structure... LightYield_LED.gain = LightYield_LED.gainEstimator() LightYield_LED.offset = LightYield_LED.Peaks[0] LightYield_NoLED.process(PedHist_NoLED, LightYield_LED, poissonfit=poissonfit) FEChannel.ADC_Pedestal = LightYield_LED.offset FEChannel.ADC_Gain = LightYield_LED.gain std_peaks = [LightYield_LED.offset + i*LightYield_LED.gain for i in range(5)] LightYield_LED.peakIntegrals(PedHist_LED, std_peaks) FEChannel.LightYieldIntLED = LightYield_LED.getMap() # Finally generate some estimates on noises: # note that the peaks are generated from the calibration for # consistency. LightYield_NoLED.peakIntegrals(PedHist_NoLED, std_peaks) # Done - save map! FEChannel.LightYieldIntNoLED = LightYield_NoLED.getMap() p_value = PedHist_NoLED.Chi2Test(PedHist_LED, "UUP") if (p_value > 0.03): FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":6,\ "Issue":"InternalLED","Comment":"LED pedestal matches no LED pedestal."}) except KeyboardInterrupt: raise except: FEChannel.Issues.append({"ChannelUID":ChannelUID, "Severity":10,\ "Issue":"Data","Comment":"Failed to process channel"}) # Done with external LED, update statuses: Calibration.status["InternalLED"] = True # Update Channel Staturses for FEChannel in Calibration.FEChannels: try: if len(FEChannel.Issues) == 0: FEChannel.Status = "GOOD" except: continue # Final Task, return Calibration: return Calibration