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 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; }
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
01288
01289
01290
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 }
01374
01375 #endif // eman__symmetry_h__
01376