From b02e721cc7c637bfd0c368d7e6d64c9fafd880f9 Mon Sep 17 00:00:00 2001 From: nstelter-slac Date: Wed, 3 Apr 2024 21:29:27 -0700 Subject: [PATCH] ENH: refactor psana*Base clases Idea is to use psanaBase for handling 1 vs 2 differences, and move all shared vars and funcs into suiteBase --- calibrationSuite/psana1.py | 81 +++++ calibrationSuite/psana1Base.py | 163 ---------- calibrationSuite/psana2.py | 89 ++++++ calibrationSuite/psana2Base.py | 290 ------------------ calibrationSuite/psanaBase.py | 122 ++++++++ .../{commonPsanaBase.py => suiteBase.py} | 207 +++++++++++-- suite_scripts/TimeScanParallelSlice.py | 4 +- 7 files changed, 467 insertions(+), 489 deletions(-) create mode 100644 calibrationSuite/psana1.py delete mode 100755 calibrationSuite/psana1Base.py create mode 100644 calibrationSuite/psana2.py delete mode 100755 calibrationSuite/psana2Base.py create mode 100755 calibrationSuite/psanaBase.py rename calibrationSuite/{commonPsanaBase.py => suiteBase.py} (74%) diff --git a/calibrationSuite/psana1.py b/calibrationSuite/psana1.py new file mode 100644 index 0000000..a15f65d --- /dev/null +++ b/calibrationSuite/psana1.py @@ -0,0 +1,81 @@ +from calibrationSuite.psanaBase import * +import logging +logger = logging.getLogger(__name__) + +def setupPsana1(baseObj): + + if baseObj.runRange is None: + baseObj.ds = baseObj.get_ds(baseObj.run) + else: + baseObj.run = baseObj.runRange[0] + baseObj.ds = baseObj.get_ds() + + baseObj.det = Detector("%s.0:%s.%d" % (baseObj.location, baseObj.detType, baseObj.camera), baseObj.ds.env()) + baseObj.evrs = None + try: + baseObj.wave8 = Detector(baseObj.fluxSource, baseObj.ds.env()) + except: + baseObj.wave8 = None + baseObj.config = None + try: + baseObj.controlData = Detector("ControlData") + except: + baseObj.controlData = None + +def getFluxPsana1(baseObj, evt): + try: + fluxes = baseObj.wave8.get(evt).peakA() + if fluxes is None: + print("No flux found") ## if baseObj.verbose? + logger.error("No flux found") + return None + f = fluxes[baseObj.fluxChannels].mean() * baseObj.fluxSign + try: + if f < baseObj.fluxCut: + return None + except: + pass + except: + return None + return f + +def isKickedPsana1(baseObj, evt): + try: + evr = evt.get(EvrData.DataV4, baseObj.evrs[0]) + except: + baseObj.get_evrs() + evr = evt.get(EvrData.DataV4, baseObj.evrs[0]) + + ## kicked = False + ## try: + ## for ec in evr.fifoEvents(): + ## if ec.eventCode() == 162: + ## return True + kicked = True + try: + for ec in evr.fifoEvents(): + if ec.eventCode() == 137: + kicked = False + except: + pass + return kicked + +def getEvtPsana1(baseObj, run=None): + oldDs = baseObj.ds + if run is not None: + baseObj.ds = baseObj.get_ds(run) + try: ## or just yield evt I think + evt = next(baseObj.ds.events()) + except StopIteration: + baseObj.ds = oldDs + return None + baseObj.ds = oldDs + return evt + +def getRawDataPsana1(baseObj, evt, gainBitsMasked=True): + frames = baseObj.det.raw(evt) + if frames is None: + return None + if gainBitsMasked: + return frames & 0x3FFF + return frames diff --git a/calibrationSuite/psana1Base.py b/calibrationSuite/psana1Base.py deleted file mode 100755 index 7e9bd98..0000000 --- a/calibrationSuite/psana1Base.py +++ /dev/null @@ -1,163 +0,0 @@ -############################################################################## -## This file is part of 'SLAC Beamtime Calibration Suite'. -## It is subject to the license terms in the LICENSE.txt file found in the -## top-level directory of this distribution and at: -## https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. -## No part of 'SLAC Beamtime Calibration Suite', including this file, -## may be copied, modified, propagated, or distributed except according to -## the terms contained in the LICENSE.txt file. -############################################################################## -from psana import * -from calibrationSuite.commonPsanaBase import * -from PSCalib.NDArrIO import load_txt -import logging -logger = logging.getLogger(__name__) - - -class PsanaBase(CommonPsanaBase): - def __init__(self, analysisType="scan"): - super().__init__(analysisType) - self.psanaType = 1 - print("in psana1Base") - logger.info("in psana1Base") - - - def get_ds(self, run=None): - if run is None: - run = self.run - return DataSource("exp=%s:run=%d:smd" % (self.exp, run)) - - def setupPsana(self): - logger.info("have built basic script class, exp %s run %d" % (self.exp, self.run)) - - if self.runRange is None: - self.ds = self.get_ds(self.run) - else: - self.run = self.runRange[0] - self.ds = self.get_ds() - - self.det = Detector("%s.0:%s.%d" % (self.location, self.detType, self.camera), self.ds.env()) - self.evrs = None - try: - self.wave8 = Detector(self.fluxSource, self.ds.env()) - except: - self.wave8 = None - self.config = None - try: - self.controlData = Detector("ControlData") - except: - self.controlData = None - - - def getEvt(self, run=None): - oldDs = self.ds - if run is not None: - self.ds = self.get_ds(run) - try: ## or just yield evt I think - evt = next(self.ds.events()) - except StopIteration: - self.ds = oldDs - return None - self.ds = oldDs - return evt - - def getEvtFromRunsTooSmartForMyOwnGood(self): - for r in self.runRange: - self.run = r - self.ds = self.get_ds() - try: - evt = next(self.ds.events()) - yield evt - except: - continue - - def getEvtFromRuns(self): - try: ## can't get yield to work - evt = next(self.ds.events()) - return evt - except StopIteration: - i = self.runRange.index(self.run) - try: - self.run = self.runRange[i + 1] - print("switching to run %d" % (self.run)) - logger.info("switching to run %d" % (self.run)) - self.ds = self.get_ds(self.run) - except: - print("have run out of new runs") - logger.exception("have run out of new runs") - return None - ##print("get event from new run") - evt = next(self.ds.events()) - return evt - - def getFlux(self, evt): - try: - fluxes = self.wave8.get(evt).peakA() - if fluxes is None: - print("No flux found") ## if self.verbose? - logger.error("No flux found") - return None - f = fluxes[self.fluxChannels].mean() * self.fluxSign - try: - if f < self.fluxCut: - return None - except: - pass - except: - return None - return f - - def get_evrs(self): - if self.config is None: - self.get_config() - - self.evrs = [] - for key in list(self.config.keys()): - if key.type() == EvrData.ConfigV7: - self.evrs.append(key.src()) - - def isKicked(self, evt): - try: - evr = evt.get(EvrData.DataV4, self.evrs[0]) - except: - self.get_evrs() - evr = evt.get(EvrData.DataV4, self.evrs[0]) - - ## kicked = False - ## try: - ## for ec in evr.fifoEvents(): - ## if ec.eventCode() == 162: - ## return True - kicked = True - try: - for ec in evr.fifoEvents(): - if ec.eventCode() == 137: - kicked = False - except: - pass - return kicked - - def getScanValue(self, foo): - return self.controlData().pvControls()[0].value() - - def getStepGen(self): - return self.ds.steps() - - def getRawData(self, evt, gainBitsMasked=True): - frames = self.det.raw(evt) - if frames is None: - return None - if gainBitsMasked: - return frames & 0x3FFF - return frames - - def getCalibData(self, evt): - return self.det.calib(evt) - - -if __name__ == "__main__": - bSS = BasicSuiteScript() - print("have built a BasicSuiteScript") - bSS.setupPsana() - evt = bSS.getEvt() - print(dir(evt)) diff --git a/calibrationSuite/psana2.py b/calibrationSuite/psana2.py new file mode 100644 index 0000000..e641576 --- /dev/null +++ b/calibrationSuite/psana2.py @@ -0,0 +1,89 @@ +from calibrationSuite.psanaBase import * +logger = logging.getLogger(__name__) + +def setupPsana2(baseObj): + + if baseObj.runRange is None: + baseObj.ds = baseObj.get_ds(baseObj.run) + else: + baseObj.run = baseObj.runRange[0] + baseObj.ds = baseObj.get_ds() + + baseObj.myrun = next(baseObj.ds.runs()) + try: + baseObj.step_value = baseObj.myrun.Detector("step_value") + baseObj.step_docstring = baseObj.myrun.Detector("step_docstring") + except: + baseObj.step_value = baseObj.step_docstring = None + + ## baseObj.det = Detector('%s.0:%s.%d' %(baseObj.location, baseObj.detType, baseObj.camera), baseObj.ds.env()) + ## make this less dumb to accomodate epixM etc. + ## use a dict etc. + baseObj.det = baseObj.myrun.Detector(baseObj.experimentHash['detectorType']) + if baseObj.det is None: + print("no det object for epixhr, what? Pretend it's ok.") + ##raise Exception + ## could set to None and reset with first frame I guess, or does the det object know? + + baseObj.timing = baseObj.myrun.Detector("timing") + baseObj.desiredCodes = {"120Hz": 272, "4kHz": 273, "5kHz": 274} + + try: + baseObj.mfxDg1 = baseObj.myrun.Detector("MfxDg1BmMon") + except: + baseObj.mfxDg1 = None + print("No flux source found") ## if baseObj.verbose? + logger.exception("No flux source found") + try: + baseObj.mfxDg2 = baseObj.myrun.Detector("MfxDg2BmMon") + except: + baseObj.mfxDg2 = None + ## fix hardcoding in the fullness of time + baseObj.detEvts = 0 + baseObj.flux = None + + baseObj.evrs = None + try: + baseObj.wave8 = Detector(baseObj.fluxSource, baseObj.ds.env()) + except: + baseObj.wave8 = None + baseObj.config = None + try: + baseObj.controlData = Detector("ControlData") + except: + baseObj.controlData = None + +def getEvtPsana2(baseObj): + try: + evt = next(baseObj.myrun.events()) + ## dumb to do the below everywhere, should best not call this method + ##try: + ## baseObj.flux = baseObj._getFlux(evt) + ##except: + ## pass + + except StopIteration: + return None + return evt + +def getRawDataPsana2(baseObj, evt, gainBitsMasked=True): + frames = baseObj.det.raw.raw(evt) + if frames is None: + return None + if baseObj.special: + if 'thirteenBits' in baseObj.special: + frames = (frames & 0xfffe) + ##print("13bits") + elif 'twelveBits' in baseObj.special: + frames = (frames & 0xfffc) + ##print("12bits") + elif 'elevenBits' in baseObj.special: + frames = (frames & 0xfff8) + ##print("11bits") + elif 'tenBits' in baseObj.special: + frames = (frames & 0xfff0) + ##print("10bits") + if gainBitsMasked: + return frames & baseObj.gainBitsMask + return frames + diff --git a/calibrationSuite/psana2Base.py b/calibrationSuite/psana2Base.py deleted file mode 100755 index 3a00009..0000000 --- a/calibrationSuite/psana2Base.py +++ /dev/null @@ -1,290 +0,0 @@ -############################################################################## -## This file is part of 'SLAC Beamtime Calibration Suite'. -## It is subject to the license terms in the LICENSE.txt file found in the -## top-level directory of this distribution and at: -## https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. -## No part of 'SLAC Beamtime Calibration Suite', including this file, -## may be copied, modified, propagated, or distributed except according to -## the terms contained in the LICENSE.txt file. -############################################################################## -from psana import * -from calibrationSuite.commonPsanaBase import * -import logging -## for parallelism -import os -##from PSCalib.NDArrIO import load_txt - -os.environ["PS_SMD_N_EVENTS"] = "50" -os.environ["PS_SRV_NODES"] = "1" -## psana2 only - - -logger = logging.getLogger(__name__) - - -class PsanaBase(CommonPsanaBase): - def __init__(self, analysisType="scan"): - super().__init__(analysisType) - self.psanaType = 2 - print("in psana2Base") - logger.info("in psana2Base") - - self.allowed_timestamp_mismatch = 1000 - - ##self.setupPsana() - - def get_ds(self, run=None): - if run is None: - run = self.run - return DataSource(exp=self.exp, run=run, intg_det=self.experimentHash['detectorType'], max_events=self.maxNevents) - - def setupPsana(self): - ##print("have built basic script class, exp %s run %d" %(self.exp, self.run)) - if self.runRange is None: - print('a') - self.ds = self.get_ds(self.run) - else: - print('b') - self.run = self.runRange[0] - self.ds = self.get_ds() - - self.myrun = next(self.ds.runs()) - try: - self.step_value = self.myrun.Detector("step_value") - self.step_docstring = self.myrun.Detector("step_docstring") - except: - self.step_value = self.step_docstring = None - - ## self.det = Detector('%s.0:%s.%d' %(self.location, self.detType, self.camera), self.ds.env()) - ## make this less dumb to accomodate epixM etc. - ## use a dict etc. - self.det = self.myrun.Detector(self.experimentHash['detectorType']) - if self.det is None: - print("no det object for epixhr, what? Pretend it's ok.") - ##raise Exception - ## could set to None and reset with first frame I guess, or does the det object know? - - self.timing = self.myrun.Detector("timing") - self.desiredCodes = {"120Hz": 272, "4kHz": 273, "5kHz": 274} - - try: - self.mfxDg1 = self.myrun.Detector("MfxDg1BmMon") - except: - self.mfxDg1 = None - print("No flux source found") ## if self.verbose? - logger.exception("No flux source found") - try: - self.mfxDg2 = self.myrun.Detector("MfxDg2BmMon") - except: - self.mfxDg2 = None - ## fix hardcoding in the fullness of time - self.detEvts = 0 - self.flux = None - - self.evrs = None - try: - self.wave8 = Detector(self.fluxSource, self.ds.env()) - except: - self.wave8 = None - self.config = None - try: - self.controlData = Detector("ControlData") - except: - self.controlData = None - - ## if self.mfxDg1 is None: - - def getEvtOld(self, run=None): - oldDs = self.ds - if run is not None: - self.ds = self.get_ds(run) - try: ## or just yield evt I think - evt = next(self.ds.events()) - except StopIteration: - self.ds = oldDs - return None - self.ds = oldDs - return evt - - def getNextEvtFromGen(self, gen): - ## this is needed to get flux information out of phase with detector - ## information in mixed lcls1/2 mode - for nevt, evt in enumerate(gen): - try: - self.flux = self._getFlux(evt) - except: - pass - if self.det.raw.raw(evt) is None: - continue - self.detEvts += 1 - ## should check for beam code here to be smarter - return self.detEvts, evt - - def matchedDetEvt(self): - self.fluxTS = 0 - for nevt, evt in enumerate(self.myrun.events()): - ec = self.getEventCodes(evt) - if ec[137]: - self.flux = self._getFlux(evt) ## fix this - self.fluxTS = self.getTimestamp(evt) - continue - elif ec[281]: - self.framesTS = self.getTimestamp(evt) - if self.framesTS - self.fluxTS > self.allowed_timestamp_mismatch: - continue - yield evt - else: - continue - - def getEvtFromRunsTooSmartForMyOwnGood(self): - for r in self.runRange: - self.run = r - self.ds = self.get_ds() - try: - evt = next(self.ds.events()) - yield evt - except: - continue - - def getEvtFromRuns(self): - try: ## can't get yield to work - evt = next(self.ds.events()) - return(evt) - except StopIteration: - i = self.runRange.index(self.run) - try: - self.run = self.runRange[i + 1] - print("switching to run %d" % (self.run)) - logger.info("switching to run %d" % (self.run)) - self.ds = self.get_ds(self.run) - except: - print("have run out of new runs") - logger.exception("have run out of new runs") - return None - ##print("get event from new run") - evt = next(self.ds.events()) - return evt - - def getAllFluxes(self, evt): - if evt is None: - return None - try: - return self.mfxDg1.raw.peakAmplitude(evt) - except: - return None - - def _getFlux(self, evt): - if self.mfxDg1 is None: - return None - - ## f = self.mfxDg1.raw.peakAmplitude(evt)[self.fluxChannels].mean()*self.fluxSign - try: - f = self.mfxDg1.raw.peakAmplitude(evt)[self.fluxChannels].mean() * self.fluxSign - ##print(f) - except Exception as e: - # print(e) - return None - try: - if f < self.fluxCut: - return None - except: - pass - return f - - def getFlux(self, evt): - ##return 1 - return self.flux - - def get_evrs(self): - if self.config is None: - self.get_config() - - self.evrs = [] - for key in list(self.config.keys()): - if key.type() == EvrData.ConfigV7: - self.evrs.append(key.src()) - - def getEventCodes(self, evt): - return self.timing.raw.eventcodes(evt) - - def getPulseId(self, evt): - return self.timing.raw.pulseId(evt) - - def isKicked(self, evt): - allcodes = self.getEventCodes(evt) - ##print(allcodes) - return allcodes[self.desiredCodes["120Hz"]] - - - def getRunGen(self): - return self.ds.runs() - - def getEvt(self): - try: - evt = next(self.myrun.events()) - ## dumb to do the below everywhere, should best not call this method - ##try: - ## self.flux = self._getFlux(evt) - ##except: - ## pass - - except StopIteration: - return None - return evt - - def getScanValue(self, step, useStringInfo=False): - ##print(self.step_value(step),self.step_docstring(step),useStringInfo) - if useStringInfo: - payload = self.step_docstring(step) - ##print(payload) - sv = eval(payload.split()[-1][:-1]) - print("step", int(self.step_value(step)), sv) - logger.info("step" + str(int(self.step_value(step))) + str(sv)) - return sv - return self.step_value(step) - - def getRawData(self, evt, gainBitsMasked=True): - frames = self.det.raw.raw(evt) - if frames is None: - return None - if self.special: - if 'thirteenBits' in self.special: - frames = (frames & 0xfffe) - ##print("13bits") - elif 'twelveBits' in self.special: - frames = (frames & 0xfffc) - ##print("12bits") - elif 'elevenBits' in self.special: - frames = (frames & 0xfff8) - ##print("11bits") - elif 'tenBits' in self.special: - frames = (frames & 0xfff0) - ##print("10bits") - if gainBitsMasked: - return frames & self.gainBitsMask - return frames - - def getCalibData(self, evt): - frames = self.det.raw.calib(evt) - return frames - - def getStepGen(self): - return self.myrun.steps() - - def getTimestamp(self, evt): - return evt.timestamp - - def getPingPongParity(self, frameRegion): - evensEvenRowsOddsOddRows = frameRegion[::2, ::2] + frameRegion[1::2, 1::2] - oddsEvenRowsEvensOddRows = frameRegion[1::2, ::2] + frameRegion[::2, 1::2] - delta = evensEvenRowsOddsOddRows.mean() - oddsEvenRowsEvensOddRows.mean() - ##print("delta:", delta) - return delta > 0 - - -if __name__ == "__main__": - bSS = BasicSuiteScript() - print("have built a BasicSuiteScript") - bSS.setupPsana() - evt = bSS.getEvt() - print(dir(evt)) diff --git a/calibrationSuite/psanaBase.py b/calibrationSuite/psanaBase.py new file mode 100755 index 0000000..4d3bab3 --- /dev/null +++ b/calibrationSuite/psanaBase.py @@ -0,0 +1,122 @@ +############################################################################## +## This file is part of 'SLAC Beamtime Calibration Suite'. +## It is subject to the license terms in the LICENSE.txt file found in the +## top-level directory of this distribution and at: +## https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. +## No part of 'SLAC Beamtime Calibration Suite', including this file, +## may be copied, modified, propagated, or distributed except according to +## the terms contained in the LICENSE.txt file. +############################################################################## +from psana import * + +import logging +import os + +from calibrationSuite.suiteBase import * +from calibrationSuite.psana2 import * +from calibrationSuite.psana1 import * + +psanaBaseNum = 0 +if os.getenv("SUITE_PSANA_NUM") == "1": + print("psana1") + psanaBaseNum = 1 +else: + print("psana2") + psanaBaseNum = 2 + +if psanaBaseNum == 2: + ## psana2 only + os.environ["PS_SMD_N_EVENTS"] = "50" + os.environ["PS_SRV_NODES"] = "1" +else: + from PSCalib.NDArrIO import load_txt + + +logger = logging.getLogger(__name__) + + +class PsanaBase(SuiteBase): + def __init__(self, analysisType="scan"): + super().__init__(analysisType) + self.psanaType = 2 + print("in PsanaBase") + logger.info("in PsanaBase") + + def setupPsana(self): + if psanaBaseNum == 2: + setupPsana2(self) + else: + setupPsana1(self) + + + ######## Start of getters + + def get_ds(self, run=None): + if run is None: + run = self.run + if psanaBaseNum == 1: + return DataSource("exp=%s:run=%d:smd" % (self.exp, run)) + else: + return DataSource(exp=self.exp, run=run, intg_det=self.experimentHash['detectorType'], max_events=self.maxNevents) + + def isKicked(self, evt): + if psanaBaseNum == 2: + allcodes = self.getEventCodes(evt) + return allcodes[self.desiredCodes["120Hz"]] + else: + return isKickedPsana1(self, evt) + + def getFlux(self, evt): + if psanaBaseNum == 2: + return self.flux + else: + return getFluxPsana1(self, evt) + + def getEvt(self): + if psanaBaseNum == 2: + return self.getEvtPsana2 + else: + return self.getEvtPsana1 + + def getStepGen(self): + if psanaBaseNum == 2: + return self.myrun.steps() + else: + return self.ds.steps() + + def getCalibData(self, evt): + if psanaBaseNum == 2: + frames = self.det.raw.calib(evt) + return frames + else: + return self.det.calib(evt) + + def getRawData(self, evt, gainBitsMasked=True): + if psanaBaseNum == 2: + return getRawDataPsana2(self, evt, gainBitsMasked) + else: + return getRawDataPsana1(self, evt, gainBitsMasked) + + def getScanValue(self, step=-1, useStringInfo=False): + # for psana1, where we don't specify a step arg + if step == -1: #psana1 + return self.controlData().pvControls()[0].value() + ##print(self.step_value(step),self.step_docstring(step),useStringInfo) + if useStringInfo: + payload = self.step_docstring(step) + ##print(payload) + sv = eval(payload.split()[-1][:-1]) + print("step", int(self.step_value(step)), sv) + logger.info("step" + str(int(self.step_value(step))) + str(sv)) + return sv + return self.step_value(step) + + ######## End of getters + + +if __name__ == "__main__": + bSS = BasicSuiteScript() + print("have built a BasicSuiteScript") + bSS.setupPsana() + evt = bSS.getEvt() + print(dir(evt)) diff --git a/calibrationSuite/commonPsanaBase.py b/calibrationSuite/suiteBase.py similarity index 74% rename from calibrationSuite/commonPsanaBase.py rename to calibrationSuite/suiteBase.py index db12ba6..593da2c 100644 --- a/calibrationSuite/commonPsanaBase.py +++ b/calibrationSuite/suiteBase.py @@ -1,27 +1,22 @@ +from psana import * + import os import sys import logging +import sys +import os import importlib.util -from psana import * -from calibrationSuite.argumentParser import ArgumentParser -## standard -from mpi4py import MPI -import argparse import numpy as np -import matplotlib.pyplot as plt -from matplotlib.ticker import AutoMinorLocator -import sys -import h5py -from scipy.optimize import curve_fit ## here? +from mpi4py import MPI + from calibrationSuite.fitFunctions import * from calibrationSuite.ancillaryMethods import * from calibrationSuite.argumentParser import ArgumentParser from calibrationSuite.detectorInfo import DetectorInfo -import os logger = logging.getLogger(__name__) -class CommonPsanaBase(object): +class SuiteBase(object): def __init__(self, analysisType="scan"): self.comm = MPI.COMM_WORLD @@ -34,6 +29,7 @@ def __init__(self, analysisType="scan"): commandUsed = sys.executable + " " + " ".join(sys.argv) logger.info("Ran with cmd: " + commandUsed) + self.allowed_timestamp_mismatch = 1000 self.camera = 0 self.gainModes = {"FH": 0, "FM": 1, "FL": 2, "AHL-H": 3, "AML-M": 4, "AHL-L": 5, "AML-L": 6} self.ePix10k_cameraTypes = {1: "Epix10ka", 4: "Epix10kaQuad", 16: "Epix10ka2M"} @@ -108,9 +104,9 @@ def __init__(self, analysisType="scan"): self.fluxChannels = self.experimentHash.get("fluxChannels", range(8, 16) ) self.fluxSign = self.experimentHash.get("fluxSign", 1) - self.setValuesFromArgs() + self.setupValuesFromArgs() - def setValuesFromArgs(self): + def setupValuesFromArgs(self): ## for standalone analysis self.file = self.args.files @@ -190,6 +186,9 @@ def importConfigFile(self, file_path): spec.loader.exec_module(config_module) return config_module + + ######## Start of getters + def get_config(self): self.config = self.ds.env().configStore() @@ -207,9 +206,133 @@ def getFivePedestalRunInfo(self): self.fpStatus = self.det.status(evt) ## does this work? self.fpRMS = self.det.rms(evt) ## does this work? - def sortArrayByList(a, data): - return [x for _, x in sorted(zip(a, data), key=lambda pair: pair[0])] + def getEvtFromRunsTooSmartForMyOwnGood(self): + for r in self.runRange: + self.run = r + self.ds = self.get_ds() + try: + evt = next(self.ds.events()) + yield evt + except: + continue + + def getEvtFromRuns(self): + try: ## can't get yield to work + evt = next(self.ds.events()) + return evt + except StopIteration: + i = self.runRange.index(self.run) + try: + self.run = self.runRange[i + 1] + print("switching to run %d" % (self.run)) + logger.info("switching to run %d" % (self.run)) + self.ds = self.get_ds(self.run) + except: + print("have run out of new runs") + logger.exception("have run out of new runs") + return None + ##print("get event from new run") + evt = next(self.ds.events()) + return evt + + def get_evrs(self): + if self.config is None: + self.get_config() + + self.evrs = [] + for key in list(self.config.keys()): + if key.type() == EvrData.ConfigV7: + self.evrs.append(key.src()) + def getPingPongParity(self, frameRegion): + evensEvenRowsOddsOddRows = frameRegion[::2, ::2] + frameRegion[1::2, 1::2] + oddsEvenRowsEvensOddRows = frameRegion[1::2, ::2] + frameRegion[::2, 1::2] + delta = evensEvenRowsOddsOddRows.mean() - oddsEvenRowsEvensOddRows.mean() + ##print("delta:", delta) + return delta > 0 + + def getAllFluxes(self, evt): + if evt is None: + return None + try: + return self.mfxDg1.raw.peakAmplitude(evt) + except: + return None + + def _getFlux(self, evt): + if self.mfxDg1 is None: + return None + + ##f = self.mfxDg1.raw.peakAmplitude(evt)[self.fluxChannels].mean()*self.fluxSign + try: + f = self.mfxDg1.raw.peakAmplitude(evt)[self.fluxChannels].mean() * self.fluxSign + ##print(f) + except Exception as e: + # print(e) + return None + try: + if f < self.fluxCut: + return None + except: + pass + return f + + def getEventCodes(self, evt): + return self.timing.raw.eventcodes(evt) + + def getPulseId(self, evt): + return self.timing.raw.pulseId(evt) + + def getRunGen(self): + return self.ds.runs() + + def getTimestamp(self, evt): + return evt.timestamp + + def getEvtOld(self, run=None): + oldDs = self.ds + if run is not None: + self.ds = self.get_ds(run) + try: ## or just yield evt I think + evt = next(self.ds.events()) + except StopIteration: + self.ds = oldDs + return None + self.ds = oldDs + return evt + + def getNextEvtFromGen(self, gen): + ## this is needed to get flux information out of phase with detector + ## information in mixed lcls1/2 mode + for nevt, evt in enumerate(gen): + try: + self.flux = self._getFlux(evt) + except: + pass + if self.det.raw.raw(evt) is None: + continue + self.detEvts += 1 + ## should check for beam code here to be smarter + return self.detEvts, evt + + ######## End of getters + + + ######## Start of setters + def isBeamEvent(self, evt): + ec = self.getEventCodes(evt) + ##print(ec[280], ec[281], ec[282], ec[283], ec[284], ec[285] ) + if ec[self.runCode]: + self.nRunCodeEvents += 1 + if ec[self.daqCode]: + self.nDaqCodeEvents += 1 + if self.fakeBeamCode: + return True + if ec[self.beamCode]: + self.nBeamCodeEvents += 1 + return True + return False + def setROI(self, roiFile=None, roi=None): """Call with both file name and roi to save roi to file and use, just name to load, @@ -222,10 +345,12 @@ def setROI(self, roiFile=None, roi=None): else: np.save(roiFile, roi) self.ROI = roi - - def sliceToDetector(self, sliceRow, sliceCol):## cp from AnalyzeH5: import? - return sliceRow + self.sliceCoordinates[0][0], sliceCol + self.sliceCoordinates[1][0] + ######## End of setters + + + ######## Start of correction functions + def noCommonModeCorrection(self, frame): return frame @@ -294,20 +419,11 @@ def colCommonModeCorrection(self, frame, arbitraryCut=1000): rowOffset += self.detectorInfo.nRowsPerBank return frame - def isBeamEvent(self, evt): - ec = self.getEventCodes(evt) - ##print(ec[280], ec[281], ec[282], ec[283], ec[284], ec[285] ) - if ec[self.runCode]: - self.nRunCodeEvents += 1 - if ec[self.daqCode]: - self.nDaqCodeEvents += 1 - if self.fakeBeamCode: - return True - if ec[self.beamCode]: - self.nBeamCodeEvents += 1 - return True - return False + ######## End of correction functions + + ######## Start of misc-utility functions + def dumpEventCodeStatistics(self): print( "have counted %d run triggers, %d DAQ triggers, %d beam events" @@ -316,4 +432,29 @@ def dumpEventCodeStatistics(self): logger.info( "have counted %d run triggers, %d DAQ triggers, %d beam events" % (self.nRunCodeEvents, self.nDaqCodeEvents, self.nBeamCodeEvents) - ) \ No newline at end of file + ) + + def sortArrayByList(a, data): + return [x for _, x in sorted(zip(a, data), key=lambda pair: pair[0])] + + + def sliceToDetector(self, sliceRow, sliceCol):## cp from AnalyzeH5: import? + return sliceRow + self.sliceCoordinates[0][0], sliceCol + self.sliceCoordinates[1][0] + + def matchedDetEvt(self): + self.fluxTS = 0 + for nevt, evt in enumerate(self.myrun.events()): + ec = self.getEventCodes(evt) + if ec[137]: + self.flux = self._getFlux(evt) ## fix this + self.fluxTS = self.getTimestamp(evt) + continue + elif ec[281]: + self.framesTS = self.getTimestamp(evt) + if self.framesTS - self.fluxTS > self.allowed_timestamp_mismatch: + continue + yield evt + else: + continue + + ######## End of misc-utility functions \ No newline at end of file diff --git a/suite_scripts/TimeScanParallelSlice.py b/suite_scripts/TimeScanParallelSlice.py index 7111c0f..76c6954 100755 --- a/suite_scripts/TimeScanParallelSlice.py +++ b/suite_scripts/TimeScanParallelSlice.py @@ -7,9 +7,7 @@ ## may be copied, modified, propagated, or distributed except according to ## the terms contained in the LICENSE.txt file. ############################################################################## -from calibrationSuite.psana2Base import PsanaBase -#from calibrationSuite.psana1Base import PsanaBase - +from calibrationSuite.psanaBase import PsanaBase import logging import os import sys