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 Sat Nov 21 02:19:17 2009 for EMAN2 by  doxygen 1.5.6