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 };
00918 template <> Factory < Symmetry3D >::Factory();
00920 template <> Symmetry3D* Factory < Symmetry3D >::get(const string & instancename);
00922 void dump_symmetries();
00924 map<string, vector<string> > dump_symmetries_list();
00925
00934 class OrientationGenerator : public FactoryBase
00935 {
00936 public:
00937 OrientationGenerator() {};
00938 virtual ~OrientationGenerator() {};
00939
00944 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const = 0;
00945
00946 virtual TypeDict get_param_types() const
00947 {
00948 TypeDict d;
00949 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.");
00950 d.put("random_phi", EMObject::BOOL, "Causes the orientations to have a random phi. This occurs before the phitoo parameter is considered.");
00951 return d;
00952 }
00953
00970 bool add_orientation(vector<Transform>& v, const float& az, const float& alt) const;
00971
00972
00973
00987 float get_optimal_delta(const Symmetry3D* const sym, const int& n) const;
00988
00995 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const = 0;
00996
00997 protected:
00998 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;
00999
01000 private:
01002 OrientationGenerator(const OrientationGenerator&);
01004 OrientationGenerator& operator=(const OrientationGenerator&);
01005 };
01006
01007
01008
01018 class EmanOrientationGenerator : public OrientationGenerator
01019 {
01020 public:
01021 EmanOrientationGenerator() {};
01022 virtual ~EmanOrientationGenerator() {};
01023
01027 static OrientationGenerator *NEW()
01028 {
01029 return new EmanOrientationGenerator();
01030 }
01031
01035 virtual string get_name() const { return NAME; }
01036
01040 virtual string get_desc() const { return "Generate orientations distributed quasi-uniformaly over the asymmetric unit using an altitude-proportional strategy"; }
01041
01046 virtual TypeDict get_param_types() const
01047 {
01048 TypeDict d = OrientationGenerator::get_param_types();
01049 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01050 d.put("perturb", EMObject::BOOL, "Whether or not to perturb the generated orientations in a small local area, default is true.");
01051 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.");
01052 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01053 d.put("alt_min", EMObject::FLOAT, "Minimum altitude value to include (alt=0 is Z axis). Default=0");
01054 d.put("alt_max", EMObject::FLOAT, "Maximum altitude value to include (alt=90 is X-Y plane). Default=no limit");
01055 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.");
01056 return d;
01057 }
01058
01063 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01064
01066 static const string NAME;
01067 private:
01069 EmanOrientationGenerator(const EmanOrientationGenerator&);
01071 EmanOrientationGenerator& operator=(const EmanOrientationGenerator&);
01072
01079 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01080
01081
01090 float get_az_delta(const float& delta,const float& altitude, const int maxcsym) const;
01091
01092 };
01093
01100 class RandomOrientationGenerator : public OrientationGenerator
01101 {
01102 public:
01103 RandomOrientationGenerator() {}
01104 virtual ~RandomOrientationGenerator() {}
01105
01109 static OrientationGenerator *NEW()
01110 {
01111 return new RandomOrientationGenerator();
01112 }
01113
01117 virtual string get_name() const { return NAME; }
01118
01122 virtual string get_desc() const { return "Generate random orientations within an asymmetric unit"; }
01123
01128 virtual TypeDict get_param_types() const
01129 {
01130 TypeDict d;
01131 d.put("n", EMObject::INT, "The number of orientations to generate.");
01132 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01133 d.put("phitoo", EMObject::BOOL, "Makes phi random as well");
01134 return d;
01135 }
01136
01141 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01142
01144 static const string NAME;
01145
01146 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const { (void)sym; (void)delta; return 0; }
01147 private:
01149 RandomOrientationGenerator(const RandomOrientationGenerator&);
01151 RandomOrientationGenerator& operator=(const RandomOrientationGenerator&);
01152 };
01153
01165 class EvenOrientationGenerator : public OrientationGenerator
01166 {
01167 public:
01168 EvenOrientationGenerator() {}
01169 virtual ~EvenOrientationGenerator() {}
01170
01174 static OrientationGenerator *NEW()
01175 {
01176 return new EvenOrientationGenerator();
01177 }
01178
01179
01183 virtual string get_name() const { return NAME; }
01184
01188 virtual string get_desc() const { return "Generate quasi-evenly distributed orientations within an asymmetric unit using Penczek's (94) approach"; }
01189
01194 virtual TypeDict get_param_types() const
01195 {
01196 TypeDict d = OrientationGenerator::get_param_types();
01197 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01198 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01199 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.");
01200 return d;
01201 }
01202
01207 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01208
01210 static const string NAME;
01211 private:
01213 EvenOrientationGenerator(const EvenOrientationGenerator&);
01215 EvenOrientationGenerator& operator=(const EvenOrientationGenerator&);
01222 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01223
01224 };
01225
01231 class SaffOrientationGenerator : public OrientationGenerator
01232 {
01233 public:
01234 SaffOrientationGenerator() {}
01235 virtual ~SaffOrientationGenerator() {}
01236
01240 static OrientationGenerator *NEW()
01241 {
01242 return new SaffOrientationGenerator();
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 a spiraling method attributed to Saff"; }
01254
01259 virtual TypeDict get_param_types() const
01260 {
01261 TypeDict d = OrientationGenerator::get_param_types();
01262 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.");
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("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
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 SaffOrientationGenerator(const SaffOrientationGenerator&);
01280 SaffOrientationGenerator& operator=(const SaffOrientationGenerator&);
01287 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01288
01289
01290
01291
01292
01293 };
01294
01295
01304 class OptimumOrientationGenerator : public OrientationGenerator
01305 {
01306 public:
01307 OptimumOrientationGenerator() {}
01308 virtual ~OptimumOrientationGenerator() {}
01309
01313 static OrientationGenerator *NEW()
01314 {
01315 return new OptimumOrientationGenerator();
01316 }
01317
01321 virtual string get_name() const { return NAME; }
01322
01326 virtual string get_desc() const { return "Generate optimally distributed orientations within an asymmetric using a basic optimization technique"; }
01327
01332 virtual TypeDict get_param_types() const
01333 {
01334 TypeDict d = OrientationGenerator::get_param_types();
01335 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.");
01336 d.put("inc_mirror", EMObject::BOOL, "Indicates whether or not to include the mirror portion of the asymmetric unit. Default is false.");
01337 d.put("delta", EMObject::FLOAT, "The angular separation of orientations in degrees. This option is mutually exclusively of the n argument.");
01338 d.put("use", EMObject::STRING, "The orientation generation technique used to generate the initial distribution on the unit sphere.");
01339 return d;
01340 }
01341
01346 virtual vector<Transform> gen_orientations(const Symmetry3D* const sym) const;
01347
01349 static const string NAME;
01350 private:
01352 OptimumOrientationGenerator(const OptimumOrientationGenerator&);
01354 OptimumOrientationGenerator& operator=(const OptimumOrientationGenerator&);
01361 virtual int get_orientations_tally(const Symmetry3D* const sym, const float& delta) const;
01362
01363
01366 vector<Vec3f> optimize_distances(const vector<Transform>& v) const;
01367 };
01368
01370 template <> Factory < OrientationGenerator >::Factory();
01372 void dump_orientgens();
01374 map<string, vector<string> > dump_orientgens_list();
01375 }
01376
01377 #endif // eman__symmetry_h__
01378