1/*******************************************************************************
2* McXtrace, X-ray tracing package
3*           Copyright, All rights reserved
4*           Risoe National Laboratory, Roskilde, Denmark
5*           Institut Laue Langevin, Grenoble, France
6*
7* Component: SAXSQMonitor
8*
9* %I
10* Written by: Martin Cramer Pedersen (mcpe@nbi.dk)
11* Based on a SANS-component in McStas by Søren Kynde
12* Date: May 2, 2012
13* Version: $Revision$
14* Origin: KU-Science
15* Release: McXtrace 1.0
16*
17* A circular detector measuring the radial average of intensity as a function
18* of the momentum transform in the sample.
19*
20* %D
21* A simple component simulating the scattering from a box-shaped, thin solution
22* of monodisperse, spherical particles.
23*
24* %P
25* RadiusDetector	: [m]	Radius of the detector (in the xy-plane).
26* DistanceFromSample: [m] 	Distance from the sample to this component.
27* LambdaMin  		: [AA]	Max sensitivity in lambda - used to compute the
28*							highest possible value of momentum transfer, q.
29* NumberOfBins      : []	Number of bins in the r (and q).
30* RFilename	        : []	File used for storing I(r).
31* qFilename         : [] 	File used for storing I(q).
32* Lambda0			: []	If lambda is given, the momentum transfers of all
33*							rays are computed from this value. Otherwise,
34*							instrumental effects are negated.
35* restore_xray      : []	If set to 1, the component restores the original
36*							x-ray.
37*
38* %E
39*******************************************************************************/
40
41DEFINE COMPONENT SAXSQMonitor
42
43DEFINITION PARAMETERS (string RFilename = "RDetector", string qFilename = "QDetector", NumberOfBins = 100, restore_xray = 0)
44
45SETTING PARAMETERS (RadiusDetector, DistanceFromSample, LambdaMin = 1.0, Lambda0 = 0.0)
46
47OUTPUT PARAMETERS (Nofq, Iofq, IofqSquared, NofR, IofR, IofRSquared)
48
49STATE PARAMETERS (x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p)
50
51DECLARE
52%{
53	// Declarations
54    double TwoThetaMax;
55    double qMax;
56
57	double Nofq[NumberOfBins];
58    double Iofq[NumberOfBins];
59    double IofqSquared[NumberOfBins];
60
61	double NofR[NumberOfBins];
62    double IofR[NumberOfBins];
63    double IofRSquared[NumberOfBins];
64%}
65
66INITIALIZE
67%{
68	// Declarations
69    int i;
70
71	// Initializations
72    for (i = 0; i < NumberOfBins; ++i) {
73		Nofq[i] = 0.0;
74		Iofq[i] = 0.0;
75		IofqSquared[i] = 0.0;
76    }
77
78	TwoThetaMax = atan(RadiusDetector / DistanceFromSample);
79	qMax = 4 * PI * sin(TwoThetaMax / 2.0) / LambdaMin;
80%}
81
82TRACE
83%{
84	// Declarations
85    int i;
86    double TwoTheta;
87	double Lambda;
88
89	double R;
90	double RLow;
91	double RHigh;
92
93    double q;
94	double qLow;
95	double qHigh;
96
97	double TwoThetaLow;
98	double TwoThetaHigh;
99	double AreaOfSlice;
100
101    PROP_Z0;
102
103	// Computation of R
104    R = sqrt(pow(x, 2) + pow(y, 2));
105
106	// Computation of q
107	if (Lambda0 <= 0.0) {
108		Lambda = 2.0 * PI / sqrt(pow(kx, 2) + pow(ky, 2) + pow(kz, 2));
109	} else {
110		Lambda = Lambda0;
111	}
112
113    TwoTheta = atan(R / DistanceFromSample);
114    q = 4.0 * PI * sin(TwoTheta / 2.0) / Lambda;
115
116	// Put photon in the correct r-bin
117	if (R < RadiusDetector) {
118		i = floor(NumberOfBins * R / RadiusDetector);
119
120		RLow = RadiusDetector / NumberOfBins * i;
121		RHigh = RadiusDetector / NumberOfBins * (i + 1);
122
123		TwoThetaLow = atan(RLow / DistanceFromSample);
124		TwoThetaHigh = atan(RHigh / DistanceFromSample);
125
126		AreaOfSlice = fabs((cos(2.0 * TwoThetaLow) - cos(2.0 * TwoThetaHigh)) * 2.0 * PI);
127
128		++NofR[i];
129		IofR[i] += p / AreaOfSlice;
130		IofRSquared[i] += pow(p / AreaOfSlice, 2);
131    }
132
133	// Put photon in the correct q-bin
134    if (q < qMax) {
135		i = floor(NumberOfBins * q / qMax);
136
137		qLow = qMax / NumberOfBins * i;
138		qHigh = qMax / NumberOfBins * (i + 1);
139
140		TwoThetaLow = asin(qLow * Lambda / (4.0 * PI));
141		TwoThetaHigh = asin(qHigh * Lambda / (4.0 * PI));
142
143		AreaOfSlice = fabs((cos(2.0 * TwoThetaLow) - cos(2.0 * TwoThetaHigh)) * 2.0 * PI);
144
145		++Nofq[i];
146		Iofq[i] += p / AreaOfSlice;
147		IofqSquared[i] += pow(p / AreaOfSlice, 2);
148
149		SCATTER;
150    }
151
152	// Restore xray if requested
153    if (restore_xray) {
154		RESTORE_XRAY(INDEX_CURRENT_COMP, x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p);
155    }
156%}
157
158SAVE
159%{
160	// Output I(r)
161    DETECTOR_OUT_1D(
162        "QMonitor - Radially averaged distribution",
163        "Radius [m]",
164        "I(r)",
165        "r",
166		0.0,
167		RadiusDetector,
168		NumberOfBins,
169        &NofR[0],
170		&IofR[0],
171		&IofRSquared[0],
172        RFilename
173	);
174
175	// Output I(q)
176    DETECTOR_OUT_1D(
177        "QMonitor - Distribution in q (Radially averaged)",
178        "q [1 / AA]",
179        "I(q)",
180        "q",
181		0.0,
182		qMax,
183		NumberOfBins,
184        &Nofq[0],
185		&Iofq[0],
186		&IofqSquared[0],
187        qFilename
188	);
189%}
190
191MCDISPLAY
192%{
193	magnify("xy");
194	circle("xy", 0, 0, 0, RadiusDetector);
195%}
196
197END
198