3 #include <boost/format.hpp>
5 #include "cctbx/sgtbx/space_group.h"
6 #include "cctbx/sgtbx/space_group_type.h"
7 #include "cctbx/miller/sym_equiv.h"
8 #include "cctbx/sgtbx/brick.h"
10 #include "ObjCryst/ObjCryst/CIF.h"
11 #include "ObjCryst/ObjCryst/Crystal.h"
12 #include "ObjCryst/ObjCryst/Atom.h"
13 #include "ObjCryst/ObjCryst/PowderPattern.h"
14 #include "ObjCryst/Quirks/Chronometer.h"
16 #define POSSIBLY_UNUSED(expr) (void)(expr)
22 CIFData::CIFAtom::CIFAtom():
23 mLabel(
""),mSymbol(
""),mOccupancy(1.0),mBiso(0.0)
29 void CIFData::ExtractAll(
const bool verbose)
31 (*fpObjCrystInformUser)(
"CIF: Extract Data...");
34 this->ExtractName(verbose);
35 this->ExtractUnitCell(verbose);
36 this->ExtractSpacegroup(verbose);
37 this->ExtractAtomicPositions(verbose);
38 this->ExtractAnisotropicADPs(verbose);
39 this->ExtractPowderPattern(verbose);
40 this->ExtractSingleCrystalData(verbose);
41 (*fpObjCrystInformUser)(
"CIF: Finished Extracting Data...");
44 void CIFData::ExtractUnitCell(
const bool verbose)
46 map<ci_string,string>::const_iterator positem;
47 positem=mvItem.find(
"_cell_length_a");
48 if(positem!=mvItem.end())
50 (*fpObjCrystInformUser)(
"CIF: Extract Unit Cell...");
51 mvLatticePar.resize(6);
52 mvLatticePar[0]=CIFNumeric2REAL(positem->second);
53 positem=mvItem.find(
"_cell_length_b");
54 if(positem!=mvItem.end())
55 mvLatticePar[1]=CIFNumeric2REAL(positem->second);
56 positem=mvItem.find(
"_cell_length_c");
57 if(positem!=mvItem.end())
58 mvLatticePar[2]=CIFNumeric2REAL(positem->second);
59 positem=mvItem.find(
"_cell_angle_alpha");
60 if(positem!=mvItem.end())
61 mvLatticePar[3]=CIFNumeric2REAL(positem->second);
62 positem=mvItem.find(
"_cell_angle_beta");
63 if(positem!=mvItem.end())
64 mvLatticePar[4]=CIFNumeric2REAL(positem->second);
65 positem=mvItem.find(
"_cell_angle_gamma");
66 if(positem!=mvItem.end())
67 mvLatticePar[5]=CIFNumeric2REAL(positem->second);
68 if(verbose) cout<<
"Found Lattice parameters:" <<mvLatticePar[0]<<
" , "<<mvLatticePar[1]<<
" , "<<mvLatticePar[2]
69 <<
" , "<<mvLatticePar[3]<<
" , "<<mvLatticePar[4]<<
" , "<<mvLatticePar[5]<<endl;
70 mvLatticePar[3]*=0.017453292519943295;
71 mvLatticePar[4]*=0.017453292519943295;
72 mvLatticePar[5]*=0.017453292519943295;
77 void CIFData::ExtractSpacegroup(
const bool verbose)
79 map<ci_string,string>::const_iterator positem;
80 positem=mvItem.find(
"_space_group_IT_number");
81 if(positem!=mvItem.end())
83 mSpacegroupNumberIT=positem->second;
84 if(verbose) cout<<
"Found spacegroup IT number:"<<mSpacegroupNumberIT<<endl;
88 positem=mvItem.find(
"_symmetry_Int_Tables_number");
89 if(positem!=mvItem.end())
91 mSpacegroupNumberIT=positem->second;
92 if(verbose) cout<<
"Found spacegroup IT number (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupNumberIT<<endl;
96 positem=mvItem.find(
"_space_group_name_Hall");
97 if(positem!=mvItem.end())
99 mSpacegroupSymbolHall=positem->second;
100 if(verbose) cout<<
"Found spacegroup Hall symbol:"<<mSpacegroupSymbolHall<<endl;
104 positem=mvItem.find(
"_symmetry_space_group_name_Hall");
105 if(positem!=mvItem.end())
107 mSpacegroupSymbolHall=positem->second;
108 if(verbose) cout<<
"Found spacegroup Hall symbol (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupSymbolHall<<endl;
112 positem=mvItem.find(
"_space_group_name_H-M_alt");
113 if(positem!=mvItem.end())
115 mSpacegroupHermannMauguin=positem->second;
116 if(verbose) cout<<
"Found spacegroup Hermann-Mauguin symbol:"<<mSpacegroupHermannMauguin<<endl;
120 positem=mvItem.find(
"_symmetry_space_group_name_H-M");
121 if(positem!=mvItem.end())
123 mSpacegroupHermannMauguin=positem->second;
124 if(verbose) cout<<
"Found spacegroup Hall Hermann-Mauguin (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupHermannMauguin<<endl;
128 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
129 loop!=mvLoop.end();++loop)
131 if(mvSymmetry_equiv_pos_as_xyz.size()>0)
break;
132 map<ci_string,vector<string> >::const_iterator pos;
133 pos=loop->second.find(
"_symmetry_equiv_pos_as_xyz");
134 if(pos!=loop->second.end())
136 if(verbose) cout<<
"Found list of _symmetry_equiv_pos_as_xyz:"<<endl;
137 for(
unsigned int i=0;i<pos->second.size();++i)
139 if(verbose) cout<<
" "<<pos->second[i]<<endl;
140 mvSymmetry_equiv_pos_as_xyz.insert(pos->second[i]);
146 void CIFData::ExtractName(
const bool verbose)
148 map<ci_string,string>::const_iterator positem;
149 positem=mvItem.find(
"_chemical_name_systematic");
150 if(positem!=mvItem.end())
152 mName=positem->second;
153 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
157 positem=mvItem.find(
"_chemical_name_mineral");
158 if(positem!=mvItem.end())
160 mName=positem->second;
161 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
165 positem=mvItem.find(
"_chemical_name_structure_type");
166 if(positem!=mvItem.end())
168 mName=positem->second;
169 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
173 positem=mvItem.find(
"_chemical_name_common");
174 if(positem!=mvItem.end())
176 mName=positem->second;
177 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
181 positem=mvItem.find(
"_chemical_formula_moiety");
182 if(positem!=mvItem.end())
184 mName=positem->second;
185 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
189 positem=mvItem.find(
"_chemical_formula_sum");
190 if(positem!=mvItem.end())
192 mName=positem->second;
193 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
201 positem=mvItem.find(
"_chemical_formula_analytical");
202 if(positem!=mvItem.end())
204 mFormula=positem->second;
205 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
209 positem=mvItem.find(
"_chemical_formula_structural");
210 if(positem!=mvItem.end())
212 mFormula=positem->second;
213 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
217 positem=mvItem.find(
"_chemical_formula_iupac");
218 if(positem!=mvItem.end())
220 mFormula=positem->second;
221 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
225 positem=mvItem.find(
"_chemical_formula_moiety");
226 if(positem!=mvItem.end())
228 mFormula=positem->second;
229 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
236 void CIFData::ExtractAtomicPositions(
const bool verbose)
238 map<ci_string,string>::const_iterator positem;
239 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
240 loop!=mvLoop.end();++loop)
242 if(mvAtom.size()>0)
break;
243 map<ci_string,vector<string> >::const_iterator posx,posy,posz,poslabel,possymbol,posoccup,posadp;
244 posx=loop->second.find(
"_atom_site_fract_x");
245 posy=loop->second.find(
"_atom_site_fract_y");
246 posz=loop->second.find(
"_atom_site_fract_z");
248 if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end()))
250 nb=posx->second.size();
252 for(
unsigned int i=0;i<nb;++i)
254 mvAtom[i].mCoordFrac.resize(3);
255 mvAtom[i].mCoordFrac[0]=CIFNumeric2REAL(posx->second[i]);
256 mvAtom[i].mCoordFrac[1]=CIFNumeric2REAL(posy->second[i]);
257 mvAtom[i].mCoordFrac[2]=CIFNumeric2REAL(posz->second[i]);
259 this->Fractional2CartesianCoord();
263 posx=loop->second.find(
"_atom_site_Cartn_x");
264 posy=loop->second.find(
"_atom_site_Cartn_y");
265 posz=loop->second.find(
"_atom_site_Cartn_z");
266 if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end()))
268 nb=posx->second.size();
270 for(
unsigned int i=0;i<nb;++i)
272 mvAtom[i].mCoordCart.resize(3);
273 mvAtom[i].mCoordCart[0]=CIFNumeric2REAL(posx->second[i]);
274 mvAtom[i].mCoordCart[1]=CIFNumeric2REAL(posy->second[i]);
275 mvAtom[i].mCoordCart[2]=CIFNumeric2REAL(posz->second[i]);
277 this->Cartesian2FractionalCoord();
282 (*fpObjCrystInformUser)(
"CIF: Extract Atoms...");
283 possymbol=loop->second.find(
"_atom_site_type_symbol");
284 if(possymbol!=loop->second.end())
285 for(
unsigned int i=0;i<nb;++i)
286 mvAtom[i].mSymbol=possymbol->second[i];
287 poslabel=loop->second.find(
"_atom_site_label");
288 if(poslabel!=loop->second.end())
289 for(
unsigned int i=0;i<nb;++i)
291 mvAtom[i].mLabel=poslabel->second[i];
292 if(possymbol==loop->second.end())
295 if(mvAtom[i].mLabel.size()==1)
296 if(isalpha(mvAtom[i].mLabel[0])) nbc=1;
297 if(mvAtom[i].mLabel.size()>=2)
299 if(isalpha(mvAtom[i].mLabel[0]) && isalpha(mvAtom[i].mLabel[1])) nbc=2;
300 else if(isalpha(mvAtom[i].mLabel[0])) nbc=1;
302 if(nbc>0) mvAtom[i].mSymbol=mvAtom[i].mLabel.substr(0,nbc);
303 else mvAtom[i].mSymbol=
"H";
307 posoccup=loop->second.find(
"_atom_site_occupancy");
308 if(posoccup!=loop->second.end())
309 for(
unsigned int i=0;i<nb;++i)
310 mvAtom[i].mOccupancy=CIFNumeric2REAL(posoccup->second[i]);
313 posadp=loop->second.find(
"_atom_site_B_iso_or_equiv");
314 if(posadp==loop->second.end())
316 mult = 8 * M_PI * M_PI;
317 posadp=loop->second.find(
"_atom_site_U_iso_or_equiv");
319 if(posadp!=loop->second.end())
320 for(
unsigned int i=0;i<nb;++i)
321 mvAtom[i].mBiso = mult*CIFNumeric2REAL(posadp->second[i]);
325 cout <<
"Found "<<nb<<
" atoms. Waouh !"<<endl;
326 for(
unsigned int i=0;i<nb;++i)
328 cout<<mvAtom[i].mLabel<<
" "<<mvAtom[i].mSymbol;
329 if(mvAtom[i].mCoordFrac.size()>0)
331 cout<<
" , Fractional: ";
332 for(
unsigned int j=0;j<mvAtom[i].mCoordFrac.size();++j)
333 cout<<mvAtom[i].mCoordFrac[j]<<
" ";
335 if(mvAtom[i].mCoordCart.size()>0)
337 cout<<
" , Cartesian: ";
338 for(
unsigned int j=0;j<mvAtom[i].mCoordCart.size();++j)
339 cout<<mvAtom[i].mCoordCart[j]<<
" ";
341 cout<<
" , Occupancy= "<<mvAtom[i].mOccupancy<<endl;
342 cout<<
" , Biso= "<<mvAtom[i].mBiso<<endl;
349 void CIFData::ExtractAnisotropicADPs(
const bool verbose)
352 typedef map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator LoopIter;
353 typedef map<ci_string,vector<string> >::const_iterator EntryIter;
355 const REAL utob = 8 * M_PI * M_PI;
357 const char* uijlabels[] = {
358 "_atom_site_aniso_U_11",
359 "_atom_site_aniso_U_22",
360 "_atom_site_aniso_U_33",
361 "_atom_site_aniso_U_12",
362 "_atom_site_aniso_U_13",
363 "_atom_site_aniso_U_23",
366 const char* bijlabels[] = {
367 "_atom_site_aniso_B_11",
368 "_atom_site_aniso_B_22",
369 "_atom_site_aniso_B_33",
370 "_atom_site_aniso_B_12",
371 "_atom_site_aniso_B_13",
372 "_atom_site_aniso_B_23"
377 EntryIter anisolabels, beta11, beta22, beta33, beta12, beta13, beta23;
379 EntryIter* betaiters[] = {&beta11, &beta22, &beta33, &beta12, &beta13, &beta23};
381 for(LoopIter loop=mvLoop.begin(); loop!=mvLoop.end();++loop)
387 anisolabels = loop->second.find(
"_atom_site_aniso_label");
390 if (anisolabels == loop->second.end())
continue;
391 if(verbose) cout <<
"Found labels!" << endl;
395 for (
int idx = 0; idx < 6; ++idx)
397 EntryIter& betaiter = *betaiters[idx];
398 betaiter = loop->second.find(bijlabels[idx]);
400 if(betaiter == loop->second.end())
402 betaiter = loop->second.find(uijlabels[idx]);
405 if(betaiter == loop->second.end()) mult[idx] = 0.0;
409 bool havedata =
false;
410 for (
int i = 0; i < 6; ++i)
412 if( mult[i] != 0 ) havedata =
true;
414 if (!havedata)
return;
418 size_t nb = anisolabels->second.size();
419 if(verbose) cout <<
"Have " << nb <<
" labels." << endl;
420 for (
size_t i = 0; i < nb; ++i)
422 string label = anisolabels->second[i];
423 if(verbose) cout << label << endl;
427 vector<CIFAtom>::iterator atom = mvAtom.begin();
428 for (; atom != mvAtom.end(); ++atom)
430 if (atom->mLabel == label)
432 atom->mBeta.resize(6, 0.0);
438 if (atom == mvAtom.end())
continue;
441 for (
int idx=0; idx<6; ++idx)
445 if(verbose) cout <<
"skipping index " << idx << endl;
449 EntryIter& betaiter = *betaiters[idx];
451 if (betaiter->second.size() <= i)
continue;
453 double beta = CIFNumeric2REAL(betaiter->second[i]);
454 atom->mBeta[idx] = mult[idx] * beta;
456 if(verbose) cout <<
"mBeta " << idx <<
" " << atom->mBeta[idx] << endl;
471 void CIFData::ExtractPowderPattern(
const bool verbose)
473 map<ci_string,string>::const_iterator positem;
474 positem=mvItem.find(
"_diffrn_radiation_wavelength");
475 if(positem==mvItem.end()) positem=mvItem.find(
"_pd_proc_wavelength");
476 if(positem!=mvItem.end())
478 mWavelength=CIFNumeric2REAL(positem->second);
485 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
486 loop!=mvLoop.end();++loop)
488 mDataType=WAVELENGTH_MONOCHROMATIC;
489 map<ci_string,vector<string> >::const_iterator pos_x,pos_iobs,pos_weight,pos_mon,pos_wavelength;
490 pos_wavelength=loop->second.find(
"_diffrn_radiation_wavelength");
491 if(pos_wavelength!=loop->second.end())
493 if(verbose) cout<<
"Found wavelength (in loop):"<<pos_wavelength->second[0];
494 mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]);
499 pos_iobs=loop->second.find(
"_pd_meas_counts_total");
500 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_meas_intensity_total");
501 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_proc_intensity_total");
502 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_proc_intensity_net");
503 if(pos_iobs==loop->second.end())
continue;
504 pos_weight=loop->second.find(
"_pd_proc_ls_weight");
505 pos_x=loop->second.find(
"_pd_proc_2theta_corrected");
506 if(pos_x==loop->second.end()) pos_x=loop->second.find(
"_pd_meas_angle_2theta");
507 if(pos_x==loop->second.end()) pos_x=loop->second.find(
"_pd_meas_2theta_scan");
508 if(pos_x==loop->second.end())
510 pos_x=loop->second.find(
"_pd_meas_time_of_flight");
511 if(pos_x!=loop->second.end()) mDataType=WAVELENGTH_TOF;
514 bool x_fixed_step=
false;
515 REAL xmin = 0, xmax = 0, xinc = 0;
516 POSSIBLY_UNUSED(xmax);
517 if(pos_x==loop->second.end())
519 map<ci_string,string>::const_iterator pos_min,pos_max,pos_inc;
520 pos_min=mvItem.find(
"_pd_proc_2theta_range_min");
521 if(pos_min==mvItem.end()) pos_min=mvItem.find(
"_pd_meas_2theta_range_min");
522 pos_max=mvItem.find(
"_pd_proc_2theta_range_max");
523 if(pos_max==mvItem.end()) pos_max=mvItem.find(
"_pd_meas_2theta_range_max");
524 pos_inc=mvItem.find(
"_pd_proc_2theta_range_inc");
525 if(pos_inc==mvItem.end()) pos_inc=mvItem.find(
"_pd_meas_2theta_range_inc");
526 if((pos_min!=mvItem.end()) && (pos_max!=mvItem.end()) && (pos_inc!=mvItem.end()) )
529 xmin=CIFNumeric2REAL(pos_min->second);
530 xmax=CIFNumeric2REAL(pos_max->second);
531 xinc=CIFNumeric2REAL(pos_inc->second);
534 pos_mon=loop->second.find(
"_pd_meas_intensity_monitor");
535 if(pos_mon==loop->second.end()) pos_mon=loop->second.find(
"_pd_meas_step_count_time");
537 if( (pos_iobs!=loop->second.end()) && ( (pos_x!=loop->second.end()) || (x_fixed_step)) )
539 const long nb=pos_iobs->second.size();
540 if(verbose) cout<<
"Found powder data, with "<<nb<<
" data points"<<endl;
541 mPowderPatternObs.resize(nb);
542 mPowderPatternX.resize(nb);
543 mPowderPatternSigma.resize(nb);
545 if(mDataType!=WAVELENGTH_TOF) mult=0.017453292519943295;
546 for(
long i=0;i<nb;++i)
548 mPowderPatternObs[i]=CIFNumeric2REAL(pos_iobs->second[i]);
549 if(x_fixed_step) mPowderPatternX[i]=(xmin+i*xinc)*mult;
550 else mPowderPatternX[i]=CIFNumeric2REAL(pos_x->second[i])*mult;
552 if(pos_weight!=loop->second.end())
554 mPowderPatternSigma[i]=CIFNumeric2REAL(pos_weight->second[i]);
555 if(mPowderPatternSigma[i]>0) mPowderPatternSigma[i]=1/sqrt(fabs(mPowderPatternSigma[i]));
556 else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i]));
558 else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i]));
559 if(pos_mon!=loop->second.end())
561 const REAL mon=CIFNumeric2REAL(pos_mon->second[i]);
564 mPowderPatternObs[i]/=mon;
565 mPowderPatternSigma[i]/=sqrt(mon);
574 void CIFData::ExtractSingleCrystalData(
const bool verbose)
576 map<ci_string,string>::const_iterator positem;
577 positem=mvItem.find(
"_diffrn_radiation_wavelength");
578 if(positem==mvItem.end()) positem=mvItem.find(
"_pd_proc_wavelength");
579 if(positem!=mvItem.end())
581 mWavelength=CIFNumeric2REAL(positem->second);
588 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
589 loop!=mvLoop.end();++loop)
591 mDataType=WAVELENGTH_MONOCHROMATIC;
592 map<ci_string,vector<string> >::const_iterator pos_h,pos_k,pos_l,pos_iobs,pos_sigma,pos_wavelength;
593 pos_wavelength=loop->second.find(
"_diffrn_radiation_wavelength");
594 if(pos_wavelength!=loop->second.end())
596 if(verbose) cout<<
"Found wavelength (in loop):"<<pos_wavelength->second[0];
597 mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]);
602 pos_iobs=loop->second.find(
"_refln_F_squared_meas");
603 if(pos_iobs==loop->second.end())
continue;
604 pos_sigma=loop->second.find(
"_refln_F_squared_sigma");
605 pos_h=loop->second.find(
"_refln_index_h");
606 pos_k=loop->second.find(
"_refln_index_k");
607 pos_l=loop->second.find(
"_refln_index_l");
609 if( (pos_iobs!=loop->second.end()) && (pos_h!=loop->second.end()) && (pos_k!=loop->second.end()) && (pos_l!=loop->second.end()))
611 const long nb=pos_iobs->second.size();
612 if(verbose) cout<<
"Found single crystal data, with "<<nb<<
" data points"<<endl;
618 for(
long i=0;i<nb;++i)
620 mIobs(i)=CIFNumeric2REAL(pos_iobs->second[i]);
621 mH(i)=CIFNumeric2Int(pos_h->second[i]);
622 mK(i)=CIFNumeric2Int(pos_k->second[i]);
623 mL(i)=CIFNumeric2Int(pos_l->second[i]);
624 if(pos_sigma!=loop->second.end()) mSigma(i)=CIFNumeric2REAL(pos_sigma->second[i]);
625 else mSigma(i)=sqrt(fabs(abs(mIobs(i))));
631 void CIFData::CalcMatrices(
const bool verbose)
633 if(mvLatticePar.size()==0)
return;
634 REAL a,b,c,alpha,beta,gamma;
635 REAL aa,bb,cc,alphaa,betaa,gammaa;
638 POSSIBLY_UNUSED(betaa);
639 POSSIBLY_UNUSED(gammaa);
644 alpha=mvLatticePar[3];
645 beta=mvLatticePar[4];
646 gamma=mvLatticePar[5];
648 v=sqrt(fabs(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
649 +2*cos(alpha)*cos(beta)*cos(gamma)));
655 alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
656 betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
657 gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
660 mOrthMatrix[0][1]=b*cos(gamma);
661 mOrthMatrix[0][2]=c*cos(beta);
664 mOrthMatrix[1][1]=b*sin(gamma);
665 mOrthMatrix[1][2]=-c*sin(beta)*cos(alphaa);
669 mOrthMatrix[2][2]=1/cc;
673 cm[0][0]=mOrthMatrix[0][0];
674 cm[0][1]=mOrthMatrix[0][1];
675 cm[0][2]=mOrthMatrix[0][2];
677 cm[1][0]=mOrthMatrix[1][0];
678 cm[1][1]=mOrthMatrix[1][1];
679 cm[1][2]=mOrthMatrix[1][2];
681 cm[2][0]=mOrthMatrix[2][0];
682 cm[2][1]=mOrthMatrix[2][1];
683 cm[2][2]=mOrthMatrix[2][2];
684 for(
long i=0;i<3;i++)
685 for(
long j=0;j<3;j++)
686 if(i==j) mOrthMatrixInvert[i][j]=1;
687 else mOrthMatrixInvert[i][j]=0;
688 for(
long i=0;i<3;i++)
691 for(
long j=i-1;j>=0;j--)
694 for(
long k=0;k<3;k++) mOrthMatrixInvert[j][k] -= mOrthMatrixInvert[i][k]*a;
695 for(
long k=0;k<3;k++) cm[j][k] -= cm[i][k]*a;
698 for(
long k=0;k<3;k++) mOrthMatrixInvert[i][k] /= a;
699 for(
long k=0;k<3;k++) cm[i][k] /= a;
703 cout <<
"Fractional2Cartesian matrix:"<<endl
704 <<mOrthMatrix[0][0]<<
" "<<mOrthMatrix[0][1]<<
" "<<mOrthMatrix[0][2]<<endl
705 <<mOrthMatrix[1][0]<<
" "<<mOrthMatrix[1][1]<<
" "<<mOrthMatrix[1][2]<<endl
706 <<mOrthMatrix[2][0]<<
" "<<mOrthMatrix[2][1]<<
" "<<mOrthMatrix[2][2]<<endl<<endl;
712 cout <<
"Cartesian2Fractional matrix:"<<endl
713 <<mOrthMatrixInvert[0][0]<<
" "<<mOrthMatrixInvert[0][1]<<
" "<<mOrthMatrixInvert[0][2]<<endl
714 <<mOrthMatrixInvert[1][0]<<
" "<<mOrthMatrixInvert[1][1]<<
" "<<mOrthMatrixInvert[1][2]<<endl
715 <<mOrthMatrixInvert[2][0]<<
" "<<mOrthMatrixInvert[2][1]<<
" "<<mOrthMatrixInvert[2][2]<<endl<<endl;
719 void CIFData::f2c(REAL &x,REAL &y, REAL &z)
721 const REAL x0=x,y0=y,z0=z;
722 x=mOrthMatrix[0][0]*x0+mOrthMatrix[0][1]*y0+mOrthMatrix[0][2]*z0;
723 y=mOrthMatrix[1][0]*x0+mOrthMatrix[1][1]*y0+mOrthMatrix[1][2]*z0;
724 z=mOrthMatrix[2][0]*x0+mOrthMatrix[2][1]*y0+mOrthMatrix[2][2]*z0;
727 void CIFData::c2f(REAL &x,REAL &y, REAL &z)
729 const REAL x0=x,y0=y,z0=z;
730 x=mOrthMatrixInvert[0][0]*x0+mOrthMatrixInvert[0][1]*y0+mOrthMatrixInvert[0][2]*z0;
731 y=mOrthMatrixInvert[1][0]*x0+mOrthMatrixInvert[1][1]*y0+mOrthMatrixInvert[1][2]*z0;
732 z=mOrthMatrixInvert[2][0]*x0+mOrthMatrixInvert[2][1]*y0+mOrthMatrixInvert[2][2]*z0;
735 void CIFData::Cartesian2FractionalCoord()
737 for(vector<CIFAtom>::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos)
739 pos->mCoordFrac.resize(3);
740 pos->mCoordFrac[0]=pos->mCoordCart.at(0);
741 pos->mCoordFrac[1]=pos->mCoordCart.at(1);
742 pos->mCoordFrac[2]=pos->mCoordCart.at(2);
743 c2f(pos->mCoordFrac[0],pos->mCoordFrac[1],pos->mCoordFrac[2]);
747 void CIFData::Fractional2CartesianCoord()
749 for(vector<CIFAtom>::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos)
751 pos->mCoordCart.resize(3);
752 pos->mCoordCart[0]=pos->mCoordFrac.at(0);
753 pos->mCoordCart[1]=pos->mCoordFrac.at(1);
754 pos->mCoordCart[2]=pos->mCoordFrac.at(2);
755 f2c(pos->mCoordCart[0],pos->mCoordCart[1],pos->mCoordCart[2]);
762 CIF::CIF(istream &is,
const bool interpret,
const bool verbose)
765 (*fpObjCrystInformUser)(
"CIF: Opening CIF");
771 while(is.get(c))in.put(c);
772 const float t0read=chrono.seconds();
773 s=(boost::format(
"CIF: Parsing CIF (reading dt=%5.3fs)")%t0read).str();
774 (*fpObjCrystInformUser)(s);
776 const float t1parse=chrono.seconds();
777 s=(boost::format(
"CIF: Finished Parsing, Extracting...(parsing dt=%5.3fs)") % (t1parse-t0read)).str();
778 (*fpObjCrystInformUser)(s);
781 for(map<string,CIFData>::iterator posd=mvData.begin();posd!=mvData.end();++posd)
782 posd->second.ExtractAll(verbose);
783 const float t2interpret=chrono.seconds();
784 s=(boost::format(
"CIF: Finished Import...(interpret dt=%5.3fs, total CIF import=%5.3fs)")%(t2interpret-t1parse)%t2interpret).str();
785 (*fpObjCrystInformUser)(s);
788 bool iseol(
const char c) {
return ((c==
'\n')||(c==
'\r'));}
790 std::string trimString(
const std::string &s)
792 const size_t i0 = s.find_first_not_of(
" \t\r\n");
793 if (i0 == std::string::npos)
return "";
794 const size_t i1 = s.find_last_not_of(
" \t\r\n");
795 return s.substr(i0, i1-i0+1);
803 while(!isgraph(in.peek())) in.get(lastc);
804 while(in.peek()==
'#')
809 while(!isgraph(in.peek())) in.get(lastc);
813 bool warning=!iseol(lastc);
815 cout<<
"WARNING: Trying to read a SemiColonTextField but last char is not an end-of-line char !"<<endl;
818 while(in.peek()!=
';')
825 if(vv) cout<<
"SemiColonTextField:"<<value<<endl;
826 if(warning && !vv) cout<<
"SemiColonTextField:"<<value<<endl;
827 return trimString(value);
829 if((in.peek()==
'\'') || (in.peek()==
'\"'))
834 while(!((lastc==delim)&&(!isgraph(in.peek()))) )
839 if(vv) cout<<
"QuotedString:"<<value<<endl;
840 return trimString(value.substr(0,value.size()-1));
844 if(vv) cout<<
"NormalValue:"<<value<<endl;
848 void CIF::Parse(stringstream &in)
858 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
865 if(block==
"") mvComment.push_back(tmp);
866 else mvData[block].mvComment.push_back(tmp);
868 if(vv)cout<<
"Comment:"<<tmp<<endl;
876 for (string::size_type pos = tag.find(
'.'); pos != string::npos; pos = tag.find(
'.', ++ pos))
877 tag.replace(pos, 1, 1,
'_');
879 if(value==
string(
"?"))
continue;
880 mvData[block].mvItem[ci_string(tag.c_str())]=value;
881 if(vv)cout<<
"New Tag:"<<tag<<
" ("<<value.size()<<
"):"<<value<<endl;
884 if((in.peek()==
'd') || (in.peek()==
'D'))
889 if(vv) cout<<endl<<endl<<
"NEW BLOCK DATA: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ->"<<block<<endl<<endl<<endl;
893 if((in.peek()==
'l') || (in.peek()==
'L'))
895 vector<ci_string> tit;
898 if(vv) cout<<
"LOOP : "<<tmp;
901 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
905 if(block==
"") mvComment.push_back(tmp);
906 else mvData[block].mvComment.push_back(tmp);
911 if(vv) cout<<endl<<
"End of loop titles:"<<(char)in.peek()<<endl;
916 for (string::size_type pos = tmp.find(
'.'); pos != string::npos; pos = tmp.find(
'.', ++ pos))
917 tmp.replace(pos, 1, 1,
'_');
918 tit.push_back(ci_string(tmp.c_str()));
919 if(vv) cout<<
" , "<<tmp;
922 map<ci_string,vector<string> > lp;
925 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
927 if(vv) cout<<
"LOOP VALUES...: "<<(char)in.peek()<<
" "<<endl;
928 if(in.peek()==
'_')
break;
933 if(block==
"") mvComment.push_back(tmp);
934 else mvData[block].mvComment.push_back(tmp);
936 if(vv) cout<<
"Comment in a loop (?):"<<tmp<<endl;
939 const std::ios::pos_type pos=in.tellg();
941 if(vv) cout<<
"WHATNEXT? "<<tmp;
942 if(ci_string(tmp.c_str())==
"loop_")
944 if(vv) cout<<endl<<
"END OF LOOP :"<<tmp<<endl;
949 if(ci_string(tmp.substr(0,5).c_str())==
"data_")
951 if(vv) cout<<endl<<
"END OF LOOP :"<<tmp<<endl;
957 for(
unsigned int i=0;i<tit.size();++i)
960 lp[tit[i]].push_back(value);
961 if(vv) cout<<
" #"<<i<<
" : "<<value<<endl;
966 for(
unsigned int i=0;i<tit.size();++i) stit.insert(tit[i]);
967 mvData[block].mvLoop[stit]=lp;
973 cout<<
"WARNING: did not understand : "<<junk<<endl;
977 REAL CIFNumeric2REAL(
const string &s)
979 if((s==
".") || (s==
"?"))
return 0.0;
983 ss.imbue(std::locale::classic());
988 int CIFNumeric2Int(
const string &s)
990 if((s==
".") || (s==
"?"))
return 0;
994 ss.imbue(std::locale::classic());
1005 const bool oneScatteringPowerPerElement,
const bool connectAtoms,
1008 (*fpObjCrystInformUser)(
"CIF: Opening CIF");
1013 std::map<ScatteringPower*,std::pair<REAL,unsigned int> > vElementBiso;
1015 bool import_multiple =
true;
1016 if(pCryst!=NULL) import_multiple =
false;
1017 bool crystal_found =
false;
1019 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1020 if(pos->second.mvLatticePar.size()==6)
1025 if((pos->second.mvAtom.size()==0) && (
gCrystalRegistry.GetNb()>0))
continue;
1028 if(pos->second.mSpacegroupSymbolHall!=
"")
try
1031 cctbx::sgtbx::space_group cctbxspg(pos->second.mSpacegroupSymbolHall);
1036 cctbxspg.type().number();
1037 cctbxspg.type().hall_symbol();
1038 cctbxspg.type().lookup_symbol();
1039 cctbxspg.match_tabulated_settings().extension();
1040 cctbxspg.match_tabulated_settings().hermann_mauguin();
1041 cctbxspg.type().universal_hermann_mauguin_symbol();
1042 cctbx::sgtbx::brick b(cctbxspg.type());
1043 spg=pos->second.mSpacegroupSymbolHall;
1047 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret Hall symbol:"<<pos->second.mSpacegroupSymbolHall, 10)
1049 if((spg==
"") && (pos->second.mSpacegroupHermannMauguin!=
""))
try
1052 cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupHermannMauguin));
1057 cctbxspg.type().number();
1058 cctbxspg.type().hall_symbol();
1059 cctbxspg.type().lookup_symbol();
1060 cctbxspg.type().universal_hermann_mauguin_symbol();
1061 cctbxspg.match_tabulated_settings().extension();
1062 cctbxspg.match_tabulated_settings().hermann_mauguin();
1063 cctbx::sgtbx::brick b(cctbxspg.type());
1064 spg=pos->second.mSpacegroupHermannMauguin;
1068 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret Hermann-Mauguin symbol:"<<pos->second.mSpacegroupHermannMauguin, 10)
1070 if((spg==
"") && (pos->second.mSpacegroupNumberIT!=
""))
1074 cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupNumberIT));
1079 cctbxspg.type().number();
1080 cctbxspg.type().hall_symbol();
1081 cctbxspg.type().lookup_symbol();
1082 cctbxspg.type().universal_hermann_mauguin_symbol();
1083 cctbxspg.match_tabulated_settings().extension();
1084 cctbxspg.match_tabulated_settings().hermann_mauguin();
1085 cctbx::sgtbx::brick b(cctbxspg.type());
1086 spg=pos->second.mSpacegroupNumberIT;
1090 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret spacegroup number (!) :"<<pos->second.mSpacegroupNumberIT, 10)
1092 if(spg==
"") spg=
"P1";
1093 if(verbose) cout<<
"Create crystal with spacegroup: "<<spg
1094 <<
" / "<<pos->second.mSpacegroupHermannMauguin
1095 <<
" / "<<pos->second.mSpacegroupSymbolHall
1096 <<
" / "<<pos->second.mSpacegroupNumberIT
1099 (*fpObjCrystInformUser)(
"CIF: Create Crystal=");
1101 pCryst=
new Crystal(pos->second.mvLatticePar[0],pos->second.mvLatticePar[1],pos->second.mvLatticePar[2],
1102 pos->second.mvLatticePar[3],pos->second.mvLatticePar[4],pos->second.mvLatticePar[5],spg);
1104 pCryst->
Init(pos->second.mvLatticePar[0],pos->second.mvLatticePar[1],pos->second.mvLatticePar[2],
1105 pos->second.mvLatticePar[3],pos->second.mvLatticePar[4],pos->second.mvLatticePar[5],spg,
"");
1106 crystal_found =
true;
1107 if( (pos->second.mSpacegroupSymbolHall==
"")
1108 &&(pos->second.mvSymmetry_equiv_pos_as_xyz.size()>0)
1109 &&(pos->second.mSpacegroupHermannMauguin!=
"")
1114 static vector<string> origin_list;
1115 if(origin_list.size()==0)
1117 origin_list.resize(5);
1119 origin_list[1]=
":1";
1120 origin_list[2]=
":2";
1121 origin_list[3]=
":R";
1122 origin_list[4]=
":H";
1125 string hmorig=pos->second.mSpacegroupHermannMauguin;
1128 if(verbose) cout<<
" Symmetry checking using symmetry_equiv_pos_as_xyz:"<<endl;
1129 string bestsymbol=hmorig;
1130 unsigned int bestscore=0;
1131 for(vector<string>::const_iterator posOrig=origin_list.begin();posOrig!=origin_list.end();++posOrig)
1138 catch(invalid_argument)
1147 unsigned int nbSymCommon=0;
1150 for(
unsigned int i=0;i<nbSymSpg;i++)
1152 for(set<string>::const_iterator posSymCIF=pos->second.mvSymmetry_equiv_pos_as_xyz.begin();
1153 posSymCIF!=pos->second.mvSymmetry_equiv_pos_as_xyz.end();++posSymCIF)
1155 cctbx::sgtbx::rt_mx mx1(*posSymCIF);
1157 mx1.mod_positive_in_place();
1158 mx2.mod_positive_in_place();
1167 <<
" nbsym:"<<nbSymSpg<<
"(cctbx), "
1168 <<pos->second.mvSymmetry_equiv_pos_as_xyz.size()<<
"(CIF)"
1169 <<
",common:"<<nbSymCommon<<endl;
1170 if(bestscore<((nbSymSpg==pos->second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon))
1172 bestscore=(nbSymSpg==pos->second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon;
1178 cout<<
"WOOPS: cctbx error ! Wrong symmetry_equiv_pos_as_xyz strings ?"<<endl;
1181 if(verbose) cout<<endl<<
"Finally using spacegroup name:"<<bestsymbol<<endl;
1185 if(pos->second.mName!=
"") pCryst->
SetName(pos->second.mName);
1186 else if(pos->second.mFormula!=
"") pCryst->
SetName(pos->second.mFormula);
1188 const float t1=chrono.seconds();
1189 (*fpObjCrystInformUser)((boost::format(
"CIF: Create Crystal:%s(%s)(dt=%6.3fs)")%pCryst->
GetName() % pCryst->
GetSpaceGroup().
GetName() % t1).str());
1191 bool doInformUserAllAtoms=
true;
1192 if(pos->second.mvAtom.size()>30) doInformUserAllAtoms =
false;
1193 unsigned int ctatom=0;
1194 for(vector<CIFData::CIFAtom>::const_iterator posat=pos->second.mvAtom.begin();posat!=pos->second.mvAtom.end();++posat)
1196 if( (posat->mLabel==
".") || (posat->mSymbol==
".") || (posat->mLabel.find(
"dummy")!=std::string::npos) || (posat->mSymbol.find(
"dummy")!=std::string::npos) )
1198 if(doInformUserAllAtoms) (*fpObjCrystInformUser)(
"CIF: Ignoring DUMMY Atom:"+posat->mLabel+
"(symbol="+posat->mSymbol+
")");
1206 if(oneScatteringPowerPerElement)
1218 if(verbose) cout<<
"Scattering power "<<posat->mSymbol<<
" not found, creating it..."<<endl;
1222 vElementBiso[sp].first+=posat->mBiso;
1223 vElementBiso[sp].second=1;
1235 if(posat->mBeta.size() == 6)
1251 if(verbose) cout<<
"Creating new scattering power for:"<<posat->mLabel<<endl;
1257 if(posat->mBeta.size() == 6)
1259 for (
int idx=0; idx<6; ++idx) sp->
SetBij(idx, posat->mBeta[idx]);
1267 pCryst->
AddScatterer(
new Atom(posat->mCoordFrac[0],posat->mCoordFrac[1],posat->mCoordFrac[2],
1268 posat->mLabel,sp,posat->mOccupancy));
1269 const float t22=chrono.seconds();
1270 if(doInformUserAllAtoms) (*fpObjCrystInformUser)((boost::format(
"CIF: new Atom: %s (%s) (Crystal creation=%6.3fs total)") % posat->mLabel % sp->
GetName() % t22).str());
1271 else if (ctatom%20 == 0)(*fpObjCrystInformUser)((boost::format(
"CIF: imported %u atoms (Crystal creation=%6.3fs total)") % ctatom % t22).str());
1273 if(oneScatteringPowerPerElement)
1275 for(std::map<
ScatteringPower*,std::pair<REAL,unsigned int> >::iterator pos=vElementBiso.begin();pos!=vElementBiso.end();++pos)
1276 pos->first->SetBiso(pos->second.first/pos->second.second);
1278 (*fpObjCrystInformUser)((boost::format(
"CIF: Finished importing %u atoms (Crystal creation=%6.3fs total)") % ctatom % chrono.seconds()).str());
1281 (*fpObjCrystInformUser)(
"CIF: connecting atoms");
1283 unsigned int ctat=0;
1284 unsigned int ctmol=0;
1290 (*fpObjCrystInformUser)((boost::format(
"CIF: finished connecting atoms (%u isolated atoms, %u molecules) (Crystal creation=%6.3fs total)") % ctat % ctmol % chrono.seconds()).str());
1293 if(!import_multiple)
return pCryst;
1295 if(!crystal_found)
throw ObjCrystException(
"CreateCrystalFromCIF: no structure found");
1302 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1304 if(pos->second.mPowderPatternObs.size()>10)
1308 (*fpObjCrystInformUser)((boost::format(
"CIF: Imported POWDER PATTERN, with %d points") % pPow->
GetNbPoint()).str());
1317 std::string name(
"");
1318 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1320 if(pos->second.mH.numElements()>0)
1322 (*fpObjCrystInformUser)((boost::format(
"CIF: Importing SINGLE CRYSTAL DIFFRACTION data")).str());
1328 (*fpObjCrystInformUser)((boost::format(
"CIF: Importing SINGLE CRYSTAL DIFFRACTION data: using last Crystal structure as corresponding crystal [%s]") % pcryst->
GetName().c_str()).str());
1334 pcryst->
SetName(
"Crystal data for Single Crystal Diffraction data imported from CIF");
1335 (*fpObjCrystInformUser)((boost::format(
"CIF: Importing SINGLE CRYSTAL DIFFRACTION data: creating new empty Crystal structure")).str());
1339 pData->
SetHklIobs(pos->second.mH,pos->second.mK,pos->second.mL,pos->second.mIobs,pos->second.mSigma);
1341 (*fpObjCrystInformUser)((boost::format(
"CIF: Imported SINGLE CRYSTAL DIFFRACTION data, with %d reflections") % pData->
GetNbRefl()).str());
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
DiffractionDataSingleCrystal * CreateSingleCrystalDataFromCIF(CIF &cif, Crystal *pcryst)
Create DiffractionDataSingleCrystal object(s) from a CIF, if possible.
Crystal * CreateCrystalFromCIF(CIF &cif, bool verbose, bool checkSymAsXYZ)
Extract Crystal object(s) from a CIF, if possible.
static REAL defaultWavelength
This is the default wavelength - whenever a "_diffrn_radiation_wavelength" or "_pd_proc_wavelength"en...
string CIFReadValue(stringstream &in, char &lastc)
Read one value, whether it is numeric, string or text.
ObjRegistry< Crystal > gCrystalRegistry("List of all Crystals")
Global registry for all Crystal objects.
PowderPattern * CreatePowderPatternFromCIF(CIF &cif)
Create PowderPattern object(s) from a CIF, if possible.
The basic atom scatterer, in a crystal.
The CIFData class holds all the information from a single data_ block from a cif file.
Main CIF class - parses the stream and separates data blocks, comments, items, loops.
std::map< std::string, CIFData > mvData
The data blocks, after parsing. The key is the name of the data block.
Crystal class: Unit cell, spacegroup, scatterers.
void ConnectAtoms(const REAL min_relat_dist=0.4, const REAL max_relat_dist=1.3, const bool warnuser_fail=false)
Convert as much as possible the crystal's atoms to molecule(s).
void AddScatteringPower(ScatteringPower *scattPow)
Add a ScatteringPower for this Crystal.
ObjRegistry< ScatteringPower > & GetScatteringPowerRegistry()
Get the registry of ScatteringPower included in this Crystal.
Scatterer & GetScatt(const string &scattName)
Provides an access to the scatterers.
std::string GetFormula() const
Formula with atoms in alphabetic order.
long GetNbScatterer() const
Number of scatterers in the crystal.
void AddScatterer(Scatterer *scatt)
Add a scatterer to the crystal.
void Init(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma, const string &SpaceGroupId, const string &name)
Init all Crystal parameters.
DiffractionData object for Single Crystal analysis.
void SetHklIobs(const CrystVector_long &h, const CrystVector_long &k, const CrystVector_long &l, const CrystVector_REAL &iObs, const CrystVector_REAL &sigma)
input H,K,L, Iobs and Sigma
Exception class for ObjCryst++ library.
This class only serves to temporarilly set the LC_NUMERIC C locale to "C", in order to use '.
Powder pattern class, with an observed pattern and several calculated components to modelize the patt...
void ImportPowderPatternCIF(const CIF &cif)
Import CIF powder pattern data.
unsigned long GetNbPoint() const
Number of points ?
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
long GetNbRefl() const
Return the number of reflections in this experiment.
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal.
virtual void SetBiso(const REAL newB)
Sets the isotropic temperature B factor.
REAL mBiso
Temperature isotropic B factor.
virtual void SetBij(const size_t &i, const size_t &j, const REAL newB)
Sets the anisotropic temperature B factor for (i, j) pair.
The Scattering Power for an Atom.
const string & GetName() const
Get the name of this spacegroup (its name, as supplied initially by the calling program or user)
const cctbx::sgtbx::space_group & GetCCTbxSpg() const
Get the underlying cctbx Spacegroup object.
void ChangeSpaceGroup(const string &spgId)
Change the spacegroup.
const SpaceGroup & GetSpaceGroup() const
Access to the SpaceGroup object.
virtual void SetName(const string &name)
Name of the object.
virtual const string & GetName() const
Name of the object.
Simple chronometer class, with microsecond precision.