Clipper
hkl_data.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_HKL_DATA
00046 #define CLIPPER_HKL_DATA
00047 
00048 
00049 #include "hkl_info.h"
00050 
00051 
00052 namespace clipper
00053 {
00054 
00055   class HKL_data_cacheobj : public HKL_info
00056   {
00057   public:
00058     class Key
00059     {
00060     public:
00061       Key( const Spgr_descr& spgr_descr, const Cell& cell_descr, const HKL_sampling& hkl_sam ) : spgr_descr_(spgr_descr), cell_descr_(cell_descr), hkl_sampling_(hkl_sam) {}
00062       const Spgr_descr& spgr_descr() const { return spgr_descr_; }
00063       const Cell_descr& cell_descr() const { return cell_descr_; }
00064       const HKL_sampling& hkl_sampling() const { return hkl_sampling_; }
00065     private:
00066       Spgr_descr spgr_descr_;
00067       Cell_descr cell_descr_;
00068       HKL_sampling hkl_sampling_;
00069     };
00070 
00071     HKL_data_cacheobj( const Key& hkl_data_cachekey );
00072     bool matches( const Key& hkl_data_cachekey ) const;
00073     String format() const;
00074     static Mutex mutex;                 
00075   private:
00076     Key key;
00077   };
00078 
00079 
00081 
00103   class Datatype_base
00104   {
00105   protected:
00107     //-- Datatype_base();
00109     void set_null();
00111     static String type();
00113     void friedel();
00115     void shift_phase(const ftype& dphi);
00117     bool missing() const;
00119     static int data_size();
00121     static String data_names();
00123     void data_export( xtype array[] ) const;
00125     void data_import( const xtype array[] );
00126   };
00127 
00128 
00130 
00136   class HKL_data_base
00137   {
00138    public:
00139     // Coordinate reference types
00141     typedef HKL_info::HKL_reference_index HKL_reference_index;
00143     typedef HKL_info::HKL_reference_coord HKL_reference_coord;
00144 
00146     virtual void init( const HKL_info& hkl_info, const Cell& cell );
00148     virtual void init( const HKL_data_base& hkl_data );
00150     virtual void init( const Spacegroup& spacegroup, const Cell& cell, const HKL_sampling& hkl_sampling );
00151 
00152     // generic methods
00154     bool is_null() const;
00155 
00157     const HKL_info& base_hkl_info() const { return *parent_hkl_info; }
00159     const Cell& base_cell() const { return *parent_cell; }
00160 
00162     const Spacegroup& spacegroup() const { return spacegroup_; }
00164     const Cell& cell() const { return cell_; }
00166     const Resolution& resolution() const { return resolution_; }
00168     const HKL_sampling& hkl_sampling() const { return hkl_sampling_; }
00170     const HKL_info& hkl_info() const { return *parent_hkl_info; }
00171 
00173     ftype invresolsq( const int& index ) const;
00175     Range<ftype> invresolsq_range() const;
00177     int num_obs() const;
00178 
00180     virtual void update() = 0;
00182     virtual String type() const = 0;
00184     virtual bool missing(const int& index) const = 0;
00186     virtual void set_null(const int& index) = 0;
00188     virtual int data_size() const = 0;
00190     virtual String data_names() const = 0;
00192     virtual void data_export( const HKL& hkl, xtype array[] ) const = 0;
00194     virtual void data_import( const HKL& hkl, const xtype array[] ) = 0;
00196     virtual void mask(const HKL_data_base& mask) = 0;
00197 
00199     HKL_reference_index first() const;
00201     HKL_reference_index first_data() const;
00203     HKL_reference_index& next_data( HKL_reference_index& ih ) const;
00204 
00205     void debug() const;
00206 
00207    protected:
00208     const HKL_info* parent_hkl_info;
00209     const Cell* parent_cell;
00210     bool cell_matches_parent;
00211 
00212     // clipper2 members
00213     ObjectCache<HKL_data_cacheobj>::Reference cacheref;  
00214     Spacegroup spacegroup_;
00215     Cell cell_;
00216     HKL_sampling hkl_sampling_;
00217     Resolution resolution_;
00218 
00220     HKL_data_base();
00222     virtual ~HKL_data_base() {}
00223   };
00224 
00225 
00227 
00234   template<class T> class HKL_data : public HKL_data_base
00235   {
00236   public:
00238     HKL_data() {}
00240     explicit HKL_data( const HKL_info& hkl_info );
00242     HKL_data( const HKL_info& hkl_info, const Cell& cell );
00244     HKL_data( const Spacegroup& spacegroup, const Cell& cell, const HKL_sampling& hkl_sampling );
00246     explicit HKL_data( const HKL_data_base& hkl_data );
00247 
00249     void init( const HKL_info& hkl_info, const Cell& cell );
00251     void init( const Spacegroup& spacegroup, const Cell& cell, const HKL_sampling& hkl_sampling );
00253     void init( const HKL_data_base& hkl_data );
00255     void update();
00256 
00257     // type specific methods
00258     String type() const { return T::type(); }
00259     bool missing(const int& index) const { return list[index].missing(); }
00260     void set_null(const int& index) { list[index].set_null(); }
00261     int data_size() const { return T::data_size(); }
00262     String data_names() const { return T::data_names(); }
00263     void data_export( const HKL& hkl, xtype array[] ) const
00264       { T datum; get_data( hkl, datum ); datum.data_export( array ); }
00265     void data_import( const HKL& hkl, const xtype array[] )
00266       { T datum; datum.data_import( array ); set_data( hkl, datum ); }
00267     void mask(const HKL_data_base& mask);
00268 
00269     // data access methods: by HKL_reference_index
00271     const T& operator[] (const HKL_info::HKL_reference_index& i) const
00272       { return list[i.index()]; }
00274     T& operator[] (const HKL_info::HKL_reference_index& i)
00275       { return list[i.index()]; }
00276 
00277     // data access methods: by HKL_reference_coord
00279     T operator[] (const HKL_info::HKL_reference_coord& ih) const;
00281     bool get_data(const HKL_info::HKL_reference_coord& ih, T& data) const;
00283     bool set_data(const HKL_info::HKL_reference_coord& ih, const T& data);
00284 
00285     // data access methods: by index
00287     const T& operator[] (const int& index) const { return list[index]; }
00289     T& operator[] (const int& index) { return list[index]; }
00290 
00291     // data access methods: by hkl
00293     T operator[] (const HKL& hkl) const;
00295     bool get_data(const HKL& hkl, T& data) const;
00297     bool set_data(const HKL& hkl, const T& data);
00298 
00299     // COMPUTATION OPERATORS
00301     template<class C> void compute( const C& op )
00302       { for (HKL_info::HKL_reference_index ih=parent_hkl_info->first(); !ih.last(); ih.next()) list[ih.index()] = op( ih ); }
00304     template<class S, class C> void compute( const HKL_data<S>& src, const C& op )
00305       { for (HKL_info::HKL_reference_index ih=parent_hkl_info->first(); !ih.last(); ih.next()) list[ih.index()] = op( ih, src[ih] ); }
00307     template<class S1, class S2, class C> void compute( const HKL_data<S1>& src1, const HKL_data<S2>& src2, const C& op )
00308       { for (HKL_info::HKL_reference_index ih=parent_hkl_info->first(); !ih.last(); ih.next()) list[ih.index()] = op( ih, src1[ih], src2[ih] ); }
00309 
00310     // inherited functions lists for documentation purposes
00311     //-- const HKL_info& base_hkl_info() const;
00312     //-- const Cell& base_cell() const;
00313     //-- const ftype invresolsq(const int& index) const;
00314     //-- const Range<ftype> invresolsq_range() const;
00315     //-- const int num_obs() const;
00316     //-- HKL_reference_index first() const;
00317     //-- HKL_reference_index first_data() const;
00318     //-- HKL_reference_index& next_data( HKL_reference_index& ih ) const;
00319 
00321     HKL_data<T>& operator =( const HKL_data<T>& other );
00323     HKL_data<T>& operator =( const T& value );
00324 
00325     void debug() const;
00326 
00327   protected:
00328     // members
00329     std::vector<T> list;
00330   };
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338   // Template implementations
00339 
00340   ftype HKL_info::HKL_reference_base::invresolsq( const HKL_data_base& hkldata ) const
00341     { return hkldata.invresolsq( index_ ); }
00342 
00345   template<class T> HKL_data<T>::HKL_data( const HKL_info& hkl_info )
00346   {
00347     init( hkl_info, hkl_info.cell() );
00348   }
00349 
00353   template<class T> HKL_data<T>::HKL_data( const HKL_info& hkl_info, const Cell& cell )
00354   {
00355     init( hkl_info, cell );
00356   }
00357 
00362   template<class T> HKL_data<T>::HKL_data( const Spacegroup& spacegroup, const Cell& cell, const HKL_sampling& hkl_sampling )
00363   {
00364     init( spacegroup, cell, hkl_sampling );
00365   }
00366 
00371   template<class T> HKL_data<T>::HKL_data( const HKL_data_base& hkl_data )
00372   {
00373     init( hkl_data );
00374   }
00375 
00379   template<class T> void HKL_data<T>::init( const HKL_info& hkl_info, const Cell& cell )
00380   {
00381     HKL_data_base::init( hkl_info, cell );
00382     update();
00383   }
00384 
00389   template<class T> void HKL_data<T>::init( const Spacegroup& spacegroup, const Cell& cell, const HKL_sampling& hkl_sampling )
00390   {
00391     HKL_data_base::init( spacegroup, cell, hkl_sampling );
00392     update();
00393   }
00394 
00399   template<class T> void HKL_data<T>::init( const HKL_data_base& hkl_data )
00400   {
00401     HKL_data_base::init( hkl_data );
00402     update();
00403   }
00404 
00406   template<class T> void HKL_data<T>::update()
00407   {
00408     if ( parent_hkl_info != NULL ) {
00409       T null; null.set_null();
00410       list.resize( parent_hkl_info->num_reflections(), null );
00411     }
00412   }
00413 
00418   template<class T> void HKL_data<T>::mask(const HKL_data_base& mask)
00419   {
00420     T null; null.set_null();
00421     for ( int i = 0; i < list.size(); i++ )
00422       if ( mask.missing(i) ) list[i] = null;
00423   }
00424 
00430   template<class T> T HKL_data<T>::operator[] (const HKL_info::HKL_reference_coord& ih) const
00431   {
00432     if ( ih.index() < 0 ) { T null; null.set_null(); return null; }
00433     T data = list[ih.index()];
00434     if ( ih.friedel() ) data.friedel();
00435     data.shift_phase( -ih.hkl().sym_phase_shift( parent_hkl_info->spacegroup().symop(ih.sym()) ) );
00436     return data;
00437   }
00438 
00445   template<class T> bool HKL_data<T>::get_data(const HKL_info::HKL_reference_coord& ih, T& data) const
00446   {
00447     if ( ih.index() < 0 ) { data.set_null(); return false; }
00448     data = list[ih.index()];
00449     if ( ih.friedel() ) data.friedel();
00450     data.shift_phase( -ih.hkl().sym_phase_shift( parent_hkl_info->spacegroup().symop(ih.sym()) ) );
00451     return true;
00452   }
00453 
00460   template<class T> bool HKL_data<T>::set_data(const HKL_info::HKL_reference_coord& ih, const T& data)
00461   {
00462     if ( ih.index() < 0 ) return false;
00463     T& ldata = list[ih.index()];
00464     ldata = data;
00465     ldata.shift_phase( ih.hkl().sym_phase_shift( parent_hkl_info->spacegroup().symop(ih.sym()) ) );
00466     if ( ih.friedel() ) ldata.friedel();
00467     return true;
00468   }
00469 
00475   template<class T> T HKL_data<T>::operator[] (const HKL& hkl) const
00476   {
00477     int index, sym; bool friedel;
00478 
00479     index = parent_hkl_info->index_of( parent_hkl_info->
00480                                        find_sym(hkl, sym, friedel) );
00481     if ( index < 0 ) { T null; null.set_null(); return null; }
00482     T data = list[index];
00483     if (friedel) data.friedel();
00484     data.shift_phase( -hkl.sym_phase_shift( parent_hkl_info->spacegroup().symop(sym) ) );
00485     return data;
00486   }
00487 
00494   template<class T> bool HKL_data<T>::get_data(const HKL& hkl, T& data) const
00495   {
00496     int index, sym; bool friedel;
00497 
00498     index = parent_hkl_info->index_of( parent_hkl_info->
00499                                         find_sym(hkl, sym, friedel) );
00500     if ( index < 0 ) { data.set_null(); return false; }
00501     data = list[index];
00502     if (friedel) data.friedel();
00503     data.shift_phase( -hkl.sym_phase_shift(parent_hkl_info->spacegroup().symop(sym)) );
00504     return true;
00505   }
00506 
00513   template<class T> bool HKL_data<T>::set_data(const HKL& hkl, const T& data_)
00514   {
00515     int index, sym; bool friedel;
00516     index = parent_hkl_info->index_of( parent_hkl_info->
00517                                        find_sym(hkl, sym, friedel) );
00518     if ( index < 0 ) { return false; }
00519     T& ldata = list[index];
00520     ldata = data_;
00521     ldata.shift_phase( hkl.sym_phase_shift(parent_hkl_info->spacegroup().symop(sym)) );
00522     if (friedel) ldata.friedel();
00523     return true;
00524   }
00525 
00526 
00534   template<class T> HKL_data<T>& HKL_data<T>::operator =( const HKL_data<T>& other )
00535   {
00536     if ( parent_hkl_info == NULL ) {
00537       init( other );
00538     } else {
00539       if ( parent_hkl_info != other.parent_hkl_info )
00540         Message::message( Message_fatal( "HKL_data<T>: mismatched parent HKL_info is assignment" ) );
00541     }
00542     list = other.list;
00543     return *this;
00544   }
00545 
00546 
00549   template<class T> HKL_data<T>& HKL_data<T>::operator =( const T& value )
00550   {
00551     for ( int i = 0; i < list.size(); i++ ) list[i] = value;
00552     return *this;
00553   }
00554 
00555 
00556   template<class T> void HKL_data<T>::debug() const
00557   {
00558     HKL_data_base::debug();
00559     std::cout << "Size " << list.size() << "\n";
00560   }
00561 
00562 
00563 } // namespace clipper
00564 
00565 #endif