21 Commits

Author SHA1 Message Date
b80a01325b Update version information for commit before merge of version 3
Some checks failed
Release / build-ubuntu-latest (push) Failing after 2s
Release / build-windows (push) Has been cancelled
Release / release (push) Has been cancelled
2025-10-06 16:12:47 +02:00
a22732c612 fixed the wrong proton-current matching 2025-09-16 11:08:52 +02:00
443cb30b79 fixes in the polarisation handlinge 2025-06-30 15:41:20 +02:00
057742cabd taking chopper info from event stream, new debug output, fix for chopper offset 2025-06-24 11:06:07 +02:00
2689a969f1 fallback in case no chopper trigger signal is available, typo fixes 2025-06-13 12:38:26 +02:00
aff4c5b603 added TODO 2025-06-10 09:55:25 +02:00
887ec6fa23 added absolute path to clas 2025-06-10 08:54:58 +02:00
6102ed7123 chopper phases defaults, e2h_2025 2025-06-08 15:50:08 +02:00
bbac3bc943 Merge branch 'main' of https://github.com/jochenstahn/amor 2025-06-08 15:33:51 +02:00
bacbd18854 uploading the correct e2h now... 2025-06-08 15:31:51 +02:00
Jochen Stahn
aa7919b83d file_reader: cache lookup extended 2025-06-08 12:06:43 +02:00
f65651d0e5 events2histogram version for new hdf archiecture 2025-06-07 17:19:40 +02:00
1b0df0ec45 some polishing 2025-05-30 11:18:59 +02:00
5f94cc7b92 adapted parameter pathes for hdf file, introduced chopper phases from file 2025-05-29 18:11:51 +02:00
a947a70d2d included polarisation info, using chopper trigger signal for normalisation 2025-05-29 11:26:37 +02:00
729332f49d Bump version number 2025-01-30 17:04:22 +01:00
500d53a9b2 Fetch commits and tags for release action 2025-01-30 16:30:35 +01:00
dac76efdd1 set the tag for github release to the last git tag 2025-01-30 15:18:52 +01:00
e78200a39d add workflow dispatch action for updating release 2025-01-30 14:57:06 +01:00
c6bde8cd85 add permission id-token to action 2025-01-30 14:53:24 +01:00
8e9c03a4fb try github action with trusted publishing (no user/token) 2025-01-30 14:48:30 +01:00
8 changed files with 2282 additions and 143 deletions

View File

@@ -19,12 +19,14 @@ on:
- all
- windows
- linux
- mac
- all_incl_release
jobs:
build-ubuntu-latest:
runs-on: ubuntu-latest
if: ${{ (github.event_name != 'workflow_dispatch') || (contains(fromJson('["all", "linux"]'), github.event.inputs.build-items)) }}
if: ${{ (github.event_name != 'workflow_dispatch') || (contains(fromJson('["all", "linux", "all_incl_release"]'), github.event.inputs.build-items)) }}
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -45,16 +47,16 @@ jobs:
path: |
dist/*.tar.gz
- name: Upload to PyPI
if: github.event_name != 'workflow_dispatch'
#if: github.event_name != 'workflow_dispatch'
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}
# user: __token__
# password: ${{ secrets.PYPI_TOKEN }}
skip-existing: true
build-windows:
runs-on: windows-latest
if: ${{ (github.event_name != 'workflow_dispatch') || (contains(fromJson('["all", "windows"]'), github.event.inputs.build-items)) }}
if: ${{ (github.event_name != 'workflow_dispatch') || (contains(fromJson('["all", "windows", "all_incl_release"]'), github.event.inputs.build-items)) }}
steps:
- uses: actions/checkout@v4
@@ -79,19 +81,25 @@ jobs:
eos.zip
release:
if: github.event_name != 'workflow_dispatch'
if: ${{ (github.event_name != 'workflow_dispatch') || (contains(fromJson('["all_incl_release"]'), github.event.inputs.build-items)) }}
runs-on: ubuntu-latest
needs: [build-ubuntu-latest, build-windows]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- uses: actions/download-artifact@v4
with:
name: linux-dist
- uses: actions/download-artifact@v4
with:
name: windows-dist
- name: get latest version tag
run: echo "RELEASE_TAG=$(git describe --abbrev=0 --tags)" >> $GITHUB_ENV
- uses: ncipollo/release-action@v1
with:
artifacts: "amor*.tar.gz,*.zip"
token: ${{ secrets.GITHUB_TOKEN }}
allowUpdates: true
tag: ${{ env.RELEASE_TAG }}

1082
e2h_new.py Normal file

File diff suppressed because it is too large Load Diff

1051
events2histogram_2025.py Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,6 @@
Package to handle data redction at AMOR instrument to be used by eos.py script.
"""
__version__ = '2.1.4'
__date__ = '2025-01-30'
__version__ = '2.2.0'
__date__ = '2025-09-16'

View File

@@ -185,6 +185,7 @@ def command_line_options():
)
experiment_config = ExperimentConfig(
sampleModel = clas.sampleModel,
chopperSpeed = clas.chopperSpeed,
chopperPhase = clas.chopperPhase,
chopperPhaseOffset = clas.chopperPhaseOffset,
yRange = clas.yRange,

View File

@@ -34,6 +34,8 @@ class AmorData:
chopperDistance: float
chopperPhase: float
chopperSpeed: float
chopper1TriggerPhase: float
chopper2TriggerPhase: float
div: float
data_file_numbers: List[int]
delta_z: np.ndarray
@@ -96,22 +98,6 @@ class AmorData:
self.monitorPerPulse = _monitorPerPulse
self.pulseTimeS = _pulseTimeS
#-------------------------------------------------------------------------------------------------
#def path_generator(self, number):
# fileName = f'amor{self.reader_config.year}n{number:06d}.hdf'
# if os.path.exists(os.path.join(self.reader_config.dataPath,fileName)):
# path = self.reader_config.dataPath
# elif os.path.exists(fileName):
# path = '.'
# elif os.path.exists(os.path.join('.','raw', fileName)):
# path = os.path.join('.','raw')
# elif os.path.exists(os.path.join('..','raw', fileName)):
# path = os.path.join('..','raw')
# elif os.path.exists(f'/afs/psi.ch/project/sinqdata/{self.reader_config.year}/amor/{int(number/1000)}/{fileName}'):
# path = f'/afs/psi.ch/project/sinqdata/{self.reader_config.year}/amor/{int(number/1000)}'
# else:
# sys.exit(f'# ERROR: the file {fileName} is nowhere to be found!')
# return os.path.join(path, fileName)
#-------------------------------------------------------------------------------------------------
def path_generator(self, number):
fileName = f'amor{self.reader_config.year}n{number:06d}.hdf'
@@ -175,7 +161,8 @@ class AmorData:
round(self.mu+self.kap+self.kad+0.5*self.div, 3),
'deg'),
wavelength = fileio.ValueRange(const.lamdaCut, self.config.lambdaRange[1], 'angstrom'),
polarization = fileio.Polarization.unpolarized,
#polarization = fileio.Polarization.unpolarized,
polarization = self.polarizationConfig
)
self.header.measurement_instrument_settings.mu = fileio.Value(round(self.mu, 3), 'deg', comment='sample angle to horizon')
self.header.measurement_instrument_settings.nu = fileio.Value(round(self.nu, 3), 'deg', comment='detector angle to horizon')
@@ -190,18 +177,17 @@ class AmorData:
logging.info(f' mu = {self.mu:6.3f}, nu = {self.nu:6.3f}, kap = {self.kap:6.3f}, kad = {self.kad:6.3f}')
self.read_event_stream()
totalNumber = np.shape(self.tof_e)[0]
# check for empty event stream
if totalNumber == 0:
logging.error('empty event stream: can not determine end time')
sys.exit()
self.sort_pulses()
self.correct_for_chopper_phases()
self.associate_pulse_with_monitor()
self.read_chopper_trigger_stream()
self.extract_walltime(norm)
self.read_proton_current_stream()
self.associate_pulse_with_monitor()
# following lines: debugging output to trace the time-offset of proton current and neutron pulses
if self.config.monitorType == 'x':
cpp, t_bins = np.histogram(self.wallTime_e, self.pulseTimeS)
@@ -213,7 +199,7 @@ class AmorData:
self.filter_strange_times()
self.merge_frames()
self.merge_time_frames()
self.filter_project_x()
@@ -223,73 +209,17 @@ class AmorData:
self.filter_qz_range(norm)
logging.info(f' number of events: total = {totalNumber:7d}, filtered = {np.shape(self.lamda_e)[0]:7d}')
logging.info(f' number of events: total = {self.totalNumber:7d}, filtered = {np.shape(self.lamda_e)[0]:7d}')
def sort_pulses(self):
chopperPeriod = np.int64(2*self.tau*1e9)
pulseTime = np.sort(self.dataPacketTime_p)
pulseTime = pulseTime[np.abs(pulseTime[:]-np.roll(pulseTime, 1)[:])>5]
def read_event_stream(self):
self.tof_e = np.array(self.hdf['/entry1/Amor/detector/data/event_time_offset'][:])/1.e9
self.pixelID_e = np.array(self.hdf['/entry1/Amor/detector/data/event_id'][:], dtype=np.int64)
self.dataPacket_p = np.array(self.hdf['/entry1/Amor/detector/data/event_index'][:], dtype=np.uint64)
self.dataPacketTime_p = np.array(self.hdf['/entry1/Amor/detector/data/event_time_zero'][:], dtype=np.int64)
pulseTime -= np.int64(self.seriesStartTime)
self.stopTime = pulseTime[-1]
pulseTime = pulseTime[pulseTime>=0]
# fill in missing pulse times
# TODO: check for real end time
try:
# further files
# TODO: use the first pulse of the respective measurement
#nextPulseTime = startTime % np.int64(self.tau*2e9)
#nextPulseTime = self.pulseTimeS[-1] + chopperPeriod
nextPulseTime = pulseTime[0]
except AttributeError:
# first file
nextPulseTime = pulseTime[0] % np.int64(self.tau*2e9)
# calculate where time tiefference between pulses exceeds its time by more than 1/2
# this yields the number of missing pulses
pulseLengths = pulseTime[1:]-pulseTime[:-1]
pulseExtra = (pulseLengths-np.int64(self.tau*1e9))//np.int64(self.tau*2e9)
gap_indices = np.where(pulseExtra>0)[0]
if len(gap_indices)==0:
# no missing pulses, just use given array
self.pulseTimeS = np.array(pulseTime, dtype=np.int64)
return
self.pulseTimeS = np.array(pulseTime[:gap_indices[0]+1], dtype=np.int64)
last_index = gap_indices[0]
for gapi in gap_indices[1:]:
# insert missing pulses into each gap
gap_pulses = pulseTime[last_index]+np.arange(1, pulseExtra[last_index]+1)*chopperPeriod
self.pulseTimeS = np.append(self.pulseTimeS, gap_pulses)
self.pulseTimeS = np.append(self.pulseTimeS, pulseTime[last_index+1:gapi+1])
last_index = gapi
if last_index<len(pulseTime):
self.pulseTimeS = np.append(self.pulseTimeS, pulseTime[last_index:-1])
def get_current_per_pulse(self, pulseTimeS, currentTimeS, currents):
# add currents for early pulses and current time value after last pulse (j+1)
currentTimeS = np.hstack([[0], currentTimeS, [pulseTimeS[-1]+1]])
currents = np.hstack([[0], currents])
pulseCurrentS = np.zeros(pulseTimeS.shape[0], dtype=float)
j = 0
for i, ti in enumerate(pulseTimeS):
if ti >= currentTimeS[j+1]:
j += 1
pulseCurrentS[i] = currents[j]
#print(f' {i} {pulseTimeS[i]} {pulseCurrentS[i]}')
return pulseCurrentS
def associate_pulse_with_monitor(self):
if self.config.monitorType == 'p': # protonCharge
self.currentTime -= np.int64(self.seriesStartTime)
self.monitorPerPulse = self.get_current_per_pulse(self.pulseTimeS, self.currentTime, self.current) * 2*self.tau * 1e-3
# filter low-current pulses
self.monitorPerPulse = np.where(self.monitorPerPulse > 2*self.tau * self.config.lowCurrentThreshold * 1e-3, self.monitorPerPulse, 0)
elif self.config.monitorType == 't': # countingTime
self.monitorPerPulse = np.ones(np.shape(self.pulseTimeS)[0])*self.tau
else:
self.monitorPerPulse = 1./np.shape(pulseTimeS)[1]
def correct_for_chopper_phases(self):
#print(f'chopperTriggerPhase: {self.ch1TriggerPhase}')
self.tof_e += self.tau * (self.ch1TriggerPhase + self.chopperPhase/2)/180
def extract_walltime(self, norm):
if nb_helpers:
@@ -302,6 +232,54 @@ class AmorData:
self.wallTime_e -= np.int64(self.seriesStartTime)
logging.debug(f' wall time from {self.wallTime_e[0]/1e9:6.1f} s to {self.wallTime_e[-1]/1e9:6.1f} s')
def read_chopper_trigger_stream(self):
self.chopper1TriggerTime = np.array(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time_zero'][:-2], dtype=np.int64)
#self.chopper2TriggerTime = self.chopper1TriggerTime + np.array(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time'][:-2], dtype=np.int64)
# + np.array(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time_offset'][:], dtype=np.int64)
if np.shape(self.chopper1TriggerTime)[0] > 2:
self.startTime = self.chopper1TriggerTime[0]
self.stopTime = self.chopper1TriggerTime[-1]
self.pulseTimeS = self.chopper1TriggerTime
else:
logging.warn(' no chopper trigger data available, using event steram instead')
self.startTime = np.array(self.hdf['/entry1/Amor/detector/data/event_time_zero'][0], dtype=np.int64)
self.stopTime = np.array(self.hdf['/entry1/Amor/detector/data/event_time_zero'][-2], dtype=np.int64)
self.pulseTimeS = np.arange(self.startTime, self.stopTime, self.tau*1e9)
if self.seriesStartTime is None:
self.seriesStartTime = self.startTime
logging.debug(f' series start time (epoch): {self.seriesStartTime/1e9:13.2f} s')
self.pulseTimeS -= self.seriesStartTime
logging.debug(f' epoch time from {self.startTime/1e9:13.2f} s to {self.stopTime/1e9:13.2f} s')
logging.debug(f' => counting time {self.stopTime/1e9-self.startTime/1e9:8.2f} s')
def read_proton_current_stream(self):
self.currentTime = np.array(self.hdf['entry1/Amor/detector/proton_current/time'][:], dtype=np.int64)
self.current = np.array(self.hdf['entry1/Amor/detector/proton_current/value'][:,0], dtype=float)
def get_current_per_pulse(self, pulseTimeS, currentTimeS, currents):
# add currents for early pulses and current time value after last pulse (j+1)
currentTimeS = np.hstack([[0], currentTimeS, [pulseTimeS[-1]+1]])
currents = np.hstack([[0], currents])
pulseCurrentS = np.zeros(pulseTimeS.shape[0], dtype=float)
j = 0
for i, ti in enumerate(pulseTimeS):
while ti >= currentTimeS[j+1]:
j += 1
pulseCurrentS[i] = currents[j]
#print(f' {i} {pulseTimeS[i]} {pulseCurrentS[i]}')
return pulseCurrentS
def associate_pulse_with_monitor(self):
if self.config.monitorType == 'p': # protonCharge
self.currentTime -= np.int64(self.seriesStartTime)
self.monitorPerPulse = self.get_current_per_pulse(self.pulseTimeS, self.currentTime, self.current) * 2*self.tau * 1e-3
# filter low-current pulses
self.monitorPerPulse = np.where(self.monitorPerPulse > 2*self.tau * self.config.lowCurrentThreshold * 1e-3, self.monitorPerPulse, 0)
elif self.config.monitorType == 't': # countingTime
self.monitorPerPulse = np.ones(np.shape(self.pulseTimeS)[0])*2*self.tau
else: # pulses
self.monitorPerPulse = np.ones(np.shape(self.pulseTimeS)[0])
def average_events_per_pulse(self):
if self.config.monitorType == 'p':
for i, time in enumerate(self.pulseTimeS):
@@ -309,18 +287,20 @@ class AmorData:
logging.info(f'pulse: {i:6.0f}, events: {events:6.0f}, monitor: {self.monitorPerPulse[i]:6.2f}')
def monitor_threshold(self):
if self.config.monitorType == 'p': # fix to check for file compatibility
#if self.config.monitorType == 'p': # fix to check for file compatibility
self.totalNumber = np.shape(self.tof_e[self.tof_e<=self.stopTime])[0]
if True:
goodTimeS = self.pulseTimeS[self.monitorPerPulse!=0]
filter_e = np.where(np.isin(self.wallTime_e, goodTimeS), True, False)
self.tof_e = self.tof_e[filter_e]
self.pixelID_e = self.pixelID_e[filter_e]
self.wallTime_e = self.wallTime_e[filter_e]
logging.info(f' rejected {np.shape(self.monitorPerPulse)[0]-np.shape(goodTimeS)[0]} out of {np.shape(self.monitorPerPulse)[0]} pulses')
logging.info(f' with {np.shape(filter_e)[0]-np.shape(self.tof_e)[0]} events due to low beam current')
logging.info(f' low-beam rejected pulses: {np.shape(self.monitorPerPulse)[0]-1-np.shape(goodTimeS)[0]} out of {np.shape(self.monitorPerPulse)[0]-1}')
logging.info(f' with {np.shape(filter_e)[0]-np.shape(self.tof_e)[0]} events')
logging.info(f' average counts per pulse = {np.shape(self.tof_e)[0] / np.shape(goodTimeS[goodTimeS!=0])[0]:7.1f}')
def filter_qz_range(self, norm):
if self.config.qzRange[1]<0.3 and not norm:
if self.config.qzRange[1]<0.5 and not norm:
self.mask_e = np.logical_and(self.mask_e,
(self.config.qzRange[0]<=self.qz_e) & (self.qz_e<=self.config.qzRange[1]))
self.detZ_e = self.detZ_e[self.mask_e]
@@ -329,7 +309,8 @@ class AmorData:
def calculate_derived_properties(self):
self.lamdaMax = const.lamdaCut+1.e13*self.tau*const.hdm/(self.chopperDetectorDistance+124.)
if nb_helpers:
#if nb_helpers:
if False:
self.lamda_e, self.qz_e, self.mask_e = nb_helpers.calculate_derived_properties_focussing(
self.tof_e, self.detXdist_e, self.delta_e, self.mask_e,
self.config.lambdaRange[0], self.config.lambdaRange[1], self.nu, self.mu,
@@ -379,8 +360,9 @@ class AmorData:
# define mask and filter y range
self.mask_e = (self.config.yRange[0]<=detY_e) & (detY_e<=self.config.yRange[1])
def merge_frames(self):
total_offset = self.tofCut+self.tau*self.config.chopperPhaseOffset/180.
# TODO: - handle each neutron pulse individually, - associate with correct monitor also for slow neutrons
def merge_time_frames(self):
total_offset = self.tofCut + self.tau * (self.ch1TriggerPhase + self.chopperPhase/2)/180
if nb_helpers:
self.tof_e = nb_helpers.merge_frames(self.tof_e, self.tofCut, self.tau, total_offset)
else:
@@ -395,44 +377,45 @@ class AmorData:
if np.shape(filter_e)[0]-np.shape(self.tof_e)[0]>0.5:
logging.warning(f' strange times: {np.shape(filter_e)[0]-np.shape(self.tof_e)[0]}')
def read_event_stream(self):
self.tof_e = np.array(self.hdf['/entry1/Amor/detector/data/event_time_offset'][:])/1.e9
self.pixelID_e = np.array(self.hdf['/entry1/Amor/detector/data/event_id'][:], dtype=np.int64)
self.dataPacket_p = np.array(self.hdf['/entry1/Amor/detector/data/event_index'][:], dtype=np.uint64)
self.dataPacketTime_p = np.array(self.hdf['/entry1/Amor/detector/data/event_time_zero'][:], dtype=np.int64)
if self.config.monitorType in ['auto', 'p']:
try:
self.currentTime = np.array(self.hdf['entry1/Amor/detector/proton_current/time'][:], dtype=np.int64)
self.current = np.array(self.hdf['entry1/Amor/detector/proton_current/value'][:,0], dtype=float)
if len(self.current)>4:
self.config.monitorType = 'p'
else:
self.config.monitorType = 't'
except(KeyError, IndexError):
self.config.monitorType = 't'
else:
self.config.monitorType = 't'
#TODO: protonMonitor
def read_individual_header(self):
self.chopperDistance = float(np.take(self.hdf['entry1/Amor/chopper/pair_separation'], 0))
self.detectorDistance = float(np.take(self.hdf['entry1/Amor/detector/transformation/distance'], 0))
self.chopperDetectorDistance = self.detectorDistance-float(np.take(self.hdf['entry1/Amor/chopper/distance'], 0))
self.tofCut = const.lamdaCut*self.chopperDetectorDistance/const.hdm*1.e-13
polarizationConfigs = ['undefined', 'unpolarized', 'po', 'mo', 'op', 'pp', 'mp', 'om', 'pm', 'mm']
try:
self.mu = float(np.take(self.hdf['/entry1/Amor/master_parameters/mu/value'], 0))
self.nu = float(np.take(self.hdf['/entry1/Amor/master_parameters/nu/value'], 0))
self.kap = float(np.take(self.hdf['/entry1/Amor/master_parameters/kap/value'], 0))
self.kad = float(np.take(self.hdf['/entry1/Amor/master_parameters/kad/value'], 0))
self.div = float(np.take(self.hdf['/entry1/Amor/master_parameters/div/value'], 0))
self.chopperSpeed = float(np.take(self.hdf['/entry1/Amor/chopper/rotation_speed/value'], 0))
self.chopperPhase = float(np.take(self.hdf['/entry1/Amor/chopper/phase/value'], 0))
self.mu = float(np.take(self.hdf['/entry1/Amor/instrument_control_parameters/mu'], 0))
self.nu = float(np.take(self.hdf['/entry1/Amor/instrument_control_parameters/nu'], 0))
self.kap = float(np.take(self.hdf['/entry1/Amor/instrument_control_parameters/kap'], 0))
self.kad = float(np.take(self.hdf['/entry1/Amor/instrument_control_parameters/kad'], 0))
self.div = float(np.take(self.hdf['/entry1/Amor/instrument_control_parameters/div'], 0))
self.ch1TriggerPhase = float(np.take(self.hdf['/entry1/Amor/chopper/ch1_trigger_phase'], 0))
self.ch2TriggerPhase = float(np.take(self.hdf['/entry1/Amor/chopper/ch2_trigger_phase'], 0))
try:
chopperTriggerTime = float(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time_zero'][2])\
- float(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time_zero'][1])
self.tau = int(1e-6*chopperTriggerTime/2+0.5)*(1e-3)
self.chopperSpeed = 30/self.tau
chopperTriggerTimeDiff = float(self.hdf['entry1/Amor/chopper/ch2_trigger/event_time_offset'][2])
chopperTriggerPhase = 180e-9*chopperTriggerTimeDiff/self.tau
#TODO: check the next line
self.chopperPhase = chopperTriggerPhase + self.ch1TriggerPhase - self.ch2TriggerPhase
except(KeyError, IndexError):
logging.debug(' chopper speed and phase taken from .hdf file')
self.chopperSpeed = float(np.take(self.hdf['/entry1/Amor/chopper/rotation_speed'], 0))
self.chopperPhase = float(np.take(self.hdf['/entry1/Amor/chopper/phase'], 0))
self.tau = 30/self.chopperSpeed
try:
polarizationConfigLabel = int(self.hdf['/entry1/Amor/polarization/configuration/value'][0])
except(KeyError, IndexError):
polarizationConfigLabel = 0
self.polarizationConfig = polarizationConfigs[polarizationConfigLabel]
logging.debug(f' polarization configuration: {self.polarizationConfig} (index {polarizationConfigLabel} (index {polarizationConfigLabel}))')
except(KeyError, IndexError):
logging.warning(" using parameters from nicos cache")
year_date = str(self.start_date).replace('-', '/', 1)
#cachePath = '/home/amor/nicosdata/amor/cache/'
#cachePath = '/home/nicos/amorcache/'
# TODO: check new cache pathes
cachePath = '/home/amor/cache/'
value = str(subprocess.getoutput(f'/usr/bin/grep "value" {cachePath}nicos-mu/{year_date}')).split('\t')[-1]
self.mu = float(value)
@@ -446,22 +429,35 @@ class AmorData:
self.div = float(value)
value = str(subprocess.getoutput(f'/usr/bin/grep "value" {cachePath}nicos-ch1_speed/{year_date}')).split('\t')[-1]
self.chopperSpeed = float(value)
self.chopperPhase = self.config.chopperPhase
self.tau = 30. / self.chopperSpeed
value = str(subprocess.getoutput(f'/usr/bin/grep "value" {cachePath}nicos-chopper_phase/{year_date}')).split('\t')[-1]
self.chopperPhase = float(value)
value = str(subprocess.getoutput(f'/usr/bin/grep "value" {cachePath}nicos-ch1_trigger_phase/{year_date}')).split('\t')[-1]
self.ch1TriggerPhase = float(value)
value = str(subprocess.getoutput(f'/usr/bin/grep "value" {cachePath}nicos-ch2_trigger_phase/{year_date}')).split('\t')[-1]
self.ch2TriggerPhase = float(value)
self.tau = 30. / self.chopperSpeed
logging.debug(f' tau = {self.tau} s')
if self.config.muOffset:
logging.debug(f' set muOffset = {self.config.muOffset}')
self.mu += self.config.muOffset
if self.config.mu:
logging.debug(f' replaced mu = {self.mu} with {self.config.mu}')
self.mu = self.config.mu
if self.config.nu:
logging.debug(f' replaced nu = {self.nu} with {self.config.nu}')
self.nu = self.config.nu
if self.config.chopperPhaseOffset:
logging.debug(f' replaced ch1TriggerPhase = {self.ch1TriggerPhase} with {self.config.chopperPhaseOffset}')
self.ch1TriggerPhase = self.config.chopperPhaseOffset
# extract start time as unix time, adding UTC offset of 1h to time string
dz = datetime.fromisoformat(self.hdf['/entry1/start_time'][0].decode('utf-8'))
self.fileDate=dz.replace(tzinfo=AMOR_LOCAL_TIMEZONE)
self.startTime = np.int64( (self.fileDate.timestamp() ) * 1e9 )
if self.seriesStartTime is None:
self.seriesStartTime = self.startTime
#self.startTime = np.int64( (self.fileDate.timestamp() ) * 1e9 )
#if self.seriesStartTime is None:
# self.seriesStartTime = self.startTime
def read_header_info(self):
# read general information and first data set

View File

@@ -29,10 +29,10 @@ class Defaults:
thetaRange = [-12., 12.]
thetaRangeR = [-0.75, 0.75]
yRange = [11, 41]
qzRange = [0.005, 0.30]
qzRange = [0.005, 0.51]
chopperSpeed = 500
chopperPhase = -13.5
chopperPhaseOffset = 7
chopperPhase = 0.0
chopperPhaseOffset = -9.1
muOffset = 0
mu = 0
nu = 0
@@ -52,6 +52,7 @@ class ReaderConfig:
class ExperimentConfig:
incidentAngle: str
chopperPhase: float
chopperSpeed: float
yRange: Tuple[float, float]
lambdaRange: Tuple[float, float]
qzRange: Tuple[float, float]

View File

@@ -22,7 +22,7 @@ class AmorReduction:
self.header = Header()
self.header.reduction.call = config.call_string()
self.monitorUnit = {'n': 'cnts', 'p': 'mC', 't': 's'}
self.monitorUnit = {'n': 'cnts', 'p': 'mC', 't': 's', 'auto': 'pulses'}
def reduce(self):
if not os.path.exists(f'{self.output_config.outputPath}'):