1 /* sfweight.cpp: structure factor weighting implementation */
2 //C Copyright (C) 2000-2006 Kevin Cowtan and University of York
3 //L
4 //L This library is free software and is distributed under the terms
5 //L and conditions of version 2.1 of the GNU Lesser General Public
6 //L Licence (LGPL) with the following additional clause:
7 //L
8 //L `You may also combine or link a "work that uses the Library" to
9 //L produce a work containing portions of the Library, and distribute
10 //L that work under terms of your choice, provided that you give
11 //L prominent notice with each copy of the work that the specified
12 //L version of the Library is used in it, and that you include or
13 //L provide public access to the complete corresponding
14 //L machine-readable source code for the Library including whatever
15 //L changes were used in the work. (i.e. If you make changes to the
16 //L Library you must distribute those, but you do not need to
17 //L distribute source or object code to those portions of the work
18 //L not covered by this licence.)'
19 //L
20 //L Note that this clause grants an additional right and does not impose
21 //L any additional restriction, and so does not affect compatibility
22 //L with the GNU General Public Licence (GPL). If you wish to negotiate
23 //L other terms, please contact the maintainer.
24 //L
25 //L You can redistribute it and/or modify the library under the terms of
26 //L the GNU Lesser General Public License as published by the Free Software
27 //L Foundation; either version 2.1 of the License, or (at your option) any
28 //L later version.
29 //L
30 //L This library is distributed in the hope that it will be useful, but
31 //L WITHOUT ANY WARRANTY; without even the implied warranty of
32 //L MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 //L Lesser General Public License for more details.
34 //L
35 //L You should have received a copy of the CCP4 licence and/or GNU
36 //L Lesser General Public License along with this library; if not, write
37 //L to the CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
38 //L The GNU Lesser General Public can also be obtained by writing to the
39 //L Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
40 //L MA 02111-1307 USA
41
42
43 #include "sfweight.h"
44 #include "../core/hkl_operators.h"
45 #include "../core/resol_targetfn.h"
46
47
48 namespace clipper {
49
50
operator ()(const HKL_class cls,const datatypes::F_sigF<T> & fo0,const datatypes::ABCD<T> & hl0,const datatypes::F_phi<T> & fc0,const ftype & s,const ftype & w,const std::vector<HLterms> & hlterms)51 template<class T> typename SFweight_spline<T>::TargetResult SFweight_spline<T>::TargetFo::operator() ( const HKL_class cls, const datatypes::F_sigF<T>& fo0, const datatypes::ABCD<T>& hl0, const datatypes::F_phi<T>& fc0, const ftype& s, const ftype& w, const std::vector<HLterms>& hlterms )
52 {
53 ftype fo(0.0), fc(0.0), phic(0.0), sfo(1.0);
54 if ( !fo0.missing() ) { fo = fo0.f(); sfo = fo0.sigf(); }
55 if ( !fc0.missing() ) { fc = fc0.f(); phic = fc0.phi(); }
56 const ftype epc = cls.epsilonc();
57 const ftype s2 = s*s;
58 const ftype fo2 = fo*fo;
59 const ftype fc2 = fc*fc;
60 const ftype d = 2.0*sfo*sfo + epc*w;
61 const ftype d2 = d*d;
62 const ftype d3 = d*d2;
63 const ftype d4 = d*d3;
64 const ftype x = 2.0*fo*fc*s/d;
65 ftype i0, di0, ddi0, cf;
66 TargetResult r;
67 if ( cls.centric() ) {
68 i0 = (fabs(x)<10.0) ? log(cosh(x)) : fabs(x)+log(0.5);
69 di0 = tanh(x);
70 ddi0 = 1.0-pow(tanh(x),2);
71 cf = 0.5;
72 } else {
73 i0 = Util::sim_integ(x);
74 di0 = Util::sim(x);
75 ddi0 = Util::sim_deriv(x);
76 cf = 1.0;
77 }
78 r.r = cf*log(d) + (fo2+s2*fc2)/d - i0;
79 r.ds = 2.0*s*fc2/d - (2.0*fo*fc/d)*di0;
80 r.dw = epc*( cf/d - (fo2+s2*fc2)/d2 + (2.0*fo*fc*s/d2)*di0 );
81 r.dss = 2.0*fc2/d - (4.0*fo2*fc2/d2)*ddi0;
82 r.dww = epc*epc*( -cf/d2 + 2.0*(fo2+s2*fc2)/d3
83 - (4.0*fo*fc*s/d3)*di0 - (4.0*fo2*fc2*s2/d4)*ddi0 );
84 r.dsw = epc*( -2.0*s*fc2/d2 + (2.0*fo*fc/d2)*di0
85 + (4.0*fo2*fc2*s/d3)*ddi0 );
86 abcd = datatypes::ABCD<T>( x*cos(phic), x*sin(phic), 0.0, 0.0 );
87 phiw = datatypes::Phi_fom<T>( phic, di0 );
88 return r;
89 }
90
91
operator ()(const HKL_class cls,const datatypes::F_sigF<T> & fo0,const datatypes::ABCD<T> & hl0,const datatypes::F_phi<T> & fc0,const ftype & s,const ftype & w,const std::vector<HLterms> & hlterms)92 template<class T> typename SFweight_spline<T>::TargetResult SFweight_spline<T>::TargetHL::operator() ( const HKL_class cls, const datatypes::F_sigF<T>& fo0, const datatypes::ABCD<T>& hl0, const datatypes::F_phi<T>& fc0, const ftype& s, const ftype& w, const std::vector<HLterms>& hlterms )
93 {
94 ftype fo(0.0), fc(0.0), phic(0.0), sfo(1.0);
95 ftype a0(0.0), b0(0.0), c0(0.0), d0(0.0);
96 if ( !fo0.missing() ) { fo = fo0.f(); sfo = fo0.sigf(); }
97 if ( !fc0.missing() ) { fc = fc0.f(); phic = fc0.phi(); }
98 if ( !hl0.missing() ) { a0=hl0.a(); b0=hl0.b(); c0=hl0.c(); d0=hl0.d(); }
99 const ftype epc = cls.epsilonc();
100 const ftype s2 = s*s;
101 const ftype fo2 = fo*fo;
102 const ftype fc2 = fc*fc;
103 const ftype d = 2.0*sfo*sfo + epc*w;
104 const ftype d2 = d*d;
105 const ftype d3 = d*d2;
106 //const ftype d4 = d*d3;
107 const ftype epcd = epc/d;
108 const ftype sf2 = fo2 + s2*fc2;
109 const ftype xs = 2.0*fo*fc/d;
110 const ftype cosc = cos(phic);
111 const ftype sinc = sin(phic);
112 const ftype hl_a = a0 + xs*s*cosc;
113 const ftype hl_b = b0 + xs*s*sinc;
114 const ftype hl_c = c0;
115 const ftype hl_d = d0;
116 ftype cf = 1.0;
117 int a_zero = 0;
118 int a_step = 1;
119 if ( cls.centric() ) {
120 a_step = hlterms.size()/2;
121 a_zero = Util::intr( ftype(hlterms.size())*cls.allowed()/Util::twopi() );
122 a_zero = Util::mod( a_zero, a_step );
123 cf = 0.5;
124 }
125 ftype an, asum, asum_ds, asum_dss, asum_dw, asum_dww, asum_dsw, asum_a, asum_b;
126 an = asum = asum_ds = asum_dss = asum_dw = asum_dww = asum_dsw = asum_a = asum_b = 0.0;
127 ftype q, q1, q2, e;
128 ftype qmax = sqrt( hl_a*hl_a + hl_b*hl_b );
129 for ( int a = a_zero; a < hlterms.size(); a += a_step ) {
130 const HLterms& trig = hlterms[a];
131 q = hl_a*trig.cosa + hl_b*trig.sina + hl_c*trig.cos2a + hl_d*trig.sin2a;
132 q1 = xs * ( cosc*trig.cosa + sinc*trig.sina );
133 q2 = s * q1;
134 e = exp( q - qmax );
135 an += 1.0;
136 asum += e;
137 asum_ds += e * q1;
138 asum_dss += e * q1*q1;
139 asum_dw += e * ( -q2 )*epcd;
140 asum_dww += e * ( 2.0 + q2 )*q2*epcd*epcd;
141 asum_a += e * trig.cosa;
142 asum_b += e * trig.sina;
143 // asum_dsw += ?;
144 }
145 asum_a /= asum;
146 asum_b /= asum;
147 asum /= an;
148 asum_ds /= an;
149 asum_dss /= an;
150 asum_dw /= an;
151 asum_dww /= an;
152 abcd = datatypes::ABCD<T>( hl_a, hl_b, hl_c, hl_d );
153 phiw = datatypes::Phi_fom<T>( atan2( asum_b, asum_a ),
154 sqrt( asum_a*asum_a + asum_b*asum_b ) );
155 TargetResult r;
156 r.r = cf*log(d) + sf2/d - log( asum ) - qmax;
157 r.ds = (2.0*s*fc2)/d - asum_ds/asum;
158 r.dw = epc*(cf/d-sf2/d2) - asum_dw/asum;
159 r.dss = (2.0*fc2)/d - asum_dss/asum + Util::sqr(asum_ds/asum);
160 r.dww = epc*epc*(-cf/d2+2.0*sf2/d3) - asum_dww/asum + Util::sqr(asum_dw/asum);
161 r.dsw = Util::nan();
162 return r;
163 }
164
165
SFweight_spline(HKL_data<datatypes::F_phi<T>> & fb,HKL_data<datatypes::F_phi<T>> & fd,HKL_data<datatypes::Phi_fom<T>> & phiw,const HKL_data<datatypes::F_sigF<T>> & fo,const HKL_data<datatypes::F_phi<T>> & fc,const HKL_data<datatypes::Flag> & usage,const int n_reflns,const int n_params)166 template<class T> SFweight_spline<T>::SFweight_spline( HKL_data<datatypes::F_phi<T> >& fb, HKL_data<datatypes::F_phi<T> >& fd, HKL_data<datatypes::Phi_fom<T> >& phiw, const HKL_data<datatypes::F_sigF<T> >& fo, const HKL_data<datatypes::F_phi<T> >& fc, const HKL_data<datatypes::Flag>& usage, const int n_reflns, const int n_params )
167 {
168 init( n_reflns, n_params );
169 (*this)( fb, fd, phiw, fo, fc, usage );
170 }
171
172
init(const int n_reflns,const int n_params,const int n_phases)173 template<class T> void SFweight_spline<T>::init( const int n_reflns, const int n_params, const int n_phases ) {
174 nreflns = n_reflns;
175 nparams = n_params;
176 hlterms.resize( n_phases );
177 for ( int a = 0; a < hlterms.size(); a++ ) {
178 ftype phi = ( Util::twopi() * ftype(a)/ftype(hlterms.size()) );
179 hlterms[a].cosa = cos(phi);
180 hlterms[a].sina = sin(phi);
181 hlterms[a].cos2a = cos(2.0*phi);
182 hlterms[a].sin2a = sin(2.0*phi);
183 }
184 }
185
186
operator ()(HKL_data<datatypes::F_phi<T>> & fb,HKL_data<datatypes::F_phi<T>> & fd,HKL_data<datatypes::Phi_fom<T>> & phiw,const HKL_data<datatypes::F_sigF<T>> & fo0,const HKL_data<datatypes::F_phi<T>> & fc0,const HKL_data<datatypes::Flag> & usage)187 template<class T> bool SFweight_spline<T>::operator() ( HKL_data<datatypes::F_phi<T> >& fb, HKL_data<datatypes::F_phi<T> >& fd, HKL_data<datatypes::Phi_fom<T> >& phiw, const HKL_data<datatypes::F_sigF<T> >& fo0, const HKL_data<datatypes::F_phi<T> >& fc0, const HKL_data<datatypes::Flag>& usage )
188 {
189 TargetFo tgt;
190 HKL_data<datatypes::ABCD<T> > hl0( fo0.hkl_info() ), hl( fo0.hkl_info() );
191 return evaluate( fb, fd, phiw, hl, fo0, hl0, fc0, usage, tgt );
192 }
193
194
operator ()(HKL_data<datatypes::F_phi<T>> & fb,HKL_data<datatypes::F_phi<T>> & fd,HKL_data<datatypes::Phi_fom<T>> & phiw,HKL_data<datatypes::ABCD<T>> & hl,const HKL_data<datatypes::F_sigF<T>> & fo0,const HKL_data<datatypes::ABCD<T>> & hl0,const HKL_data<datatypes::F_phi<T>> & fc0,const HKL_data<datatypes::Flag> & usage)195 template<class T> bool SFweight_spline<T>::operator() ( HKL_data<datatypes::F_phi<T> >& fb, HKL_data<datatypes::F_phi<T> >& fd, HKL_data<datatypes::Phi_fom<T> >& phiw, HKL_data<datatypes::ABCD<T> >& hl, const HKL_data<datatypes::F_sigF<T> >& fo0, const HKL_data<datatypes::ABCD<T> >& hl0, const HKL_data<datatypes::F_phi<T> >& fc0, const HKL_data<datatypes::Flag>& usage )
196 {
197 TargetHL tgt;
198 return evaluate( fb, fd, phiw, hl, fo0, hl0, fc0, usage, tgt );
199 }
200
201
evaluate(HKL_data<datatypes::F_phi<T>> & fb,HKL_data<datatypes::F_phi<T>> & fd,HKL_data<datatypes::Phi_fom<T>> & phiw,HKL_data<datatypes::ABCD<T>> & hl,const HKL_data<datatypes::F_sigF<T>> & fo0,const HKL_data<datatypes::ABCD<T>> & hl0,const HKL_data<datatypes::F_phi<T>> & fc0,const HKL_data<datatypes::Flag> & usage,F tgt)202 template<class T> template<class F> bool SFweight_spline<T>::evaluate( HKL_data<datatypes::F_phi<T> >& fb, HKL_data<datatypes::F_phi<T> >& fd, HKL_data<datatypes::Phi_fom<T> >& phiw, HKL_data<datatypes::ABCD<T> >& hl, const HKL_data<datatypes::F_sigF<T> >& fo0, const HKL_data<datatypes::ABCD<T> >& hl0, const HKL_data<datatypes::F_phi<T> >& fc0, const HKL_data<datatypes::Flag>& usage, F tgt )
203 {
204 const HKL_info& hkls = fo0.base_hkl_info();
205 typedef clipper::HKL_info::HKL_reference_index HRI;
206 bool status = false;
207
208 // count reflections and determine number of params
209 HKL_data<datatypes::Flag_bool> flag(hkls);
210 for ( HRI ih = flag.first(); !ih.last(); ih.next() )
211 flag[ih].flag() = (!fo0[ih].missing()) && (!fc0[ih].missing()) &&
212 (usage[ih].flag()!=SFweight_base<T>::NONE);
213 int npar_sig = num_params( flag );
214 int npar_scl = npar_sig;
215 while ( npar_scl < 12 ) npar_scl *= 2;
216
217 // prepare function
218 BasisFn_spline basisfn( flag, npar_sig, 1.0 );
219 BasisFn_spline basissc( flag, npar_scl, 1.0 );
220 BasisFn_base::Fderiv dsdp, dwdp;
221 TargetResult fn;
222 scale_fo.resize( hkls.num_reflections() );
223 scale_fc.resize( hkls.num_reflections() );
224 value_s.resize( hkls.num_reflections() );
225 value_w.resize( hkls.num_reflections() );
226
227 // create E's for scaling
228 HKL_data<datatypes::E_sigE<T> > eo( hkls ), ec( hkls );
229 for ( HRI ih = fo0.first(); !ih.last(); ih.next() ) {
230 eo[ih].E() = fo0[ih].f() / sqrt( ih.hkl_class().epsilon() );
231 ec[ih].E() = fc0[ih].f() / sqrt( ih.hkl_class().epsilon() );
232 eo[ih].sigE() = ec[ih].sigE() = 1.0;
233 }
234 // calc scale
235 std::vector<ftype> param_fo( basissc.num_params(), 1.0 );
236 TargetFn_scaleEsq<datatypes::E_sigE<T> > tfn_fo( eo );
237 ResolutionFn rfn_fo( hkls, basissc, tfn_fo, param_fo );
238 param_fo = rfn_fo.params();
239 std::vector<ftype> param_fc( basissc.num_params(), 1.0 );
240 TargetFn_scaleEsq<datatypes::E_sigE<T> > tfn_fc( ec );
241 ResolutionFn rfn_fc( hkls, basissc, tfn_fc, param_fc );
242 param_fc = rfn_fc.params();
243
244 // prescale Fo, Fc
245 HKL_data<datatypes::F_sigF<T> > fo = fo0;
246 HKL_data<datatypes::F_phi<T> > fc = fc0;
247 for ( HRI ih = fo0.first(); !ih.last(); ih.next() ) {
248 scale_fo[ ih.index() ] = sqrt( basissc.f_s( ih.invresolsq(), param_fo ) );
249 scale_fc[ ih.index() ] = sqrt( basissc.f_s( ih.invresolsq(), param_fc ) );
250 fo[ih].scale( scale_fo[ ih.index() ] );
251 fc[ih].scale( scale_fc[ ih.index() ] );
252 }
253
254 // make first estimate of s
255 param_s = std::vector<ftype>( npar_sig, 1.0 );
256
257 // make first estimate of w
258 HKL_data<datatypes::F_sigF<T> > ftmp( hkls );
259 for ( HRI ih = flag.first(); !ih.last(); ih.next() ) if ( flag[ih].flag() )
260 ftmp[ih].f() = ftmp[ih].sigf() =
261 pow( fo[ih].f() - sqrt(basisfn.f_s(ih.invresolsq(),param_s))*fc[ih].f(), 2.0 ) / ih.hkl_class().epsilonc();
262 TargetFn_meanFnth<datatypes::F_sigF<T> > target_w( ftmp, 1.0 );
263 ResolutionFn rfn2( hkls, basisfn, target_w, param_w );
264 param_w = rfn2.params();
265 //for ( int i = 0; i < npar_sig; i++ ) std::cout << i << " " << param_s[i] << " \t" << param_w[i] << "\n";
266
267 // smooth the error term
268 for ( int i = 0; i < npar_sig-1; i++ )
269 param_w[i] = Util::max( param_w[i], 0.5*param_w[i+1] );
270 //for ( int i = 0; i < npar_sig; i++ ) std::cout << i << " " << param_s[i] << " \t" << param_w[i] << "\n";
271
272 ftype ll, ll_old = 1.0e30;
273 // now 25 cycles to refine s and w
274 int c = 0, clim = 25;
275 for ( c = 0; c < clim; c++ ) {
276 std::vector<ftype> grad_s( npar_sig, 0.0 ), shft_s( npar_sig, 0.0 );
277 std::vector<ftype> grad_w( npar_sig, 0.0 ), shft_w( npar_sig, 0.0 );
278 Matrix<ftype> curv_s( npar_sig, npar_sig, 0.0 );
279 Matrix<ftype> curv_w( npar_sig, npar_sig, 0.0 );
280 ll = 0.0;
281
282 // build matrices
283 for ( HRI ih = flag.first(); !ih.last(); ih.next() ) if ( flag[ih].flag() ) {
284 dsdp = basisfn.fderiv_s( ih.invresolsq(), param_s );
285 dwdp = basisfn.fderiv_s( ih.invresolsq(), param_w );
286 fn = tgt( ih.hkl_class(), fo[ih], hl0[ih], fc[ih], dsdp.f, dwdp.f, hlterms );
287 //if ( Util::isnan(fn.r) ) std::cout << ih.hkl().format() << fo[ih].f() << " " << fo[ih].sigf() << " " << fc[ih].f() << " " << fc[ih].missing() << flag[ih].missing() << " " << hl0[ih].a() << " " << hl0[ih].b() << " " << hl0[ih].c() << " " << hl0[ih].d() << " " << dsdp.f << " " << dwdp.f << " \tFo,SIGo,Fc,missing\n";
288 ll += fn.r;
289 for ( int i = 0; i < npar_sig; i++ ) {
290 grad_s[i] += fn.ds * dsdp.df[i];
291 grad_w[i] += fn.dw * dwdp.df[i];
292 //for ( int j = 0; j < npar_sig; j++ ) {
293 for ( int j = Util::max(i-1,0); j <= Util::min(i+1,npar_sig-1); j++ ) {
294 curv_s(i,j) += dsdp.df2(i,j)*fn.ds + dsdp.df[i]*dsdp.df[j]*fn.dss;
295 curv_w(i,j) += dwdp.df2(i,j)*fn.dw + dwdp.df[i]*dwdp.df[j]*fn.dww;
296 }
297 }
298 }
299 //std::cout << c << "\t" << ll << "\n";
300
301 if ( ll > ll_old ) break; // break on divergence
302
303 shft_s = curv_s.solve( grad_s );
304 shft_w = curv_w.solve( grad_w );
305 for ( int i = 0; i < npar_sig; i++ ) {
306 //std::cout << i << " \t" << param_s[i] << " \t" << param_w[i] << " \t" << shft_s[i] << " \t" << shft_w[i] << "\n";
307 // soft buffers to prevent negatives
308 param_s[i] -= Util::min( shft_s[i], 0.25*param_s[i] );
309 param_w[i] -= Util::min( shft_w[i], 0.25*param_w[i] );
310 }
311
312 if ( ll / ll_old > 0.999999 ) { status=true; break; } // break on convergence
313 ll_old = ll;
314 }
315
316 // store s,w
317 for ( HRI ih = fo0.first(); !ih.last(); ih.next() ) {
318 value_s[ih.index()] = basisfn.f_s( ih.invresolsq(), param_s );
319 value_w[ih.index()] = basisfn.f_s( ih.invresolsq(), param_w );
320 }
321
322 // calculate map coeffs and FOM
323 reevaluate( fb, fd, phiw, hl, fo0, hl0, fc0, usage, tgt );
324
325 return status;
326 }
327
328
reevaluate(HKL_data<datatypes::F_phi<T>> & fb,HKL_data<datatypes::F_phi<T>> & fd,HKL_data<datatypes::Phi_fom<T>> & phiw,HKL_data<datatypes::ABCD<T>> & hl,const HKL_data<datatypes::F_sigF<T>> & fo0,const HKL_data<datatypes::ABCD<T>> & hl0,const HKL_data<datatypes::F_phi<T>> & fc0,const HKL_data<datatypes::Flag> & usage,F tgt)329 template<class T> template<class F> bool SFweight_spline<T>::reevaluate( HKL_data<datatypes::F_phi<T> >& fb, HKL_data<datatypes::F_phi<T> >& fd, HKL_data<datatypes::Phi_fom<T> >& phiw, HKL_data<datatypes::ABCD<T> >& hl, const HKL_data<datatypes::F_sigF<T> >& fo0, const HKL_data<datatypes::ABCD<T> >& hl0, const HKL_data<datatypes::F_phi<T> >& fc0, const HKL_data<datatypes::Flag>& usage, F tgt )
330 {
331 typedef clipper::HKL_info::HKL_reference_index HRI;
332
333 // prepare function
334 TargetResult fn;
335 datatypes::F_sigF<T> fo;
336 datatypes::F_phi<T> fc, twomfo, mfo, dfc, fzero(0.0,0.0);
337
338 // calculate map coeffs and FOM
339 llw = llf = 0.0;
340 for ( HRI ih = fo0.first(); !ih.last(); ih.next() ) {
341 // prescale Fo, Fc
342 fo = fo0[ih];
343 fc = fc0[ih];
344 fo.scale( scale_fo[ih.index()] );
345 fc.scale( scale_fc[ih.index()] );
346 // get params an llk
347 const ftype s = value_s[ih.index()];
348 const ftype w = value_w[ih.index()];
349 fn = tgt( ih.hkl_class(), fo, hl0[ih], fc, s, w, hlterms );
350 hl[ih] = tgt.abcd;
351 phiw[ih] = tgt.phiw;
352 mfo = datatypes::F_phi<T>( tgt.phiw.fom() * fo.f(), tgt.phiw.phi() );
353 twomfo = datatypes::F_phi<T>( 2.0 * mfo.f(), mfo.phi() );
354 dfc = datatypes::F_phi<T>( s * fc.f(), fc.phi() );
355 if ( (!fo.missing()) && (!fc.missing()) ) {
356 if ( usage[ih].flag()==SFweight_base<T>::BOTH ) llw += fn.r;
357 else if ( usage[ih].flag()==SFweight_base<T>::NONE ) llf += fn.r;
358 }
359 // deal with all possibilities of missing and non-missing
360 if ( !fc.missing() ) {
361 if ( !fo.missing() ) {
362 fb[ih] = twomfo - dfc;
363 fd[ih] = mfo - dfc;
364 } else {
365 fb[ih] = dfc;
366 fd[ih] = fzero;
367 }
368 } else {
369 if ( !fo.missing() ) {
370 fb[ih] = mfo;
371 fd[ih] = fzero;
372 } else {
373 fb[ih] = fzero;
374 fd[ih] = fzero;
375 }
376 }
377 // undo scaling on fb, fd
378 fb[ih].scale( 1.0/scale_fo[ih.index()] );
379 fd[ih].scale( 1.0/scale_fo[ih.index()] );
380 }
381
382 return true;
383 }
384
385
targetfn(const HKL_class cls,const datatypes::F_sigF<T> & fo0,const datatypes::F_phi<T> & fc0,const ftype & s,const ftype & w) const386 template<class T> typename SFweight_spline<T>::TargetResult SFweight_spline<T>::targetfn( const HKL_class cls, const datatypes::F_sigF<T>& fo0, const datatypes::F_phi<T>& fc0, const ftype& s, const ftype& w ) const
387 {
388 const datatypes::ABCD<T> hl0;
389 TargetFo tgt;
390 return tgt( cls, fo0, hl0, fc0, s, w, hlterms );
391 }
392
393
targethl(const HKL_class cls,const datatypes::F_sigF<T> & fo0,const datatypes::ABCD<T> & hl0,const datatypes::F_phi<T> & fc0,const ftype & s,const ftype & w) const394 template<class T> typename SFweight_spline<T>::TargetResult SFweight_spline<T>::targethl( const HKL_class cls, const datatypes::F_sigF<T>& fo0, const datatypes::ABCD<T>& hl0, const datatypes::F_phi<T>& fc0, const ftype& s, const ftype& w ) const
395 {
396 TargetHL tgt;
397 return tgt( cls, fo0, hl0, fc0, s, w, hlterms );
398 }
399
400
num_params(const HKL_data<datatypes::Flag_bool> & flag) const401 template<class T> int SFweight_spline<T>::num_params( const HKL_data<datatypes::Flag_bool>& flag ) const
402 {
403 int npar;
404 int n_use = flag.num_obs();
405 if ( nparams == 0 ) {
406 npar = Util::max( n_use / nreflns, 2 );
407 } else if ( nreflns == 0 ) {
408 npar = nparams;
409 } else {
410 ftype np1 = ftype(nparams+0.499);
411 ftype np2 = ftype(n_use) / ftype(nreflns);
412 ftype np = sqrt( np1*np1*np2*np2 / ( np1*np1+np2*np2 ) );
413 npar = Util::max( int(np), 2 );
414 }
415 return npar;
416 }
417
418
debug() const419 template<class T> void SFweight_spline<T>::debug() const
420 {
421 TargetResult r00, r01, r10, r11, rxx;
422 Spacegroup p1( Spacegroup::P1 );
423 HKL_class cls;
424 datatypes::F_sigF<T> fo;
425 datatypes::F_phi<T> fc;
426 fo.f() = 10.0; fo.sigf() = 2.0;
427 fc.f() = 15.0; fc.phi() = 0.0;
428 fo.sigf() = 0.0; //!!!!!
429 ftype ds = 0.000001;
430 ftype dw = 0.000001;
431 datatypes::ABCD<T> hl( 0.0, 0.0, 0.0, 0.0 );
432 for ( int h = 0; h < 2; h++ ) {
433 cls = HKL_class( p1, HKL( h, 0, 0 ) );
434 std::cout << "\nCentric? " << cls.centric() << " epsc " << cls.epsilonc() << "\n";
435 for ( ftype w = 10.0; w < 1000.0; w *= 3.0 )
436 for ( ftype s = 0.4; s < 2.0; s *= 2.0 ) {
437
438 rxx = targethl( cls, fo, hl, fc, s, w );
439 r00 = targetfn( cls, fo, fc, s, w );
440 r01 = targetfn( cls, fo, fc, s, w+dw );
441 r10 = targetfn( cls, fo, fc, s+ds, w );
442 r11 = targetfn( cls, fo, fc, s+ds, w+dw );
443
444 std::cout << w << " " << s << "\t" << r00.r << " " << r01.r << " " << r10.r << " " << r11.r << " " << rxx.r << "\n";
445 std::cout << (r10.r-r00.r)/ds << "\t" << r00.ds << "\n";
446 std::cout << (r01.r-r00.r)/dw << "\t" << r00.dw << "\n";
447 std::cout << (r10.ds-r00.ds)/ds << "\t" << r00.dss << "\n";
448 std::cout << (r01.dw-r00.dw)/dw << "\t" << r00.dww << "\n";
449 std::cout << (r01.ds-r00.ds)/dw << "\t" << r00.dsw << "\n";
450 std::cout << (r10.dw-r00.dw)/ds << "\t" << r00.dsw << "\n";
451 }
452 }
453 for ( int h = 0; h < 2; h++ ) {
454 cls = HKL_class( p1, HKL( h, 0, 0 ) );
455 std::cout << "\nCentric? " << cls.centric() << " epsc " << cls.epsilonc() << "\n";
456 for ( ftype w = 10.0; w < 1000.0; w *= 3.0 )
457 for ( ftype s = 0.4; s < 2.0; s *= 2.0 ) {
458
459 rxx = targetfn( cls, fo, fc, s, w );
460 r00 = targethl( cls, fo, hl, fc, s, w );
461 r01 = targethl( cls, fo, hl, fc, s, w+dw );
462 r10 = targethl( cls, fo, hl, fc, s+ds, w );
463 r11 = targethl( cls, fo, hl, fc, s+ds, w+dw );
464
465 std::cout << w << " " << s << "\t" << r00.r << " " << r01.r << " " << r10.r << " " << r11.r << " " << rxx.r << "\n";
466 std::cout << (r10.r-r00.r)/ds << "\t" << r00.ds << "\n";
467 std::cout << (r01.r-r00.r)/dw << "\t" << r00.dw << "\n";
468 std::cout << (r10.ds-r00.ds)/ds << "\t" << r00.dss << "\n";
469 std::cout << (r01.dw-r00.dw)/dw << "\t" << r00.dww << "\n";
470 std::cout << (r01.ds-r00.ds)/dw << "\t" << r00.dsw << "\n";
471 std::cout << (r10.dw-r00.dw)/ds << "\t" << r00.dsw << "\n";
472 }
473 }
474 }
475
476
477 // compile templates
478
479 template class SFweight_spline<ftype32>;
480
481 template class SFweight_spline<ftype64>;
482
483
484 } // namespace clipper
485