symmetry.h

Go to the documentation of this file.
00001 
00002 /*
00003  * Author: David Woolford, 09/23/2008 (woolford@bcm.edu)
00004  * Copyright (c) 2000-2006 Baylor College of Medicine
00005  *
00006  * This software is issued under a joint BSD/GNU license. You may use the
00007  * source code in this file under either license. However, note that the
00008  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00009  * so you are responsible for compliance with the licenses of these packages
00010  * if you opt to use BSD licensing. The warranty disclaimer below holds
00011  * in either instance.
00012  *
00013  * This complete copyright notice must be included in any revised version of the
00014  * source code. Additional authorship citations may be added, but existing
00015  * author citations must be preserved.
00016  *
00017  * This program is free software; you can redistribute it and/or modify
00018  * it under the terms of the GNU General Public License as published by
00019  * the Free Software Foundation; either version 2 of the License, or
00020  * (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful,
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00025  * GNU General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00030  *
00031  * */
00032 #ifndef eman__symmetry_h__
00033 #define eman__symmetry_h__ 1
00034 
00035 
00036 #include "emobject.h"
00037 #include "vec3.h"
00038 #include "transform.h"
00039 
00040 namespace EMAN {
00041 
00056         class Symmetry3D : public FactoryBase
00057         {
00058         public:
00059                 typedef vector<vector<Vec3f> >::const_iterator cit;
00060                 typedef vector<vector<Vec3f> >::iterator ncit;
00061                 Symmetry3D();
00062                 virtual  ~Symmetry3D();
00063 
00069                 virtual Dict get_delimiters(const bool inc_mirror=false) const = 0;
00070 
00076                 virtual Transform get_sym(const int n) const = 0;
00077 
00081                 virtual int get_nsym() const = 0;
00082 
00086                 virtual float get_az_alignment_offset() const { return 0.0; }
00087 
00088 
00089 
00094                 virtual bool is_platonic_sym() const { return false; }
00095 
00100                 virtual bool is_h_sym() const { return false; }
00101 
00106                 virtual bool is_c_sym() const { return false; }
00107 
00112                 virtual bool is_d_sym() const { return false; }
00113 
00118                 virtual bool is_tet_sym() const { return false; }
00119 
00120 
00121 
00125                 virtual int get_max_csym() const = 0;
00126 
00136                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror) const = 0;
00144                 vector<Transform> gen_orientations(const string& generatorname="eman", const Dict& parms=Dict());
00145 
00154                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const = 0;
00155 
00165                 virtual Transform reduce(const Transform& t3d, int n=0) const;
00166 
00167 
00174                 virtual int in_which_asym_unit(const Transform& t3d) const;
00175 
00183                 virtual int point_in_which_asym_unit(const Vec3f& v) const;
00184 
00189                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const = 0;
00190 
00200                 virtual vector<Transform> get_touching_au_transforms(bool inc_mirror = true) const;
00201 
00202                 virtual vector<Transform> get_syms() const;
00203                 static vector<Transform> get_symmetries(const string& symmetry);
00204         protected:
00207                 mutable float** cached_au_planes;
00208 
00210                 mutable int cache_size;
00212                 mutable int num_triangles;
00214                 mutable vector< vector<Vec3f> > au_sym_triangles;
00217                 void cache_au_planes() const;
00218 
00221                 void delete_au_planes();
00222         private:
00224                 Symmetry3D(const Symmetry3D&);
00226                 Symmetry3D& operator=(const Symmetry3D&);
00227 };
00228 
00233         class CSym : public Symmetry3D
00234 {
00235         public:
00236                 CSym() {};
00237                 virtual  ~CSym() {};
00238 
00242                 static Symmetry3D *NEW()
00243                 {
00244                         return new CSym();
00245                 }
00246 
00250                 virtual string get_name() const { return NAME; }
00251 
00255                 virtual string get_desc() const { return "C symmetry support"; }
00256 
00260                 virtual TypeDict get_param_types() const
00261                 {
00262                         TypeDict d;
00263                         d.put("nsym", EMObject::INT, "The symmetry number");
00264                         return d;
00265                 }
00266 
00274                 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00275 
00283                 virtual Transform get_sym(const int n) const;
00284 
00289                 virtual int get_nsym() const { return params["nsym"]; };
00290 
00291 
00296                 virtual int get_max_csym() const { return params["nsym"]; }
00297 
00299                 static const string NAME;
00300 
00305                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00306 
00315                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00316 
00320                 virtual bool is_c_sym() const { return  true; }
00321 
00322 
00327                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00328         private:
00330                 CSym(const CSym&);
00332                 CSym& operator=(const CSym&);
00333 
00334 };
00335 
00340         class DSym : public Symmetry3D
00341 {
00342         public:
00343                 DSym() {};
00344                 virtual  ~DSym() {};
00345 
00349                 static Symmetry3D *NEW()
00350                 {
00351                         return new DSym();
00352                 }
00353 
00357                 virtual string get_name() const { return NAME; }
00358 
00362                 virtual string get_desc() const { return "D symmetry support"; }
00363 
00367                 virtual TypeDict get_param_types() const
00368                 {
00369                         TypeDict d;
00370                         d.put("nsym", EMObject::INT, "The symmetry number");
00371                         return d;
00372                 }
00373 
00381                 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00382 
00391                 virtual Transform get_sym(const int n) const;
00392 
00397                 virtual int get_nsym() const { return 2*(int)params["nsym"]; };
00398 
00399 
00404                 virtual int get_max_csym() const { return params["nsym"]; }
00405 
00410                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00411 
00420                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00421 
00423                 static const string NAME;
00424 
00428                 virtual bool is_d_sym() const { return  true; }
00429 
00434                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00435         private:
00437                 DSym(const DSym&);
00439                 DSym& operator=(const DSym&);
00440 };
00441 
00446         class HSym : public Symmetry3D
00447 {
00448         public:
00449                 HSym() {};
00450                 virtual  ~HSym() {};
00451 
00455                 static Symmetry3D *NEW()
00456                 {
00457                         return new HSym();
00458                 }
00459 
00463                 virtual string get_name() const { return NAME; }
00464 
00468                 virtual string get_desc() const { return "H symmetry support"; }
00469 
00476                 virtual TypeDict get_param_types() const
00477                 {
00478                         TypeDict d;
00479                         d.put("nsym", EMObject::INT, "The symmetry number of the helix, around the equator.");
00480                         d.put("equator_range", EMObject::FLOAT, "The amount altitude angles are allowed to vary above and below the equator. Default is 5");
00481                         d.put("tz", EMObject::FLOAT, "The translational distance (along z) between successive identical subunits in angstrom (default a/pix is 1)");
00482                         d.put("daz", EMObject::FLOAT, "The rotational angle (about z) between successive identical subunits in degrees");
00483                         d.put("apix", EMObject::FLOAT, "Angstrom per pixel, default is one.");
00484                         return d;
00485                 }
00486 
00499                 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00500 
00501 
00510                 virtual Transform get_sym(const int n) const;
00511 
00521                 virtual int get_nsym() const { return (int)params["nsym"]; }; // ming, this is the number of helix turns
00522                 /*virtual int get_nsym() const {
00523                         float daz = params.set_default("daz",0.0f);
00524                         if ( daz <= 0 ) throw InvalidValueException(daz,"Error, you must specify a positive non zero d_az");
00525                         return static_cast<int>(360.0/daz);
00526                 };*/
00527 
00532                 virtual int get_max_csym() const { return params["nsym"]; }
00533 
00535                 static const string NAME;
00536 
00540                 virtual bool is_h_sym() const { return true; }
00541 
00550                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00551 
00556                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00557 
00562                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00563         private:
00565                 HSym(const HSym&);
00567                 HSym& operator=(const HSym&);
00568 };
00569 
00583         class PlatonicSym : public Symmetry3D
00584 {
00585         public:
00586                 PlatonicSym() {};
00587                 virtual  ~PlatonicSym() {};
00588 
00593                 virtual TypeDict get_param_types() const
00594                 {
00595                         TypeDict d;
00596                         return d;
00597                 }
00598 
00614                 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00615 
00624                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00625 
00629                 virtual bool is_platonic_sym() const { return true; }
00630 
00631         protected:
00633                 Dict platonic_params;
00634 
00640                 void init();
00641 
00649                 float platonic_alt_lower_bound(const float& azimuth, const float& alpha) const;
00650 
00655                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00656 
00661                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00662         private:
00664                 PlatonicSym(const PlatonicSym&);
00666                 PlatonicSym& operator=(const PlatonicSym&);
00667 };
00668 
00677         class TetrahedralSym : public PlatonicSym
00678 {
00679         public:
00682                 TetrahedralSym()  {init();}
00683                 virtual  ~TetrahedralSym() {}
00684 
00688                 static Symmetry3D *NEW()
00689                 {
00690                         return new TetrahedralSym();
00691                 }
00692 
00696                 virtual string get_name() const { return NAME; }
00697 
00698 
00702                 virtual string get_desc() const { return "Tetrahedral symmetry support"; }
00703 
00708                 virtual int get_max_csym() const { return 3; }
00709 
00722                 virtual Transform get_sym(const int n) const;
00723 
00732                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00733 
00738                 virtual int get_nsym() const { return 12; };
00739 
00746                 virtual float get_az_alignment_offset() const;
00747 
00749                 static const string NAME;
00750 
00755                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00756 
00760                 virtual bool is_tet_sym() const { return true; }
00761 
00762         private:
00764                 TetrahedralSym(const TetrahedralSym&);
00766                 TetrahedralSym& operator=(const TetrahedralSym&);
00767 
00768 
00769 };
00770 
00781         class OctahedralSym : public PlatonicSym
00782 {
00783         public:
00786                 OctahedralSym()  {init();}
00787                 virtual  ~OctahedralSym() {}
00788 
00792                 static Symmetry3D *NEW()
00793                 {
00794                         return new OctahedralSym();
00795                 }
00796 
00800                 virtual string get_name() const { return NAME; };
00801 
00805                 virtual string get_desc() const { return "Octahedral symmetry support"; }
00806 
00811                 virtual int get_max_csym() const { return 4; }
00812 
00830                 virtual Transform get_sym(const int n) const;
00831 
00836                 virtual int get_nsym() const { return 24; };
00837 
00839                 static const string NAME;
00840         private:
00842                 OctahedralSym(const OctahedralSym&);
00844                 OctahedralSym& operator=(const OctahedralSym&);
00845 };
00846 
00857         class IcosahedralSym : public PlatonicSym
00858 {
00859         public:
00862                 IcosahedralSym() {init(); }
00863                 virtual  ~IcosahedralSym() { }
00864 
00868                 static Symmetry3D *NEW()
00869                 {
00870                         return new IcosahedralSym();
00871                 }
00872 
00876                 virtual string get_name() const { return NAME; };
00877 
00881                 virtual string get_desc() const { return "Icosahedral symmetry support"; }
00882 
00887                 virtual int get_max_csym() const { return 5; }// 5 is the greatest symmetry
00888 
00895                 virtual Transform get_sym(const int n) const;
00896 
00901                 virtual int get_nsym() const { return 60; };
00902 
00909                 virtual float get_az_alignment_offset() const;
00910 
00912                 static const string NAME;
00913         private:
00915                 IcosahedralSym(const IcosahedralSym&);
00917                 IcosahedralSym& operator=(const IcosahedralSym&);
00918 };
00920         template <> Factory < Symmetry3D >::Factory();
00922         template <> Symmetry3D* Factory < Symmetry3D >::get(const string & instancename);
00924         void dump_symmetries();
00926         map<string, vector<string> > dump_symmetries_list();
00927 
00936         class OrientationGenerator : public FactoryBase
00937 {
00938         public:
00939                 OrientationGenerator() {};
00940                 virtual ~OrientationGenerator() {};
00941 
00946                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const  = 0;
00947 
00948                 virtual TypeDict get_param_types() const
00949                 {
00950                         TypeDict d;
00951                         d.put("phitoo", EMObject::FLOAT,  "Specifying a non zero value for this argument will cause phi rotations to be included. The value specified is the angular spacing of the phi rotations in degrees. The default for this value is 0, causing no extra phi rotations to be included.");
00952                         d.put("random_phi", EMObject::BOOL,  "Causes the orientations to have a random phi. This occurs before the phitoo parameter is considered.");
00953                         return d;
00954                 }
00955 
00972                 bool add_orientation(vector<Transform>& v, const float& az, const float& alt) const;
00973 
00974 
00975 
00989                 float get_optimal_delta(const Symmetry3D* const sym, const int& n) const;
00990 
00997                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const = 0;
00998 
00999         protected:
01000                 void get_az_max(const Symmetry3D* const sym, const float& altmax, const bool inc_mirror, const float& alt_iterator,const float& h,bool& d_odd_mirror_flag, float& azmax_adjusted) const;
01001 
01002         private:
01004                 OrientationGenerator(const OrientationGenerator&);
01006                 OrientationGenerator& operator=(const OrientationGenerator&);
01007 };
01008 
01009 
01010 
01020 class EmanOrientationGenerator : public OrientationGenerator
01021 {
01022         public:
01023                 EmanOrientationGenerator() {};
01024                 virtual  ~EmanOrientationGenerator() {};
01025 
01029                 static OrientationGenerator *NEW()
01030                 {
01031                         return new EmanOrientationGenerator();
01032                 }
01033 
01037                 virtual string get_name() const { return NAME; }
01038 
01042                 virtual string get_desc() const { return "Generate orientations distributed quasi-uniformaly over the asymmetric unit using an altitude-proportional strategy"; }
01043 
01048                 virtual TypeDict get_param_types() const
01049                 {
01050                         TypeDict d = OrientationGenerator::get_param_types();
01051                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01052                         d.put("perturb", EMObject::BOOL, "Whether or not to perturb the generated orientations in a small local area, default is false.");
01053                         d.put("n", EMObject::INT, "The number of orientations to generate. This option is mutually exclusively of the delta argument.Will attempt to get as close to the number specified as possible.");
01054                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01055                         return d;
01056                 }
01057 
01062                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01063 
01065                 static const string NAME;
01066         private:
01068                 EmanOrientationGenerator(const EmanOrientationGenerator&);
01070                 EmanOrientationGenerator& operator=(const EmanOrientationGenerator&);
01071 
01078                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01079 
01080 
01089                 float get_az_delta(const float& delta,const float& altitude, const int maxcsym) const;
01090 
01091 };
01092 
01099 class RandomOrientationGenerator : public OrientationGenerator
01100 {
01101         public:
01102                 RandomOrientationGenerator() {}
01103                 virtual ~RandomOrientationGenerator() {}
01104 
01108                 static OrientationGenerator *NEW()
01109                 {
01110                         return new RandomOrientationGenerator();
01111                 }
01112 
01116                 virtual string get_name() const { return NAME; }
01117 
01121                 virtual string get_desc() const { return "Generate random orientations within an asymmetric unit"; }
01122 
01127                 virtual TypeDict get_param_types() const
01128                 {
01129                         TypeDict d;
01130                         d.put("n", EMObject::INT, "The number of orientations to generate.");
01131                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01132                         d.put("phitoo", EMObject::BOOL, "Makes phi random as well");
01133                         return d;
01134                 }
01135 
01140                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01141 
01143                 static const string NAME;
01144 
01145                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const { (void)sym; (void)delta; return 0; }
01146         private:
01148                 RandomOrientationGenerator(const RandomOrientationGenerator&);
01150                 RandomOrientationGenerator& operator=(const RandomOrientationGenerator&);
01151 };
01152 
01164         class EvenOrientationGenerator : public OrientationGenerator
01165 {
01166         public:
01167                 EvenOrientationGenerator() {}
01168                 virtual ~EvenOrientationGenerator() {}
01169 
01173                 static OrientationGenerator *NEW()
01174                 {
01175                         return new EvenOrientationGenerator();
01176                 }
01177 
01178 
01182                 virtual string get_name() const { return NAME; }
01183 
01187                 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using Penczek's (94) approach"; }
01188 
01193                 virtual TypeDict get_param_types() const
01194                 {
01195                         TypeDict d = OrientationGenerator::get_param_types();
01196                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01197                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01198                         d.put("n", EMObject::INT, "The number of orientations to generate. This option is mutually exclusively of the delta argument.Will attempt to get as close to the number specified as possible.");
01199                         return d;
01200                 }
01201 
01206                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01207 
01209                 static const string NAME;
01210         private:
01212                 EvenOrientationGenerator(const EvenOrientationGenerator&);
01214                 EvenOrientationGenerator& operator=(const EvenOrientationGenerator&);
01221                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01222 
01223 };
01224 
01230 class SaffOrientationGenerator : public OrientationGenerator
01231 {
01232         public:
01233                 SaffOrientationGenerator() {}
01234                 virtual ~SaffOrientationGenerator() {}
01235 
01239                 static OrientationGenerator *NEW()
01240                 {
01241                         return new SaffOrientationGenerator();
01242                 }
01243 
01247                 virtual string get_name() const { return NAME; }
01248 
01252                 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using a spiraling method attributed to Saff"; }
01253 
01258                 virtual TypeDict get_param_types() const
01259                 {
01260                         TypeDict d = OrientationGenerator::get_param_types();
01261                         d.put("n", EMObject::INT, "The number of orientations to generate. This option is mutually exclusively of the delta argument.Will attempt to get as close to the number specified as possible.");
01262                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01263                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01264                         return d;
01265                 }
01266 
01271                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01272 
01274                 static const string NAME;
01275         private:
01277                 SaffOrientationGenerator(const SaffOrientationGenerator&);
01279                 SaffOrientationGenerator& operator=(const SaffOrientationGenerator&);
01286                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01287 
01288                 // This was a function that paid special considerations to the overall algorithm in the
01289                 // case of the Platonic symmetries, which have non trivial asymmetric units. But unfortunately
01290                 // it was bug-prone, and the approach in place already seemed good enough
01291                 //vector<Transform> gen_platonic_orientations(const Symmetry3D* const sym, const float& delta) const;
01292 };
01293 
01294 
01303 class OptimumOrientationGenerator : public OrientationGenerator
01304 {
01305         public:
01306                 OptimumOrientationGenerator() {}
01307                 virtual ~OptimumOrientationGenerator() {}
01308 
01312                 static OrientationGenerator *NEW()
01313                 {
01314                         return new OptimumOrientationGenerator();
01315                 }
01316 
01320                 virtual string get_name() const { return NAME; }
01321 
01325                 virtual string get_desc() const { return "Generate optimally distributed orientations within an asymmetric using a basic optimization technique"; }
01326 
01331                 virtual TypeDict get_param_types() const
01332                 {
01333                         TypeDict d = OrientationGenerator::get_param_types();
01334                         d.put("n", EMObject::INT, "The number of orientations to generate. This option is mutually exclusively of the delta argument.Will attempt to get as close to the number specified as possible.");
01335                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01336                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01337                         d.put("use", EMObject::STRING, "The orientation generation technique used to generate the initial distribution on the unit sphere.");
01338                         return d;
01339                 }
01340 
01345                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01346 
01348                 static const string NAME;
01349         private:
01351                 OptimumOrientationGenerator(const OptimumOrientationGenerator&);
01353                 OptimumOrientationGenerator& operator=(const OptimumOrientationGenerator&);
01360                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01361 
01362 
01365                 vector<Vec3f> optimize_distances(const vector<Transform>& v) const;
01366 };
01367 
01369         template <> Factory < OrientationGenerator >::Factory();
01371         void dump_orientgens();
01373         map<string, vector<string> > dump_orientgens_list();
01374 } // namespace EMAN
01375 
01376 #endif // eman__symmetry_h__
01377 

Generated on Tue May 25 17:13:36 2010 for EMAN2 by  doxygen 1.4.7