It is possible to perform algebraic and mathematical operations on populated IXTrunfile objects
as the IXTrunfile object is more complicated than other simple datasets there are certain rules as to how a simple algebraic operation might be performed
Consider a run file as a pair of IXTdata objects, one for the detector information and one for the monitor information, together with various objects that are for everything else. The ‘everything else’ includes the instrument description, user, source, but in particular the IXTspectra and IXTdetector classes as part of IXTinstrument. The IXTdata object contains bridging arrays to the IXTspectra object. For the purposes of the algebra, lets write an IXTrunfile as: R= α(d,m)
where α the ‘everything else’ d dataset2D or array of dataset2D, or (if no detector map given) unassigned.
Binary operators with a d1d, d2d, scalar, vector, array
We permit the addition if the two conditions are true: (i) the operation is valid on both the detector and monitor dataset2D (using whatever rules apply to dataset2d as at the moment) (ii) the resultant detector and monitor dataset2d have the same sizes as the initial ones (this ensures that the ‘everything else is valid)
In summary, (if a dash refers to the detector or monitor IXTdata being unassigned):
α(d,m) + a = α(d+a,m+a)
α(d,-) + a = α(d+a,-)
α(-,m) + a = α(-,m+a)
Binary operators for two run files
The different cases for consideration when combining two runfiles are legion – what if they have different numbers of detector and or monitor mapping, what if they have the same number of workspaces but different grouping of spectra, what if they have no monitor workspaces, what if from different instrument? The best criteria for algebra are
- Simple to implement, which will probably also satisfy:
- Simple for a user to predict the behaviour,
- Not place undue restrictions on what can be combined,
- Does the sensible thing in commonly encountered situations.
Simple to implement is important, as it means code is also less prone to bugs. Simple for a user to predict is important – the outcome should be intuitively obvious. This will probably follow from ‘simple to implement’: if we don’t treat lots of special cases then the user won’t be worrying about lots of rules that need to be remembered. We shouldn’t place unnecessary restrictions: e.g. if a user wants to add MARI and HET data let them: they probably have a good reason to be trying to do so. It also means that the code doesn’t have to make copious checks, or worry too much about how to combine the ‘everything else’. Finally, the first three rules mean that the scheme will almost certainly do the sensible thing in common situations.
For the sake of definiteness, consider addition. The rules for any other binary operation will be the same. The minimum scheme is: (i) Add the D2D for each of the detector and monitor data (using implicitly whatever rules we have in place for the algebra of dataset2d regarding sizes of arrays, units, point or histogram) i.e. (d1,m1) + (d2,m2) = (d1+d2, m1+m2) (ii) The ‘everything else’ comes from the IXTrunfile whose number of detector workspaces and monitor workspaces match those of the pair of D2D resulting from the operations on the detector and monitor D2D. If the D2D operations produce a pair whose dimensions do not match one of the two input pairs, then the operation is invalid. That is, we require the number of y values to satisfy (nd1+d2, nm1+m2) = (nd1, nm1) or (nd2, nm2) In particular this forbids the case where have (nd1,nm1)=(41472,1) and (nd2,nm2)=(1,3) – this would result in (41472,3) following the rules for adding D2D of different dimensions together. In the case when both α1 and α2 match, then take α1.
These rules are fine when d and m are assigned for both runfiles. Likewise, if m is assigned for neither, or d is assigned for neither, then we apply the same principles to just the d or the m, respectively. In summary:
α1 (d1,m1) + α2 (d2,m2) = α (d1+d2, m1+m2) α is whichever of α1 and α2 match (α1 if both match); operation invalid if neither α1 nor α2 match α1 (d1,-) + α2 (d2,-) = α (d1+d2, -)
α1 (-,m1) + α2 (-,m2) = α (-, m1+m2)
The above forbids some operations we would like to perform, in particular if the operation is ‘divide’ and we want to normalise the detectors by a monitor. In this case we would want to be able to achieve this operation by having no detector map file, i.e. we want R1/R2 = α1(d1,m1) / α2(-,m2) = α1(d1/m2, m1/m2) for m2 corresponding to a single monitor. So let’s consider the various combinations of unassigned detector and/or monitor d2D:
α1 (d1,-) + α2 (d2,m2) = α (d1+d2, d1+m2) α is α2 if it matches; else operation is invalid. (This rule is the same as the one above, as α1 is guaranteed not to match) α1 (-,m1) + α2 (d2,m2) = α (m1+d2, m1+m2)
and by symmetry;
α1 (d1, m1) + α2 (d2,-) = α (d1+d2, m1+d2) α is α1 if it matches; else operation is invalid (This rule is the same as the one above, as α1 is guaranteed not to match)
α1 (d1, m1) + α2 (-,m2) = α (d1+m2, m1+m2)
(The qualitative rule here is: ‘if one of d and m is unassigned for just one of the two runfiles, fill in the missing d or m with the m or d respectively, then add as when nothing is missing’)
α1 (d1,-) + α2 (-,m2) = α (d1+m2, -) Same rule on α as always
α1 (-, m1) + α2 (d2,-) = α (m1+d2, -)
all these functions have a basic syntax and do not take any parameters except for shift_x
the operation is appled to both the monitor data and the detector data.
>> runfile_out=fn_x(runfile_in,parameters) >> runfile_out=fn_x_mon(runfile_in,parameters) >> runfile_out=fn_x_det(runfile_in,parameters)