Skip to content

Commit

Permalink
Merge pull request #70 from slaclab/detector_class
Browse files Browse the repository at this point in the history
Add detectorInfo class
  • Loading branch information
nstelter-slac authored Apr 1, 2024
2 parents 7b18a5e + 61f528e commit 2888685
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 83 deletions.
125 changes: 51 additions & 74 deletions calibrationSuite/basicSuiteScript.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
##############################################################################
import argparse
import numpy as np
import importlib.util
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator
import sys
Expand All @@ -18,7 +17,7 @@
from calibrationSuite.fitFunctions import *
from calibrationSuite.ancillaryMethods import *
from calibrationSuite.argumentParser import ArgumentParser

from calibrationSuite.detectorInfo import DetectorInfo
import os

if os.getenv("foo") == "1":
Expand All @@ -39,24 +38,8 @@ def __init__(self, analysisType="scan"):
print("in BasicSuiteScript, inheriting from PsanaBase, type is psana%d" %(self.psanaType))
logger.info("in BasicSuiteScript, inheriting from PsanaBase, type is psana%d" %(self.psanaType))

args = ArgumentParser().parse_args()
logger.info("parsed cmdline args: " + str(args))
##mymodule = importlib.import_module(full_module_name)

# if the SUITE_CONFIG env var is set use that, otherwise if the cmd line arg is set use that.
# if neither are set, use the default 'suiteConfig.py' file.
defaultConfigFileName = "suiteConfig.py"
secondaryConfigFileName = defaultConfigFileName if args.configFile is None else args.configFile
# secondaryConfigFileName is returned if env var not set
configFileName = os.environ.get("SUITE_CONFIG", secondaryConfigFileName)
config = self.importConfigFile(configFileName)
if config is None:
print("\ncould not find or read config file: " + configFileName)
print("please set SUITE_CONFIG env-var or use the '-cf' cmd-line arg to specify a valid config file")
print("exiting...")
sys.exit(1)
experimentHash = config.experimentHash

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"}
self.camera = 0
Expand All @@ -65,19 +48,21 @@ def __init__(self, analysisType="scan"):
logging.info("output dir: " + self.outputDir)
##self.outputDir = '/tmp'

self.detectorInfo = DetectorInfo(self.experimentHash['detectorType'])

self.className = self.__class__.__name__

try:
self.location = experimentHash["location"]
self.location = self.experimentHash["location"]
except:
pass
try:
self.exp = experimentHash["exp"]
self.exp = self.experimentHash["exp"]
except:
pass
try:
##if True:
self.ROIfileNames = experimentHash["ROIs"]
self.ROIfileNames = self.experimentHash["ROIs"]
self.ROIs = []
for f in self.ROIfileNames:
self.ROIs.append(np.load(f + ".npy"))
Expand All @@ -93,11 +78,11 @@ def __init__(self, analysisType="scan"):
self.ROI = None
self.ROIs = None
try:
self.singlePixels = experimentHash["singlePixels"]
self.singlePixels = self.experimentHash["singlePixels"]
except:
self.singlePixels = None
try:
self.regionSlice = experimentHash["regionSlice"]
self.regionSlice = self.experimentHash["regionSlice"]
except:
self.regionSlice = None
if self.regionSlice is not None:
Expand All @@ -109,13 +94,13 @@ def __init__(self, analysisType="scan"):
self.sliceEdges = [sc[0][1] - sc[0][0], sc[1][1] - sc[1][0]]

try:
self.fluxSource = experimentHash["fluxSource"]
self.fluxSource = self.experimentHash["fluxSource"]
try:
self.fluxChannels = experimentHash["fluxChannels"]
self.fluxChannels = self.experimentHash["fluxChannels"]
except:
self.fluxChannels = range(8, 16) ## wave8
try:
self.fluxSign = experimentHash["fluxSign"]
self.fluxSign = self.experimentHash["fluxSign"]
except:
self.fluxSign = 1
except:
Expand All @@ -135,27 +120,27 @@ def __init__(self, analysisType="scan"):

## for standalone analysis
self.file = None
if args.files is not None:
self.file = args.files
if self.args.files is not None:
self.file = self.args.files
self.label = ""
if args.label is not None:
self.label = args.label

## analyzing xtc
if args.run is not None:
self.run = args.run
if args.camera is not None:
self.camera = args.camera
if args.exp is not None:
self.exp = args.exp
if args.location is not None:
self.location = args.location
if args.maxNevents is not None:
self.maxNevents = args.maxNevents
if args.skipNevents is not None:
self.skipNevents = args.skipNevents
if args.path is not None:
self.outputDir = args.path
if self.args.label is not None:
self.label = self.args.label

## analyzing xtcs
if self.args.run is not None:
self.run = self.args.run
if self.args.camera is not None:
self.camera = self.args.camera
if self.args.exp is not None:
self.exp = self.args.exp
if self.args.location is not None:
self.location = self.args.location
if self.args.maxNevents is not None:
self.maxNevents = self.args.maxNevents
if self.args.skipNevents is not None:
self.skipNevents = self.args.skipNevents
if self.args.path is not None:
self.outputDir = self.args.path
# if set, output folders will be relative to OUTPUT_ROOT
# if not, they will be relative to the current script file
self.outputDir = os.getenv("OUTPUT_ROOT", "") + self.outputDir
Expand All @@ -172,31 +157,32 @@ def __init__(self, analysisType="scan"):
#os.makedirs(self.outputDir)
# give dir read, write, execute permissions
#os.chmod(self.outputDir, 0o777)
self.detObj = args.detObj
if args.threshold is not None:
self.threshold = eval(args.threshold)
self.detObj = self.args.detObj
if self.args.threshold is not None:
self.threshold = eval(self.args.threshold)
else:
self.threshold = None
if args.fluxCut is not None:
self.fluxCut = args.fluxCut
if self.args.fluxCut is not None:
self.fluxCut = self.args.fluxCut
try:
self.runRange = eval(args.runRange) ## in case needed
self.runRange = eval(self.args.runRange) ## in case needed
except:
self.runRange = None

self.fivePedestalRun = args.fivePedestalRun ## in case needed
self.fakePedestal = args.fakePedestal ## in case needed
self.fivePedestalRun = self.args.fivePedestalRun ## in case needed
self.fakePedestal = self.args.fakePedestal ## in case needed
if self.fakePedestal is not None:
self.fakePedestalFrame = np.load(self.fakePedestal) ##cast to uint32???

if args.detType == "":
if self.args.detType == "":
## assume epix10k for now
if args.nModules is not None:
self.detType = self.ePix10k_cameraTypes[args.nModules]
if self.args.nModules is not None:
self.detectorInfo.setNModules(self.args.nModules)
self.detType = self.detectorInfo.getCameraType()
else:
self.detType = args.detType
self.detType = self.args.detType

self.special = args.special
self.special = self.args.special
## done with configuration

self.ds = None
Expand All @@ -205,15 +191,6 @@ def __init__(self, analysisType="scan"):
##self.setupPsana()
##do this later or skip for -file

def importConfigFile(self, file_path):
if not os.path.exists(file_path):
print(f"The file '{file_path}' does not exist")
return None
spec = importlib.util.spec_from_file_location("config", file_path)
config_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(config_module)
return config_module

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,
Expand Down Expand Up @@ -242,7 +219,7 @@ def rowCommonModeCorrection(self, frame, arbitraryCut=1000):
## cut keeps photons in common mode - e.g. set to <<1 photon

##rand = np.random.random()
for r in range(self.detRows):
for r in range(self.detectorInfo.nRows):
colOffset = 0
##for b in range(0, self.detNbanks):
for b in range(0, 2):
Expand Down Expand Up @@ -277,22 +254,22 @@ def colCommonModeCorrection(self, frame, arbitraryCut=1000):
##for b in range(0, 2):
try:
colCM = np.median(
frame[rowOffset : rowOffset + self.detRowsPerBank, c][
frame[rowOffset : rowOffset + self.detRowsPerBank, c] < arbitraryCut
frame[rowOffset : rowOffset + self.detectorInfo.nRowsPerBank, c][
frame[rowOffset : rowOffset + self.detectorInfo.nRowsPerBank, c] < arbitraryCut
]
)
##if r == 280 and rand > 0.999:
##print(b, frame[r, colOffset:colOffset + self.detColsPerBank], rowCM, rowCM<arbitraryCut-1, rowCM*(rowCM<arbitraryCut-1))
##frame[r, colOffset:colOffset + self.detColsPerBank] -= rowCM*(rowCM<arbitraryCut-1)
frame[rowOffset : rowOffset + self.detRowsPerBank, c] -= colCM
frame[rowOffset : rowOffset + self.detectorInfo.nRowsPerBank, c] -= colCM
##if r == 280 and rand > 0.999:
##print(frame[r, colOffset:colOffset + self.detColsPerBank], np.median(frame[r, colOffset:colOffset + self.detColsPerBank]))
except:
colCM = -666
print("colCM problem")
logger.error("colCM problem")
print(frame[rowOffset : rowOffset + self.detRowsPerBank], c)
rowOffset += self.detRowsPerBank
print(frame[rowOffset : rowOffset + self.detectorInfo.nRowsPerBank], c)
rowOffset += self.detectorInfo.nRowsPerBank
return frame

def isBeamEvent(self, evt):
Expand Down
62 changes: 62 additions & 0 deletions calibrationSuite/detectorInfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
##############################################################################
## 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.
##############################################################################
class DetectorInfo:
def __init__(self, detType):

# declare these here in case any setup_X functions don't
# and -1 so caller knows things are not setup (non-0 to avoid error on divide)
self.nRows = -1
self.nCols = -1
self.nColsPerBank = -1
self.detNbanks = -1
self.nBanksCol = -1
self.nRowsPerBank = -1
self.dimension = -1

knownTypes = ['epixhr', 'epixM', 'rixsCCD']
if detType not in knownTypes:
raise Exception("type %s not in known types" % (detType, knownTypes))

self.ePix10kCameraTypes = {1: "Epix10ka", 4: "Epix10kaQuad", 16: "Epix10ka2M"}
self.chosenCameraType = None

if detType == 'epixhr':
self.setup_epixhr()
elif detType == 'epixM':
self.setup_epixM()
elif detType == 'rixsCCD':
self.setup_rixsCCD()

def setNModules(self, n):
self.choosenCameraType = self.ePix10kCameraTypes[n]

def getCameraType(self):
return self.choosenCameraType

def setup_epixhr(self, version=0):
self.nRows = 288
self.nCols = 666
self.nColsPerBank = 96
self.detNbanks = int(self.nCols / self.nColsPerBank)
self.nBanksCol = 2
self.nRowsPerBank = int(self.nRows / self.nBanksCol)

#need to still implement getGainMode()
#self.gainMode = self.getGainMode()
self.preferredCommonMode = 'regionCommonMode'
self.clusterShape = [3,3]

def setup_epixM(self, version=0):
#todo: setup detector here
temp = 0 #make python happy

def setup_rixsCCD(self, version=0):
#todo: setup detector here
temp = 0 #make python happy
34 changes: 33 additions & 1 deletion calibrationSuite/psana1Base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from PSCalib.NDArrIO import load_txt
import logging
import sys
import os
from calibrationSuite.argumentParser import ArgumentParser
logger = logging.getLogger(__name__)


Expand All @@ -27,7 +29,37 @@ def __init__(self, analysisType="scan"):
self.g0cut = 1 << 14
self.gainBitsMask = self.g0cut - 1

## self.setupPsana()
self.args = ArgumentParser().parse_args()
logger.info("parsed cmdline args: " + str(self.args))

# if the SUITE_CONFIG env var is set use that, otherwise if the cmd line arg is set use that
# if neither are set, use the default 'suiteConfig.py' file
defaultConfigFileName = "suiteConfig.py"
secondaryConfigFileName = defaultConfigFileName if self.args.configFile is None else self.args.configFile
# secondaryConfigFileName is returned if env var not set
configFileName = os.environ.get("SUITE_CONFIG", secondaryConfigFileName)
config = self.importConfigFile(configFileName)
if config is None:
print("\ncould not find or read config file: " + configFileName)
print("please set SUITE_CONFIG env-var or use the '-cf' cmd-line arg to specify a valid config file")
print("exiting...")
sys.exit(1)
self.experimentHash = config.experimentHash
knownTypes = ['epixhr', 'epixM', 'rixsCCD']
if self.experimentHash['detectorType'] not in knownTypes:
print ("type %s not in known types" %(self.experimentHash['detectorType']), knownTypes)
return -1

## self.setupPsana()

def importConfigFile(self, file_path):
if not os.path.exists(file_path):
print(f"The file '{file_path}' does not exist")
return None
spec = importlib.util.spec_from_file_location("config", file_path)
config_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(config_module)
return config_module

def get_ds(self, run=None):
if run is None:
Expand Down
Loading

0 comments on commit 2888685

Please sign in to comment.