Clipper
resol_targetfn.h
00001 
00004 //C Copyright (C) 2000-2006 Kevin Cowtan and University of York
00005 //L
00006 //L  This library is free software and is distributed under the terms
00007 //L  and conditions of version 2.1 of the GNU Lesser General Public
00008 //L  Licence (LGPL) with the following additional clause:
00009 //L
00010 //L     `You may also combine or link a "work that uses the Library" to
00011 //L     produce a work containing portions of the Library, and distribute
00012 //L     that work under terms of your choice, provided that you give
00013 //L     prominent notice with each copy of the work that the specified
00014 //L     version of the Library is used in it, and that you include or
00015 //L     provide public access to the complete corresponding
00016 //L     machine-readable source code for the Library including whatever
00017 //L     changes were used in the work. (i.e. If you make changes to the
00018 //L     Library you must distribute those, but you do not need to
00019 //L     distribute source or object code to those portions of the work
00020 //L     not covered by this licence.)'
00021 //L
00022 //L  Note that this clause grants an additional right and does not impose
00023 //L  any additional restriction, and so does not affect compatibility
00024 //L  with the GNU General Public Licence (GPL). If you wish to negotiate
00025 //L  other terms, please contact the maintainer.
00026 //L
00027 //L  You can redistribute it and/or modify the library under the terms of
00028 //L  the GNU Lesser General Public License as published by the Free Software
00029 //L  Foundation; either version 2.1 of the License, or (at your option) any
00030 //L  later version.
00031 //L
00032 //L  This library is distributed in the hope that it will be useful, but
00033 //L  WITHOUT ANY WARRANTY; without even the implied warranty of
00034 //L  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00035 //L  Lesser General Public License for more details.
00036 //L
00037 //L  You should have received a copy of the CCP4 licence and/or GNU
00038 //L  Lesser General Public License along with this library; if not, write
00039 //L  to the CCP4 Secretary, Daresbury Laboratory, Warrington WA4 4AD, UK.
00040 //L  The GNU Lesser General Public can also be obtained by writing to the
00041 //L  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00042 //L  MA 02111-1307 USA
00043 
00044 
00045 #ifndef CLIPPER_RESOL_TARGETFN
00046 #define CLIPPER_RESOL_TARGETFN
00047 
00048 #include "resol_basisfn.h"
00049 #include "hkl_datatypes.h"
00050 
00051 
00052 namespace clipper {
00053 
00054 
00056 
00064   template<class T> class TargetFn_meanFnth : public TargetFn_base
00065   {
00066   public:
00068     TargetFn_meanFnth( const HKL_data<T>& hkl_data_, const ftype& n );
00070     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00072     FNtype type() const { return QUADRATIC; }
00073   private:
00074     ftype power;
00075     const HKL_data<T>* hkl_data;
00076   };
00077 
00078 
00080 
00088   template<class T> class TargetFn_meanEnth : public TargetFn_base
00089   {
00090   public:
00092     TargetFn_meanEnth( const HKL_data<T>& hkl_data_, const ftype& n );
00094     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00096     FNtype type() const { return QUADRATIC; }
00097   private:
00098     ftype power;
00099     const HKL_data<T>* hkl_data;
00100   };
00101 
00102 
00104 
00108   template<class T1, class T2> class TargetFn_scaleF1F2 : public TargetFn_base
00109   {
00110   public:
00112     TargetFn_scaleF1F2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ );
00114     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00116     FNtype type() const { return QUADRATIC; }
00117   private:
00118     const HKL_data<T1>* hkl_data1;
00119     const HKL_data<T2>* hkl_data2;
00120   };
00121 
00122 
00124 
00132   template<class T1, class T2> class TargetFn_scaleLogF1F2 : public TargetFn_base
00133   {
00134   public:
00136     TargetFn_scaleLogF1F2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ );
00138     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00140     FNtype type() const { return QUADRATIC; }
00141   private:
00142     const HKL_data<T1>* hkl_data1;
00143     const HKL_data<T2>* hkl_data2;
00144   };
00145 
00146 
00151   template<class T1, class T2> class TargetFn_scaleI1I2 : public TargetFn_base
00152   {
00153   public:
00155     TargetFn_scaleI1I2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ );
00157     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00159     FNtype type() const { return QUADRATIC; }
00160   private:
00161     const HKL_data<T1>* hkl_data1;
00162     const HKL_data<T2>* hkl_data2;
00163   };
00164 
00165 
00167 
00175   template<class T1, class T2> class TargetFn_scaleLogI1I2 : public TargetFn_base
00176   {
00177   public:
00179     TargetFn_scaleLogI1I2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ );
00181     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00183     FNtype type() const { return QUADRATIC; }
00184   private:
00185     const HKL_data<T1>* hkl_data1;
00186     const HKL_data<T2>* hkl_data2;
00187   };
00188 
00189 
00191 
00197   template<class T> class TargetFn_scaleEsq : public TargetFn_base
00198   {
00199   public:
00201     TargetFn_scaleEsq( const HKL_data<T>& hkl_data_ );
00203     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const;
00205     FNtype type() const { return QUADRATIC; }
00206   private:
00207     const HKL_data<T>* hkl_data;
00208   };
00209 
00210 
00212 
00229   template<class T> class TargetFn_sigmaa_omegaa : public TargetFn_base
00230   {
00231   public:
00233     TargetFn_sigmaa_omegaa( const HKL_data<T>& eo, const HKL_data<T>& ec );
00235     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& omegaa ) const;
00237     static ftype sigmaa( const ftype& omegaa )
00238     {
00239       ftype omeg = (omegaa>0.05) ? omegaa : (0.05*exp(omegaa/0.05-1.0));
00240       return 0.5 * ( sqrt( 4.0*omeg*omeg + 1.0 ) - 1.0 ) / omeg;
00241     }
00242   private:
00243     const HKL_data<T>* eo_data;
00244     const HKL_data<T>* ec_data;
00245   };
00246 
00247 
00249 
00261   template<class T> class TargetFn_sigmaa : public TargetFn_base
00262   {
00263   public:
00265     TargetFn_sigmaa( const HKL_data<T>& eo, const HKL_data<T>& ec );
00267     Rderiv rderiv( const HKL_info::HKL_reference_index& ih, const ftype& sigmaa0 ) const;
00269     static ftype sigmaa( const ftype& sigm ) { return sigm; }
00270   private:
00271     const HKL_data<T>* eo_data;
00272     const HKL_data<T>* ec_data;
00273   };
00274 
00275 
00276 
00277   // implementations for template functions
00278 
00279   // mean F^nth
00280 
00281   template<class T> TargetFn_meanFnth<T>::TargetFn_meanFnth( const HKL_data<T>& hkl_data_, const ftype& n )
00282   {
00283     power = n;
00284     hkl_data = &hkl_data_;
00285   }
00286 
00287   template<class T> TargetFn_base::Rderiv TargetFn_meanFnth<T>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00288   {
00289     Rderiv result;
00290     const HKL_data<T>& data = *hkl_data;
00291     if ( !data[ih].missing() ) {
00292       ftype d = fh - pow( ftype(data[ih].f()) / sqrt(ih.hkl_class().epsilon()),
00293                           power );
00294       result.r = d * d;
00295       result.dr = 2.0 * d;
00296       result.dr2 = 2.0;
00297     } else {
00298       result.r = result.dr = result.dr2 = 0.0;
00299     }
00300     return result;
00301   }
00302 
00303   // mean E^nth
00304 
00305   template<class T> TargetFn_meanEnth<T>::TargetFn_meanEnth( const HKL_data<T>& hkl_data_, const ftype& n )
00306   {
00307     power = n;
00308     hkl_data = &hkl_data_;
00309   }
00310 
00311   template<class T> TargetFn_base::Rderiv TargetFn_meanEnth<T>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00312   {
00313     Rderiv result;
00314     const HKL_data<T>& data = *hkl_data;
00315     if ( !data[ih].missing() ) {
00316       ftype d = fh - pow( ftype(data[ih].E()), power );
00317       result.r = d * d;
00318       result.dr = 2.0 * d;
00319       result.dr2 = 2.0;
00320     } else {
00321       result.r = result.dr = result.dr2 = 0.0;
00322     }
00323     return result;
00324   }
00325 
00326   // F1-F2 scaling
00327 
00328   template<class T1, class T2> TargetFn_scaleF1F2<T1,T2>::TargetFn_scaleF1F2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ )
00329   {
00330     hkl_data1 = &hkl_data1_;
00331     hkl_data2 = &hkl_data2_;
00332   }
00333 
00334   template<class T1, class T2> TargetFn_base::Rderiv TargetFn_scaleF1F2<T1,T2>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00335   {
00336     Rderiv result;
00337     const T1& ft1 = (*hkl_data1)[ih];
00338     const T2& ft2 = (*hkl_data2)[ih];
00339     if ( !ft1.missing() && !ft2.missing() ) {
00340       const ftype eps = ih.hkl_class().epsilon();
00341       const ftype f1 = pow( ft1.f(), 2 ) / eps;
00342       const ftype f2 = pow( ft2.f(), 2 ) / eps;
00343       const ftype d = fh*f1 - f2;
00344       result.r = d * d / f1;
00345       result.dr = 2.0 * d;
00346       result.dr2 = 2.0 * f1;
00347     } else {
00348       result.r = result.dr = result.dr2 = 0.0;
00349     }
00350     return result;
00351   }
00352 
00353   // Log F1-F2 scaling
00354 
00355   template<class T1, class T2> TargetFn_scaleLogF1F2<T1,T2>::TargetFn_scaleLogF1F2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ )
00356   {
00357     hkl_data1 = &hkl_data1_;
00358     hkl_data2 = &hkl_data2_;
00359   }
00360 
00361   template<class T1, class T2> TargetFn_base::Rderiv TargetFn_scaleLogF1F2<T1,T2>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00362   {
00363     Rderiv result;
00364     result.r = result.dr = result.dr2 = 0.0;
00365     const T1& ft1 = (*hkl_data1)[ih];
00366     const T2& ft2 = (*hkl_data2)[ih];
00367     if ( !ft1.missing() && !ft2.missing() )
00368       if ( ft1.f() > 1.0e-6 && ft2.f() > 1.0e-6 ) {
00369         const ftype eps = ih.hkl_class().epsilon();
00370         const ftype f1 = pow( ft1.f(), 2 ) / eps;
00371         const ftype f2 = pow( ft2.f(), 2 ) / eps;
00372         const ftype w = 1.0;  // f1 * f2;
00373         const ftype d = fh + log(f1) - log(f2);
00374         result.r   =       w * d * d;
00375         result.dr  = 2.0 * w * d;
00376         result.dr2 = 2.0 * w;
00377     }
00378     return result;
00379   }
00380 
00381   // I1-I2 scaling
00382 
00383   template<class T1, class T2> TargetFn_scaleI1I2<T1,T2>::TargetFn_scaleI1I2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ )
00384   {
00385     hkl_data1 = &hkl_data1_;
00386     hkl_data2 = &hkl_data2_;
00387   }
00388 
00389   template<class T1, class T2> TargetFn_base::Rderiv TargetFn_scaleI1I2<T1,T2>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00390   {
00391     Rderiv result;
00392     const T1& ft1 = (*hkl_data1)[ih];
00393     const T2& ft2 = (*hkl_data2)[ih];
00394     if ( !ft1.missing() && !ft2.missing() ) {
00395       const ftype eps = ih.hkl_class().epsilon();
00396       const ftype f1 = ft1.I() / eps;
00397       const ftype f2 = ft2.I() / eps;
00398       const ftype d = fh*f1 - f2;
00399       result.r = d * d / f1;
00400       result.dr = 2.0 * d;
00401       result.dr2 = 2.0 * f1;
00402     } else {
00403       result.r = result.dr = result.dr2 = 0.0;
00404     }
00405     return result;
00406   }
00407 
00408   // Log I1-I2 scaling
00409 
00410   template<class T1, class T2> TargetFn_scaleLogI1I2<T1,T2>::TargetFn_scaleLogI1I2( const HKL_data<T1>& hkl_data1_, const HKL_data<T2>& hkl_data2_ )
00411   {
00412     hkl_data1 = &hkl_data1_;
00413     hkl_data2 = &hkl_data2_;
00414   }
00415 
00416   template<class T1, class T2> TargetFn_base::Rderiv TargetFn_scaleLogI1I2<T1,T2>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00417   {
00418     Rderiv result;
00419     result.r = result.dr = result.dr2 = 0.0;
00420     const T1& ft1 = (*hkl_data1)[ih];
00421     const T2& ft2 = (*hkl_data2)[ih];
00422     if ( !ft1.missing() && !ft2.missing() )
00423       if ( ft1.I() > 1.0e-6 && ft2.I() > 1.0e-6 ) {
00424         const ftype eps = ih.hkl_class().epsilon();
00425         const ftype f1 = ft1.I() / eps;
00426         const ftype f2 = ft2.I() / eps;
00427         const ftype w = 1.0;  // f1 * f2;
00428         const ftype d = fh + log(f1) - log(f2);
00429         result.r   =       w * d * d;
00430         result.dr  = 2.0 * w * d;
00431         result.dr2 = 2.0 * w;
00432     }
00433     return result;
00434   }
00435 
00436   // E^2 scaling
00437 
00438   template<class T> TargetFn_scaleEsq<T>::TargetFn_scaleEsq( const HKL_data<T>& hkl_data_ )
00439   {
00440     hkl_data = &hkl_data_;
00441   }
00442 
00443   template<class T> TargetFn_base::Rderiv TargetFn_scaleEsq<T>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& fh ) const
00444   {
00445     Rderiv result;
00446     const HKL_data<T>& data = *hkl_data;
00447     const ftype two(2.0);
00448     if ( !data[ih].missing() ) {
00449       ftype fsq = pow( ftype(data[ih].E()), two );
00450       ftype d = fsq * fh - 1.0;
00451       result.r = d * d / fsq;
00452       result.dr = two * d;
00453       result.dr2 = two * fsq;
00454     } else {
00455       result.r = result.dr = result.dr2 = 0.0;
00456     }
00457     return result;
00458   }
00459 
00460 
00461   // sigmaa (omegaa)
00462 
00463   template<class T> TargetFn_sigmaa_omegaa<T>::TargetFn_sigmaa_omegaa( const HKL_data<T>& eo, const HKL_data<T>& ec )
00464   {
00465     eo_data = &eo;
00466     ec_data = &ec;
00467   }
00468 
00469   template<class T> TargetFn_base::Rderiv TargetFn_sigmaa_omegaa<T>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& omegaa ) const
00470   {
00471     Rderiv result;
00472     
00473     const HKL_data<T>& eodata = *eo_data;
00474     const HKL_data<T>& ecdata = *ec_data;
00475     if ( eodata[ih].missing() || ecdata[ih].missing()  ) {
00476       result.r = result.dr = result.dr2 = 0.0;
00477     } else {
00478       ftype eo = eodata[ih].E();
00479       ftype ec = ecdata[ih].E();
00480       ftype omeg = (omegaa>0.05) ? omegaa : (0.05*exp(omegaa/0.05-1.0));
00481       ftype sigmaa = 0.5*(sqrt(4*omeg*omeg+1)-1)/omeg;
00482       ftype dx = 2.0 * eo * ec;
00483       ftype x = dx * omeg;
00484       ftype t0 = 1.0/(1-sigmaa*sigmaa) + 0.5*log((1-sigmaa*sigmaa));
00485       ftype t1 = sigmaa;
00486       ftype t2 = pow(1-sigmaa*sigmaa,2)/(1+sigmaa*sigmaa);
00487       if ( ih.hkl_class().centric() ) {
00488         result.r = 1.0*t0 - log( cosh( x/2 ) );
00489         result.dr = 1.0*t1 - dx*0.5*tanh( x/2 );
00490         result.dr2 = 1.0*t2 - dx*dx*0.25*(1.0 - pow(tanh(x/2),2) );
00491       } else {
00492         result.r = 2.0*t0 - Util::sim_integ( x );
00493         result.dr = 2.0*t1 - dx*Util::sim( x );
00494         result.dr2 = 2.0*t2 - dx*dx*Util::sim_deriv( x );
00495       }
00496       if ( omegaa < 0.05 ) {
00497         ftype dy = exp( omegaa/0.05 ) / exp( 1.0 );
00498         ftype dy2 = exp( omegaa/0.05 ) / ( 0.05*exp( 1.0 ) );
00499         result.dr2 = result.dr*dy2 + result.dr2*dy*dy;
00500         result.dr = result.dr*dy;
00501       }
00502     }
00503     return result;
00504   }
00505 
00506 
00507   // sigmaa (norm)
00508 
00509   template<class T> TargetFn_sigmaa<T>::TargetFn_sigmaa( const HKL_data<T>& eo, const HKL_data<T>& ec )
00510   {
00511     eo_data = &eo;
00512     ec_data = &ec;
00513   }
00514 
00515   template<class T> TargetFn_base::Rderiv TargetFn_sigmaa<T>::rderiv( const HKL_info::HKL_reference_index& ih, const ftype& sigmaa0 ) const
00516   {
00517     Rderiv result;
00518     
00519     const HKL_data<T>& eodata = *eo_data;
00520     const HKL_data<T>& ecdata = *ec_data;
00521     if ( eodata[ih].missing() || ecdata[ih].missing()  ) {
00522       result.r = result.dr = result.dr2 = 0.0;
00523     } else {
00524       ftype eo = eodata[ih].E();
00525       ftype ec = ecdata[ih].E();
00526       ftype sigmaa = (sigmaa0>0.99)?(0.99):((sigmaa0<0.01)?0.01:sigmaa0);
00527       ftype dx = 2.0 * eo * ec;
00528       ftype x = dx * sigmaa/(1-sigmaa*sigmaa);
00529       ftype t0 = 1.0/(1-sigmaa*sigmaa) + 0.5*log((1-sigmaa*sigmaa));
00530       ftype t1 = sigmaa;
00531       ftype t2 = pow(1-sigmaa*sigmaa,2)/(1+sigmaa*sigmaa);
00532       if ( ih.hkl_class().centric() ) {
00533         result.r = 1.0*t0 - log( cosh( x/2 ) );
00534         result.dr = 1.0*t1 - dx*0.5*tanh( x/2 );
00535         result.dr2 = 1.0*t2 - dx*dx*0.25*(1.0 - pow(tanh(x/2),2) );
00536       } else {
00537         result.r = 2.0*t0 - Util::sim_integ( x );
00538         result.dr = 2.0*t1 - dx*Util::sim( x );
00539         result.dr2 = 2.0*t2 - dx*dx*Util::sim_deriv( x );
00540       }
00541       ftype ds = (1+sigmaa*sigmaa)/pow(1-sigmaa*sigmaa,2);
00542       ftype ds2 = 2*sigmaa*(3+sigmaa*sigmaa)/pow(1-sigmaa*sigmaa,3);
00543       result.dr2 = result.dr*ds2 + result.dr2*ds*ds;
00544       result.dr = result.dr*ds;
00545     }
00546     return result;
00547   }
00548 
00549 
00550 } // namespace clipper
00551 
00552 #endif