PEARL Procedures rev-distro-2.1.1-1-gf419e92-dirty Igor procedures for the analysis of PEARL data

fermi-edge-analysis.ipf
Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #include "pearl-area-profiles"
3
4 // $Id$
5
25
26
27 function analyse_curved_edge(data)
28 wave data // 2D counts data, x-scale = kinetic energy, y-scale = analyser angle
29 variable guess_EF // initial guess of the Fermi level
30
31 dfref savedf = GetDataFolderDFR()
32 dfref datadf = GetWavesDataFolderDFR(data)
33 setdatafolder datadf
34
35 make /n=5 /d /o w_coef_int
36 make /n=7 /d /o w_coef_curved
37
38 // 1) integrate data
39 wave xint = ad_profile_x(data, -inf, inf, "", noavg=1)
40 duplicate /free xint, xint_sig
41 xint_sig = sqrt(xint * 4) / 4
42 variable xmin = wavemin(xint)
43 variable xmax = wavemax(xint)
44 variable xmean = mean(xint)
45
46 // 2) fit integrated data for reference
47 w_coef_int[0] = xmin
48 w_coef_int[1] = 0
49 w_coef_int[2] = xmax - xmin
50 w_coef_int[3] = dimoffset(xint, 0) + dimdelta(xint, 0) * dimsize(xint, 0) / 2
51 w_coef_int[4] = 100
52 FuncFit /NTHR=0 FermiFuncLinDOS w_coef_int xint /D /I=1 /W=xint_sig
53 wave w_sigma
54 duplicate /o w_sigma, w_sigma_int
55
56 // 3) normalize data
57 wave yavg = ad_profile_y(data, -inf, inf, "")
58 variable ymean = mean(yavg)
59
60 duplicate /o data, data_norm, data_sig
61 data_sig = sqrt(data * 4) / 4
62 data_norm = data_norm * ymean / yavg[q]
63 data_sig = data_sig * ymean / yavg[q]
64
65 // 4) fit normalized data
66 wave xavg = ad_profile_x(data, -inf, inf, "")
67 xmin = wavemin(xavg)
68 xmax = wavemax(xavg)
69 xmean = mean(xavg)
70
71 w_coef_curved[0] = {0, 0, 1, 95.5, 100, 0, -0.0001}
72 w_coef_curved[0] = xmin
73 w_coef_curved[2] = xmax - xmin
74 w_coef_curved[3] = w_coef_int[3]
75 w_coef_curved[4] = w_coef_int[4]
76
77 //variable box = min(11, numpnts(xavg) / 5)
78 //FindLevel /B=(box) /EDGE=2 /Q xavg, (xmin + xmax) / 2
79 //if (v_flag == 0)
80 // w_coef_curved[3] = v_levelx
81 //else
82 // w_coef_curved[3] = dimoffset(data, 0) + dimdelta(data, 0) * dimsize(data, 0) / 2
83 //endif
84
85 duplicate /o data_norm, fit_data_norm
86 FuncFitMD /X=1 /NTHR=0 FermiFuncLinDOS_2Dcorr w_coef_curved data_norm /D=fit_data_norm /I=1 /W=data_sig
87 wave w_sigma
88 duplicate /o w_sigma, w_sigma_curved
89
90 display /k=1; appendimage data_norm
91 ModifyImage data_norm ctab= {xmin,xmax,Grays,0}
92 AppendMatrixContour fit_data_norm
93
94 setdatafolder savedf
95 return 0
96 end
97
98 function record_results(index)
99 variable index
100
101 dfref savedf = GetDataFolderDFR()
102 wave /sdfr=root: Tint, Tint_sig, Tcurv, Tcurv_sig, EFcurv, EFcurv_sig
103 wave w_coef_int, w_coef_curved
104 wave w_sigma_int, w_sigma_curved
105
106 Tint[index] = w_coef_int[4]
107 Tint_sig[index] = w_sigma_int[4]
108 Tcurv[index] = w_coef_curved[4]
109 Tcurv_sig[index] = w_sigma_curved[4]
110 EFcurv[index] = w_coef_curved[3]
111 EFcurv_sig[index] = w_sigma_curved[3]
112
113 setdatafolder savedf
114 end
115
116 function integrate_curved_edge(data, data_sig)
117 wave data
118 wave /z data_sig
119 //wave coef
120
121 string name = nameofwave(data)
122
123 duplicate /o data, data_out
124 redimension /n=(dimsize(data,0)) data_out
125 data_out = 0
126
127 if (waveexists(data_sig))
128 duplicate /o data_sig, sig_out
129 redimension /n=(dimsize(data,0)) sig_out
130 sig_out = 0
131 endif
132
133 wave ywgt = ad_profile_y(data, -inf, inf, "", noavg=1)
134 ywgt = 1 / ywgt / 4
135 //ywgt = 1 / 4
136 variable sum_ywgt = sum(ywgt)
137
138 variable nx = dimsize(data, 0)
139 variable ny = dimsize(data, 1)
140 variable iy
141 variable yy
142 variable dx
143 variable dy
144 variable dp
145 variable dp_min = 0
146
147 wave PassEnergy = :attr:PassEnergy
148 wave NumSlices = :attr:NumSlices
149
150 for (iy = 0; iy < ny; iy += 1)
151 dy = dimoffset(data, 1) + dimdelta(data, 1) * iy
152 dy = dy / dimdelta(data, 1)
153 dx = slit_shift(dy * 902 / NumSlices[0], PassEnergy[0])
154 dp = round(dx / dimdelta(data, 0)) // <= 0
155 dp_min = min(dp_min, dp)
156
157 data_out[] = p+dp >= 0 ? data_out + data[p+dp][iy] * ywgt[iy] : data_out
158
159 if (waveexists(data_sig))
160 sig_out = p+dp >= 0 ? sig_out + data_sig[p+dp][iy] * ywgt[iy] : sig_out
161 endif
162 endfor
163
164 data_out /= sum_ywgt
165 data_out[0, -dp_min][] = nan
166
167 if (waveexists(sig_out))
168 sig_out /= sum_ywgt
169 //sig_out[0, -dp_min] = nan
170 endif
171 end
172
173 function slit_correction(data, data_out, epass)
174 wave data // must be image with original dimensions (no cropping!)
175 wave /z data_out // 2D or 1D wave to receive the result
176 // X dimension must be identical to the one of data
177 // if 2D, Y dimension must be either identical to the one of data
178 // if 1D, the result will be the sum of the corrected slices
179 variable epass // pass energy
180
181 if (!WaveExists(data_out))
182 string name = nameofwave(data) + "_corr"
183 duplicate /o data, $name
184 wave data_out = $name
185 //redimension /n=(dimsize(data,0)) data_out
186 endif
187 data_out = 0
188
189 variable nx = dimsize(data, 0)
190 variable ny = dimsize(data, 1)
191 variable iy
192 variable yy
193 variable dx
194 variable dy
195 variable dp
196 variable dp_min = 0
197
198 for (iy = 0; iy < ny; iy += 1)
199 dy = dimoffset(data, 1) + dimdelta(data, 1) * iy
200 dy = dy / dimdelta(data, 1)
201 dx = slit_shift(dy * 902 / ny, epass)
202 dp = round(dx / dimdelta(data, 0)) // <= 0
203 dp_min = min(dp_min, dp)
204
205 if (wavedims(data_out) >= 2)
206 data_out[][iy] = p+dp >= 0 ? data_out + data[p+dp][iy] : data_out
207 else
208 data_out = p+dp >= 0 ? data_out + data[p+dp][iy] : data_out
209 endif
210 endfor
211
212 data_out[0, -dp_min][] = nan
213 end
214
215 //------------------------------------------------------------------------------
216 threadsafe Function FermiFuncLinDOS2D_corr(w,x,y) : FitFunc
217 // linear density of states below Fermi level
218 // 2D data with corrections:
219 // - straight slit (slit shift)
220 // - transmission function (polynomial)
221 //------------------------------------------------------------------------------
222 Wave w; Variable x; variable y
223 // w[0] = background far above the fermi level
224 // w[1] = slope of the linear background
225 // w[2] = amplitude
226 // w[3] = fermi level in eV
227 // w[4] = temperature in K
228 // w[5] = transmission - linear term
229 // w[6] = transmission - quadratic term
230 // w[7] = transmission - cubic term
231 // w[8] = pass energy (hold this value)
232 // w[9] = y scale: pixels / unit of y
233
234 variable pos = w[3] + slit_shift(y * w[9], w[8])
235 variable transm = 1 + w[5] * y + w[6] * y^2 + w[7] * y^3
236 variable fermi = (w[1] * min(x - pos, 0) + w[2]) / ( exp( (x - pos) / (kBoltzmann * w[4]) ) + 1.0 )
237 return transm * (fermi + w[0])
238 end
239
240 //------------------------------------------------------------------------------
241 threadsafe Function FermiFuncLinDOS_2Dcorr_old(w,x,y) : FitFunc
242 // linear density of states below Fermi level
243 // 2D data with a polynomial shift of the Fermi level in the second dimension
244 //------------------------------------------------------------------------------
245 Wave w; Variable x; variable y
246 // w[0] = background far above the fermi level
247 // w[1] = slope of the linear background
248 // w[2] = amplitude
249 // w[3] = fermi level in eV
250 // w[4] = temperature in K
251 // w[5] = shift - linear term
252 // w[6] = shift - quadratic term
253
254 variable pos = w[3] + w[5] * y + w[6] * y^2
255 return w[0] + (w[1] * min(x - pos, 0) + w[2]) / ( exp( (x - pos) / (kBoltzmann * w[4]) ) + 1.0 )
256 end
257
259 static constant mcp_radius_pix = 555
261 static constant mcp_radius_mm = 20
263 static constant hemi_radius_mm = 200
265 static constant mcp_radius_epass = 0.04
266
267 threadsafe function slit_shift(ypix, epass)
268 // calculates the energy shift due to straight slit
269 // the radius of the curve is 1/2 of the hemisphere radius
270 variable ypix // vertical (angle/position) pixels distance from center
271 // = slice coordinate * 902 / number of slices
272 variable epass // pass energy
273
274 variable rpix = mcp_radius_pix * hemi_radius_mm / mcp_radius_mm
275 //variable rpix = mcp_radius_pix * hemi_radius_mm / 2 / mcp_radius_mm
276 variable rene = epass * mcp_radius_epass * hemi_radius_mm / 2 / mcp_radius_mm
277
278 variable isin = asin(ypix / rpix)
279 variable dene = rene * (cos(isin) - 1)
280
281 return dene
282 end
283
284 function show_shift(data)
285 wave data
286 variable epass
287
288 variable ny = dimsize(data, 1)
289 make /o /n=(ny) shift_x
290 setscale /i x -ny/2, ny/2, "", shift_x
291 wave PassEnergy = :attr:PassEnergy
292 wave NumSlices = :attr:NumSlices
293
294 shift_x = slit_shift(x * 902 / NumSlices[0], PassEnergy[0])
295
296 variable ecenter = dimoffset(data, 0) + dimdelta(data, 0) * dimsize(data, 0) / 2
297 shift_x += ecenter
298 end
299
306 function analyser_energy_resolution(epass, slit)
307 variable epass
308 variable slit
309
310 variable respow
311 if (epass < 4)
312 respow = 1110
313 elseif (epass < 8)
314 respow = 1400
315 else
316 respow = 1750
317 endif
318
319 return epass * max(0.2, slit) / 0.2 / respow
320 end
FermiFuncLinDOS2D_corr
threadsafe variable FermiFuncLinDOS2D_corr(variable w, threadsafe x, wave y)
Definition: fermi-edge-analysis.ipf:216
slit_shift
threadsafe variable slit_shift(variable ypix, variable epass)
Definition: fermi-edge-analysis.ipf:267
mcp_radius_pix
static const variable mcp_radius_pix
MCP radius seen by the camera in pixels.
Definition: fermi-edge-analysis.ipf:259
mcp_radius_mm
static const variable mcp_radius_mm
physical size (radius) of the MCP in mm
Definition: fermi-edge-analysis.ipf:261
ad_profile_y
threadsafe wave ad_profile_y(wave dataset, variable p1, variable p2, string destname, variable noavg=defaultValue)
1D cut through 2D dataset along Y dimension, new destination wave.
Definition: pearl-area-profiles.ipf:542
analyse_curved_edge
variable analyse_curved_edge(wave data)
Definition: fermi-edge-analysis.ipf:27
hemi_radius_mm
static const variable hemi_radius_mm
physical size (radius) of the hemisphere in mm
Definition: fermi-edge-analysis.ipf:263
analyser_energy_resolution
variable analyser_energy_resolution(variable epass, variable slit)
calculate the energy resolution of the analyser
Definition: fermi-edge-analysis.ipf:306
slit_correction
variable slit_correction(wave data, wave data_out, variable epass)
Definition: fermi-edge-analysis.ipf:173
mcp_radius_epass
static const variable mcp_radius_epass
energy range imaged on MCP relative to the pass energy
Definition: fermi-edge-analysis.ipf:265
integrate_curved_edge
variable integrate_curved_edge(wave data, wave data_sig)
Definition: fermi-edge-analysis.ipf:116
show_shift
variable show_shift(wave data)
Definition: fermi-edge-analysis.ipf:284
ad_profile_x
threadsafe wave ad_profile_x(wave dataset, variable q1, variable q2, string destname, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, new destination wave.
Definition: pearl-area-profiles.ipf:480
record_results
variable record_results(variable index)
Definition: fermi-edge-analysis.ipf:98