Add TofZProjection
This commit is contained in:
@@ -12,6 +12,7 @@ from eos.options import ReflectivityConfig, ReaderConfig, ExperimentConfig, Refl
|
||||
from eos.command_line import commandLineArgs
|
||||
from eos.logconfig import setup_logging, update_loglevel
|
||||
|
||||
|
||||
def main():
|
||||
setup_logging()
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
"""
|
||||
events2histogram vizualising data from Amor@SINQ, PSI
|
||||
|
||||
Author: Jochen Stahn (algorithms, python draft),
|
||||
Artur Glavic (structuring and optimisation of code)
|
||||
"""
|
||||
import logging
|
||||
|
||||
# need to do absolute import here as pyinstaller requires it
|
||||
from eos.options import E2HConfig, ReaderConfig, ExperimentConfig, E2HReductionConfig
|
||||
from eos.command_line import commandLineArgs
|
||||
from eos.logconfig import setup_logging, update_loglevel
|
||||
from eos.reduction_e2h import E2HReduction
|
||||
|
||||
|
||||
def main():
|
||||
@@ -22,6 +27,7 @@ def main():
|
||||
config = E2HConfig(reader_config, experiment_config, reduction_config)
|
||||
|
||||
logging.warning('######## events2histogram - data vizualization for Amor ########')
|
||||
from eos.reduction_e2h import E2HReduction
|
||||
|
||||
# only import heavy module if sufficient command line parameters were provided
|
||||
from eos.reduction_reflectivity import ReflectivityReduction
|
||||
|
||||
@@ -609,6 +609,7 @@ class E2HPlotArguments(StrEnum):
|
||||
@dataclass
|
||||
class E2HReductionConfig(ArgParsable):
|
||||
fileIdentifier: str = field(
|
||||
default='0',
|
||||
metadata={
|
||||
'short': 'f',
|
||||
'priority': 100,
|
||||
|
||||
@@ -49,7 +49,8 @@ class PathResolver:
|
||||
if len(potential_file)>0:
|
||||
path = os.path.dirname(potential_file[0])
|
||||
else:
|
||||
raise FileNotFoundError(f'# ERROR: the file {fileName} can not be found in {self.rawPath}')
|
||||
raise FileNotFoundError(f'# ERROR: the file {fileName} can not be found '
|
||||
f'in {self.rawPath+["/home/amor/data"]}')
|
||||
return os.path.join(path, fileName)
|
||||
|
||||
def search_latest(self, number):
|
||||
@@ -72,4 +73,10 @@ class PathResolver:
|
||||
possible_files += glob(f'/home/amor/data/{self.year}/*/amor{self.year}n??????.hdf')
|
||||
possible_indices = list(set([int(os.path.basename(fi)[9:15]) for fi in possible_files]))
|
||||
possible_indices.sort()
|
||||
return possible_indices[number-1]
|
||||
try:
|
||||
return possible_indices[number-1]
|
||||
except IndexError:
|
||||
raise FileNotFoundError(f'# Could not find suitable file for relative index {number} '
|
||||
f'in {self.rawPath+["/home/amor/data"]}, '
|
||||
f'possible indices {possible_indices}')
|
||||
|
||||
|
||||
@@ -394,7 +394,10 @@ class YZProjection(ProjectionInterface):
|
||||
if not 'norm' in kwargs:
|
||||
kwargs['norm'] = LogNorm()
|
||||
|
||||
self._graph = plt.imshow(self.data.I[:, ::-1].T, **kwargs)
|
||||
self._graph = plt.imshow(self.data.I.T,
|
||||
extent=(float(self.y[0]), float(self.y[-1]),
|
||||
float(self.z[0]), float(self.z[-1])),
|
||||
**kwargs)
|
||||
if cmap:
|
||||
plt.colorbar(label='I / cpm')
|
||||
|
||||
@@ -410,7 +413,7 @@ class YZProjection(ProjectionInterface):
|
||||
"""
|
||||
Inline update of previous plot by just updating the data.
|
||||
"""
|
||||
self._graph.set_array(self.data.I[:, ::-1].T)
|
||||
self._graph.set_array(self.data.I.T)
|
||||
|
||||
def draw_yzcross(self, event):
|
||||
if event.inaxes is not self._graph_axis:
|
||||
@@ -426,3 +429,88 @@ class YZProjection(ProjectionInterface):
|
||||
for art in list(plt.gca().lines)+list(plt.gca().texts):
|
||||
art.remove()
|
||||
plt.draw()
|
||||
|
||||
class TofZProjection(ProjectionInterface):
|
||||
tof: np.ndarray
|
||||
z: np.ndarray
|
||||
|
||||
data: np.recarray
|
||||
_dtype = np.dtype([
|
||||
('cts', np.float64),
|
||||
('I', np.float64),
|
||||
('err', np.float64),
|
||||
])
|
||||
|
||||
def __init__(self, tau, foldback=False):
|
||||
self.z = np.arange(Detector.nBlades*Detector.nWires+1)-0.5
|
||||
if foldback:
|
||||
self.tof = np.arange(0, tau, 0.0005)
|
||||
else:
|
||||
self.tof = np.arange(0, 2*tau, 0.0005)
|
||||
self.data = np.zeros((self.tof.shape[0]-1, self.z.shape[0]-1), dtype=self._dtype).view(np.recarray)
|
||||
self.monitor = 0.
|
||||
|
||||
def project(self, dataset: EventDatasetProtocol, monitor: float):
|
||||
detYi, detZi, detX, delta = Detector.pixelLookUp[dataset.data.events.pixelID-1].T
|
||||
|
||||
cts , *_ = np.histogram2d(dataset.data.events.tof, detZi, bins=(self.tof, self.z))
|
||||
self.data.cts += cts
|
||||
self.monitor += monitor
|
||||
|
||||
self.data.I = self.data.cts / self.monitor
|
||||
self.data.err = np.sqrt(self.data.cts) / self.monitor
|
||||
|
||||
def clear(self):
|
||||
self.data[:] = 0
|
||||
self.monitor = 0.
|
||||
|
||||
def plot(self, **kwargs):
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.colors import LogNorm
|
||||
|
||||
if 'colorbar' in kwargs:
|
||||
cmap=True
|
||||
del(kwargs['colorbar'])
|
||||
else:
|
||||
cmap=False
|
||||
if not 'aspect' in kwargs:
|
||||
kwargs['aspect'] = 'auto'
|
||||
|
||||
if not 'norm' in kwargs:
|
||||
kwargs['norm'] = LogNorm()
|
||||
|
||||
self._graph = plt.imshow(self.data.I.T,
|
||||
extent=(float(self.tof[0])*1e3, float(self.tof[-1])*1e3,
|
||||
float(self.z[0]), float(self.z[-1])),
|
||||
**kwargs)
|
||||
if cmap:
|
||||
plt.colorbar(label='I / cpm')
|
||||
|
||||
plt.xlabel('Time of Flight / ms')
|
||||
plt.ylabel('Z')
|
||||
plt.xlim(self.tof[0]*1e3, self.tof[-1]*1e3)
|
||||
plt.ylim(self.z[0], self.z[-1])
|
||||
|
||||
self._graph_axis = plt.gca()
|
||||
plt.connect('button_press_event', self.draw_tzcross)
|
||||
|
||||
def update_plot(self):
|
||||
"""
|
||||
Inline update of previous plot by just updating the data.
|
||||
"""
|
||||
self._graph.set_array(self.data.I.T)
|
||||
|
||||
def draw_tzcross(self, event):
|
||||
if event.inaxes is not self._graph_axis:
|
||||
return
|
||||
from matplotlib import pyplot as plt
|
||||
tbm = self._graph_axis.figure.canvas.manager.toolbar.mode
|
||||
if event.button is plt.MouseButton.LEFT and tbm=='':
|
||||
plt.plot([event.xdata, event.xdata], [self.z[0], self.z[-1]], '-', color='grey')
|
||||
plt.plot([self.tof[0]*1e3, self.tof[-1]*1e3], [event.ydata, event.ydata], '-', color='grey')
|
||||
plt.text(event.xdata, event.ydata, f'({event.xdata:.2f}, {event.ydata:.1f})', backgroundcolor='white')
|
||||
plt.draw()
|
||||
if event.button is plt.MouseButton.RIGHT and tbm=='':
|
||||
for art in list(plt.gca().lines)+list(plt.gca().texts):
|
||||
art.remove()
|
||||
plt.draw()
|
||||
|
||||
@@ -16,10 +16,11 @@ from .header import Header
|
||||
from .instrument import LZGrid
|
||||
from .normalization import LZNormalisation
|
||||
from .options import E2HConfig, E2HPlotArguments, IncidentAngle, MonitorType, E2HPlotSelection
|
||||
from . import event_handling as eh, event_analysis as ea
|
||||
from . import event_handling as eh
|
||||
from .path_handling import PathResolver
|
||||
from .projection import LZProjection, ProjectionInterface, YZProjection
|
||||
from .projection import LZProjection, ProjectionInterface, TofZProjection, YZProjection
|
||||
|
||||
NEEDS_LAMDA = (E2HPlotSelection.All, E2HPlotSelection.LT, E2HPlotSelection.Q, E2HPlotSelection.L)
|
||||
|
||||
class E2HReduction:
|
||||
config: E2HConfig
|
||||
@@ -50,6 +51,9 @@ class E2HReduction:
|
||||
# live update implies plotting
|
||||
self.config.reduction.show_plot = True
|
||||
|
||||
if not self.config.reduction.fast or self.config.reduction.plot in NEEDS_LAMDA:
|
||||
from . import event_analysis as ea
|
||||
|
||||
# Actions on datasets not used for normalization
|
||||
self.event_actions = eh.ApplyPhaseOffset(self.config.experiment.chopperPhaseOffset)
|
||||
if not self.config.reduction.fast:
|
||||
@@ -64,9 +68,13 @@ class E2HReduction:
|
||||
self.event_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
|
||||
if not self.config.reduction.fast:
|
||||
self.event_actions |= eh.FilterStrangeTimes()
|
||||
if self.config.reduction.plot==E2HPlotSelection.TZ:
|
||||
# perform time fold-back and corrections for tof if not fast mode
|
||||
self.event_actions |= ea.MergeFrames()
|
||||
self.event_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
|
||||
self.event_actions |= eh.TofTimeCorrection(self.config.experiment.incidentAngle==IncidentAngle.alphaF)
|
||||
# select needed actions in depenence of plots
|
||||
if self.config.reduction.plot in [E2HPlotSelection.All, E2HPlotSelection.LT, E2HPlotSelection.Q,
|
||||
E2HPlotSelection.L]:
|
||||
if self.config.reduction.plot in NEEDS_LAMDA:
|
||||
self.event_actions |= ea.MergeFrames()
|
||||
self.event_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
|
||||
self.event_actions |= eh.TofTimeCorrection(self.config.experiment.incidentAngle==IncidentAngle.alphaF)
|
||||
@@ -77,7 +85,7 @@ class E2HReduction:
|
||||
if self.config.reduction.plot in [E2HPlotSelection.All, E2HPlotSelection.LT, E2HPlotSelection.Q]:
|
||||
self.grid = LZGrid(0.01, [0.0, 0.25])
|
||||
|
||||
if self.config.reduction.plot in [E2HPlotSelection.LT, E2HPlotSelection.YZ]:
|
||||
if self.config.reduction.plot in [E2HPlotSelection.LT, E2HPlotSelection.YZ, E2HPlotSelection.TZ]:
|
||||
self.plot_kwds['colorbar'] = True
|
||||
self.plot_kwds['cmap'] = str(self.config.reduction.plot_colormap)
|
||||
|
||||
@@ -119,6 +127,9 @@ class E2HReduction:
|
||||
if self.config.reduction.plot==E2HPlotSelection.YZ:
|
||||
self.projection = YZProjection()
|
||||
|
||||
if self.config.reduction.plot==E2HPlotSelection.TZ:
|
||||
self.projection = TofZProjection(last_file_header.timing.tau, foldback=not self.config.reduction.fast)
|
||||
|
||||
def read_data(self):
|
||||
fileName = self.file_list[self.file_index]
|
||||
self.file_index += 1
|
||||
|
||||
Reference in New Issue
Block a user