00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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"]; };
00522
00523
00524
00525
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; }
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
01289
01290
01291
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 }
01375
01376 #endif // eman__symmetry_h__
01377