Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

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 succesive 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 {
00522                         float daz = params.set_default("daz",0.0f);
00523                         if ( daz <= 0 ) throw InvalidValueException(daz,"Error, you must specify a positive non zero d_az");
00524                         return static_cast<int>(360.0/daz);
00525                 };
00526 
00531                 virtual int get_max_csym() const { return params["nsym"]; }
00532 
00534                 static const string NAME;
00535 
00539                 virtual bool is_h_sym() const { return true; }
00540 
00549                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00550 
00555                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00556 
00561                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00562         private:
00564                 HSym(const HSym&);
00566                 HSym& operator=(const HSym&);
00567 };
00568 
00582         class PlatonicSym : public Symmetry3D
00583 {
00584         public:
00585                 PlatonicSym() {};
00586                 virtual  ~PlatonicSym() {};
00587 
00592                 virtual TypeDict get_param_types() const
00593                 {
00594                         TypeDict d;
00595                         return d;
00596                 }
00597 
00613                 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00614 
00623                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00624 
00628                 virtual bool is_platonic_sym() const { return true; }
00629 
00630         protected:
00632                 Dict platonic_params;
00633 
00639                 void init();
00640 
00648                 float platonic_alt_lower_bound(const float& azimuth, const float& alpha) const;
00649 
00654                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00655 
00660                 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00661         private:
00663                 PlatonicSym(const PlatonicSym&);
00665                 PlatonicSym& operator=(const PlatonicSym&);
00666 };
00667 
00676         class TetrahedralSym : public PlatonicSym
00677 {
00678         public:
00681                 TetrahedralSym()  {init();}
00682                 virtual  ~TetrahedralSym() {}
00683 
00687                 static Symmetry3D *NEW()
00688                 {
00689                         return new TetrahedralSym();
00690                 }
00691 
00695                 virtual string get_name() const { return NAME; }
00696 
00697 
00701                 virtual string get_desc() const { return "Tetrahedral symmetry support"; }
00702 
00707                 virtual int get_max_csym() const { return 3; }
00708 
00721                 virtual Transform get_sym(const int n) const;
00722 
00731                 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00732 
00737                 virtual int get_nsym() const { return 12; };
00738 
00745                 virtual float get_az_alignment_offset() const;
00746 
00748                 static const string NAME;
00749 
00754                 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00755 
00759                 virtual bool is_tet_sym() const { return true; }
00760 
00761         private:
00763                 TetrahedralSym(const TetrahedralSym&);
00765                 TetrahedralSym& operator=(const TetrahedralSym&);
00766 
00767 
00768 };
00769 
00780         class OctahedralSym : public PlatonicSym
00781 {
00782         public:
00785                 OctahedralSym()  {init();}
00786                 virtual  ~OctahedralSym() {}
00787 
00791                 static Symmetry3D *NEW()
00792                 {
00793                         return new OctahedralSym();
00794                 }
00795 
00799                 virtual string get_name() const { return NAME; };
00800 
00804                 virtual string get_desc() const { return "Octahedral symmetry support"; }
00805 
00810                 virtual int get_max_csym() const { return 4; }
00811 
00829                 virtual Transform get_sym(const int n) const;
00830 
00835                 virtual int get_nsym() const { return 24; };
00836 
00838                 static const string NAME;
00839         private:
00841                 OctahedralSym(const OctahedralSym&);
00843                 OctahedralSym& operator=(const OctahedralSym&);
00844 };
00845 
00856         class IcosahedralSym : public PlatonicSym
00857 {
00858         public:
00861                 IcosahedralSym() {init(); }
00862                 virtual  ~IcosahedralSym() { }
00863 
00867                 static Symmetry3D *NEW()
00868                 {
00869                         return new IcosahedralSym();
00870                 }
00871 
00875                 virtual string get_name() const { return NAME; };
00876 
00880                 virtual string get_desc() const { return "Icosahedral symmetry support"; }
00881 
00886                 virtual int get_max_csym() const { return 5; }// 5 is the greatest symmetry
00887 
00894                 virtual Transform get_sym(const int n) const;
00895 
00900                 virtual int get_nsym() const { return 60; };
00901 
00908                 virtual float get_az_alignment_offset() const;
00909 
00911                 static const string NAME;
00912         private:
00914                 IcosahedralSym(const IcosahedralSym&);
00916                 IcosahedralSym& operator=(const IcosahedralSym&);
00917 };
00919         template <> Factory < Symmetry3D >::Factory();
00921         template <> Symmetry3D* Factory < Symmetry3D >::get(const string & instancename);
00923         void dump_symmetries();
00925         map<string, vector<string> > dump_symmetries_list();
00926 
00935         class OrientationGenerator : public FactoryBase
00936 {
00937         public:
00938                 OrientationGenerator() {};
00939                 virtual ~OrientationGenerator() {};
00940 
00945                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const  = 0;
00946 
00947                 virtual TypeDict get_param_types() const
00948                 {
00949                         TypeDict d;
00950                         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.");
00951                         d.put("random_phi", EMObject::BOOL,  "Causes the orientations to have a random phi. This occurs before the phitoo parameter is considered.");
00952                         return d;
00953                 }
00954 
00971                 bool add_orientation(vector<Transform>& v, const float& az, const float& alt) const;
00972 
00973 
00974 
00988                 float get_optimal_delta(const Symmetry3D* const sym, const int& n) const;
00989 
00996                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const = 0;
00997 
00998         protected:
00999                 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;
01000 
01001         private:
01003                 OrientationGenerator(const OrientationGenerator&);
01005                 OrientationGenerator& operator=(const OrientationGenerator&);
01006 };
01007 
01008 
01009 
01019 class EmanOrientationGenerator : public OrientationGenerator
01020 {
01021         public:
01022                 EmanOrientationGenerator() {};
01023                 virtual  ~EmanOrientationGenerator() {};
01024 
01028                 static OrientationGenerator *NEW()
01029                 {
01030                         return new EmanOrientationGenerator();
01031                 }
01032 
01036                 virtual string get_name() const { return NAME; }
01037 
01041                 virtual string get_desc() const { return "Generate orientations distributed quasi-uniformaly over the asymmetric unit using an altitude-proportional strategy"; }
01042 
01047                 virtual TypeDict get_param_types() const
01048                 {
01049                         TypeDict d = OrientationGenerator::get_param_types();
01050                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01051                         d.put("perturb", EMObject::BOOL, "Whether or not to perturb the generated orientations in a small local area, default is false.");
01052                         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.");
01053                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01054                         return d;
01055                 }
01056 
01061                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01062 
01064                 static const string NAME;
01065         private:
01067                 EmanOrientationGenerator(const EmanOrientationGenerator&);
01069                 EmanOrientationGenerator& operator=(const EmanOrientationGenerator&);
01070 
01077                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01078 
01079 
01088                 float get_az_delta(const float& delta,const float& altitude, const int maxcsym) const;
01089 
01090 };
01091 
01098 class RandomOrientationGenerator : public OrientationGenerator
01099 {
01100         public:
01101                 RandomOrientationGenerator() {}
01102                 virtual ~RandomOrientationGenerator() {}
01103 
01107                 static OrientationGenerator *NEW()
01108                 {
01109                         return new RandomOrientationGenerator();
01110                 }
01111 
01115                 virtual string get_name() const { return NAME; }
01116 
01120                 virtual string get_desc() const { return "Generate random orientations within an asymmetric unit"; }
01121 
01126                 virtual TypeDict get_param_types() const
01127                 {
01128                         TypeDict d;
01129                         d.put("n", EMObject::INT, "The number of orientations to generate.");
01130                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01131                         d.put("phitoo", EMObject::BOOL, "Makes phi random as well");
01132                         return d;
01133                 }
01134 
01139                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01140 
01142                 static const string NAME;
01143 
01144                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const { (void)sym; (void)delta; return 0; }
01145         private:
01147                 RandomOrientationGenerator(const RandomOrientationGenerator&);
01149                 RandomOrientationGenerator& operator=(const RandomOrientationGenerator&);
01150 };
01151 
01163         class EvenOrientationGenerator : public OrientationGenerator
01164 {
01165         public:
01166                 EvenOrientationGenerator() {}
01167                 virtual ~EvenOrientationGenerator() {}
01168 
01172                 static OrientationGenerator *NEW()
01173                 {
01174                         return new EvenOrientationGenerator();
01175                 }
01176 
01177 
01181                 virtual string get_name() const { return NAME; }
01182 
01186                 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using Penczek's (94) approach"; }
01187 
01192                 virtual TypeDict get_param_types() const
01193                 {
01194                         TypeDict d = OrientationGenerator::get_param_types();
01195                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01196                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01197                         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.");
01198                         return d;
01199                 }
01200 
01205                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01206 
01208                 static const string NAME;
01209         private:
01211                 EvenOrientationGenerator(const EvenOrientationGenerator&);
01213                 EvenOrientationGenerator& operator=(const EvenOrientationGenerator&);
01220                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01221 
01222 };
01223 
01229 class SaffOrientationGenerator : public OrientationGenerator
01230 {
01231         public:
01232                 SaffOrientationGenerator() {}
01233                 virtual ~SaffOrientationGenerator() {}
01234 
01238                 static OrientationGenerator *NEW()
01239                 {
01240                         return new SaffOrientationGenerator();
01241                 }
01242 
01246                 virtual string get_name() const { return NAME; }
01247 
01251                 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using a spiraling method attributed to Saff"; }
01252 
01257                 virtual TypeDict get_param_types() const
01258                 {
01259                         TypeDict d = OrientationGenerator::get_param_types();
01260                         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.");
01261                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01262                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01263                         return d;
01264                 }
01265 
01270                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01271 
01273                 static const string NAME;
01274         private:
01276                 SaffOrientationGenerator(const SaffOrientationGenerator&);
01278                 SaffOrientationGenerator& operator=(const SaffOrientationGenerator&);
01285                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01286 
01287                 // This was a function that paid special considerations to the overall algorithm in the
01288                 // case of the Platonic symmetries, which have non trivial asymmetric units. But unfortunately
01289                 // it was bug-prone, and the approach in place already seemed good enough
01290                 //vector<Transform> gen_platonic_orientations(const Symmetry3D* const sym, const float& delta) const;
01291 };
01292 
01293 
01302 class OptimumOrientationGenerator : public OrientationGenerator
01303 {
01304         public:
01305                 OptimumOrientationGenerator() {}
01306                 virtual ~OptimumOrientationGenerator() {}
01307 
01311                 static OrientationGenerator *NEW()
01312                 {
01313                         return new OptimumOrientationGenerator();
01314                 }
01315 
01319                 virtual string get_name() const { return NAME; }
01320 
01324                 virtual string get_desc() const { return "Generate optimally distributed orientations within an asymmetric using a basic optimization technique"; }
01325 
01330                 virtual TypeDict get_param_types() const
01331                 {
01332                         TypeDict d = OrientationGenerator::get_param_types();
01333                         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.");
01334                         d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01335                         d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01336                         d.put("use", EMObject::STRING, "The orientation generation technique used to generate the initial distribution on the unit sphere.");
01337                         return d;
01338                 }
01339 
01344                 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01345 
01347                 static const string NAME;
01348         private:
01350                 OptimumOrientationGenerator(const OptimumOrientationGenerator&);
01352                 OptimumOrientationGenerator& operator=(const OptimumOrientationGenerator&);
01359                 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01360 
01361 
01364                 vector<Vec3f> optimize_distances(const vector<Transform>& v) const;
01365 };
01366 
01368         template <> Factory < OrientationGenerator >::Factory();
01370         void dump_orientgens();
01372         map<string, vector<string> > dump_orientgens_list();
01373 } // namespace EMAN
01374 
01375 #endif // eman__symmetry_h__
01376 

Generated on Fri Apr 30 15:38:57 2010 for EMAN2 by  doxygen 1.3.9.1