Clipper
|
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_XMAP 00046 #define CLIPPER_XMAP 00047 00048 00049 #include "fftmap.h" 00050 #include "fftmap_sparse.h" 00051 #include "derivs.h" 00052 00053 00054 namespace clipper 00055 { 00056 00057 class Xmap_cacheobj 00058 { 00059 public: 00060 class Key 00061 { 00062 public: 00063 Key( const Spgr_descr& spgr_descr, const Grid_sampling& grid ) : 00064 spgr_descr_(spgr_descr), grid_sampling_(grid) {} 00065 const Spgr_descr& spgr_descr() const { return spgr_descr_; } 00066 const Grid_sampling& grid_sampling() const { return grid_sampling_; } 00067 private: 00068 Spgr_descr spgr_descr_; 00069 Grid_sampling grid_sampling_; 00070 }; 00071 00072 Xmap_cacheobj( const Key& xmap_cachekey ); 00073 bool matches( const Key& xmap_cachekey ) const; 00074 String format() const; 00075 // data 00076 Key key; 00077 Grid_sampling xtl_grid; 00078 Grid_range asu_grid; 00079 Grid_range map_grid; 00080 int nsym; // number of symops 00081 std::vector<unsigned char> asu; 00082 std::vector<Isymop> isymop; 00083 std::vector<int> du, dv, dw; 00084 Array2d<unsigned char> symperm; 00085 Mat33<> mat_grid_orth; 00086 static Mutex mutex; 00087 }; 00088 00089 00091 00100 class Xmap_base 00101 { 00102 public: 00103 enum FFTtype { Default, Normal, Sparse }; 00104 00106 bool is_null() const; 00107 00109 const Cell& cell() const { return cell_; } 00111 const Spacegroup& spacegroup() const { return spacegroup_; } 00113 const Grid_sampling& grid_sampling() const { return grid_sam_; } 00115 const Grid_range& grid_asu() const { return cacheref.data().asu_grid; } 00117 00118 inline Coord_grid coord_of( const int& index ) const 00119 { return cacheref.data().map_grid.deindex( index ); } 00121 00123 inline int index_of( const Coord_grid& coord ) const { 00124 if ( cacheref.data().asu_grid.in_grid( coord ) ) { 00125 const int i = cacheref.data().map_grid.index( coord ); 00126 if ( asu[ i ] == 0 ) return i; 00127 } 00128 return -1; 00129 } 00131 Coord_grid to_map_unit( const Coord_grid& pos ) const 00132 { return pos.unit( grid_sam_ ); } 00133 00135 const RTop<>& operator_orth_grid() const { return rt_orth_grid; } 00137 const RTop<>& operator_grid_orth() const { return rt_grid_orth; } 00139 00141 inline Coord_orth coord_orth( const Coord_map& cm ) const 00142 { return Coord_orth( rt_grid_orth.rot()*cm ); } 00144 00146 inline Coord_map coord_map( const Coord_orth& co ) const 00147 { return Coord_map ( rt_orth_grid.rot()*co ); } 00148 00150 bool in_map( const Coord_grid& ) const { return true; } 00152 template<class I> bool in_map( const Coord_map& cm ) const { return true; } 00153 00155 int multiplicity( const Coord_grid& pos ) const; 00156 00158 00162 class Map_reference_base 00163 { 00164 public: 00166 inline const Xmap_base& base_xmap() const { return *map_; } 00168 inline const int& index() const { return index_; } 00170 bool last() const { return ( index_ >= map_->map_grid.size() ); } 00171 protected: 00173 const Xmap_base* map_; 00175 int index_; 00176 }; 00177 00179 00190 class Map_reference_index : public Map_reference_base 00191 { 00192 public: 00194 Map_reference_index() {} 00196 explicit Map_reference_index( const Xmap_base& map ) 00197 { map_ = ↦ index_=0; next(); } 00199 Map_reference_index( const Xmap_base& map, const Coord_grid& pos ) { map_ = ↦ int sym; map_->find_sym( pos, index_, sym ); } 00201 inline Coord_grid coord() const 00202 { return map_->map_grid.deindex(index_); } 00204 inline const Coord_orth coord_orth() const 00205 { return Coord_orth( map_->rt_grid_orth.rot() * coord().coord_map() ); } 00207 inline Map_reference_index& set_coord( const Coord_grid& pos ) 00208 { int sym; map_->find_sym( pos, index_, sym ); return *this; } 00210 inline Map_reference_index& next() { 00211 do { 00212 index_++; if ( last() ) break; 00213 } while ( map_->asu[index_] != 0 ); 00214 return *this; 00215 } 00217 /* Use for e.g. peak search. Valid for -1 <= du/dv/dw <= 1 only. 00218 \param du/dv/dw Coordinate offset. \return Map index. */ 00219 inline int index_offset(const int& du,const int& dv,const int& dw) const { 00220 int i = index_ + du*map_->du[0] + dv*map_->dv[0] + dw*map_->dw[0]; 00221 if ( map_->asu[i] != 0 ) { i = map_->map_grid.index( map_->to_map_unit( map_->map_grid.deindex(i).transform( map_->isymop[map_->asu[i]-1] ) ) ); } 00222 return i; 00223 } 00224 // inherited functions listed for documentation purposes 00225 //-- const Xmap_base& base_xmap() const; 00226 //-- const int& index() const; 00227 //-- bool last() const; 00228 }; 00229 00231 00242 class Map_reference_coord : public Map_reference_base 00243 { 00244 public: 00246 Map_reference_coord() {} 00248 explicit Map_reference_coord( const Xmap_base& map ) 00249 { map_ = ↦ index_ = 0; next(); } 00251 Map_reference_coord( const Xmap_base& map, const Coord_grid& pos ) { 00252 map_ = ↦ 00253 pos_ = pos; 00254 map_->find_sym( pos_, index_, sym_ ); 00255 } 00257 inline const Coord_grid& coord() const { return pos_; } 00259 inline const Coord_orth coord_orth() const 00260 { return Coord_orth( map_->rt_grid_orth.rot() * coord().coord_map() ); } 00262 inline const int& sym() const { return sym_; } 00264 Map_reference_coord& set_coord( const Coord_grid& pos ); 00266 00267 inline Map_reference_coord& next() { 00268 sym_ = 0; 00269 do { 00270 index_++; if ( last() ) break; 00271 } while ( map_->asu[index_] != 0 ); 00272 pos_ = map_->map_grid.deindex(index_); 00273 return *this; 00274 } 00275 // Increment u,v,w 00276 inline Map_reference_coord& next_u() { pos_.u()++; index_ += map_->du[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00277 inline Map_reference_coord& next_v() { pos_.v()++; index_ += map_->dv[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00278 inline Map_reference_coord& next_w() { pos_.w()++; index_ += map_->dw[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00279 inline Map_reference_coord& prev_u() { pos_.u()--; index_ -= map_->du[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00280 inline Map_reference_coord& prev_v() { pos_.v()--; index_ -= map_->dv[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00281 inline Map_reference_coord& prev_w() { pos_.w()--; index_ -= map_->dw[sym_]; if (map_->asu[index_] != 0) edge(); return *this; } 00282 00283 inline Map_reference_coord& operator =( const Coord_grid& pos ) 00284 { return set_coord( pos ); } 00285 // inherited functions listed for documentation purposes 00286 //-- const Xmap_base& base_xmap() const; 00287 //-- const int& index() const; 00288 //-- bool last() const; 00289 00290 protected: 00292 int sym_; 00294 Coord_grid pos_; 00295 00297 void edge(); 00298 }; 00299 00301 Map_reference_index first() const { return Map_reference_index( *this ); } 00303 Map_reference_coord first_coord() const { return Map_reference_coord( *this ); } 00305 static FFTtype& default_type() { return default_type_; } 00306 protected: 00307 ObjectCache<Xmap_cacheobj>::Reference cacheref; 00308 const unsigned char* asu; 00309 const Isymop* isymop; 00310 const int* du; 00311 const int* dv; 00312 const int* dw; 00313 Grid_range asu_grid; 00314 Grid_range map_grid; 00315 int nsym; 00316 00317 Cell cell_; 00318 Spacegroup spacegroup_; 00319 Grid_sampling grid_sam_; 00320 00321 RTop<> rt_orth_grid; 00322 RTop<> rt_grid_orth; 00323 00325 Xmap_base(); 00327 void init( const Spacegroup& spacegroup, const Cell& cell, const Grid_sampling& grid_sam ); 00328 inline void find_sym( const Coord_grid& base, int& index, int& sym ) const; 00329 void asu_error( const Coord_grid& pos ) const; 00330 00331 static FFTtype default_type_; 00332 00333 friend class Xmap_base::Map_reference_base; 00334 friend class Xmap_base::Map_reference_index; 00335 friend class Xmap_base::Map_reference_coord; 00336 }; 00337 00338 00339 00340 00342 00356 template<class T> class Xmap : public Xmap_base 00357 { 00358 public: 00360 Xmap() {} 00362 Xmap( const Spacegroup& spacegroup, const Cell& cell, const Grid_sampling& grid_sam ) { init( spacegroup, cell, grid_sam ); } 00364 void init( const Spacegroup& spacegroup, const Cell& cell, const Grid_sampling& grid_sam ) { Xmap_base::init( spacegroup, cell, grid_sam ); list.resize( cacheref.data().asu.size() ); } 00365 00367 inline const T& operator[] (const Xmap_base::Map_reference_index& ix) const 00368 { return list[ix.index()]; } 00370 inline T& operator[] (const Xmap_base::Map_reference_index& ix) 00371 { return list[ix.index()]; } 00372 00374 inline const T& operator[] (const Xmap_base::Map_reference_coord& ix) const 00375 { return list[ix.index()]; } 00377 inline T& operator[] (const Xmap_base::Map_reference_coord& ix) 00378 { return list[ix.index()]; } 00379 00381 const T& get_data( const Coord_grid& pos ) const; 00383 void set_data( const Coord_grid& pos, const T& val ); 00385 inline const T& get_data( const int& index ) const; 00387 bool set_data( const int& index, const T& val ); 00388 00390 template<class I> T interp( const Coord_frac& pos ) const; 00392 template<class I> void interp_grad( const Coord_frac& pos, T& val, Grad_frac<T>& grad ) const; 00394 template<class I> void interp_curv( const Coord_frac& pos, T& val, Grad_frac<T>& grad, Curv_frac<T>& curv ) const; 00396 template<class I> T interp( const Coord_map& pos ) const; 00398 template<class I> void interp_grad( const Coord_map& pos, T& val, Grad_map<T>& grad ) const; 00400 template<class I> void interp_curv( const Coord_map& pos, T& val, Grad_map<T>& grad, Curv_map<T>& curv ) const; 00401 00403 template<class H> void fft_from( const H& fphidata, const FFTtype type = Default ); 00405 template<class H> void fft_to ( H& fphidata, const FFTtype type = Default ) const; 00406 00407 // inherited functions listed for documentation purposes 00408 //-- const Cell& cell() const; 00409 //-- const Spacegroup& spacegroup() const; 00410 //-- const Grid_sampling& grid_sampling() const; 00411 //-- const Grid_range& grid_asu() const; 00412 //-- inline Coord_grid coord_of( const int& index ) const; 00413 //-- inline int index_of( const Coord_grid& coord ) const; 00414 //-- const int multiplicity( const Coord_grid& pos ) const; 00415 //-- const Coord_grid to_map_unit( const Coord_grid& pos ) const; 00416 //-- const Map_reference_index first() const; 00417 //-- const Map_reference_coord first_coord() const; 00418 00420 const T& operator =( const T& value ); 00422 const Xmap<T>& operator +=( const Xmap<T>& other ); 00424 const Xmap<T>& operator -=( const Xmap<T>& other ); 00425 00426 private: 00427 std::vector<T> list; 00428 }; 00429 00430 00431 00432 // implementations 00433 00434 void Xmap_base::find_sym( const Coord_grid& base, int& index, int& sym ) const 00435 { 00436 // first deal with first symop, and cache for highest performance 00437 Coord_grid rot = to_map_unit( base ); 00438 if ( asu_grid.in_grid( rot ) ) { 00439 index = map_grid.index( rot ); 00440 if ( asu[ index ] == 0 ) { 00441 sym = 0; 00442 } else { 00443 sym = asu[ index ] - 1; 00444 index = map_grid.index( to_map_unit( base.transform(isymop[sym]) ) ); 00445 } 00446 } else { 00447 // now deal with other symops 00448 for ( sym = 1; sym < nsym; sym++ ) { 00449 rot = to_map_unit( base.transform( isymop[sym] ) ); 00450 if ( asu_grid.in_grid( rot ) ) { 00451 index = map_grid.index( rot ); 00452 if ( asu[ index ] == 0 ) return; 00453 } 00454 } 00455 index = 0; // redundent, to avoid compiler warnings 00456 asu_error( base ); 00457 } 00458 return; 00459 } 00460 00461 00466 template<class T> const T& Xmap<T>::get_data( const Coord_grid& pos ) const 00467 { 00468 int index, sym; 00469 find_sym( pos, index, sym ); 00470 return list[ index ]; 00471 } 00472 00477 template<class T> void Xmap<T>::set_data( const Coord_grid& pos, const T& val ) 00478 { 00479 int index, sym; 00480 find_sym( pos, index, sym ); 00481 list[ index ] = val; 00482 } 00483 00490 template<class T> const T& Xmap<T>::get_data( const int& index ) const 00491 { return list[index]; } 00492 00500 template<class T> bool Xmap<T>::set_data( const int& index, const T& val ) 00501 { 00502 if ( index >= 0 && index < list.size() ) 00503 if ( asu[index] == 0 ) { 00504 list[index] = val; 00505 return true; 00506 } 00507 return false; 00508 } 00509 00518 template<class T> template<class I> T Xmap<T>::interp( const Coord_frac& pos ) const 00519 { 00520 T val; 00521 I::interp( *this, pos.coord_map( grid_sam_ ), val ); 00522 return val; 00523 } 00524 00525 00533 template<class T> template<class I> void Xmap<T>::interp_grad( const Coord_frac& pos, T& val, Grad_frac<T>& grad ) const 00534 { 00535 Grad_map<T> g; 00536 I::interp_grad( *this, pos.coord_map( grid_sam_ ), val, g ); 00537 grad = g.grad_frac( grid_sam_ ); 00538 } 00539 00540 00550 template<class T> template<class I> void Xmap<T>::interp_curv( const Coord_frac& pos, T& val, Grad_frac<T>& grad, Curv_frac<T>& curv ) const 00551 { 00552 Grad_map<T> g; 00553 Curv_map<T> c; 00554 I::interp_curv( *this, pos.coord_map( grid_sam_ ), val, g, c ); 00555 grad = g.grad_frac( grid_sam_ ); 00556 curv = c.curv_frac( grid_sam_ ); 00557 } 00558 00559 00568 template<class T> template<class I> T Xmap<T>::interp( const Coord_map& pos ) const 00569 { 00570 T val; 00571 I::interp( *this, pos, val ); 00572 return val; 00573 } 00574 00575 00583 template<class T> template<class I> void Xmap<T>::interp_grad( const Coord_map& pos, T& val, Grad_map<T>& grad ) const 00584 { I::interp_grad( *this, pos, val, grad ); } 00585 00586 00596 template<class T> template<class I> void Xmap<T>::interp_curv( const Coord_map& pos, T& val, Grad_map<T>& grad, Curv_map<T>& curv ) const 00597 { I::interp_curv( *this, pos, val, grad, curv ); } 00598 00599 00604 template<class T> template<class H> void Xmap<T>::fft_from( const H& fphidata, const FFTtype type ) 00605 { 00606 if ( type == Sparse || ( type == Default && default_type() == Sparse ) ) { 00607 // make a sparse fftmap 00608 FFTmap_sparse_p1_hx fftmap( grid_sampling() ); 00609 // copy from reflection data 00610 typename H::HKL_reference_index ih; 00611 ffttype f, phi0, phi1; 00612 int sym; 00613 for ( ih = fphidata.first_data(); !ih.last(); fphidata.next_data( ih ) ) { 00614 f = fphidata[ih].f(); 00615 if ( f != 0.0 ) { 00616 phi0 = fphidata[ih].phi(); 00617 const HKL& hkl = ih.hkl(); 00618 fftmap.set_hkl( hkl, 00619 std::complex<ffttype>( f*cos(phi0), f*sin(phi0) ) ); 00620 for ( sym = 1; sym < spacegroup_.num_primops(); sym++ ) { 00621 phi1 = phi0 + hkl.sym_phase_shift( spacegroup_.symop(sym) ); 00622 fftmap.set_hkl( hkl.transform( isymop[sym] ), 00623 std::complex<ffttype>( f*cos(phi1), f*sin(phi1) ) ); 00624 } 00625 } 00626 } 00627 // require output ASU coords 00628 for ( Map_reference_index ix = first(); !ix.last(); ix.next() ) 00629 fftmap.require_real_data( ix.coord() ); 00630 // do fft 00631 fftmap.fft_h_to_x(1.0/cell().volume()); 00632 // fill map ASU 00633 for ( Map_reference_index ix = first(); !ix.last(); ix.next() ) 00634 (*this)[ix] = fftmap.real_data( ix.coord() ); 00635 } else { 00636 // make a normal fftmap 00637 FFTmap_p1 fftmap( grid_sampling() ); 00638 // copy from reflection data 00639 typename H::HKL_reference_index ih; 00640 ffttype f, phi0, phi1; 00641 int sym; 00642 for ( ih = fphidata.first_data(); !ih.last(); fphidata.next_data( ih ) ) { 00643 f = fphidata[ih].f(); 00644 if ( f != 0.0 ) { 00645 phi0 = fphidata[ih].phi(); 00646 const HKL& hkl = ih.hkl(); 00647 fftmap.set_hkl( hkl, 00648 std::complex<ffttype>( f*cos(phi0), f*sin(phi0) ) ); 00649 for ( sym = 1; sym < spacegroup_.num_primops(); sym++ ) { 00650 phi1 = phi0 + hkl.sym_phase_shift( spacegroup_.symop(sym) ); 00651 fftmap.set_hkl( hkl.transform( isymop[sym] ), 00652 std::complex<ffttype>( f*cos(phi1), f*sin(phi1) ) ); 00653 } 00654 } 00655 } 00656 // do fft 00657 fftmap.fft_h_to_x(1.0/cell().volume()); 00658 // fill map ASU 00659 for ( Map_reference_index ix = first(); !ix.last(); ix.next() ) 00660 (*this)[ix] = fftmap.real_data( ix.coord() ); 00661 } 00662 } 00663 00664 00673 template<class T> template<class H> void Xmap<T>::fft_to ( H& fphidata, const FFTtype type ) const 00674 { 00675 if ( type == Sparse || ( type == Default && default_type() == Sparse ) ) { 00676 // make a sparse fftmap 00677 FFTmap_sparse_p1_xh fftmap( grid_sampling() ); 00678 // copy from map data 00679 ffttype f; 00680 int sym; 00681 for ( Map_reference_index ix = first(); !ix.last(); ix.next() ) { 00682 f = (*this)[ix]; 00683 if ( f != 0.0 ) { 00684 fftmap.real_data( ix.coord() ) = f; 00685 for ( sym = 1; sym < cacheref.data().nsym; sym++ ) 00686 fftmap.real_data( 00687 ix.coord().transform( isymop[sym] ).unit( grid_sam_ ) ) = f; 00688 } 00689 } 00690 // require output ASU coords 00691 typename H::HKL_reference_index ih; 00692 for ( ih = fphidata.first(); !ih.last(); ih.next() ) 00693 fftmap.require_hkl( ih.hkl() ); 00694 // do fft 00695 fftmap.fft_x_to_h(cell().volume()); 00696 // fill data ASU 00697 for ( ih = fphidata.first(); !ih.last(); ih.next() ) { 00698 std::complex<ffttype> c = fftmap.get_hkl( ih.hkl() ); 00699 fphidata[ih].f() = std::abs(c); 00700 fphidata[ih].phi() = std::arg(c); 00701 } 00702 } else { 00703 // make a normal fftmap 00704 FFTmap_p1 fftmap( grid_sampling() ); 00705 // copy from map data 00706 ffttype f; 00707 int sym; 00708 for ( Map_reference_index ix = first(); !ix.last(); ix.next() ) { 00709 f = (*this)[ix]; 00710 if ( f != 0.0 ) { 00711 fftmap.real_data( ix.coord() ) = f; 00712 for ( sym = 1; sym < cacheref.data().nsym; sym++ ) 00713 fftmap.real_data( 00714 ix.coord().transform( isymop[sym] ).unit( grid_sam_ ) ) = f; 00715 } 00716 } 00717 // do fft 00718 fftmap.fft_x_to_h(cell().volume()); 00719 // fill data ASU 00720 typename H::HKL_reference_index ih; 00721 for ( ih = fphidata.first(); !ih.last(); ih.next() ) { 00722 std::complex<ffttype> c = fftmap.get_hkl( ih.hkl() ); 00723 fphidata[ih].f() = std::abs(c); 00724 fphidata[ih].phi() = std::arg(c); 00725 } 00726 } 00727 } 00728 00729 00732 template<class T> const T& Xmap<T>::operator =( const T& value ) 00733 { 00734 // copy value into map 00735 for ( Map_reference_index im = first(); !im.last(); im.next() ) 00736 list[im.index()] = value; 00737 return value; 00738 } 00739 00740 00742 template<class T> const Xmap<T>& Xmap<T>::operator +=( const Xmap<T>& other ) 00743 { 00744 if ( spacegroup().hash() != other.spacegroup().hash() || 00745 grid_sampling() != other.grid_sampling() ) 00746 Message::message( Message_fatal( "Xmap: map mismatch in +=" ) ); 00747 for ( Map_reference_index im = first(); !im.last(); im.next() ) 00748 list[im.index()] += other[im]; 00749 return (*this); 00750 } 00751 00753 template<class T> const Xmap<T>& Xmap<T>::operator -=( const Xmap<T>& other ) 00754 { 00755 if ( spacegroup().hash() != other.spacegroup().hash() || 00756 grid_sampling() != other.grid_sampling() ) 00757 Message::message( Message_fatal( "Xmap: map mismatch in -=" ) ); 00758 for ( Map_reference_index im = first(); !im.last(); im.next() ) 00759 list[im.index()] -= other[im]; 00760 return (*this); 00761 } 00762 00763 00764 } // namespace clipper 00765 00766 #endif