diff --git a/man.md b/man.md new file mode 100644 index 0000000..ffbdb5f --- /dev/null +++ b/man.md @@ -0,0 +1,308 @@ + +# documentation for **neos.py** + +**neos** is a python program used at the neutron reflectometer *Amor* at *SINQ* +to turn *raw data*, i.e. from the *nexus hdf5* format, +into reduced an *orso* comptible *reflectivity file*. + +raw: *nexus hdf5* format: + +- event arrays for detector and monitor events +- arrays for device propertise +- entries for instrument configuration + +reduced: *orso reflectivity* format: + +- header with information about + + - data origin + - measurement conditions + - reduction steps + +- array with basic or expanded reflectivity data (in the simplest version: the *reflectivity curve*) + +## environment + +**neos** (version 2.0 and later) was developen with python3.9. + +The following (non-trivial) python modules are required: + +- `numpy` +- `h5py` +- `orsopy` + +## usage + +**neos** is using command line arguments to + +- find the raw data +- overwrite default values +- define the parameter range for reduction +- define reduction steps +- define the output path and name + +More detailed explanations for some arguments are given in the next section. + +### output for `python eos.py -h`: + +``` man +usage: neos.py [-h] [-d DATAPATH] [-Y YEAR] + [-n FILEIDENTIFIER [FILEIDENTIFIER ...]] + [-r NORMALISATIONFILEIDENTIFIER [NORMALISATIONFILEIDENTIFIER ...]] + [-sub SUBTRACT] [-o OUTPUTNAME] + [-of OUTPUTFORMAT [OUTPUTFORMAT ...]] + [--offSpecular OFFSPECULAR] [-a QRESOLUTION] + [-ts TIMESLIZE [TIMESLIZE ...]] [-s SCALE [SCALE ...]] + [-S AUTOSCALE AUTOSCALE] [-l LAMBDARANGE LAMBDARANGE] + [-t THETARANGE THETARANGE] [-T THETARANGER THETARANGER] + [-y YRANGE YRANGE] [-q QZRANGE QZRANGE] [-cs CHOPPERSPEED] + [-cp CHOPPERPHASE] [-co CHOPPERPHASEOFFSET] [-m MUOFFSET] + [-mu MU] [-nu NU] [-sm SAMPLEMODEL] + +eos reads data from (one or several) raw file(s) of the .hdf format, performs +various corrections, conversations and projections and exports the resulting +reflectivity in an orso-compatible format. + +optional arguments: + -h, --help show this help message and exit + +input data: + -d DATAPATH, --dataPath DATAPATH + relative path to directory with .hdf files + -Y YEAR, --year YEAR year the measurement was performed + -n FILEIDENTIFIER [FILEIDENTIFIER ...], --fileIdentifier FILEIDENTIFIER [FILEIDENTIFIER ...] + file number(s) or offset (if negative) + -r NORMALISATIONFILEIDENTIFIER [NORMALISATIONFILEIDENTIFIER ...], --normalisationFileIdentifier NORMALISATIONFILEIDENTIFIER [NORMALISATIONFILEIDENTIFIER ...] + file number(s) of normalisation measurement + -sub SUBTRACT, --subtract SUBTRACT + R(q_z) curve to be subtracted (in .Rqz.ort format + +output: + -o OUTPUTNAME, --outputName OUTPUTNAME + output file name (withot suffix) + -of OUTPUTFORMAT [OUTPUTFORMAT ...], --outputFormat OUTPUTFORMAT [OUTPUTFORMAT ...] + --offSpecular OFFSPECULAR + -a QRESOLUTION, --qResolution QRESOLUTION + q_z resolution + -ts TIMESLIZE [TIMESLIZE ...], --timeSlize TIMESLIZE [TIMESLIZE ...] + time slizing ,[ [,stop]] + -s SCALE [SCALE ...], --scale SCALE [SCALE ...] + scaling factor for R(q_z) + -S AUTOSCALE AUTOSCALE, --autoscale AUTOSCALE AUTOSCALE + scale to 1 in the given q_z range + +masks: + -l LAMBDARANGE LAMBDARANGE, --lambdaRange LAMBDARANGE LAMBDARANGE + wavelength range + -t THETARANGE THETARANGE, --thetaRange THETARANGE THETARANGE + absolute theta range + -T THETARANGER THETARANGER, --thetaRangeR THETARANGER THETARANGER + relative theta range + -y YRANGE YRANGE, --yRange YRANGE YRANGE + detector y range + -q QZRANGE QZRANGE, --qzRange QZRANGE QZRANGE + q_z range + +overwrite: + -cs CHOPPERSPEED, --chopperSpeed CHOPPERSPEED + chopper speed in rpm + -cp CHOPPERPHASE, --chopperPhase CHOPPERPHASE + chopper phase + -co CHOPPERPHASEOFFSET, --chopperPhaseOffset CHOPPERPHASEOFFSET + phase offset between chopper opening and trigger pulse + -m MUOFFSET, --muOffset MUOFFSET + mu offset + -mu MU, --mu MU value of mu + -nu NU, --nu NU value of nu + -sm SAMPLEMODEL, --sampleModel SAMPLEMODEL + 1-line orso sample model description +``` + +## read data file(s) + +### absolute minimum + +purposes: + +- fast access to human-readable meta data in the output header +- get an idea about $q_z$ range and statistics + +actions: + +- read in one raw data file +- convert the event stream into an $I(\lambda, \alpha_f)$ map +- project this map onto $q_z$ io give an $I(q_z)$ curve +- write this curve in *orso* format to disk + +example: + +`> python neos.py -n 456 -o foo` +looks for the file `amorn000456.hdf` in one of the default locations +(`./`, `./raw/`, `../raw`, local raw data directory on Amor) and +writes the output to `foo.Rqz.ort`. + +### normaliation + +purposes: + +- fast access to human-readable meta data in the output header +- get a reduced and (partially) corrected reflectivity curve + +actions: + +- read in raw data file(s) and raw normalisation file(s) +- convert the normalisation measurement into a $N(\lambda, z_{detector})$ + map containing information about guide and detector efficiencies, + illuminated detector area and incoming intensity. +- convert the event stream into an $I(\lambda, \alpha_f)$ map +- normalisation: $R(\lambda, \alpha_f)_{la} = I(\lambda, \alpha_f)_{la} / N(\lambda, z_{detector})_{la}$. +- project this map onto $q_z$ io give a $R(q_z)$ curve (not necessarily scaled) +- write this curve in *orso* format to disk + +example: + +`> python neos.py -n 456 -r 123 -o foo` +looks for the files `amorn000456.hdf` (reflectivity) and `amorn000123.hdf` +(normalisation) in one of the default locations +(`./`, `./raw/`, `../raw`, local raw data directory on Amor) and +writes the output to `foo.Rqz.ort`. + +### read multiple files + +#### for the same instrument parameter set (same $\mu$) + +The arguments of the keys `-n` and `-r` have the general form +`[-[:[-[:` in the output file. + +example: +`> python neos.py -n 20,21 30 -r 123 -o foo` +results in two reflectivity curves, the first made from files #20 and #21, +the second from file #30. Both are saved in `foo.Rqz.ort`. + +warning: +`-r` does accept only one argument! + +### misc. + +The raw file name is created using the file number and the actual year. In case +the data to be processed were recorded in a previous year, this must be +explicitely stated with `-Y `. + +The default location for the output (and for starting the search for the input files) +iis the present working directory. This can be altered by using the argument +`-d `. + +It is possible to provide a $R(q_z)$ curve in `.Rqz.ort` format to be subtracted +from the reduced data. E.g. to emphasize the high-$q$ region on a linear scale, or +to illustrate changes in a series of measurements. The argument is +`-sub `. + +## output options + +### other formats + +Besides the standard *orso* format `.Rqz.ort`, there is the option to +write the $R(\lambda, \alpha_f)$ array and the related input, normalisation and +mask arrays. This output can help with the sample alignment or the readjustment +of parameters (see below), or it can be used for debugging the data processing or +instrument operation. The suffix of this output is `.Rlt.ort` + +The format is chosen by using or several of the argumnets + +- `Rqz.ort`, `Rlt.ort`, `Rqz.orb`, `Rlt.orb` +- `Rqz` (= `Rqz.ort` and `Rqz.orb`) +- `Rlt` (= `Rlt.ort` and `Rlt.orb`), +- `ort` (= `Rqz.ort` and `Rlt.ort`), +- `orb` (= `Rqz.orb` and `Rlt.orb`) +where `.orb` will be the future nexus comptibe output format. + +### $q_z$ binning + +The $R(\lambda, \alpha_f)$ arrays are projected onto a $q_z$ grid withbin boundaries +defined by: + +$$ + q_z \in \left{ \begin{array}{ll} + \[ 0, i \cdot 0.1 \cdot c\] & \forall q_z < q_\mathrm{base} \\ + \[ q_\mathrm{base} \cdot (1+c)^j \] & \forall q_z \gt q_\mathrm{base} + \right. +$$ + +$q_\mathrm{base} = 0.1\,\mathrm{\AA}^{-1}$ is fixed for the moment. +The *resolution* can be chosen with `-a` among the values +[0.005, 0.01, 0.02, 0.025, 0.04, 0.05, 0.1, 1] +(this is restricted to ensure a *smooth* transition between the +linear and exponential regions). + +### intensity scaling + +The argument `-s ` leads to a multiplication of all $R(q_z)$ curves +with ``. This is useful only for one curve, only, or in combination with the +`-S` argument. + +$R(q_z)$ of the first reflectivity curve can be scaled to 1 in the $q_z$ interval define +by `-S `. The following $R(q_z)$ curves are then scaled to match the +respective previous one. + +### time-slizing + +One (combined) data set can be chopped in slizes with the argument +`-ts [ [stop>]]` +where `` is the time interval length in seconds. The chopping starts +`` seconds after the start of the measurement (default: 0) and ends at +`` seconds (default: end of the measurement). + +All the resulting $R(q_z)$ curves are stored in one file, one after the other. An additional +column is added with the start time of the respective slize. This enables fast plotting. + +example: +`python -n 20-22 -r 123 -ts 60 1200 4000 -f foo` +The event streams of the measurements #20, #21 and #22 are merged. All events before +$t = 1200\,\mathrm{s}$ with respect to the start of meausrement #20 are discarded. +Then until $t = 4020\,\mathrm{s}$ (or the end of measurement #22) a $R(q_z)$ curve is generated +for each $60\,\mathrm{s}$ interval. + +## masksing + + -l LAMBDARANGE LAMBDARANGE, --lambdaRange LAMBDARANGE LAMBDARANGE + wavelength range + -t THETARANGE THETARANGE, --thetaRange THETARANGE THETARANGE + absolute theta range + -T THETARANGER THETARANGER, --thetaRangeR THETARANGER THETARANGER + relative theta range + -y YRANGE YRANGE, --yRange YRANGE YRANGE + detector y range + -q QZRANGE QZRANGE, --qzRange QZRANGE QZRANGE + q_z range + +overwrite: + -cs CHOPPERSPEED, --chopperSpeed CHOPPERSPEED + chopper speed in rpm + -cp CHOPPERPHASE, --chopperPhase CHOPPERPHASE + chopper phase + -co CHOPPERPHASEOFFSET, --chopperPhaseOffset CHOPPERPHASEOFFSET + phase offset between chopper opening and trigger pulse + -m MUOFFSET, --muOffset MUOFFSET + mu offset + -mu MU, --mu MU value of mu + -nu NU, --nu NU value of nu + -sm SAMPLEMODEL, --sampleModel SAMPLEMODEL + 1-line orso sample model description + diff --git a/neos.py b/neos.py index 0bb11af..3a2d93c 100644 --- a/neos.py +++ b/neos.py @@ -18,7 +18,7 @@ conventions (not strictly followed, yet): """ __version__ = '2.0' -__date__ = '2024-01-29' +__date__ = '2024-02-23' import os import sys @@ -525,17 +525,24 @@ def normalisation_map(short_notation): norm_lz, bins_l, bins_z = np.histogram2d(lamda_e, detZ_e, bins = (grid.lamda(), grid.z())) norm_lz = np.where(norm_lz>0, norm_lz, np.nan) # TODO: correct for the SM reflectivity - # q_lz - # -> Rsm_lz + lamda_l = grid.lamda() + theta_z = normAngle + fromHDF.delta_z + lamda_lz = (grid.lz().T*lamda_l[:-1]).T + theta_lz = grid.lz()*theta_z + qz_lz = 4.0*np.pi * np.sin(np.deg2rad(theta_lz)) / lamda_lz + Rsm_lz = np.ones(np.shape(qz_lz)) + Rsm_lz = np.where(qz_lz>0.0217, 1-(qz_lz-0.0217)*(0.0625/0.0217), Rsm_lz) + Rsm_lz = np.where(qz_lz>0.0217*5, np.nan, Rsm_lz) + norm_lz = norm_lz / Rsm_lz if len(lamda_e) > 1e6: - head = f'normalisation matrix based on the measurements \n\ - {fromHDF.file_list} \n\ - nu - mu = {normAngle}\n\ - shape= {np.shape(norm_lz)} (lambda, z) \n\ - measured at mu = {fromHDF.mu:6.3f} deg \n\ - N(l_lambda, z) = theta(z) / sum_i=-1..1 I(l_lambda+i, z)' - head = head.replace(' ', '') + head = ('normalisation matrix based on the measurements\n' + f'{fromHDF.file_list}\n' + f'nu - mu = {normAngle}\n' + f'shape= {np.shape(norm_lz)} (lambda, z)\n' + f'measured at mu = {fromHDF.mu:6.3f} deg\n' + f'N(l_lambda, z) = theta(z) / sum_i=-1..1 I(l_lambda+i, z)') head = head.replace('../', '') + head = head.replace('./', '') head = head.replace('raw/', '') np.savetxt(f'{clas.dataPath}/{name}.norm', norm_lz, header = head) normFileList = fromHDF.file_list @@ -758,7 +765,7 @@ def main(): if clas.timeSlize: wallTime_e = fromHDF.wallTime_e - headerRqz = fileio.Orso(header.data_source(), header.reduction, header.columns()) + headerRqz = fileio.Orso(header.data_source(), header.reduction, header.columns()) columns = np.append(header.columns(), fileio.Column('time', 's', 'time relative to start of measurement series')) interval = clas.timeSlize[0]