File: Source_extended.comp

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (254 lines) | stat: -rw-r--r-- 7,960 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*******************************************************************************
*
* McXtrace, x-ray tracing package
*         Copyright, All rights reserved
*         DTU Physics, Kgs. Lyngby, Denmark
*         Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: Source_extended
*
* %Identification
* Written by:Arne 'S Jegers
* Date: May 6, 2019
* Origin: Technical University of Denmark
* Release: McXtrace 1.4
*
* A plane source emitting x-rays to emulate a distant extended source, such as a
* nebula or galaxy
*
* %Description
* A rectangular x-ray source that samples ray intensity from an image, and
* deflects the emitted ray to reflect having been emitted from the sampled part
* of the extended source. Rays that are sampled from the same point on the image
* are collimated, but can be emitted from anywhere on the rectangular source.
* The image should be provided as a 2D-ascii table, whose header includes the
* following entries:
*
* w_pixels and h_pixels: The width and height of the image in pixels
* x_ref and y_ref: x and y reference values of the FITS image
* r_max: The maximum distance from the point (x_ref, y_ref) to any corner of the image
* iCD11, iCD12, iCD21 and iCD22: The values of the FITS image's CD matrix
*
* %Parameters
* yheight [m]   Height of rectangle in (x,y,0) plane where x-rays
*               are generated.
* xwidth  [m]   Width of rectangle in (x,y,0) plane where x-rays
*               are generated.
* E0:     [keV] Mean energy of xrays.
* dE:     [keV] Energy half spread of x-rays (flat or gaussian sigma).
* lambda0:[AA]  Mean wavelength of x-rays.
* dlambda:[AA]  Wavelength half spread of x-rays.
* gauss:  [1]   Gaussian (1) or Flat (0) energy/wavelength distribution
* flux: [pht/s] total flux radiated from the source
* incoherent: [] Source is fully incoherent
* phase: [] Set phase to something given.
* image_path: [string] Path to file containing the heat map of the source 
* %End
*******************************************************************************/

DEFINE COMPONENT Source_extended
SETTING PARAMETERS (string spectrum_file=NULL,yheight=0, xwidth=0,
  dist=0, E0=0, dE=0, lambda0=0, dlambda=0, flux=0,gauss=0,incoherent=1,phase=0, string image_path="")

SHARE
%{
  %include "read_table-lib"
  struct Sextended_prms {
    double l0,dl;
    double pmul,pint;
    t_Table T;
  };
  struct Sextended_table_prms {
    double xref, yref, rmax;
    int pw, ph;
    t_Table data;
    double iCD[2][2];
  };
  double* sphericalToCartesian(double r, double theta, double Phi, double* cartesian){
    cartesian[0] = r*cos(theta)*cos(Phi);
    cartesian[1] = r*cos(theta)*sin(Phi);
    cartesian[2] = r*sin(theta);
  }

  double* cartesianToSpherical(double x, double y, double z, double* spherical){
    spherical[0] = sqrt(x*x + y*y + z*z);
    spherical[1] = atan2(z, sqrt(x*x + y*y));
    spherical[2] = atan2(y, x);
  }  
%}

DECLARE
%{
  double srcArea;
  int square;
  struct Sextended_prms prms;
  struct Sextended_table_prms extendedParams;
%}

INITIALIZE
%{
    square = 0;srcArea=0;
    square = 1;
    srcArea = xwidth * yheight;

  if (srcArea <= 0) {
    printf("Source_flat: %s: Source area is <= 0 !\n ERROR - Exiting\n",
           NAME_CURRENT_COMP);
    exit(0);
  }

  int status = 0;
  if (status=Table_Read(&(extendedParams.data), image_path, 0)==-1){
      fprintf(stderr,"Source_extended(%s) Error: Could not parse file \"%s\"\n",NAME_CURRENT_COMP,image_path?image_path:"");
      exit(-1);
  }

  char** header_parsed = Table_ParseHeader(extendedParams.data.header,
          "w_pixels=","h_pixels=", "x_ref=", "y_ref=", "r_max=", "iCD11=", "iCD12=", "iCD21=", "iCD22=", NULL);
  if (header_parsed[0] && header_parsed[1] && header_parsed[2] && header_parsed[3] &&
      header_parsed[4] && header_parsed[5] && header_parsed[6] && header_parsed[7])
  {
      printf(header_parsed[0]);printf("\n");
      extendedParams.pw=strtod(header_parsed[0],NULL);
      extendedParams.ph=strtod(header_parsed[1],NULL);
      extendedParams.xref=strtod(header_parsed[2],NULL);
      extendedParams.yref=strtod(header_parsed[3],NULL);
      extendedParams.rmax=strtod(header_parsed[4],NULL);
      extendedParams.iCD[0][0] = strtod(header_parsed[5], NULL);
      extendedParams.iCD[0][1] = strtod(header_parsed[6], NULL);
      extendedParams.iCD[1][0] = strtod(header_parsed[7], NULL);
      extendedParams.iCD[1][1] = strtod(header_parsed[8], NULL);
  }

  if (spectrum_file){
    /*read spectrum from file*/
    int status=0;
    if ( (status=Table_Read(&(prms.T),spectrum_file,0))==-1){
      fprintf(stderr,"Source_extended(%s) Error: Could not parse file \"%s\"\n",NAME_CURRENT_COMP,spectrum_file?spectrum_file:"");
      exit(-1);
    }
    /*data is now in table t*/
    /*integrate to get total flux, assuming raw numbers have been corrected for measuring aperture*/
    int i;
    prms.pint=0;
    t_Table *T=&(prms.T);
    for (i=0;i<prms.T.rows-1;i++){
      prms.pint+=((T->data[i*T->columns+1]+T->data[(i+1)*T->columns+1])/2.0)*(T->data[(i+1)*T->columns]-T->data[i*T->columns]);
    }
    printf("Source_flat(%s) Integrated intensity radiated is %g pht/s\n",NAME_CURRENT_COMP,prms.pint);
    if(E0) printf("Source_flat(%s) E0!=0 -> assuming intensity spectrum is parametrized by energy [keV]\n",NAME_CURRENT_COMP);
  }else if ( !E0 && !lambda0){
    fprintf(stderr,"Source_flat(%s): Error: Must specify either wavelength or energy distribution\n",NAME_CURRENT_COMP);
    exit(0);
  }
  /*calculate the X-ray weight from the flux*/
  if (flux){
    prms.pmul=flux;
  }else{
    prms.pmul=1;
  }
  prms.pmul*=1.0/((double) mcget_ncount());
%}


TRACE
%{
  double chi,e,k,l,r, pdir;
  char done = 0;
  double xpix, ypix, theta, Phi;
  double xDeg, yDeg, xRel, yRel;

  Phi=0;
  z=0;
  if (square == 1) {
    x = xwidth * (rand01() - 0.5);
    y = yheight * (rand01() - 0.5);
  }

  /*pdir contains the unnormalized solid angle weighting */
  p = 1;

  if (spectrum_file){
    double pp=0;
    //while (pp<=0){
    l=prms.T.data[0]+ (prms.T.data[(prms.T.rows-1)*prms.T.columns] -prms.T.data[0])*rand01();
    pp=Table_Value(prms.T,l,1);
    //}
    p*=pp;
    /*if E0!=0 convert the tabled value to wavelength*/
  }else if (E0){
    if(!dE){
      e=E0;
    }else if (gauss){
      e=E0+dE*randnorm();
    }else{
      e=randpm1()*dE*0.5 + E0;
    }
    k=E2K*e;
  }else if (lambda0){
    if (!dlambda){
      l=lambda0;
    }else if (gauss){
      l=lambda0+dlambda*randnorm();
    }else{
      l=randpm1()*dlambda*0.5 + lambda0;
    }
    k=(2*M_PI/l);
  }

  // ===========================================================================
  //  This section randomly picks a direction to emit a ray to, and samples the
  //  source image for an intensity at the appropriate point

  while(!done){
      theta = sqrt(rand01())*extendedParams.rmax/180*M_PI; //normalized
      Phi = rand01()*2*M_PI;

      xDeg = tan(theta)*cos(Phi)*180/M_PI;
      yDeg = tan(theta)*sin(Phi)*180/M_PI;

      xRel = extendedParams.iCD[0][0]*xDeg + extendedParams.iCD[0][1]*yDeg;
      yRel = extendedParams.iCD[1][0]*xDeg + extendedParams.iCD[1][1]*yDeg;

      xpix = xRel + extendedParams.xref;
      ypix = yRel + extendedParams.yref;

      if(xpix > 0 && xpix < extendedParams.pw && ypix > 0 && ypix < extendedParams.ph){
        done = 1;
      }
  }
  //Both are inverted because, relative to the spherical coordinate system of
  //theta and Phi, the rays are emitted 'backwards'
  kx = -sin(theta)*cos(Phi)*k;
  ky = -sin(theta)*sin(Phi)*k;

  kz = cos(theta)*k;

  p = Table_Value2d(extendedParams.data, ypix, xpix);

  /*randomly pick phase or set to something real*/
  if (incoherent){
    Phi=rand01()*2*M_PI;
  }else{
    Phi=phase;
  }

  /*set polarization vector*/
  Ex=0;Ey=0;Ez=0;
%}

FINALLY
%{
  Table_Free(&(prms.T));
  Table_Free(&(extendedParams.data));
%}

MCDISPLAY
%{
  if (square == 1) {
    magnify("xy");
    rectangle("xy",0,0,0,xwidth,yheight);
  }
%}

END