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