separate AssociatePulseWithMonitor and FilterMonitorThreshold to allow monitor use without wallTime
This commit is contained in:
+1
-1
@@ -29,7 +29,7 @@ def main():
|
||||
logging.warning('######## eos - data reduction for Amor ########')
|
||||
|
||||
# only import heavy module if sufficient command line parameters were provided
|
||||
from eos.reduction import ReflectivityReduction
|
||||
from eos.reduction_reflectivity import ReflectivityReduction
|
||||
# Create reducer with these arguments
|
||||
reducer = ReflectivityReduction(config)
|
||||
# Perform actual reduction
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import argparse
|
||||
|
||||
from typing import List
|
||||
from typing import List, Type
|
||||
from .options import ArgParsable
|
||||
|
||||
|
||||
def commandLineArgs(config_items: List[ArgParsable], program_name=None):
|
||||
def commandLineArgs(config_items: List[Type[ArgParsable]], program_name=None):
|
||||
"""
|
||||
Process command line argument.
|
||||
The type of the default values is used for conversion and validation.
|
||||
|
||||
+23
-21
@@ -77,16 +77,12 @@ class CorrectSeriesTime(EventDataAction):
|
||||
|
||||
|
||||
class AssociatePulseWithMonitor(EventDataAction):
|
||||
def __init__(self, monitorType:MonitorType, lowCurrentThreshold:float):
|
||||
def __init__(self, monitorType:MonitorType):
|
||||
self.monitorType = monitorType
|
||||
self.lowCurrentThreshold = lowCurrentThreshold
|
||||
|
||||
def perform_action(self, dataset: EventDatasetProtocol)->None:
|
||||
logging.debug(f' using monitor type {self.monitorType}')
|
||||
if self.monitorType in [MonitorType.proton_charge or MonitorType.debug]:
|
||||
if not 'wallTime' in dataset.data.events.dtype.names:
|
||||
raise ValueError(
|
||||
"AssociatePulseWithMonitor requires walltTime to be extracted, please run ExtractWalltime first")
|
||||
monitorPerPulse = self.get_current_per_pulse(dataset.data.pulses.time,
|
||||
dataset.data.proton_current.time,
|
||||
dataset.data.proton_current.current)\
|
||||
@@ -101,25 +97,12 @@ class AssociatePulseWithMonitor(EventDataAction):
|
||||
dataset.data.pulses.monitor = 1
|
||||
|
||||
if self.monitorType == MonitorType.debug:
|
||||
if not 'wallTime' in dataset.data.events.dtype.names:
|
||||
raise ValueError(
|
||||
"AssociatePulseWithMonitor requires walltTime for debugging, please run ExtractWalltime first")
|
||||
cpp, t_bins = np.histogram(dataset.data.events.wallTime, dataset.data.pulses.time)
|
||||
np.savetxt('tme.hst', np.vstack((dataset.data.pulses.time[:-1], cpp, dataset.data.pulses.monitor[:-1])).T)
|
||||
|
||||
if self.monitorType in [MonitorType.proton_charge or MonitorType.debug]:
|
||||
self.monitor_threshold(dataset)
|
||||
|
||||
def monitor_threshold(self, dataset):
|
||||
goodTimeS = dataset.data.pulses.time[dataset.data.pulses.monitor!=0]
|
||||
filter_e = np.logical_not(np.isin(dataset.data.events.wallTime, goodTimeS))
|
||||
dataset.data.events.mask += EVENT_BITMASKS['MonitorThreshold']*filter_e
|
||||
logging.info(f' low-beam (<{self.lowCurrentThreshold} mC) rejected pulses: '
|
||||
f'{dataset.data.pulses.monitor.shape[0]-goodTimeS.shape[0]} '
|
||||
f'out of {dataset.data.pulses.monitor.shape[0]}')
|
||||
logging.info(f' with {filter_e.sum()} events')
|
||||
if goodTimeS.shape[0]:
|
||||
logging.info(f' average counts per pulse = {dataset.data.events.shape[0]/goodTimeS.shape[0]:7.1f}')
|
||||
else:
|
||||
logging.info(f' average counts per pulse = undefined')
|
||||
|
||||
@staticmethod
|
||||
def get_current_per_pulse(pulseTimeS, currentTimeS, currents):
|
||||
# add currents for early pulses and current time value after last pulse (j+1)
|
||||
@@ -134,6 +117,25 @@ class AssociatePulseWithMonitor(EventDataAction):
|
||||
pulseCurrentS[i] = currents[j]
|
||||
return pulseCurrentS
|
||||
|
||||
class FilterMonitorThreshold(EventDataAction):
|
||||
def __init__(self, lowCurrentThreshold:float):
|
||||
self.lowCurrentThreshold = lowCurrentThreshold
|
||||
|
||||
def perform_action(self, dataset: EventDatasetProtocol) ->None:
|
||||
if not 'wallTime' in dataset.data.events.dtype.names:
|
||||
raise ValueError(
|
||||
"FilterMonitorThreshold requires walltTime to be extracted, please run ExtractWalltime first")
|
||||
goodTimeS = dataset.data.pulses.time[dataset.data.pulses.monitor!=0]
|
||||
filter_e = np.logical_not(np.isin(dataset.data.events.wallTime, goodTimeS))
|
||||
dataset.data.events.mask += EVENT_BITMASKS['MonitorThreshold']*filter_e
|
||||
logging.info(f' low-beam (<{self.lowCurrentThreshold} mC) rejected pulses: '
|
||||
f'{dataset.data.pulses.monitor.shape[0]-goodTimeS.shape[0]} '
|
||||
f'out of {dataset.data.pulses.monitor.shape[0]}')
|
||||
logging.info(f' with {filter_e.sum()} events')
|
||||
if goodTimeS.shape[0]:
|
||||
logging.info(f' average counts per pulse = {dataset.data.events.shape[0]/goodTimeS.shape[0]:7.1f}')
|
||||
else:
|
||||
logging.info(f' average counts per pulse = undefined')
|
||||
|
||||
class FilterStrangeTimes(EventDataAction):
|
||||
def perform_action(self, dataset: EventDatasetProtocol)->None:
|
||||
|
||||
+12
-1
@@ -201,6 +201,14 @@ class MonitorType(StrEnum):
|
||||
neutron_monitor = 'n'
|
||||
debug = 'x'
|
||||
|
||||
MONITOR_UNITS = {
|
||||
MonitorType.neutron_monitor: 'cnts',
|
||||
MonitorType.proton_charge: 'mC',
|
||||
MonitorType.time: 's',
|
||||
MonitorType.auto: 'various',
|
||||
MonitorType.debug: 'mC',
|
||||
}
|
||||
|
||||
@dataclass
|
||||
class ExperimentConfig(ArgParsable):
|
||||
chopperPhase: float = field(
|
||||
@@ -581,4 +589,7 @@ class EOSConfig:
|
||||
logging.debug(f'Argument list build in EOSConfig.call_string: {mlst}')
|
||||
return mlst
|
||||
|
||||
|
||||
@dataclass
|
||||
class E2HConfig:
|
||||
reader: ReaderConfig
|
||||
|
||||
|
||||
@@ -8,21 +8,13 @@ from orsopy import fileio
|
||||
from .file_reader import AmorEventData
|
||||
from .header import Header
|
||||
from .path_handling import PathResolver
|
||||
from .options import EOSConfig, IncidentAngle, MonitorType, NormalisationMethod
|
||||
from .instrument import Detector, LZGrid
|
||||
from .options import EOSConfig, IncidentAngle, MonitorType, NormalisationMethod, MONITOR_UNITS
|
||||
from .instrument import LZGrid
|
||||
from .normalization import LZNormalisation
|
||||
from . import event_handling as eh, event_analysis as ea
|
||||
from .projection import LZProjection
|
||||
|
||||
|
||||
MONITOR_UNITS = {
|
||||
MonitorType.neutron_monitor: 'cnts',
|
||||
MonitorType.proton_charge: 'mC',
|
||||
MonitorType.time: 's',
|
||||
MonitorType.auto: 'various',
|
||||
MonitorType.debug: 'mC',
|
||||
}
|
||||
|
||||
class ReflectivityReduction:
|
||||
config: EOSConfig
|
||||
header: Header
|
||||
@@ -39,7 +31,7 @@ class ReflectivityReduction:
|
||||
|
||||
def prepare_actions(self):
|
||||
"""
|
||||
Does not do any actual reduction.
|
||||
Prepare the actions applied to each event dataset, does not do any actual reduction.
|
||||
"""
|
||||
self.path_resolver = PathResolver(self.config.reader.year, self.config.reader.rawPath)
|
||||
|
||||
@@ -49,10 +41,10 @@ class ReflectivityReduction:
|
||||
# explicit steps performed on AmorEventDataset for normalization files
|
||||
self.normevent_actions = eh.ApplyPhaseOffset(self.config.experiment.chopperPhaseOffset)
|
||||
self.normevent_actions |= eh.CorrectChopperPhase()
|
||||
self.normevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType)
|
||||
if self.config.experiment.monitorType in [MonitorType.proton_charge, MonitorType.debug]:
|
||||
self.normevent_actions |= ea.ExtractWalltime()
|
||||
self.normevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType,
|
||||
self.config.experiment.lowCurrentThreshold)
|
||||
self.dataevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
|
||||
self.normevent_actions |= eh.FilterStrangeTimes()
|
||||
self.normevent_actions |= ea.MergeFrames()
|
||||
self.normevent_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
|
||||
@@ -66,8 +58,10 @@ class ReflectivityReduction:
|
||||
self.dataevent_actions |= ea.ExtractWalltime()
|
||||
self.dataevent_time_correction = eh.CorrectSeriesTime(0) # will be set from first dataset
|
||||
self.dataevent_actions |= self.dataevent_time_correction
|
||||
self.dataevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType,
|
||||
self.config.experiment.lowCurrentThreshold)
|
||||
self.dataevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType)
|
||||
if self.config.experiment.monitorType in [MonitorType.proton_charge or MonitorType.debug]:
|
||||
# the filtering only makes sense if using actual monitor data, not time
|
||||
self.dataevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
|
||||
self.dataevent_actions |= eh.FilterStrangeTimes()
|
||||
self.dataevent_actions |= ea.MergeFrames()
|
||||
self.dataevent_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
import cProfile
|
||||
from unittest import TestCase
|
||||
from dataclasses import fields, MISSING
|
||||
from eos import options, reduction, logconfig
|
||||
from eos import options, reduction_reflectivity, logconfig
|
||||
|
||||
logconfig.setup_logging()
|
||||
logconfig.update_loglevel(1)
|
||||
|
||||
Reference in New Issue
Block a user