amor-eos 3.3.0__tar.gz → 3.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {amor_eos-3.3.0 → amor_eos-3.3.2}/PKG-INFO +1 -1
  2. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/PKG-INFO +1 -1
  3. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/SOURCES.txt +2 -1
  4. amor_eos-3.3.2/eos/__init__.py +6 -0
  5. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/__main__.py +2 -1
  6. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/command_line.py +2 -2
  7. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/event_handling.py +17 -16
  8. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/file_reader.py +31 -4
  9. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/options.py +10 -2
  10. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/reduction_e2h.py +1 -8
  11. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/reduction_reflectivity.py +23 -9
  12. amor_eos-3.3.2/tests/test_full_analysis_v2.py +125 -0
  13. amor_eos-3.3.0/eos/__init__.py +0 -6
  14. {amor_eos-3.3.0 → amor_eos-3.3.2}/LICENSE +0 -0
  15. {amor_eos-3.3.0 → amor_eos-3.3.2}/README.rst +0 -0
  16. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/dependency_links.txt +0 -0
  17. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/entry_points.txt +0 -0
  18. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/requires.txt +0 -0
  19. {amor_eos-3.3.0 → amor_eos-3.3.2}/amor_eos.egg-info/top_level.txt +0 -0
  20. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/compat.py +0 -0
  21. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/const.py +0 -0
  22. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/e2h.py +0 -0
  23. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/event_analysis.py +0 -0
  24. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/event_data_types.py +0 -0
  25. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/header.py +0 -0
  26. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/helpers.py +0 -0
  27. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/helpers_fallback.py +0 -0
  28. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/helpers_numba.py +0 -0
  29. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/instrument.py +0 -0
  30. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/kafka_events.py +0 -0
  31. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/kafka_serializer.py +0 -0
  32. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/logconfig.py +0 -0
  33. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/ls.py +0 -0
  34. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/nicos.py +0 -0
  35. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/nicos_interface.py +0 -0
  36. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/normalization.py +0 -0
  37. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/path_handling.py +0 -0
  38. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/projection.py +0 -0
  39. {amor_eos-3.3.0 → amor_eos-3.3.2}/eos/reduction_kafka.py +0 -0
  40. {amor_eos-3.3.0 → amor_eos-3.3.2}/pyproject.toml +0 -0
  41. {amor_eos-3.3.0 → amor_eos-3.3.2}/setup.cfg +0 -0
  42. {amor_eos-3.3.0 → amor_eos-3.3.2}/tests/test_event_handling.py +0 -0
  43. {amor_eos-3.3.0 → amor_eos-3.3.2}/tests/test_full_analysis.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amor_eos
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: EOS reflectometry reduction for AMOR instrument
5
5
  Author: Jochen Stahn - Paul Scherrer Institut
6
6
  Author-email: jochen.stahn@psi.ch
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amor_eos
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: EOS reflectometry reduction for AMOR instrument
5
5
  Author: Jochen Stahn - Paul Scherrer Institut
6
6
  Author-email: jochen.stahn@psi.ch
@@ -37,4 +37,5 @@ eos/reduction_e2h.py
37
37
  eos/reduction_kafka.py
38
38
  eos/reduction_reflectivity.py
39
39
  tests/test_event_handling.py
40
- tests/test_full_analysis.py
40
+ tests/test_full_analysis.py
41
+ tests/test_full_analysis_v2.py
@@ -0,0 +1,6 @@
1
+ """
2
+ Package to handle data redction at the AMOR instrument to be used by __main__.py script.
3
+ """
4
+
5
+ __version__ = '3.3.2'
6
+ __date__ = '2026-08-24'
@@ -8,6 +8,7 @@ Author: Jochen Stahn (algorithms, python draft),
8
8
  import logging
9
9
 
10
10
  # need to do absolute import here as pyinstaller requires it
11
+ from eos import __version__
11
12
  from eos.options import ReflectivityConfig, ReaderConfig, ExperimentConfig, ReflectivityReductionConfig, ReflectivityOutputConfig
12
13
  from eos.command_line import commandLineArgs
13
14
  from eos.logconfig import setup_logging, update_loglevel, setup_logfile
@@ -29,7 +30,7 @@ def main():
29
30
 
30
31
  if output_config.logFile:
31
32
  setup_logfile()
32
- logging.warning('######## eos - data reduction for Amor ########')
33
+ logging.warning(f'######## eos ({__version__}) - data reduction for Amor ########')
33
34
 
34
35
  # only import heavy module if sufficient command line parameters were provided
35
36
  from eos.reduction_reflectivity import ReflectivityReduction
@@ -2,14 +2,14 @@ import argparse
2
2
 
3
3
  from typing import List, Type
4
4
  from .options import ArgParsable
5
-
5
+ from . import __version__
6
6
 
7
7
  def commandLineArgs(config_items: List[Type[ArgParsable]], program_name=None, extra_args=[]):
8
8
  """
9
9
  Process command line argument.
10
10
  The type of the default values is used for conversion and validation.
11
11
  """
12
- msg = "eos reads data from (one or several) raw file(s) of the .hdf format, \
12
+ msg = f"eos ({__version__}) reads data from (one or several) raw file(s) of the .hdf format, \
13
13
  performs various corrections, conversations and projections and exports\
14
14
  the resulting reflectivity in an orso-compatible format."
15
15
  clas = argparse.ArgumentParser(prog=program_name,
@@ -184,7 +184,7 @@ class ApplyMask(EventDataAction):
184
184
  # only run this calculation if debug level is actually active
185
185
  filtered_by_mask = {}
186
186
  for key, value in EVENT_BITMASKS.items():
187
- filtered_by_mask[key] = ((d.events.mask & value)!=0).sum()
187
+ filtered_by_mask[key] = int(((d.events.mask & value)!=0).sum())
188
188
  logging.debug(f" Removed by filters: {filtered_by_mask}")
189
189
  if self.bitmask_filter is None:
190
190
  d.events = d.events[d.events.mask==0]
@@ -197,18 +197,19 @@ class ApplyMask(EventDataAction):
197
197
  logging.info(f' number of events: total = {pre_filter:7d}, after filtering = {post_filter:7d}')
198
198
  if d.device_logs == {} or not hasattr(dataset, 'update_info_from_logs'):
199
199
  return
200
- # filter pulses and logs to allow update of header information
201
- from .helpers import add_log_to_pulses
202
- times = np.unique(d.events.wallTime)
203
- # make sure all log variables are associated with pulses
204
- for key, log in d.device_logs.items():
205
- if not key in d.pulses.dtype.names:
206
- # interpolate the parameter values for all existing pulses
207
- add_log_to_pulses(key, dataset)
208
- # remove all pulses that have no more events
209
- d.pulses = d.pulses[np.isin(d.pulses.time, times)]
210
- for key, log in d.device_logs.items():
211
- d.device_logs[key] = np.recarray(d.pulses.shape, dtype = log.dtype)
212
- d.device_logs[key].time = d.pulses.time
213
- d.device_logs[key].value = d.pulses[key]
214
- dataset.update_info_from_logs()
200
+ if 'wallTime' in d.events.dtype.names:
201
+ # filter pulses and logs to allow update of header information
202
+ from .helpers import add_log_to_pulses
203
+ times = np.unique(d.events.wallTime)
204
+ # make sure all log variables are associated with pulses
205
+ for key, log in d.device_logs.items():
206
+ if not key in d.pulses.dtype.names:
207
+ # interpolate the parameter values for all existing pulses
208
+ add_log_to_pulses(key, dataset)
209
+ # remove all pulses that have no more events
210
+ d.pulses = d.pulses[np.isin(d.pulses.time, times)]
211
+ for key, log in d.device_logs.items():
212
+ d.device_logs[key] = np.recarray(d.pulses.shape, dtype = log.dtype)
213
+ d.device_logs[key].time = d.pulses.time
214
+ d.device_logs[key].value = d.pulses[key]
215
+ dataset.update_info_from_logs()
@@ -63,7 +63,7 @@ class AmorHeader:
63
63
  nu=('entry1/measurement_configuration/nu', float, 'nu'),
64
64
  kap=('entry1/measurement_configuration/kappa', float, 'kappa'),
65
65
  kad=('entry1/measurement_configuration/kappa_offset', float, 'kappa_offset'),
66
- div=('entry1/measurement_configuration/div', float, 'div'),
66
+ div=('entry1/measurement_configuration/divergence', float, 'div'),
67
67
  virtual_source_horizontal=('entry1/Amor/virtual_source/horizontal', float),
68
68
  virtual_source_vertical=('entry1/Amor/virtual_source/vertical', float),
69
69
  ch1_trigger_phase=('entry1/Amor/chopper/ch1_trigger_phase', float, 'ch1_trigger_phase'),
@@ -379,6 +379,7 @@ class AmorEventData(AmorHeader):
379
379
  data: AmorEventStream
380
380
 
381
381
  eventStartTime: np.int64
382
+ correctTimeFallback:bool = True
382
383
 
383
384
  def __init__(self, fileName:Union[str, h5py.File, BinaryIO], first_index:int=0, max_events:int=100_000_000):
384
385
  if type(fileName) is str:
@@ -520,11 +521,26 @@ class AmorEventData(AmorHeader):
520
521
  startTime = chopper1TriggerTime[0]
521
522
  pulseTimeS = chopper1TriggerTime
522
523
  elif self._beam_monitor.time.shape[0] > 1:
523
- logging.critical(' No chopper trigger data available, using first monitor time!')
524
+ logging.critical(' No chopper trigger data available, using first monitor time!')
524
525
  startTime = np.array(self._beam_monitor.time[0], dtype=np.int64)
525
526
  pulseTimeS = self._beam_monitor.time
527
+ elif self.correctTimeFallback:
528
+ logging.critical(
529
+ ' No chopper trigger data or monitor time available, using event stearm and packet times instead!')
530
+ data_group = self.hdf[self.hdf_paths['data'][0]]
531
+ startTime = np.array(data_group['event_time_zero'][0], dtype=np.int64)
532
+ stopTime = np.array(data_group['event_time_zero'][-1], dtype=np.int64)
533
+ pulseTimeS = np.arange(startTime, stopTime, self.timing.tau*1e9, dtype=np.int64)
534
+ # find times that are closest to the next packet time and correct them to fit exactly
535
+ all_times = np.unique(packets.time)
536
+ all_times.sort()
537
+ tauhalf = self.timing.tau*5e8
538
+ for ti in all_times:
539
+ idx = np.where((pulseTimeS+tauhalf)>=ti)[0][0]
540
+ # to keep approximate tau spacing, correct all times after the current packet
541
+ pulseTimeS[idx:] -= (pulseTimeS[idx]-ti)
526
542
  else:
527
- logging.critical(' No chopper trigger data available, using event steram instead, pulse filtering will fail!')
543
+ logging.critical(' No chopper trigger data or monitor time available, using event steram instead, pulse filtering will fail!')
528
544
  data_group = self.hdf[self.hdf_paths['data'][0]]
529
545
  startTime = np.array(data_group['event_time_zero'][0], dtype=np.int64)
530
546
  stopTime = np.array(data_group['event_time_zero'][-2], dtype=np.int64)
@@ -605,9 +621,20 @@ class AmorEventData(AmorHeader):
605
621
  new_beam_monitor = None
606
622
  else:
607
623
  new_beam_monitor = np.concatenate([self.data.beam_monitor, other.data.beam_monitor]).view(np.recarray)
624
+ if self.data.device_logs is None or other.data.device_logs is None:
625
+ new_device_logs = None
626
+ else:
627
+ new_device_logs = {}
628
+ for key, slog in self.data.device_logs.items():
629
+ olog = other.data.device_logs[key]
630
+ new_device_logs[key] = np.recarray(slog.shape[0]+olog.shape[0],
631
+ dtype = slog.dtype)
632
+ new_device_logs[key].time = np.concatenate([slog.time, olog.time])
633
+ new_device_logs[key].value = np.concatenate([slog.value, olog.value])
608
634
  new_packets = np.concatenate([self.data.packets, other.data.packets]).view(np.recarray)
609
635
  new_packets.start_index[self.data.packets.shape[0]:] += self.data.events.shape[0]
610
- self.data = AmorEventStream(new_events, new_packets, new_pulses, new_proton_current, new_beam_monitor)
636
+ self.data = AmorEventStream(new_events, new_packets, new_pulses, new_proton_current, new_beam_monitor,
637
+ new_device_logs)
611
638
  # Indicate that this is a modified dataset, basically counts number of appends as negative indices
612
639
  self.last_index = min(self.last_index-1, -1)
613
640
  self.file_list += other.file_list
@@ -433,8 +433,8 @@ class ReflectivityReductionConfig(ArgParsable):
433
433
  metadata={
434
434
  'group': 'input data',
435
435
  'help': 'apply convolution on lambda axes to smooth the normalization data, useful for low statistics'})
436
- scale: List[float] = field(
437
- default_factory=lambda: [],
436
+ scale: Optional[List[float]] = field(
437
+ default=None,
438
438
  metadata={
439
439
  'short': 's',
440
440
  'group': 'data manicure',
@@ -490,6 +490,14 @@ class ReflectivityReductionConfig(ArgParsable):
490
490
  },
491
491
  )
492
492
 
493
+ correctTimeFallback: bool = field(
494
+ default=True,
495
+ metadata={
496
+ 'group': 'data manicure',
497
+ 'help': 'if falleng back to event stream for pulse time estimation, correct exact values '
498
+ 'to recover filtering options (slower)',
499
+ },
500
+ )
493
501
 
494
502
  class OutputFomatOption(StrEnum):
495
503
  Rqz_ort = "Rqz.ort"
@@ -131,11 +131,7 @@ class E2HReduction:
131
131
  # safe to image file if not auto-updating graph
132
132
  plt.savefig(f'e2h_{self.config.reduction.plot}.png', dpi=300)
133
133
  if self.config.reduction.kafka:
134
- from .kafka_serializer import ESSSerializer
135
- self.serializer = ESSSerializer()
136
- self.fig.canvas.mpl_connect('close_event', self.serializer.end_command_thread)
137
- self.serializer.start_command_thread()
138
- self.serializer.send(self.projection)
134
+ raise RuntimeError("--kafka not implemented for events2histogram, use eos nicos script")
139
135
  if self.config.reduction.update:
140
136
  self.timer = self.fig.canvas.new_timer(1000)
141
137
  self.timer.add_callback(self.update)
@@ -313,6 +309,3 @@ class E2HReduction:
313
309
  self.projection.update_plot()
314
310
  plt.suptitle(self.create_title())
315
311
  plt.draw()
316
-
317
- if self.config.reduction.kafka:
318
- self.serializer.send(self.projection)
@@ -46,7 +46,10 @@ class ReflectivityReduction:
46
46
  self.normevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType)
47
47
  if self.config.experiment.monitorType in [MonitorType.proton_charge, MonitorType.debug]:
48
48
  self.normevent_actions |= ea.ExtractWalltime()
49
- self.normevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
49
+ if self.config.experiment.lowCurrentThreshold>0:
50
+ self.normevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
51
+ else:
52
+ logging.debug(' low current threashold disabled')
50
53
  self.normevent_actions |= eh.FilterStrangeTimes()
51
54
  self.normevent_actions |= ea.MergeFrames()
52
55
  self.normevent_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
@@ -61,9 +64,10 @@ class ReflectivityReduction:
61
64
  self.dataevent_time_correction = eh.CorrectSeriesTime(0) # will be set from first dataset
62
65
  self.dataevent_actions |= self.dataevent_time_correction
63
66
  self.dataevent_actions |= eh.AssociatePulseWithMonitor(self.config.experiment.monitorType)
64
- if self.config.experiment.monitorType in [MonitorType.proton_charge or MonitorType.debug]:
67
+ if self.config.experiment.monitorType in [MonitorType.proton_charge, MonitorType.debug]:
65
68
  # the filtering only makes sense if using actual monitor data, not time
66
- self.dataevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
69
+ if self.config.experiment.lowCurrentThreshold>0:
70
+ self.dataevent_actions |= eh.FilterMonitorThreshold(self.config.experiment.lowCurrentThreshold)
67
71
  self.dataevent_actions |= eh.FilterStrangeTimes()
68
72
  self.dataevent_actions |= ea.MergeFrames(extractNeutronPulses=self.config.reduction.extractNeutronPulses)
69
73
  self.dataevent_actions |= ea.AnalyzePixelIDs(self.config.experiment.yRange)
@@ -78,6 +82,9 @@ class ReflectivityReduction:
78
82
 
79
83
  self.grid = LZGrid(self.config.reduction.qResolution, self.config.reduction.qzRange)
80
84
 
85
+ # transfer option to data reader
86
+ AmorEventData.correctTimeFallback = self.config.reduction.correctTimeFallback
87
+
81
88
  def reduce(self):
82
89
  if not os.path.exists(f'{self.config.output.outputPath}'):
83
90
  logging.debug(f'Creating destination path {self.config.output.outputPath}')
@@ -231,6 +238,13 @@ class ReflectivityReduction:
231
238
  logging.warning(
232
239
  f'backgroung file {self.sFileName} not compatible with q_z scale ({len(self.sq_q)} vs. {len(result.Q)})')
233
240
 
241
+ if not self.config.reduction.is_default('scale'):
242
+ try:
243
+ scale = self.config.reduction.scale[i]
244
+ except IndexError:
245
+ scale = self.config.reduction.scale[-1]
246
+ result.scale(scale)
247
+
234
248
  orso_data = fileio.OrsoDataset(headerRqz, result.data)
235
249
  self.last_result = result
236
250
  self.datasetsRqz.append(orso_data)
@@ -310,12 +324,12 @@ class ReflectivityReduction:
310
324
  logging.info(f' {ti:<4d} {time:6.0f} {self.monitor:7.2f} {MONITOR_UNITS[self.config.experiment.monitorType]}')
311
325
 
312
326
  proj: LZProjection = self.project_on_lz(slice)
313
- try:
314
- scale = self.config.reduction.scale[i]
315
- except IndexError:
316
- scale = self.config.reduction.scale[-1]
317
- # TODO: causes error if no '-s' argumnet is given
318
- proj.scale(scale)
327
+ if not self.config.reduction.is_default('scale'):
328
+ try:
329
+ scale = self.config.reduction.scale[i]
330
+ except IndexError:
331
+ scale = self.config.reduction.scale[-1]
332
+ proj.scale(scale)
319
333
 
320
334
  # projection on qz-grid
321
335
  result = proj.project_on_qz()
@@ -0,0 +1,125 @@
1
+ import os
2
+ import cProfile
3
+ import numpy as np
4
+ from unittest import TestCase
5
+ from dataclasses import fields, MISSING
6
+ from eos import options, reduction_reflectivity, logconfig
7
+ from orsopy import fileio
8
+
9
+ logconfig.setup_logging()
10
+ logconfig.update_loglevel(1)
11
+
12
+ # TODO: add unit tests for individual parts of reduction
13
+
14
+ class FullAmorTest(TestCase):
15
+ @classmethod
16
+ def setUpClass(cls):
17
+ # generate map for option defaults
18
+ cls._field_defaults = {}
19
+ for opt in [options.ExperimentConfig, options.ReflectivityReductionConfig, options.ReflectivityOutputConfig]:
20
+ defaults = {}
21
+ for field in fields(opt):
22
+ if field.default not in [None, MISSING]:
23
+ defaults[field.name] = field.default
24
+ elif field.default_factory not in [None, MISSING]:
25
+ defaults[field.name] = field.default_factory()
26
+ cls._field_defaults[opt.__name__] = defaults
27
+ cls.pr = cProfile.Profile()
28
+
29
+ @classmethod
30
+ def tearDownClass(cls):
31
+ cls.pr.dump_stats("profile_test.prof")
32
+
33
+ def setUp(self):
34
+ self.pr.enable()
35
+ self.reader_config = options.ReaderConfig(
36
+ year=2026,
37
+ rawPath=["test_data"],
38
+ )
39
+
40
+ def tearDown(self):
41
+ self.pr.disable()
42
+ for fi in ['test_results/test.Rqz.ort', 'test_results/5952.norm']:
43
+ try:
44
+ os.unlink(fi)
45
+ except FileNotFoundError:
46
+ pass
47
+
48
+ def test_time_slicing(self):
49
+ experiment_config = options.ExperimentConfig(
50
+ yRange=(18, 48),
51
+ lambdaRange=(3., 11.5),
52
+ sampleModel='air | 10 H2O | D2O'
53
+ )
54
+ reduction_config = options.ReflectivityReductionConfig(
55
+ qResolution=0.01,
56
+ qzRange=(0.01, 0.15),
57
+ thetaRange=(-0.75, 0.75),
58
+ fileIdentifier=["3629", "3630"],
59
+ scale=[1],
60
+ normalisationFileIdentifier=[],
61
+ timeSlize=[300.0]
62
+ )
63
+ output_config = options.ReflectivityOutputConfig(
64
+ outputFormats=[options.OutputFomatOption.Rqz_ort],
65
+ outputName='test',
66
+ outputPath='test_results',
67
+ )
68
+ config=options.ReflectivityConfig(self.reader_config, experiment_config, reduction_config, output_config)
69
+ # run three times to get similar timing to noslicing runs
70
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
71
+ reducer.reduce()
72
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
73
+ reducer.reduce()
74
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
75
+ reducer.reduce()
76
+
77
+ def test_noslicing(self):
78
+ experiment_config = options.ExperimentConfig(
79
+ yRange=(18, 48),
80
+ lambdaRange=(3., 11.5),
81
+ )
82
+ reduction_config = options.ReflectivityReductionConfig(
83
+ qResolution=0.01,
84
+ thetaRange=(-0.75, 0.75),
85
+ fileIdentifier=["3629", "3630"],
86
+ scale=[1],
87
+ normalisationFileIdentifier=["3631"],
88
+ autoscale=(0.0, 0.05),
89
+ )
90
+ output_config = options.ReflectivityOutputConfig(
91
+ outputFormats=[options.OutputFomatOption.Rqz_ort],
92
+ outputName='test',
93
+ outputPath='test_results',
94
+ )
95
+ config=options.ReflectivityConfig(self.reader_config, experiment_config, reduction_config, output_config)
96
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
97
+ reducer.reduce()
98
+ # run second time to reuse norm file
99
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
100
+ reducer.reduce()
101
+
102
+ def test_noslicing_nmon(self):
103
+ experiment_config = options.ExperimentConfig(
104
+ yRange=(18, 48),
105
+ lambdaRange=(3., 11.5),
106
+ )
107
+ reduction_config = options.ReflectivityReductionConfig(
108
+ qResolution=0.01,
109
+ thetaRange=(-0.75, 0.75),
110
+ fileIdentifier=["3629", "3630"],
111
+ scale=[1],
112
+ normalisationFileIdentifier=["3631"],
113
+ autoscale=(0.0, 0.05),
114
+ )
115
+ output_config = options.ReflectivityOutputConfig(
116
+ outputFormats=[options.OutputFomatOption.Rqz_ort],
117
+ outputName='test',
118
+ outputPath='test_results',
119
+ )
120
+ config=options.ReflectivityConfig(self.reader_config, experiment_config, reduction_config, output_config)
121
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
122
+ reducer.reduce()
123
+ # run second time to reuse norm file
124
+ reducer = reduction_reflectivity.ReflectivityReduction(config)
125
+ reducer.reduce()
@@ -1,6 +0,0 @@
1
- """
2
- Package to handle data redction at AMOR instrument to be used by __main__.py script.
3
- """
4
-
5
- __version__ = '3.3.0'
6
- __date__ = '2026-07-09'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes