Skip to content

Commit c9547af

Browse files
committed
igor procedure for C0/C1 added
1 parent 7e6910d commit c9547af

File tree

22 files changed

+359
-0
lines changed

22 files changed

+359
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Obtain C<sub>0</sub>/C<sub>1</sub>
2+
3+
Intensity calibration of Raman spectra based on a three step procedure has been established in our research. (See [10.1002/jrs.5955](https://onlinelibrary.wiley.com/doi/full/10.1002/jrs.5955) for more details)
4+
5+
These three corrections for the intensity calibration steps are labelled as C<sub>0</sub>, C<sub>1</sub> and C<sub>2</sub>.
6+
7+
- C<sub>0</sub> is derived from the vector representing the x-axis.
8+
- C<sub>1</sub> comes from the fit of the broadband white-light spectrum ( which is corrected for C<sub>0</sub>) to the number of photons from a black-body emitter.
9+
- and C<sub>2</sub> comes from the Raman intensities (which are already corrected using C<sub>0</sub> and C<sub>1</sub>. This correction rectifies any inconsistencies not covered in the previous steps of intensity calibration. See the above paper for more details.
10+
The total multiplicative correction is given as C<sub>0</sub>/(C<sub>1</sub> * C<sub>2</sub>).
11+
12+
13+
The procedure file in this folder, `gen_correction.ipf` has the function defined as `gen_C0_C1 ` for generating the first two corrections, and which returns : (C<sub>0</sub>/C<sub>1</sub>). For common Raman measurements, where very high accuracy in the relative Raman intensities is not required, this might suffice.
Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
2+
3+
// -------------------------------------------------------------------------------
4+
// -------------------------------------------------------------------------------
5+
6+
// Main function
7+
// Example :
8+
// gen_C0_C1 ( x_wavenumber, 632.8 , root:whitelight , 670 , maskWave = mask1D )
9+
// wave laser_nm wave pixel maskWave
10+
11+
// returns : intensity_corr : 1D wave which corresponds to (C0/C1), to be multiplied to the Raman spectra.
12+
13+
function gen_C0_C1 ( ramanshift , laser_nm , wl_wave , norm_pnt , [ maskWave , set_mask_nan] )
14+
15+
wave ramanshift // relative, vector
16+
variable laser_nm // laser wavelength, nm, scalar
17+
wave wl_wave // white_light spectra, un-normalized, 1D or 2D, vector
18+
variable norm_pnt // normalization index, pnt, scalar
19+
20+
wave maskWave // optional, supply mask for wl fitting , for eg. maskWave = mask_1D, vector
21+
variable set_mask_nan // optional, 0 or 1. When set to 1, the masked region is set to nan in the output
22+
// intensity_corr wave. When set to 0, intensity_corr wave is not modified for the mask
23+
// region.
24+
25+
variable nPnts = dimsize(ramanshift, 0)
26+
variable mid = nPnts/2
27+
28+
29+
// initialization
30+
killwaves /Z W_coef, W_ParamConfidenceInterval, W_sigma, fit
31+
32+
// generate the C0 correction
33+
gen_C0(ramanshift , norm_pnt)
34+
wave C0
35+
36+
// wl spectra (check averaging)
37+
variable nCols_wl = dimsize(wl_wave,1)
38+
if (nCols_wl > 1)
39+
print "\twl_wave is 2D. Averaging.\r"
40+
do_average_custom(wl_wave)
41+
string newWave= nameofwave(wl_wave)+"_avg"
42+
printf "\tAveraged wave : %s\r", newWave
43+
wave wl_wave = $newWave
44+
endif
45+
46+
// wl spectra (normalization) and multiply with C0
47+
make /d /o /n=(nPnts) wl_norm = wl_wave/ wavemax(wl_wave)
48+
wl_norm=wl_norm*C0
49+
wave wl_norm
50+
51+
// wl spectra (subset)
52+
variable result // returned value is assigned to result
53+
54+
// Determine if the optional parameters were supplied
55+
if( ParamIsDefault(maskWave) )
56+
57+
print "\t Mask wave not supplied. Working with full wave.\r"
58+
result = gen_C1(ramanshift, laser_nm , wl_norm , norm_pnt)
59+
60+
elseif ( waveExists ( maskWave ))
61+
print "\tMask wave is supplied. Using it for fit.\r"
62+
result = gen_C1_mask (ramanshift, laser_nm , wl_norm , norm_pnt , maskWave)
63+
endif
64+
65+
66+
//--------------------------------------------------------------
67+
// wave references (C0 and C1 should exist in present folder)
68+
wave C0
69+
wave C1
70+
//--------------------------------------------------------------
71+
72+
if (result ==2 )
73+
74+
if (set_mask_nan == 1)
75+
printf "\n\n\tset_mask_nan parameter is set to 1. Masked region in the intensity corr will be set to Nan.\r"
76+
77+
wave C1_out = set_nan_correspond_to_mask (C1, maskWave)
78+
wave C1= C1_out
79+
else
80+
printf "\n\n\tset_mask_nan parameter not set to 1.\r"
81+
endif
82+
endif
83+
//--------------------------------------------------------------
84+
make /d /o /n=(nPnts) intensity_corr = (C0/C1)
85+
86+
printf "\n\tintensity_corr generated. Done. This is equal to (C0/C1)\r"
87+
88+
// cleanup
89+
killwaves /Z abs_wavenumber_subset, wl_norm_subset, W_coef, fit, coefs
90+
killwaves /Z W_ParamConfidenceInterval, W_sigma
91+
92+
end
93+
94+
95+
// -------------------------------------------------------------------------------
96+
// -------------------------------------------------------------------------------
97+
98+
STATIC function gen_C0(ramanshift , norm_pnt)
99+
100+
wave ramanshift // relative
101+
variable norm_pnt // normalization index, pnt
102+
103+
variable nPnts = dimsize(ramanshift, 0)
104+
variable mid = nPnts/2
105+
106+
make /FREE /o /n=(nPnts-1) wavenumber_spacing =0
107+
wavenumber_spacing = ramanshift [p] - ramanshift [p+1]
108+
109+
// normalization
110+
make /d /o /n=(nPnts-1) waveum_corr = ( wavenumber_spacing / wavenumber_spacing [ norm_pnt ])
111+
make /FREE /d /n=(nPnts-1) xax=p
112+
// ------------------------
113+
114+
// computing the value at the last point
115+
CurveFit /Q poly 3, waveum_corr /X=xax
116+
wave W_coef
117+
variable val_plus1_pnt = poly(W_coef, nPnts-1 )
118+
//print val_plus1_pnt
119+
120+
InsertPoints (nPnts-1),1, waveum_corr
121+
waveum_corr [nPnts-1] = val_plus1_pnt
122+
123+
duplicate /O waveum_corr, C0
124+
125+
killwaves /Z wavenum_corr
126+
127+
128+
end
129+
130+
// -------------------------------------------------------------------------------
131+
// -------------------------------------------------------------------------------
132+
133+
STATIC function gen_C1(ramanshift, laser_nm , wl_input norm_pnt)
134+
135+
wave ramanshift // relative
136+
variable laser_nm // laser wavelength (nm)
137+
wave wl_input // normalized wl wave with C0 multiplied
138+
variable norm_pnt // normalization index, pnt
139+
140+
variable nPnts = dimsize(ramanshift, 0)
141+
variable mid = nPnts/2
142+
143+
144+
// cleanup from prev run
145+
killwindow /Z genC0C1
146+
147+
// make abs_wavenumber, for xaxis
148+
149+
make /o /d /n=(nPnts) abs_wavenumber = ((1e7/laser_nm)-ramanshift)*100
150+
make /o /d /n=2 coefs
151+
152+
// defining initial coefs
153+
coefs[0] = 0.856e-18
154+
coefs[1] = 2759 // 0.856e-18
155+
156+
157+
Display /K=1 wl_input vs abs_wavenumber
158+
FuncFit photons_per_unit_wavenum_abs coefs wl_input /X=abs_wavenumber
159+
160+
printf "\tFit (not using mask), Obtained fit coef:%5.6e, %5.6e",coefs[0],coefs[1]
161+
162+
make /o /d /n=(nPnts) fit = photons_per_unit_wavenum_abs(coefs,abs_wavenumber)
163+
appendtograph fit vs abs_wavenumber
164+
165+
// customize graph
166+
ModifyGraph grid=1,mirror=1,axThick=1.2,lblPosMode(bottom)=2;DelayUpdate
167+
ModifyGraph lblMargin(bottom)=2,gridHair=1,manTick(left)={0,0.1,0,1},manMinor(left)={3,2},manTick(bottom)={0,0.02,6,2}
168+
ModifyGraph manMinor(bottom)={3,2},gridRGB(left)=(13107,13107,13107),gridRGB(bottom)=(17476,17476,17476);
169+
Label left "Intensity";DelayUpdate
170+
Label bottom "Wavenumber / m\\S-1"
171+
ModifyGraph fSize=25
172+
ModifyGraph rgb(fit)=(0,0,65535)
173+
ModifyGraph lsize=2
174+
SetAxis left 0,*
175+
DoUpdate;
176+
177+
// generate C1
178+
make /o /d /n=(nPnts) C1 = wl_input / fit
179+
180+
// remove fit and residual wave
181+
string fname="fit_"+nameofwave(wl_input)
182+
killwaves /Z $fname
183+
184+
fname="Res_"+nameofwave(wl_input)
185+
killwaves /Z $fname
186+
187+
188+
if (waveexists(C1) && coefs[1]< 6000 ) // 6000 is the temperature of the lamp in K, too large value may be unreasonable.
189+
return 1
190+
endif
191+
192+
193+
end
194+
195+
// -------------------------------------------------------------------------------
196+
// -------------------------------------------------------------------------------
197+
198+
STATIC function gen_C1_mask (ramanshift, laser_nm , wl_input , norm_pnt , maskWave )
199+
200+
wave ramanshift // relative
201+
variable laser_nm // laser wavelength (nm)
202+
wave wl_input // normalized wl wave with C0 multiplied
203+
variable norm_pnt // normalization index, pnt
204+
wave maskWave
205+
206+
variable nPnts = dimsize(ramanshift, 0)
207+
variable mid = nPnts/2
208+
209+
// cleanup from prev run
210+
killwindow /Z genC0C1
211+
212+
// make abs_wavenumber, for xaxis
213+
214+
make /o /d /n=(nPnts) abs_wavenumber = ((1e7/laser_nm)-ramanshift)*100
215+
make /o /d /n=2 coefs
216+
217+
// defining initial coefs
218+
coefs[0] = 0.856e-18
219+
coefs[1] = 2659 // 0.856e-18
220+
221+
222+
Display /N=genC0C1 /K=1 wl_input vs abs_wavenumber
223+
224+
// perform fitting, with mask applied
225+
FuncFit photons_per_unit_wavenum_abs coefs wl_input /X=abs_wavenumber /M=maskWave
226+
227+
printf "\tMasked wl fit, obtained coefs : %5.6e, %5.6e",coefs[0],coefs[1]
228+
229+
// generate the fit curve
230+
make /o /d /n=(nPnts) fit = photons_per_unit_wavenum_abs(coefs,abs_wavenumber)
231+
232+
// generate C1
233+
make /o /d /n=(nPnts) C1 = wl_input / fit
234+
235+
//customize the graph
236+
appendtograph /W=genC0C1 fit vs abs_wavenumber
237+
238+
ModifyGraph /W=genC0C1 grid=1,mirror=1,axThick=1.2,lblPosMode(bottom)=2;DelayUpdate
239+
ModifyGraph /W=genC0C1 lblMargin(bottom)=2,gridHair=1,manTick(left)={0,0.1,0,1},manMinor(left)={3,2},manTick(bottom)={0,0.02,6,2}
240+
ModifyGraph /W=genC0C1 manMinor(bottom)={3,2},gridRGB(left)=(13107,13107,13107),gridRGB(bottom)=(17476,17476,17476);
241+
Label /W=genC0C1 left "Intensity";DelayUpdate
242+
Label /W=genC0C1 bottom "Wavenumber / m\\S-1"
243+
ModifyGraph /W=genC0C1 fSize=25
244+
ModifyGraph /W=genC0C1 rgb(fit)=(0,0,65535)
245+
ModifyGraph /W=genC0C1 lsize=2
246+
SetAxis /W=genC0C1 left 0,*
247+
DoUpdate;
248+
249+
// generate C1
250+
make /o /d /n=(nPnts) C1 = wl_input / fit
251+
252+
// remove fit wave
253+
string fname="fit_"+nameofwave(wl_input)
254+
killwaves /Z $fname
255+
256+
fname="Res_"+nameofwave(wl_input)
257+
killwaves /Z $fname
258+
259+
if (waveexists(C1) && coefs[1]< 6000 ) // 6000 is the temperature of the lamp in K, too large value may be unreasonable.
260+
return 2
261+
endif
262+
263+
264+
end
265+
266+
267+
// -------------------------------------------------------------------------------
268+
// -------------------------------------------------------------------------------
269+
// Custom fit function
270+
271+
Function photons_per_unit_wavenum_abs(w0,w) : FitFunc
272+
Wave w0
273+
Variable w
274+
275+
//CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
276+
//CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
277+
//CurveFitDialog/ Equation:
278+
//CurveFitDialog/ f(w) = a0*599584916*w^2/(exp(0.1438776877e-1*w/T)-1)
279+
//CurveFitDialog/ End of Equation
280+
//CurveFitDialog/ Independent Variables 1
281+
//CurveFitDialog/ w
282+
//CurveFitDialog/ Coefficients 2
283+
//CurveFitDialog/ w0[0] = a0
284+
//CurveFitDialog/ w0[1] = T
285+
286+
return w0[0]*599584916*w^2/(exp(0.1438776877e-1*w/w0[1])-1)
287+
End
288+
289+
// -------------------------------------------------------------------------------
290+
// -------------------------------------------------------------------------------
291+
292+
// for averaging 2D input wave across columns
293+
STATIC function do_average_custom(input)
294+
wave input
295+
296+
variable nRows
297+
variable nCols
298+
variable i
299+
300+
nRows=dimsize(input, 0)
301+
nCols=dimsize(input, 1)
302+
303+
304+
string name=nameofwave (input)
305+
306+
string new_name
307+
sprintf new_name, "%s_avg",name
308+
printf "\t%s\t%g\t%g\r" new_name, nRows, nCols
309+
310+
make /o/d /n=(nRows) $new_name
311+
wave output=$new_name
312+
313+
make /o/d /n=(nRows) temp=0
314+
315+
for (i=0 ; i<nCols ; i=i+1)
316+
temp=temp+input [p][(i)]
317+
endfor
318+
319+
output=temp / nCols
320+
321+
killwaves /Z temp
322+
323+
end
324+
325+
// -------------------------------------------------------------------------------
326+
// -------------------------------------------------------------------------------
327+
328+
// set points in input 1D wavto nan, for points where mask has values == 0
329+
// returns wave reference
330+
STATIC function /WAVE set_nan_correspond_to_mask (input, mask)
331+
wave input
332+
wave mask
333+
334+
variable nRows=dimsize (input, 0)
335+
variable i
336+
337+
for (i=0 ; i<nRows ; i=i+1)
338+
if (mask[i]==0)
339+
input[i] = nan
340+
endif
341+
342+
endfor
343+
return input
344+
end
345+
// -------------------------------------------------------------------------------
346+
// -------------------------------------------------------------------------------

0 commit comments

Comments
 (0)