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 "Helical symmetry, with support for N-start, pitch and limited tilt range. Specify as H<nsym>,<nstart>,<daz>,<tz in pix>[,<maxtilt>]"; }
00469
00476 virtual TypeDict get_param_types() const
00477 {
00478 TypeDict d;
00479 d.put("nsym", EMObject::INT, "The number of asymmetric units to generate. This could be infinite for helical symmetry. Normally a multiple of nstart.");
00480 d.put("nstart", EMObject::INT, "The Cn symmetry of a single Z-slice of the helix.");
00481 d.put("tz", EMObject::FLOAT, "The translational distance (along z) between successive identical subunits in angstroms (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, "Angstroms per pixel, default is 1.0, used only for tz");
00484 d.put("maxtilt", EMObject::FLOAT, "When generating projections, normally only 'side views' are created (3-D Z along Y in 2-D). This is the maximum out of plane tilt in degrees.");
00485 return d;
00486 }
00487
00500 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00501
00502
00511 virtual Transform get_sym(const int n) const;
00512
00519 virtual int get_nsym() const { return (int)params["nsym"]; };
00520
00521
00522
00523
00524
00525
00530 virtual int get_max_csym() const { return (int)params["nstart"]; }
00531
00533 static const string NAME;
00534
00538 virtual bool is_h_sym() const { return true; }
00539
00548 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00549
00554 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00555
00560 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00561 private:
00563 HSym(const HSym&);
00565 HSym& operator=(const HSym&);
00566 };
00567
00581 class PlatonicSym : public Symmetry3D
00582 {
00583 public:
00584 PlatonicSym() {};
00585 virtual ~PlatonicSym() {};
00586
00591 virtual TypeDict get_param_types() const
00592 {
00593 TypeDict d;
00594 return d;
00595 }
00596
00612 virtual Dict get_delimiters(const bool inc_mirror=false) const;
00613
00622 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00623
00627 virtual bool is_platonic_sym() const { return true; }
00628
00629 protected:
00631 Dict platonic_params;
00632
00638 void init();
00639
00647 float platonic_alt_lower_bound(const float& azimuth, const float& alpha) const;
00648
00653 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00654
00659 virtual vector<vector<Vec3f> > get_asym_unit_triangles(bool inc_mirror) const;
00660 private:
00662 PlatonicSym(const PlatonicSym&);
00664 PlatonicSym& operator=(const PlatonicSym&);
00665 };
00666
00675 class TetrahedralSym : public PlatonicSym
00676 {
00677 public:
00680 TetrahedralSym() {init();}
00681 virtual ~TetrahedralSym() {}
00682
00686 static Symmetry3D *NEW()
00687 {
00688 return new TetrahedralSym();
00689 }
00690
00694 virtual string get_name() const { return NAME; }
00695
00696
00700 virtual string get_desc() const { return "Tetrahedral symmetry support"; }
00701
00706 virtual int get_max_csym() const { return 3; }
00707
00720 virtual Transform get_sym(const int n) const;
00721
00730 virtual bool is_in_asym_unit(const float& altitude, const float& azimuth, const bool inc_mirror) const;
00731
00736 virtual int get_nsym() const { return 12; };
00737
00744 virtual float get_az_alignment_offset() const;
00745
00747 static const string NAME;
00748
00753 virtual vector<Vec3f> get_asym_unit_points(bool inc_mirror = false) const;
00754
00758 virtual bool is_tet_sym() const { return true; }
00759
00760 private:
00762 TetrahedralSym(const TetrahedralSym&);
00764 TetrahedralSym& operator=(const TetrahedralSym&);
00765
00766
00767 };
00768
00779 class OctahedralSym : public PlatonicSym
00780 {
00781 public:
00784 OctahedralSym() {init();}
00785 virtual ~OctahedralSym() {}
00786
00790 static Symmetry3D *NEW()
00791 {
00792 return new OctahedralSym();
00793 }
00794
00798 virtual string get_name() const { return NAME; };
00799
00803 virtual string get_desc() const { return "Octahedral symmetry support"; }
00804
00809 virtual int get_max_csym() const { return 4; }
00810
00828 virtual Transform get_sym(const int n) const;
00829
00834 virtual int get_nsym() const { return 24; };
00835
00837 static const string NAME;
00838 private:
00840 OctahedralSym(const OctahedralSym&);
00842 OctahedralSym& operator=(const OctahedralSym&);
00843 };
00844
00855 class IcosahedralSym : public PlatonicSym
00856 {
00857 public:
00860 IcosahedralSym() {init(); }
00861 virtual ~IcosahedralSym() { }
00862
00866 static Symmetry3D *NEW()
00867 {
00868 return new IcosahedralSym();
00869 }
00870
00874 virtual string get_name() const { return NAME; };
00875
00879 virtual string get_desc() const { return "Icosahedral symmetry support"; }
00880
00885 virtual int get_max_csym() const { return 5; }
00886
00893 virtual Transform get_sym(const int n) const;
00894
00899 virtual int get_nsym() const { return 60; };
00900
00907 virtual float get_az_alignment_offset() const;
00908
00910 static const string NAME;
00911 private:
00913 IcosahedralSym(const IcosahedralSym&);
00915 IcosahedralSym& operator=(const IcosahedralSym&);
00916 };
00917
00919 class Icosahedral2Sym : public PlatonicSym
00920 {
00921 public:
00924 Icosahedral2Sym() { }
00925 virtual ~Icosahedral2Sym() { init(); }
00926
00930 static Symmetry3D *NEW()
00931 {
00932 return new Icosahedral2Sym();
00933 }
00934
00938 virtual string get_name() const { return NAME; };
00939
00943 virtual string get_desc() const { return "Icosahedral 2 symmetry support"; }
00944
00949 virtual int get_max_csym() const { return 2; }
00950
00957 virtual Transform get_sym(const int n) const;
00958
00963 virtual int get_nsym() const { return 60; };
00964
00971 virtual float get_az_alignment_offset() const;
00972
00974 static const string NAME;
00975 private:
00977 Icosahedral2Sym(const Icosahedral2Sym&);
00979 Icosahedral2Sym& operator=(const Icosahedral2Sym&);
00980 };
00981
00983 template <> Factory < Symmetry3D >::Factory();
00985 template <> Symmetry3D* Factory < Symmetry3D >::get(const string & instancename);
00987 void dump_symmetries();
00989 map<string, vector<string> > dump_symmetries_list();
00990
00999 class OrientationGenerator : public FactoryBase
01000 {
01001 public:
01002 OrientationGenerator() {};
01003 virtual ~OrientationGenerator() {};
01004
01009 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const = 0;
01010
01011 virtual TypeDict get_param_types() const
01012 {
01013 TypeDict d;
01014 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.");
01015 d.put("random_phi", EMObject::BOOL, "Causes the orientations to have a random phi. This occurs before the phitoo parameter is considered.");
01016 return d;
01017 }
01018
01035 bool add_orientation(vector<Transform>& v, const float& az, const float& alt) const;
01036
01037
01038
01052 float get_optimal_delta(const Symmetry3D* const sym, const int& n) const;
01053
01060 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const = 0;
01061
01062 protected:
01063 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;
01064
01065 private:
01067 OrientationGenerator(const OrientationGenerator&);
01069 OrientationGenerator& operator=(const OrientationGenerator&);
01070 };
01071
01072
01073
01083 class EmanOrientationGenerator : public OrientationGenerator
01084 {
01085 public:
01086 EmanOrientationGenerator() {};
01087 virtual ~EmanOrientationGenerator() {};
01088
01092 static OrientationGenerator *NEW()
01093 {
01094 return new EmanOrientationGenerator();
01095 }
01096
01100 virtual string get_name() const { return NAME; }
01101
01105 virtual string get_desc() const { return "Generate orientations distributed quasi-uniformaly over the asymmetric unit using an altitude-proportional strategy"; }
01106
01111 virtual TypeDict get_param_types() const
01112 {
01113 TypeDict d = OrientationGenerator::get_param_types();
01114 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01115 d.put("perturb", EMObject::BOOL, "Whether or not to perturb the generated orientations in a small local area, default is true.");
01116 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.");
01117 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01118 d.put("alt_min", EMObject::FLOAT, "Minimum altitude value to include (alt=0 is Z axis). Default=0");
01119 d.put("alt_max", EMObject::FLOAT, "Maximum altitude value to include (alt=90 is X-Y plane). Default=no limit");
01120 d.put("breaksym", EMObject::BOOL, "If specified, still generates orientations filling the unit (hemi)sphere, but does it by filling one asymmetric unit, then generating all symmetric equivalents.");
01121 return d;
01122 }
01123
01128 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01129
01131 static const string NAME;
01132 private:
01134 EmanOrientationGenerator(const EmanOrientationGenerator&);
01136 EmanOrientationGenerator& operator=(const EmanOrientationGenerator&);
01137
01144 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01145
01146
01155 float get_az_delta(const float& delta,const float& altitude, const int maxcsym) const;
01156
01157 };
01158
01165 class RandomOrientationGenerator : public OrientationGenerator
01166 {
01167 public:
01168 RandomOrientationGenerator() {}
01169 virtual ~RandomOrientationGenerator() {}
01170
01174 static OrientationGenerator *NEW()
01175 {
01176 return new RandomOrientationGenerator();
01177 }
01178
01182 virtual string get_name() const { return NAME; }
01183
01187 virtual string get_desc() const { return "Generate random orientations within an asymmetric unit"; }
01188
01193 virtual TypeDict get_param_types() const
01194 {
01195 TypeDict d;
01196 d.put("n", EMObject::INT, "The number of orientations to generate.");
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("phitoo", EMObject::BOOL, "Makes phi random as well");
01199 return d;
01200 }
01201
01206 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01207
01209 static const string NAME;
01210
01211 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const { (void)sym; (void)delta; return 0; }
01212 private:
01214 RandomOrientationGenerator(const RandomOrientationGenerator&);
01216 RandomOrientationGenerator& operator=(const RandomOrientationGenerator&);
01217 };
01218
01230 class EvenOrientationGenerator : public OrientationGenerator
01231 {
01232 public:
01233 EvenOrientationGenerator() {}
01234 virtual ~EvenOrientationGenerator() {}
01235
01239 static OrientationGenerator *NEW()
01240 {
01241 return new EvenOrientationGenerator();
01242 }
01243
01244
01248 virtual string get_name() const { return NAME; }
01249
01253 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using Penczek's (94) approach"; }
01254
01259 virtual TypeDict get_param_types() const
01260 {
01261 TypeDict d = OrientationGenerator::get_param_types();
01262 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01263 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01264 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.");
01265 return d;
01266 }
01267
01272 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01273
01275 static const string NAME;
01276 private:
01278 EvenOrientationGenerator(const EvenOrientationGenerator&);
01280 EvenOrientationGenerator& operator=(const EvenOrientationGenerator&);
01287 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01288
01289 };
01290
01296 class SaffOrientationGenerator : public OrientationGenerator
01297 {
01298 public:
01299 SaffOrientationGenerator() {}
01300 virtual ~SaffOrientationGenerator() {}
01301
01305 static OrientationGenerator *NEW()
01306 {
01307 return new SaffOrientationGenerator();
01308 }
01309
01313 virtual string get_name() const { return NAME; }
01314
01318 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using a spiraling method attributed to Saff"; }
01319
01324 virtual TypeDict get_param_types() const
01325 {
01326 TypeDict d = OrientationGenerator::get_param_types();
01327 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.");
01328 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01329 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01330 return d;
01331 }
01332
01337 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01338
01340 static const string NAME;
01341 private:
01343 SaffOrientationGenerator(const SaffOrientationGenerator&);
01345 SaffOrientationGenerator& operator=(const SaffOrientationGenerator&);
01352 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01353
01354
01355
01356
01357
01358 };
01359
01360
01369 class OptimumOrientationGenerator : public OrientationGenerator
01370 {
01371 public:
01372 OptimumOrientationGenerator() {}
01373 virtual ~OptimumOrientationGenerator() {}
01374
01378 static OrientationGenerator *NEW()
01379 {
01380 return new OptimumOrientationGenerator();
01381 }
01382
01386 virtual string get_name() const { return NAME; }
01387
01391 virtual string get_desc() const { return "Generate optimally distributed orientations within an asymmetric using a basic optimization technique"; }
01392
01397 virtual TypeDict get_param_types() const
01398 {
01399 TypeDict d = OrientationGenerator::get_param_types();
01400 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.");
01401 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01402 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01403 d.put("use", EMObject::STRING, "The orientation generation technique used to generate the initial distribution on the unit sphere.");
01404 return d;
01405 }
01406
01411 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01412
01414 static const string NAME;
01415 private:
01417 OptimumOrientationGenerator(const OptimumOrientationGenerator&);
01419 OptimumOrientationGenerator& operator=(const OptimumOrientationGenerator&);
01426 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01427
01428
01431 vector<Vec3f> optimize_distances(const vector<Transform>& v) const;
01432 };
01433
01435 template <> Factory < OrientationGenerator >::Factory();
01437 void dump_orientgens();
01439 map<string, vector<string> > dump_orientgens_list();
01440 }
01441
01442 #endif // eman__symmetry_h__
01443