-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfitPatternObject.pro
More file actions
executable file
·322 lines (294 loc) · 9.97 KB
/
fitPatternObject.pro
File metadata and controls
executable file
·322 lines (294 loc) · 9.97 KB
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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
; *******************************************************************
; Polydefix stress, strain, and texture analysis for experiment in
; angle dispersive geometry
; Copyright (C) 2000-2011 S. Merkel, Universite Lille 1
; http://merkel.zoneo.net/Multifit/
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version 2
; of the License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; *******************************************************************
COMPILE_OPT IDL2
PRO FitPatternObject__DEFINE
struct = { FitPatternObject, nsubpat:0, peakprofile: 0, subpatterns: PTR_NEW() }
END
; basic init method
function FitPatternObject::Init
return, 1
end
; Cleanup method
pro FitPatternObject::Cleanup
end
; Use the fit results to build a synthetic dataset.
; send
; + the array of azimuth angles
; + the array of 2theta
; + the number of azimuth angles
; + the number of 2theta values
; If the azimuth angles are different that those in the fit, it will fail!
function FitPatternObject::buildSynthethicData, alpha, twotheta, nalpha, ntheta
builtdata = fltarr(nalpha,ntheta)
for i=0, nalpha-1 do begin
for j=0, self.nsubpat-1 do begin
builtdata(i,*) = builtdata(i,*) + (*(self.subpatterns))(j)->syntheticdata(alpha(i),twotheta,ntheta)
endfor
endfor
return, builtdata
end
; Lattice strain.. Fits a lattice strain equation for one peak with no center correction
function FitPatternObject::latticeStrainFit, i, wavelength
index = self->findPeak(i)
return, (*self.subpatterns)(index[0])->latticeStrainFit(index[1], wavelength)
end
; Lattice strain fit for several peaks, no offset fitting, no beam center correction
function FitPatternObject::latticeStrainFitNoCorr, peaks, wavelength, offsetstart
common fitinfo, npeaks, ndeltapeak, wave, offset
; Extracting data to fit
wave = wavelength
offset = !PI*offsetstart/180.
npeaks = N_ELEMENTS(peaks)
delta = PTRARR(npeaks)
mes2Theta = PTRARR(npeaks)
ndeltapeak = intarr(npeaks)
ndelta = 0
for i=0, npeaks-1 do begin
index = self->findPeak(peaks[i])
delta[i] = ptr_new((*self.subpatterns)(index[0])->getDelta(index[1]))
mes2Theta[i] = ptr_new((*self.subpatterns)(index[0])->getTheta(index[1]))
ndeltapeak[i] = N_ELEMENTS(*delta[i])
ndelta += ndeltapeak[i]
endfor
; For each peak, we fit d0 and Q + 1 parameter for offset
; Starting values are
; - d0: av(d)
; - Q: 0
guess = fltarr(2*npeaks)
for i=1, npeaks do begin
guess[2*(i-1)] = mean(wavelength/(2.*sin(!PI*(*mes2Theta[i-1])/360.))) ; d0 for peak i
guess[2*(i-1)+1] = 0. ; Q for peak i
end
; creating x and y data to fit
x = fltarr(ndelta)
y = fltarr(ndelta)
step = 0
; In order to set the fit data, we simply put all 2theta vs. delta one peak after the other-1 do begin
for i=0, npeaks-1 do begin
for j=0, ndeltapeak[i]-1 do begin
x[step] = !PI*(*delta[i])[j]/180.
y[step] = !PI*(*mes2Theta[i])[j]/180.
;
step += 1
endfor
endfor
sigma = 0.0005*(y)
fit = MPFITFUN('LATTICESTRAINMULTIPLEPEAKSNOCORR', x, y, sigma, guess, perror = perror, /quiet)
;for i=1, npeaks do fit[2*i] = wavelength/(2.*sin(fit[2*i]))
return, {fit:fit , perror: perror}
end
; Lattice strain fit for several peaks WITH center correction
function FitPatternObject::latticeStrainFitCenter, peaks, wavelength, offsetstart
common fitinfo, npeaks, ndeltapeak, wave, offset
; Extracting data to fit
wave = wavelength
offset = !PI*offsetstart/180.
npeaks = N_ELEMENTS(peaks)
delta = PTRARR(npeaks)
mes2Theta = PTRARR(npeaks)
ndeltapeak = intarr(npeaks)
ndelta = 0
for i=0, npeaks-1 do begin
index = self->findPeak(peaks[i])
delta[i] = ptr_new((*self.subpatterns)(index[0])->getDelta(index[1]))
mes2Theta[i] = ptr_new((*self.subpatterns)(index[0])->getTheta(index[1]))
ndeltapeak[i] = N_ELEMENTS(*delta[i])
ndelta += ndeltapeak[i]
endfor
; For each peak, we fit d0 and Q + 2 parameters for center correction (x0, y0)
; Starting values are
; - d0: av(d)
; - Q: 0
; - x0: 0
; - y0: 0
guess = fltarr(2*npeaks+2)
guess[0] = 0.001 ; x0
guess[1] = 0.001 ; y0
for i=1, npeaks do begin
guess[2*i] = mean(wavelength/(2.*sin(!PI*(*mes2Theta[i-1])/360.))) ; d0 for peak i
guess[2*i+1] = 0. ; Q for peak i
end
; creating x and y data to fit
x = fltarr(ndelta)
y = fltarr(ndelta)
step = 0
; In order to set the fit data, we simply put all 2theta vs. delta one peak after the other-1 do begin
for i=0, npeaks-1 do begin
for j=0, ndeltapeak[i]-1 do begin
x[step] = !PI*(*delta[i])[j]/180.
y[step] = !PI*(*mes2Theta[i])[j]/180.
;
step += 1
endfor
endfor
sigma = 0.0005*(y)
fit = MPFITFUN('LATTICESTRAINMULTIPLEPEAKSCENTER', x, y, sigma, guess, perror = perror, /quiet)
;for i=1, npeaks do fit[2*i] = wavelength/(2.*sin(fit[2*i]))
return, {fit:fit , perror: perror}
end
; Lattice strain fit for several peaks WITH offset correction
function FitPatternObject::latticeStrainFitOffset, peaks, wavelength, offsetstart
common fitinfo, npeaks, ndeltapeak, wave, offset
; Extracting data to fit
wave = wavelength
npeaks = N_ELEMENTS(peaks)
delta = PTRARR(npeaks)
mes2Theta = PTRARR(npeaks)
ndeltapeak = intarr(npeaks)
ndelta = 0
for i=0, npeaks-1 do begin
index = self->findPeak(peaks[i])
delta[i] = ptr_new((*self.subpatterns)(index[0])->getDelta(index[1]))
mes2Theta[i] = ptr_new((*self.subpatterns)(index[0])->getTheta(index[1]))
ndeltapeak[i] = N_ELEMENTS(*delta[i])
ndelta += ndeltapeak[i]
endfor
; For each peak, we fit d0 and Q + 1 parameter for offset
; Starting values are
; - d0: av(d)
; - Q: 0
; - offset: offsetstart, converted to radians
guess = fltarr(2*npeaks+1)
guess[0] = !PI*offsetstart/180.
for i=1, npeaks do begin
guess[2*(i-1)+1] = mean(wavelength/(2.*sin(!PI*(*mes2Theta[i-1])/360.))) ; d0 for peak i
guess[2*(i-1)+2] = 0. ; Q for peak i
end
; creating x and y data to fit
x = fltarr(ndelta)
y = fltarr(ndelta)
step = 0
; In order to set the fit data, we simply put all 2theta vs. delta one peak after the other-1 do begin
for i=0, npeaks-1 do begin
for j=0, ndeltapeak[i]-1 do begin
x[step] = !PI*(*delta[i])[j]/180.
y[step] = !PI*(*mes2Theta[i])[j]/180.
;
step += 1
endfor
endfor
sigma = 0.0005*(y)
fit = MPFITFUN('LATTICESTRAINMULTIPLEPEAKSOFFSET', x, y, sigma, guess, perror = perror, /quiet)
;for i=1, npeaks do fit[2*i] = wavelength/(2.*sin(fit[2*i]))
return, {fit:fit , perror: perror}
end
; Returns azimtuh angles for peak number i
function FitPatternObject::getDelta, i
index = self->findPeak(i)
return, (*self.subpatterns)(index[0])->getDelta(index[1])
end
; Returns intensities of peak number i
function FitPatternObject::getIntensity, i
index = self->findPeak(i)
return, (*self.subpatterns)(index[0])->getIntensity(index[1])
end
; Returns 2theta of peak number i
function FitPatternObject::getTheta, i
index = self->findPeak(i)
return, (*self.subpatterns)(index[0])->getTheta(index[1])
end
; Returns intensities of peak number i at one angle
function FitPatternObject::getIntensityAtAngle, i, angle
index = self->findPeak(i)
angles = (*self.subpatterns)(index[0])->getDelta(index[1])
intensities = (*self.subpatterns)(index[0])->getIntensity(index[1])
j = WHERE(angles eq angle)
if j eq (-1) then return, !VALUES.F_NAN
return, intensities[j]
end
; Returns half widths of peak number i at one angle.
; Added 05/06/2013 N Hilairet
function FitPatternObject::getPeakWidthAtAngle, i, angle
index = self->findPeak(i)
angles = (*self.subpatterns)(index[0])->getDelta(index[1])
peakwidths = (*self.subpatterns)(index[0])->getHalfWidth(index[1])
j = WHERE(angles eq angle)
if j eq (-1) then return, !VALUES.F_NAN
return, peakwidths[j]
end
; Returns d-spacings for peak number i
; Parameter: wavelength
function FitPatternObject::getDSpacing, i, wavelength
dspacings = wavelength/(2.*sin(!PI*self->getTheta(i)/360.))
return, dspacings
end
; Returns d-spacings for peak number i, with a correct for center of the image plate
; Parameter: wavelength
function FitPatternObject::getDSpacingCorrectCenter, i, wavelength, centerx, centery
r0 = tan(!PI*self->getTheta(i)/180.)
delta = !PI*self->getDelta(i)/180.
r1 = r0 + centerx * cos(delta) + centery * sin(delta)
theta = atan(r1)/2.
dspacings = wavelength/(2.*sin(theta))
return, dspacings
end
; Returns half-width of peak number i
function FitPatternObject::getHalfWidth, i
index = self->findPeak(i)
return, (*self.subpatterns)(index[0])->getHalfWidth(index[1])
end
; returns the number of peaks
function FitPatternObject::getNPeaks
npeaks = 0
for j=0, self.nsubpat-1 do begin
npeaks += (*self.subpatterns)(j)->nPeaks()
endfor
return, npeaks
end
; Locates the supattern and peak number for a peak
function FitPatternObject::findPeak, i
npeaks = fltarr(self.nsubpat)
for j=0, self.nsubpat-1 do begin
npeaks[j] = (*self.subpatterns)(j)->nPeaks()
endfor
total = 0
subpat = -1
while (total lt i+1) do begin
subpat = subpat + 1
total = total + npeaks[subpat]
endwhile
index = fix(i-total+npeaks[subpat])
return, [subpat,index]
end
; Loads results of a fit from an Ascii file
function FitPatternObject::readFromAscii, lun
on_ioerror, bad
; file version
row = readascii(lun, com='#')
if (fix(row) ne 1) then return, 'Sorry, we can only read file format 1 at this time'
; peak profile
row = readascii(lun, com='#')
self.peakprofile = fix(row)
; number of subpatterns
row = readascii(lun, com='#')
self.nsubpat = fix(row)
self.subpatterns = PTR_NEW(OBJARR(self.nsubpat))
; subpatterns
for i=0, self.nsubpat-1 do begin
;print, 'Reading subpattern' + STRING(i, /PRINT)
(*(self.subpatterns))(i) = OBJ_NEW('FitSubPatternObject')
noerror = (*self.subpatterns)(i)->readFromAscii(lun)
if (noerror ne 1) then return, noerror
endfor
RETURN, 1
bad: return, !ERR_STRING
end