From 86fddb4d53e8269463a5fab7e085a3afe677506d Mon Sep 17 00:00:00 2001 From: jochenstahn Date: Thu, 14 Mar 2024 10:12:04 +0100 Subject: [PATCH] new management of defaults, migration of 'call_string' --- libeos/call_string.py | 79 ------------------------ libeos/command_line.py | 51 ++++++++-------- libeos/file_reader.py | 8 +-- libeos/header.py | 92 +--------------------------- libeos/options.py | 136 ++++++++++++++++++++++++++++++++++++++++- libeos/reduction.py | 22 ++++--- 6 files changed, 178 insertions(+), 210 deletions(-) delete mode 100644 libeos/call_string.py diff --git a/libeos/call_string.py b/libeos/call_string.py deleted file mode 100644 index 9433128..0000000 --- a/libeos/call_string.py +++ /dev/null @@ -1,79 +0,0 @@ -# module to assemble an orso 'call' string form command line arguments and some default values. - -def call_string(): - base = 'python eos.py ' - - inpt = '' - if clas.year: - inpt += f' --year {clas.year}' - else: - inpt += f' --year {datetime.now().year}' - if clas.dataPath: - inpt += f' --dataPath {clas.dataPath}' - if clas.subtract: - inpt += f' -subtract {clas.subtract}' - if clas.normalisationFileIdentifier: - inpt += f' -r {clas.normalisationFileIdentifier}' - # get file list somehow - if ...: - inpt += f' -n {flie_list}' - else: - inpt += f' -n {clas.fileIdentifier}' - - otpt = '' - if outputFormats != 'Rqz.ort': - otpt = f" -of '{outputFormats}'" - if clas.outputName: - otpt += f' -o {clas.outputName}' - else: - pass - # default name - - mask = '' - if clas.yRange: - mask += f' -y {clas.yRange}' - if clas.lambdaRange: - mask += f' -l {clas.lambdaRange}' - if clas.thetaRange: - mask += f' -- thetaRange {clas.thetaRange}' - elif clas.thetaRangeR: - mask += f' -t {clas.thetaRangeR}' - if clas.qzRange: - mask += f' -q {clas.qzRange}' - if clas.qResolution: - mask += f' -a {clas.qResolution}' - - para = '' - if clas.chopperPhase: - para += f' --chopperPhase {clas.chopperPhase}' - if clas.chopperPhaseOffset: - para += f' --chopperPhaseOffset {clas.chopperPhaseOffset}' - if clas.mu: - para += f' --mu {clas.mu}' - elif clas.muOffset: - para += f' --muOffset {clas.muOffset}' - if clas.nu: - para += f' --nu {clas.nu}' - - if clas.sampleModel: - modl = f" --sampleModel '{clas.sampleModel}'" - - acts = '' - if clas.autoscale: - acts += f' --autoscale {clas.autoscale}' - if clas.scale: - acts += f' --scale {clas.scale}' - if clas.timeSlize: - acts += f' --timeSlize {clas.timeSlize}' - - mlst = base + '\n' + inpt + '\n' + outp - if mask: - mlst += '\n' + mask - if para: - mlst += '\n' + para - if acts: - mlst += '\n' + acts - if mask: - modl += '\n' + modl - - return mlst diff --git a/libeos/command_line.py b/libeos/command_line.py index 7e5c8f9..66375ac 100644 --- a/libeos/command_line.py +++ b/libeos/command_line.py @@ -2,7 +2,7 @@ import argparse from datetime import date from .logconfig import update_loglevel -from .options import ReaderConfig, EOSConfig, ExperimentConfig, OutputConfig, ReductionConfig +from .options import ReaderConfig, EOSConfig, ExperimentConfig, OutputConfig, ReductionConfig, Defaults def commandLineArgs(): @@ -16,20 +16,20 @@ def commandLineArgs(): clas = argparse.ArgumentParser(description = msg) input_data = clas.add_argument_group('input data') - input_data.add_argument("-n", "--fileIdentifier", - default = ['0'], + input_data.add_argument("-f", "--fileIdentifier", + required = True, nargs = '+', - help = "file number(s) or offset (if negative)") - input_data.add_argument("-r", "--normalisationFileIdentifier", - default = [], + help = "file number(s) or offset (if < 1)") + input_data.add_argument("-n", "--normalisationFileIdentifier", + default = Defaults.normalisationFileIdentifier, nargs = '+', help = "file number(s) of normalisation measurement") input_data.add_argument("-d", "--dataPath", type = str, - default = '.', + default = Defaults.dataPath, help = "relative path to directory with .hdf files") input_data.add_argument("-Y", "--year", - default = date.today().year, + default = Defaults.year, type = int, help = "year the measurement was performed") input_data.add_argument("-sub", "--subtract", @@ -37,17 +37,18 @@ def commandLineArgs(): output = clas.add_argument_group('output') output.add_argument("-o", "--outputName", - default = "fromEOS", + default = Defaults.outputName, help = "output file name (withot suffix)") output.add_argument("-of", "--outputFormat", nargs = '+', - default = ['Rqz.ort']) + default = Defaults.outputFormat, + help = "one of [Rqz.ort, Rlt.ort]") output.add_argument("--offSpecular", type = bool, - default = False, + default = Defaults.offSpecular, ) - output.add_argument("-a", "--qResolution", - default = 0.01, + output.add_argument("-r", "--qResolution", + default = Defaults.qResolution, type = float, help = "q_z resolution") output.add_argument("-ts", "--timeSlize", @@ -56,7 +57,7 @@ def commandLineArgs(): help = "time slizing ,[ [,stop]]") output.add_argument("-s", "--scale", nargs = '+', - default = [1], + default = Defaults.scale, type = float, help = "scaling factor for R(q_z)") output.add_argument("-S", "--autoscale", @@ -66,56 +67,58 @@ def commandLineArgs(): masks = clas.add_argument_group('masks') masks.add_argument("-l", "--lambdaRange", - default = [2., 15.], + default = Defaults.lambdaRange, nargs = 2, type = float, help = "wavelength range") masks.add_argument("-t", "--thetaRange", - default = [-12., 12.], + default = Defaults.thetaRange, nargs = 2, type = float, help = "absolute theta range") masks.add_argument("-T", "--thetaRangeR", - default = [-12., 12.], + default = Defaults.thetaRangeR, nargs = 2, type = float, help = "relative theta range") masks.add_argument("-y", "--yRange", - default = [11, 41], + default = Defaults.yRange, nargs = 2, type = int, help = "detector y range") masks.add_argument("-q", "--qzRange", - default = [0.005, 0.30], + default = Defaults.qzRange, nargs = 2, type = float, help = "q_z range") overwrite = clas.add_argument_group('overwrite') overwrite.add_argument("-cs", "--chopperSpeed", + default = Defaults.chopperSpeed, type = float, help = "chopper speed in rpm") overwrite.add_argument("-cp", "--chopperPhase", - default = -13.5, + default = Defaults.chopperPhase, type = float, help = "chopper phase") overwrite.add_argument("-co", "--chopperPhaseOffset", - default = -5, + default = Defaults.chopperPhaseOffset, type = float, help = "phase offset between chopper opening and trigger pulse") overwrite.add_argument("-m", "--muOffset", - default = 0., + default = Defaults.muOffset, type = float, help = "mu offset") overwrite.add_argument("-mu", "--mu", - default = 0, + default = Defaults.mu, type = float, help ="value of mu") overwrite.add_argument("-nu", "--nu", - default = 0, + default = Defaults.nu, type = float, help = "value of nu") overwrite.add_argument("-sm", "--sampleModel", + default = Defaults.sampleModel, type = str, help = "1-line orso sample model description") diff --git a/libeos/file_reader.py b/libeos/file_reader.py index 7a4fd0b..579de06 100644 --- a/libeos/file_reader.py +++ b/libeos/file_reader.py @@ -132,7 +132,7 @@ class AmorData: if self.readHeaderInfo: self.read_header_info() - logging.info(f'# data from file: {fileName}') + logging.warning(f' data from file: {fileName}') self.read_individual_header() # add header content @@ -151,7 +151,7 @@ class AmorData: self.header.measurement_additional_files.append(fileio.File(file=fileName.split('/')[-1], timestamp=self.fileDate)) else: self.header.measurement_data_files.append(fileio.File(file=fileName.split('/')[-1], timestamp=self.fileDate)) - logging.info(f'# mu = {self.mu:6.3f}, nu = {self.nu:6.3f}, kap = {self.kap:6.3f}, kad = {self.kap:6.3f}') + logging.info(f' mu = {self.mu:6.3f}, nu = {self.nu:6.3f}, kap = {self.kap:6.3f}, kad = {self.kap:6.3f}') # TODO: should extract monitor from counts or beam current times time self.monitor1 = self.ctime @@ -177,7 +177,7 @@ 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 = {totalNumber:7d}, filtered = {np.shape(self.lamda_e)[0]:7d}') def filter_qz_range(self, norm): if self.config.qzRange[1]<0.3 and not norm: @@ -311,7 +311,7 @@ class AmorData: def read_header_info(self): # read general information and first data set - logging.info(f'# meta data from: {self.file_list[0]}') + logging.info(f' meta data from: {self.file_list[0]}') self.hdf = h5py.File(self.file_list[0], 'r', swmr=True) title = self.hdf['entry1/title'][0].decode('utf-8') proposal_id = self.hdf['entry1/proposal_id'][0].decode('utf-8') diff --git a/libeos/header.py b/libeos/header.py index 44eb7ea..7a400cc 100644 --- a/libeos/header.py +++ b/libeos/header.py @@ -14,7 +14,7 @@ from . import __version__ class Header: """orso compatible output file header content""" - def __init__(self, config): + def __init__(self): self.owner = None self.experiment = None self.sample = None @@ -25,7 +25,7 @@ class Header: self.reduction = fileio.Reduction( software = fileio.Software('eos', version=__version__), - call = self.call_string(config), + call = 'placeholder', computer = platform.node(), timestamp = datetime.now(), creator = None, @@ -71,91 +71,3 @@ class Header: callString += f' -Y {datetime.now().year}' return callString #------------------------------------------------------------------------------------------------- - def call_string(self, config): - self.experiment_config = config.experiment - self.reader_config = config.reader - self.reduction_config = config.reductoin - self.output_config = config.output - - base = 'python eos.py' - - inpt = '' - if self.reader_config.year: - inpt += f' --year {self.reader_config.year}' - else: - inpt += f' --year {datetime.now().year}' - if self.reader_config.dataPath != '.': - inpt += f' --dataPath {self.reader_config.dataPath}' - if self.reduction_config.subtract: - inpt += f' -subtract {self.reduction_config.subtract}' - if self.reduction_config.normalisationFileIdentifier: - inpt += f' -r {" ".join(self.reduction_config.normalisationFileIdentifier)}' - # get file list somehow - if False: - pass - #inpt += f' -n {file_list}' - else: - inpt += f' -n {" ".join(self.reduction_config.fileIdentifier)}' - - otpt = '' - if self.reduction_config.qResolution: - otpt += f' -q {self.reduction_config.qResolution}' - if self.output_config.outputFormats != 'Rqz.ort': - otpt = f' -of {" ".join(self.output_config.outputFormats)}' - if self.output_config.outputName: - otpt += f' -o {self.output_config.outputName}' - else: - pass - # default name - - mask = '' - if self.experiment_config.yRange != [11, 41]: - mask += f' -y {" ".join(str(ii) for ii in self.experiment_config.yRange)}' - if self.experiment_config.lambdaRange!= [2, 15]: - mask += f' -l {" ".join(str(ff) for ff in self.experiment_config.lambdaRange)}' - if self.reduction_config.thetaRange != [-12, 12]: - mask += f' --thetaRange {" ".join(str(ff) for ff in self.reduction_config.thetaRange)}' - elif self.reduction_config.thetaRangeR != [-12, 12]: - mask += f' -t {" ".join(str(ff) for ff in self.reduction_config.thetaRangeR)}' - if self.experiment_config.qzRange!= [0.005, 0.3]: - mask += f' -q {" ".join(str(ff) for ff in self.experiment_config.qzRange)}' - - para = '' - if self.experiment_config.chopperPhase != -13.5: - para += f' --chopperPhase {self.experiment_config.chopperPhase}' - if self.experiment_config.chopperPhaseOffset != -5: - para += f' --chopperPhaseOffset {self.experiment_config.chopperPhaseOffset}' - if self.experiment_config.mu: - para += f' --mu {self.experiment_config.mu}' - elif self.experiment_config.muOffset: - para += f' --muOffset {self.experiment_config.muOffset}' - if self.experiment_config.nu: - para += f' --nu {self.experiment_config.nu}' - - modl = '' - if self.experiment_config.sampleModel: - modl += f" --sampleModel '{self.experiment_config.sampleModel}'" - - acts = '' - if self.reduction_config.autoscale: - acts += f' --autoscale {" ".join(str(ff) for ff in self.reduction_config.autoscale)}' - if self.reduction_config.scale != [1]: - acts += f' --scale {self.reduction_config.scale}' - if self.reduction_config.timeSlize: - acts += f' --timeSlize {" ".join(str(ff) for ff in self.reduction_config.timeSlize)}' - - #experiment_config = ExperimentConfig( - # offSpecular = clas.offSpecular, - # ) - - mlst = base + ' ' + inpt + ' ' + otpt - if mask: - mlst += ' ' + mask - if para: - mlst += ' ' + para - if acts: - mlst += ' ' + acts - if modl: - mlst += ' ' + modl - - return mlst diff --git a/libeos/options.py b/libeos/options.py index 22c9208..13dedee 100644 --- a/libeos/options.py +++ b/libeos/options.py @@ -3,6 +3,37 @@ Classes for stroing various configurations needed for reduction. """ from dataclasses import dataclass, field from typing import Optional, Tuple +from datetime import datetime + + +class Defaults: + #fileIdentifier + normalisationFileIdentifier = [] + dataPath = '.' + year = datetime.now().year + #subtract + outputName = "fromEOS" + outputFormat = ['Rqz.ort'] + offSpecular = False + qResolution = 0.01 + #timeSlize + scale = [1] + #autoscale + lambdaRange = [2., 15.] + thetaRange = [-12., 12.] + thetaRangeR = [-0.7, 0.7] + yRange = [11, 41] + qzRange = [0.005, 0.30] + chopperSpeed = 500 + chopperPhase = -13.5 + chopperPhaseOffset = -5 + muOffset = 0 + mu = 0 + nu = 0 + sampleModel = None + # + + @dataclass class ReaderConfig: @@ -18,7 +49,7 @@ class ExperimentConfig: qzRange: Tuple[float, float] sampleModel: Optional[str] = None - chopperPhaseOffset: float = 0.0 + chopperPhaseOffset: float = 0 mu: Optional[float] = None nu: Optional[float] = None muOffset: Optional[float] = None @@ -47,5 +78,104 @@ class OutputConfig: class EOSConfig: reader: ReaderConfig experiment: ExperimentConfig - reductoin: ReductionConfig - output: OutputConfig \ No newline at end of file + reduction: ReductionConfig + output: OutputConfig + + _call_string_overwrite=None + + #@property + #def call_string(self)->str: + # if self._call_string_overwrite: + # return self._call_string_overwrite + # else: + # return self.calculate_call_string() + + def call_string(self): + base = 'python eos.py' + + inpt = '' + if self.reader_config.year: + inpt += f' -Y {self.reader_config.year}' + else: + inpt += f' -Y {datetime.now().year}' + if self.reader_config.dataPath != '.': + inpt += f' --dataPath {self.reader_config.dataPath}' + if self.reduction_config.subtract: + inpt += f' -subtract {self.reduction_config.subtract}' + if self.reduction_config.normalisationFileIdentifier: + inpt += f' -n {" ".join(self.reduction_config.normalisationFileIdentifier)}' + if self.reduction_config.fileIdentifier: + inpt += f' -f {" ".join(self.reduction_config.fileIdentifier)}' + + otpt = '' + if self.reduction_config.qResolution: + otpt += f' -r {self.reduction_config.qResolution}' + if self.output_config.outputName: + otpt += f' -o {self.output_config.outputName}' + if self.output_config.outputFormats != ['Rqz.ort']: + otpt += f' -of {" ".join(self.output_config.outputFormats)}' + + mask = '' + if self.experiment_config.yRange != Defaults.yRange: + mask += f' -y {" ".join(str(ii) for ii in self.experiment_config.yRange)}' + if self.experiment_config.lambdaRange!= Defaults.lambdaRange: + mask += f' -l {" ".join(str(ff) for ff in self.experiment_config.lambdaRange)}' + if self.reduction_config.thetaRange != Defaults.thetaRange: + mask += f' -T {" ".join(str(ff) for ff in self.reduction_config.thetaRange)}' + elif self.reduction_config.thetaRangeR != Defaults.thetaRangeR: + mask += f' -t {" ".join(str(ff) for ff in self.reduction_config.thetaRangeR)}' + if self.experiment_config.qzRange!= Defaults.qzRange: + mask += f' -q {" ".join(str(ff) for ff in self.experiment_config.qzRange)}' + + para = '' + if self.experiment_config.chopperPhase != Defaults.chopperPhase: + para += f' --chopperPhase {self.experiment_config.chopperPhase}' + if self.experiment_config.chopperPhaseOffset != Defaults.chopperPhaseOffset: + para += f' --chopperPhaseOffset {self.experiment_config.chopperPhaseOffset}' + if self.experiment_config.mu: + para += f' --mu {self.experiment_config.mu}' + elif self.experiment_config.muOffset: + para += f' --muOffset {self.experiment_config.muOffset}' + if self.experiment_config.nu: + para += f' --nu {self.experiment_config.nu}' + + modl = '' + if self.experiment_config.sampleModel: + modl += f" --sampleModel '{self.experiment_config.sampleModel}'" + + acts = '' + if self.reduction_config.autoscale: + acts += f' --autoscale {" ".join(str(ff) for ff in self.reduction_config.autoscale)}' + if self.reduction_config.scale != Defaults.scale: + acts += f' --scale {self.reduction_config.scale}' + if self.reduction_config.timeSlize: + acts += f' --timeSlize {" ".join(str(ff) for ff in self.reduction_config.timeSlize)}' + + # TODO: experiment_config = ExperimentConfig( + # offSpecular = clas.offSpecular, + # ) + + mlst = base + inpt + otpt + if mask: + mlst += mask + if para: + mlst += para + if acts: + mlst += acts + if modl: + mlst += modl + + if len(mlst) > 70: + mlst = base + ' ' + inpt + ' ' + otpt + if mask: + mlst += ' ' + mask + if para: + mlst += ' ' + para + if acts: + mlst += ' ' + acts + if modl: + mlst += ' ' + modl + + return mlst + + \ No newline at end of file diff --git a/libeos/reduction.py b/libeos/reduction.py index 06b84fa..133f9e5 100644 --- a/libeos/reduction.py +++ b/libeos/reduction.py @@ -15,10 +15,12 @@ class AmorReduction: def __init__(self, config: EOSConfig): self.experiment_config = config.experiment self.reader_config = config.reader - self.reduction_config = config.reductoin + self.reduction_config = config.reduction self.output_config = config.output - self.grid = Grid(config.reductoin.qResolution) - self.header = Header(config) + self.grid = Grid(config.reduction.qResolution) + self.header = Header() + + self.header.reduction.call = EOSConfig.call_string(self) def reduce(self): if not os.path.exists(f'{self.reader_config.dataPath}'): @@ -211,13 +213,13 @@ class AmorReduction: def save_Rqz(self): fname = os.path.join(self.reader_config.dataPath, f'{self.output_config.outputName}.Rqz.ort') - logging.warning(f' {fname}') + logging.warning(f' {fname}') theSecondLine = f' {self.header.experiment.title} | {self.header.experiment.start_date} | sample {self.header.sample.name} | R(q_z)' fileio.save_orso(self.datasetsRqz, fname, data_separator='\n', comment=theSecondLine) def save_Rtl(self): fname = os.path.join(self.reader_config.dataPath, f'{self.output_config.outputName}.Rlt.ort') - logging.warning(f' {fname}') + logging.warning(f' {fname}') theSecondLine = f' {self.header.experiment.title} | {self.header.experiment.start_date} | sample {self.header.sample.name} | R(lambda, theta)' fileio.save_orso(self.datasetsRlt, fname, data_separator='\n', comment=theSecondLine) @@ -229,7 +231,7 @@ class AmorReduction: if len(filter_q[filter_q]) > 0: scale = np.sum(R_q[filter_q]**2/dR_q[filter_q]) / np.sum(R_q[filter_q]/dR_q[filter_q]) else: - logging.warning('# automatic scaling not possible') + logging.warning(' automatic scaling not possible') scale = 1. else: filter_q = np.where(np.isnan(pR_q*R_q), False, True) @@ -239,11 +241,11 @@ class AmorReduction: scale = np.sum(R_q[filter_q]**3 * pR_q[filter_q] / (dR_q[filter_q]**2 * pdR_q[filter_q]**2)) \ / np.sum(R_q[filter_q]**2 * pR_q[filter_q]**2 / (dR_q[filter_q]**2 * pdR_q[filter_q]**2)) else: - logging.warning('# automatic scaling not possible') + logging.warning(' automatic scaling not possible') scale = 1. R_q /= scale dR_q /= scale - logging.debug(f'# scaling factor = {scale}') + logging.debug(f' scaling factor = {scale}') return R_q, dR_q @@ -296,7 +298,7 @@ class AmorReduction: name = f'{name}_{normalisation_list[i]}' n_path = os.path.join(dataPath, f'{name}.norm') if os.path.exists(n_path): - logging.info(f'# normalisation matrix: found and using {n_path}') + logging.warning(f'normalisation matrix: found and using {n_path}') #self.norm_lz = np.loadtxt(f'{dataPath}/{name}.norm') #with open(n_path, 'r') as fh: # fh.readline() @@ -310,7 +312,7 @@ class AmorReduction: self.normFileList[i] = entry.split('/')[-1] self.header.measurement_additional_files = self.normFileList else: - logging.info(f'# normalisation matrix: using the files {normalisation_list}') + logging.warning(f'normalisation matrix: using the files {normalisation_list}') fromHDF = AmorData(header=self.header, reader_config=self.reader_config, config=self.experiment_config,