4 #include "cctbx/sgtbx/space_group.h"
5 #include "cctbx/sgtbx/space_group_type.h"
6 #include "cctbx/miller/sym_equiv.h"
7 #include "cctbx/sgtbx/brick.h"
9 #include "ObjCryst/ObjCryst/CIF.h"
10 #include "ObjCryst/ObjCryst/Crystal.h"
11 #include "ObjCryst/ObjCryst/Atom.h"
12 #include "ObjCryst/ObjCryst/PowderPattern.h"
13 #include "ObjCryst/Quirks/Chronometer.h"
19 CIFData::CIFAtom::CIFAtom():
20 mLabel(
""),mSymbol(
""),mOccupancy(1.0),mBiso(0.0)
26 void CIFData::ExtractAll(
const bool verbose)
28 (*fpObjCrystInformUser)(
"CIF: Extract Data...");
31 this->ExtractName(verbose);
32 this->ExtractUnitCell(verbose);
33 this->ExtractSpacegroup(verbose);
34 this->ExtractAtomicPositions(verbose);
35 this->ExtractAnisotropicADPs(verbose);
36 this->ExtractPowderPattern(verbose);
37 this->ExtractSingleCrystalData(verbose);
38 (*fpObjCrystInformUser)(
"CIF: Finished Extracting Data...");
41 void CIFData::ExtractUnitCell(
const bool verbose)
43 map<ci_string,string>::const_iterator positem;
44 positem=mvItem.find(
"_cell_length_a");
45 if(positem!=mvItem.end())
47 (*fpObjCrystInformUser)(
"CIF: Extract Unit Cell...");
48 mvLatticePar.resize(6);
49 mvLatticePar[0]=CIFNumeric2REAL(positem->second);
50 positem=mvItem.find(
"_cell_length_b");
51 if(positem!=mvItem.end())
52 mvLatticePar[1]=CIFNumeric2REAL(positem->second);
53 positem=mvItem.find(
"_cell_length_c");
54 if(positem!=mvItem.end())
55 mvLatticePar[2]=CIFNumeric2REAL(positem->second);
56 positem=mvItem.find(
"_cell_angle_alpha");
57 if(positem!=mvItem.end())
58 mvLatticePar[3]=CIFNumeric2REAL(positem->second);
59 positem=mvItem.find(
"_cell_angle_beta");
60 if(positem!=mvItem.end())
61 mvLatticePar[4]=CIFNumeric2REAL(positem->second);
62 positem=mvItem.find(
"_cell_angle_gamma");
63 if(positem!=mvItem.end())
64 mvLatticePar[5]=CIFNumeric2REAL(positem->second);
65 if(verbose) cout<<
"Found Lattice parameters:" <<mvLatticePar[0]<<
" , "<<mvLatticePar[1]<<
" , "<<mvLatticePar[2]
66 <<
" , "<<mvLatticePar[3]<<
" , "<<mvLatticePar[4]<<
" , "<<mvLatticePar[5]<<endl;
67 mvLatticePar[3]*=0.017453292519943295;
68 mvLatticePar[4]*=0.017453292519943295;
69 mvLatticePar[5]*=0.017453292519943295;
74 void CIFData::ExtractSpacegroup(
const bool verbose)
76 map<ci_string,string>::const_iterator positem;
77 positem=mvItem.find(
"_space_group_IT_number");
78 if(positem!=mvItem.end())
80 mSpacegroupNumberIT=positem->second;
81 if(verbose) cout<<
"Found spacegroup IT number:"<<mSpacegroupNumberIT<<endl;
85 positem=mvItem.find(
"_symmetry_Int_Tables_number");
86 if(positem!=mvItem.end())
88 mSpacegroupNumberIT=positem->second;
89 if(verbose) cout<<
"Found spacegroup IT number (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupNumberIT<<endl;
93 positem=mvItem.find(
"_space_group_name_Hall");
94 if(positem!=mvItem.end())
96 mSpacegroupSymbolHall=positem->second;
97 if(verbose) cout<<
"Found spacegroup Hall symbol:"<<mSpacegroupSymbolHall<<endl;
101 positem=mvItem.find(
"_symmetry_space_group_name_Hall");
102 if(positem!=mvItem.end())
104 mSpacegroupSymbolHall=positem->second;
105 if(verbose) cout<<
"Found spacegroup Hall symbol (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupSymbolHall<<endl;
109 positem=mvItem.find(
"_space_group_name_H-M_alt");
110 if(positem!=mvItem.end())
112 mSpacegroupHermannMauguin=positem->second;
113 if(verbose) cout<<
"Found spacegroup Hermann-Mauguin symbol:"<<mSpacegroupHermannMauguin<<endl;
117 positem=mvItem.find(
"_symmetry_space_group_name_H-M");
118 if(positem!=mvItem.end())
120 mSpacegroupHermannMauguin=positem->second;
121 if(verbose) cout<<
"Found spacegroup Hall Hermann-Mauguin (with OBSOLETE CIF #1.0 TAG):"<<mSpacegroupHermannMauguin<<endl;
125 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
126 loop!=mvLoop.end();++loop)
128 if(mvSymmetry_equiv_pos_as_xyz.size()>0)
break;
129 map<ci_string,vector<string> >::const_iterator pos;
130 pos=loop->second.find(
"_symmetry_equiv_pos_as_xyz");
131 if(pos!=loop->second.end())
133 if(verbose) cout<<
"Found list of _symmetry_equiv_pos_as_xyz:"<<endl;
134 for(
unsigned int i=0;i<pos->second.size();++i)
136 if(verbose) cout<<
" "<<pos->second[i]<<endl;
137 mvSymmetry_equiv_pos_as_xyz.insert(pos->second[i]);
143 void CIFData::ExtractName(
const bool verbose)
145 map<ci_string,string>::const_iterator positem;
146 positem=mvItem.find(
"_chemical_name_systematic");
147 if(positem!=mvItem.end())
149 mName=positem->second;
150 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
154 positem=mvItem.find(
"_chemical_name_mineral");
155 if(positem!=mvItem.end())
157 mName=positem->second;
158 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
162 positem=mvItem.find(
"_chemical_name_structure_type");
163 if(positem!=mvItem.end())
165 mName=positem->second;
166 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
170 positem=mvItem.find(
"_chemical_name_common");
171 if(positem!=mvItem.end())
173 mName=positem->second;
174 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
178 positem=mvItem.find(
"_chemical_formula_moiety");
179 if(positem!=mvItem.end())
181 mName=positem->second;
182 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
186 positem=mvItem.find(
"_chemical_formula_sum");
187 if(positem!=mvItem.end())
189 mName=positem->second;
190 if(verbose) cout<<
"Found chemical name:"<<mName<<endl;
198 positem=mvItem.find(
"_chemical_formula_analytical");
199 if(positem!=mvItem.end())
201 mFormula=positem->second;
202 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
206 positem=mvItem.find(
"_chemical_formula_structural");
207 if(positem!=mvItem.end())
209 mFormula=positem->second;
210 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
214 positem=mvItem.find(
"_chemical_formula_iupac");
215 if(positem!=mvItem.end())
217 mFormula=positem->second;
218 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
222 positem=mvItem.find(
"_chemical_formula_moiety");
223 if(positem!=mvItem.end())
225 mFormula=positem->second;
226 if(verbose) cout<<
"Found chemical formula:"<<mFormula<<endl;
233 void CIFData::ExtractAtomicPositions(
const bool verbose)
235 map<ci_string,string>::const_iterator positem;
236 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
237 loop!=mvLoop.end();++loop)
239 if(mvAtom.size()>0)
break;
240 map<ci_string,vector<string> >::const_iterator posx,posy,posz,poslabel,possymbol,posoccup,posadp;
241 posx=loop->second.find(
"_atom_site_fract_x");
242 posy=loop->second.find(
"_atom_site_fract_y");
243 posz=loop->second.find(
"_atom_site_fract_z");
245 if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end()))
247 nb=posx->second.size();
249 for(
unsigned int i=0;i<nb;++i)
251 mvAtom[i].mCoordFrac.resize(3);
252 mvAtom[i].mCoordFrac[0]=CIFNumeric2REAL(posx->second[i]);
253 mvAtom[i].mCoordFrac[1]=CIFNumeric2REAL(posy->second[i]);
254 mvAtom[i].mCoordFrac[2]=CIFNumeric2REAL(posz->second[i]);
256 this->Fractional2CartesianCoord();
260 posx=loop->second.find(
"_atom_site_Cartn_x");
261 posy=loop->second.find(
"_atom_site_Cartn_y");
262 posz=loop->second.find(
"_atom_site_Cartn_z");
263 if( (posx!=loop->second.end()) && (posy!=loop->second.end()) && (posz!=loop->second.end()))
265 nb=posx->second.size();
267 for(
unsigned int i=0;i<nb;++i)
269 mvAtom[i].mCoordCart.resize(3);
270 mvAtom[i].mCoordCart[0]=CIFNumeric2REAL(posx->second[i]);
271 mvAtom[i].mCoordCart[1]=CIFNumeric2REAL(posy->second[i]);
272 mvAtom[i].mCoordCart[2]=CIFNumeric2REAL(posz->second[i]);
274 this->Cartesian2FractionalCoord();
279 (*fpObjCrystInformUser)(
"CIF: Extract Atoms...");
280 possymbol=loop->second.find(
"_atom_site_type_symbol");
281 if(possymbol!=loop->second.end())
282 for(
unsigned int i=0;i<nb;++i)
283 mvAtom[i].mSymbol=possymbol->second[i];
284 poslabel=loop->second.find(
"_atom_site_label");
285 if(poslabel!=loop->second.end())
286 for(
unsigned int i=0;i<nb;++i)
288 mvAtom[i].mLabel=poslabel->second[i];
289 if(possymbol==loop->second.end())
292 if(mvAtom[i].mLabel.size()==1)
293 if(isalpha(mvAtom[i].mLabel[0])) nbc=1;
294 if(mvAtom[i].mLabel.size()>=2)
296 if(isalpha(mvAtom[i].mLabel[0]) && isalpha(mvAtom[i].mLabel[1])) nbc=2;
297 else if(isalpha(mvAtom[i].mLabel[0])) nbc=1;
299 if(nbc>0) mvAtom[i].mSymbol=mvAtom[i].mLabel.substr(0,nbc);
300 else mvAtom[i].mSymbol=
"H";
304 posoccup=loop->second.find(
"_atom_site_occupancy");
305 if(posoccup!=loop->second.end())
306 for(
unsigned int i=0;i<nb;++i)
307 mvAtom[i].mOccupancy=CIFNumeric2REAL(posoccup->second[i]);
310 posadp=loop->second.find(
"_atom_site_B_iso_or_equiv");
311 if(posadp==loop->second.end())
313 mult = 8 * M_PI * M_PI;
314 posadp=loop->second.find(
"_atom_site_U_iso_or_equiv");
316 if(posadp!=loop->second.end())
317 for(
unsigned int i=0;i<nb;++i)
318 mvAtom[i].mBiso = mult*CIFNumeric2REAL(posadp->second[i]);
322 cout <<
"Found "<<nb<<
" atoms. Waouh !"<<endl;
323 for(
unsigned int i=0;i<nb;++i)
325 cout<<mvAtom[i].mLabel<<
" "<<mvAtom[i].mSymbol;
326 if(mvAtom[i].mCoordFrac.size()>0)
328 cout<<
" , Fractional: ";
329 for(
unsigned int j=0;j<mvAtom[i].mCoordFrac.size();++j)
330 cout<<mvAtom[i].mCoordFrac[j]<<
" ";
332 if(mvAtom[i].mCoordCart.size()>0)
334 cout<<
" , Cartesian: ";
335 for(
unsigned int j=0;j<mvAtom[i].mCoordCart.size();++j)
336 cout<<mvAtom[i].mCoordCart[j]<<
" ";
338 cout<<
" , Occupancy= "<<mvAtom[i].mOccupancy<<endl;
339 cout<<
" , Biso= "<<mvAtom[i].mBiso<<endl;
346 void CIFData::ExtractAnisotropicADPs(
const bool verbose)
349 typedef map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator LoopIter;
350 typedef map<ci_string,vector<string> >::const_iterator EntryIter;
352 const REAL utob = 8 * M_PI * M_PI;
354 const char* uijlabels[] = {
355 "_atom_site_aniso_U_11",
356 "_atom_site_aniso_U_22",
357 "_atom_site_aniso_U_33",
358 "_atom_site_aniso_U_12",
359 "_atom_site_aniso_U_13",
360 "_atom_site_aniso_U_23",
363 const char* bijlabels[] = {
364 "_atom_site_aniso_B_11",
365 "_atom_site_aniso_B_22",
366 "_atom_site_aniso_B_33",
367 "_atom_site_aniso_B_12",
368 "_atom_site_aniso_B_13",
369 "_atom_site_aniso_B_23"
374 EntryIter anisolabels, beta11, beta22, beta33, beta12, beta13, beta23;
376 EntryIter* betaiters[] = {&beta11, &beta22, &beta33, &beta12, &beta13, &beta23};
378 for(LoopIter loop=mvLoop.begin(); loop!=mvLoop.end();++loop)
384 anisolabels = loop->second.find(
"_atom_site_aniso_label");
387 if (anisolabels == loop->second.end())
continue;
388 if(verbose) cout <<
"Found labels!" << endl;
392 for (
int idx = 0; idx < 6; ++idx)
394 EntryIter& betaiter = *betaiters[idx];
395 betaiter = loop->second.find(bijlabels[idx]);
397 if(betaiter == loop->second.end())
399 betaiter = loop->second.find(uijlabels[idx]);
402 if(betaiter == loop->second.end()) mult[idx] = 0.0;
406 bool havedata =
false;
407 for (
int i = 0; i < 6; ++i)
409 if( mult[i] != 0 ) havedata =
true;
411 if (!havedata)
return;
415 size_t nb = anisolabels->second.size();
416 if(verbose) cout <<
"Have " << nb <<
" labels." << endl;
417 for (
size_t i = 0; i < nb; ++i)
419 string label = anisolabels->second[i];
420 if(verbose) cout << label << endl;
424 vector<CIFAtom>::iterator atom = mvAtom.begin();
425 for (; atom != mvAtom.end(); ++atom)
427 if (atom->mLabel == label)
429 atom->mBeta.resize(6, 0.0);
435 if (atom == mvAtom.end())
continue;
438 for (
int idx=0; idx<6; ++idx)
442 if(verbose) cout <<
"skipping index " << idx << endl;
446 EntryIter& betaiter = *betaiters[idx];
448 if (betaiter->second.size() <= i)
continue;
450 double beta = CIFNumeric2REAL(betaiter->second[i]);
451 atom->mBeta[idx] = mult[idx] * beta;
453 if(verbose) cout <<
"mBeta " << idx <<
" " << atom->mBeta[idx] << endl;
468 void CIFData::ExtractPowderPattern(
const bool verbose)
470 map<ci_string,string>::const_iterator positem;
471 positem=mvItem.find(
"_diffrn_radiation_wavelength");
472 if(positem==mvItem.end()) positem=mvItem.find(
"_pd_proc_wavelength");
473 if(positem!=mvItem.end())
475 mWavelength=CIFNumeric2REAL(positem->second);
476 defaultWavelength=mWavelength;
477 cout<<
"Found wavelength:"<<defaultWavelength<<endl;
479 else mWavelength=defaultWavelength;
482 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
483 loop!=mvLoop.end();++loop)
485 mDataType=WAVELENGTH_MONOCHROMATIC;
486 map<ci_string,vector<string> >::const_iterator pos_x,pos_iobs,pos_weight,pos_mon,pos_wavelength;
487 pos_wavelength=loop->second.find(
"_diffrn_radiation_wavelength");
488 if(pos_wavelength!=loop->second.end())
490 cout<<
"Found wavelength (in loop):"<<pos_wavelength->second[0];
491 mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]);
492 defaultWavelength=mWavelength;
493 cout<<
" -> "<<defaultWavelength<<endl;
496 pos_iobs=loop->second.find(
"_pd_meas_counts_total");
497 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_meas_intensity_total");
498 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_proc_intensity_total");
499 if(pos_iobs==loop->second.end()) pos_iobs=loop->second.find(
"_pd_proc_intensity_net");
500 if(pos_iobs==loop->second.end())
continue;
501 pos_weight=loop->second.find(
"_pd_proc_ls_weight");
502 pos_x=loop->second.find(
"_pd_proc_2theta_corrected");
503 if(pos_x==loop->second.end()) pos_x=loop->second.find(
"_pd_meas_angle_2theta");
504 if(pos_x==loop->second.end()) pos_x=loop->second.find(
"_pd_meas_2theta_scan");
505 if(pos_x==loop->second.end())
507 pos_x=loop->second.find(
"_pd_meas_time_of_flight");
508 if(pos_x!=loop->second.end()) mDataType=WAVELENGTH_TOF;
511 bool x_fixed_step=
false;
512 REAL xmin = 0, xmax = 0, xinc = 0;
513 if(pos_x==loop->second.end())
515 map<ci_string,string>::const_iterator pos_min,pos_max,pos_inc;
516 pos_min=mvItem.find(
"_pd_proc_2theta_range_min");
517 if(pos_min==mvItem.end()) pos_min=mvItem.find(
"_pd_meas_2theta_range_min");
518 pos_max=mvItem.find(
"_pd_proc_2theta_range_max");
519 if(pos_max==mvItem.end()) pos_max=mvItem.find(
"_pd_meas_2theta_range_max");
520 pos_inc=mvItem.find(
"_pd_proc_2theta_range_inc");
521 if(pos_inc==mvItem.end()) pos_inc=mvItem.find(
"_pd_meas_2theta_range_inc");
522 if((pos_min!=mvItem.end()) && (pos_max!=mvItem.end()) && (pos_inc!=mvItem.end()) )
525 xmin=CIFNumeric2REAL(pos_min->second);
526 xmax=CIFNumeric2REAL(pos_max->second);
527 xinc=CIFNumeric2REAL(pos_inc->second);
530 pos_mon=loop->second.find(
"_pd_meas_intensity_monitor");
531 if(pos_mon==loop->second.end()) pos_mon=loop->second.find(
"_pd_meas_step_count_time");
533 if( (pos_iobs!=loop->second.end()) && ( (pos_x!=loop->second.end()) || (x_fixed_step)) )
535 const long nb=pos_iobs->second.size();
536 if(verbose) cout<<
"Found powder data, with "<<nb<<
" data points"<<endl;
537 mPowderPatternObs.resize(nb);
538 mPowderPatternX.resize(nb);
539 mPowderPatternSigma.resize(nb);
541 if(mDataType!=WAVELENGTH_TOF) mult=0.017453292519943295;
542 for(
long i=0;i<nb;++i)
544 mPowderPatternObs[i]=CIFNumeric2REAL(pos_iobs->second[i]);
545 if(x_fixed_step) mPowderPatternX[i]=(xmin+i*xinc)*mult;
546 else mPowderPatternX[i]=CIFNumeric2REAL(pos_x->second[i])*mult;
548 if(pos_weight!=loop->second.end())
550 mPowderPatternSigma[i]=CIFNumeric2REAL(pos_weight->second[i]);
551 if(mPowderPatternSigma[i]>0) mPowderPatternSigma[i]=1/sqrt(fabs(mPowderPatternSigma[i]));
552 else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i]));
554 else mPowderPatternSigma[i]=sqrt(fabs(mPowderPatternObs[i]));
555 if(pos_mon!=loop->second.end())
557 const REAL mon=CIFNumeric2REAL(pos_mon->second[i]);
560 mPowderPatternObs[i]/=mon;
561 mPowderPatternSigma[i]/=sqrt(mon);
570 void CIFData::ExtractSingleCrystalData(
const bool verbose)
572 map<ci_string,string>::const_iterator positem;
573 positem=mvItem.find(
"_diffrn_radiation_wavelength");
574 if(positem==mvItem.end()) positem=mvItem.find(
"_pd_proc_wavelength");
575 if(positem!=mvItem.end())
577 mWavelength=CIFNumeric2REAL(positem->second);
578 defaultWavelength=mWavelength;
579 cout<<
"Found wavelength:"<<defaultWavelength<<endl;
581 else mWavelength=defaultWavelength;
584 for(map<set<ci_string>,map<ci_string,vector<string> > >::const_iterator loop=mvLoop.begin();
585 loop!=mvLoop.end();++loop)
587 mDataType=WAVELENGTH_MONOCHROMATIC;
588 map<ci_string,vector<string> >::const_iterator pos_h,pos_k,pos_l,pos_iobs,pos_sigma,pos_wavelength;
589 pos_wavelength=loop->second.find(
"_diffrn_radiation_wavelength");
590 if(pos_wavelength!=loop->second.end())
592 cout<<
"Found wavelength (in loop):"<<pos_wavelength->second[0];
593 mWavelength=CIFNumeric2REAL(pos_wavelength->second[0]);
594 defaultWavelength=mWavelength;
595 cout<<
" -> "<<defaultWavelength<<endl;
598 pos_iobs=loop->second.find(
"_refln_F_squared_meas");
599 if(pos_iobs==loop->second.end())
continue;
600 pos_sigma=loop->second.find(
"_refln_F_squared_sigma");
601 pos_h=loop->second.find(
"_refln_index_h");
602 pos_k=loop->second.find(
"_refln_index_k");
603 pos_l=loop->second.find(
"_refln_index_l");
605 if( (pos_iobs!=loop->second.end()) && (pos_h!=loop->second.end()) && (pos_k!=loop->second.end()) && (pos_l!=loop->second.end()))
607 const long nb=pos_iobs->second.size();
608 if(verbose) cout<<
"Found single crystal data, with "<<nb<<
" data points"<<endl;
614 for(
long i=0;i<nb;++i)
616 mIobs(i)=CIFNumeric2REAL(pos_iobs->second[i]);
617 mH(i)=CIFNumeric2Int(pos_h->second[i]);
618 mK(i)=CIFNumeric2Int(pos_k->second[i]);
619 mL(i)=CIFNumeric2Int(pos_l->second[i]);
620 if(pos_sigma!=loop->second.end()) mSigma(i)=CIFNumeric2REAL(pos_sigma->second[i]);
621 else mSigma(i)=sqrt(fabs(abs(mIobs(i))));
627 void CIFData::CalcMatrices(
const bool verbose)
629 if(mvLatticePar.size()==0)
return;
630 REAL a,b,c,alpha,beta,gamma;
631 REAL aa,bb,cc,alphaa,betaa,gammaa;
636 alpha=mvLatticePar[3];
637 beta=mvLatticePar[4];
638 gamma=mvLatticePar[5];
640 v=sqrt(fabs(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
641 +2*cos(alpha)*cos(beta)*cos(gamma)));
647 alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
648 betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
649 gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
652 mOrthMatrix[0][1]=b*cos(gamma);
653 mOrthMatrix[0][2]=c*cos(beta);
656 mOrthMatrix[1][1]=b*sin(gamma);
657 mOrthMatrix[1][2]=-c*sin(beta)*cos(alphaa);
661 mOrthMatrix[2][2]=1/cc;
665 cm[0][0]=mOrthMatrix[0][0];
666 cm[0][1]=mOrthMatrix[0][1];
667 cm[0][2]=mOrthMatrix[0][2];
669 cm[1][0]=mOrthMatrix[1][0];
670 cm[1][1]=mOrthMatrix[1][1];
671 cm[1][2]=mOrthMatrix[1][2];
673 cm[2][0]=mOrthMatrix[2][0];
674 cm[2][1]=mOrthMatrix[2][1];
675 cm[2][2]=mOrthMatrix[2][2];
676 for(
long i=0;i<3;i++)
677 for(
long j=0;j<3;j++)
678 if(i==j) mOrthMatrixInvert[i][j]=1;
679 else mOrthMatrixInvert[i][j]=0;
680 for(
long i=0;i<3;i++)
683 for(
long j=i-1;j>=0;j--)
686 for(
long k=0;k<3;k++) mOrthMatrixInvert[j][k] -= mOrthMatrixInvert[i][k]*a;
687 for(
long k=0;k<3;k++) cm[j][k] -= cm[i][k]*a;
690 for(
long k=0;k<3;k++) mOrthMatrixInvert[i][k] /= a;
691 for(
long k=0;k<3;k++) cm[i][k] /= a;
695 cout <<
"Fractional2Cartesian matrix:"<<endl
696 <<mOrthMatrix[0][0]<<
" "<<mOrthMatrix[0][1]<<
" "<<mOrthMatrix[0][2]<<endl
697 <<mOrthMatrix[1][0]<<
" "<<mOrthMatrix[1][1]<<
" "<<mOrthMatrix[1][2]<<endl
698 <<mOrthMatrix[2][0]<<
" "<<mOrthMatrix[2][1]<<
" "<<mOrthMatrix[2][2]<<endl<<endl;
704 cout <<
"Cartesian2Fractional matrix:"<<endl
705 <<mOrthMatrixInvert[0][0]<<
" "<<mOrthMatrixInvert[0][1]<<
" "<<mOrthMatrixInvert[0][2]<<endl
706 <<mOrthMatrixInvert[1][0]<<
" "<<mOrthMatrixInvert[1][1]<<
" "<<mOrthMatrixInvert[1][2]<<endl
707 <<mOrthMatrixInvert[2][0]<<
" "<<mOrthMatrixInvert[2][1]<<
" "<<mOrthMatrixInvert[2][2]<<endl<<endl;
711 void CIFData::f2c(REAL &x,REAL &y, REAL &z)
713 const REAL x0=x,y0=y,z0=z;
714 x=mOrthMatrix[0][0]*x0+mOrthMatrix[0][1]*y0+mOrthMatrix[0][2]*z0;
715 y=mOrthMatrix[1][0]*x0+mOrthMatrix[1][1]*y0+mOrthMatrix[1][2]*z0;
716 z=mOrthMatrix[2][0]*x0+mOrthMatrix[2][1]*y0+mOrthMatrix[2][2]*z0;
719 void CIFData::c2f(REAL &x,REAL &y, REAL &z)
721 const REAL x0=x,y0=y,z0=z;
722 x=mOrthMatrixInvert[0][0]*x0+mOrthMatrixInvert[0][1]*y0+mOrthMatrixInvert[0][2]*z0;
723 y=mOrthMatrixInvert[1][0]*x0+mOrthMatrixInvert[1][1]*y0+mOrthMatrixInvert[1][2]*z0;
724 z=mOrthMatrixInvert[2][0]*x0+mOrthMatrixInvert[2][1]*y0+mOrthMatrixInvert[2][2]*z0;
727 void CIFData::Cartesian2FractionalCoord()
729 for(vector<CIFAtom>::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos)
731 pos->mCoordFrac.resize(3);
732 pos->mCoordFrac[0]=pos->mCoordCart.at(0);
733 pos->mCoordFrac[1]=pos->mCoordCart.at(1);
734 pos->mCoordFrac[2]=pos->mCoordCart.at(2);
735 c2f(pos->mCoordFrac[0],pos->mCoordFrac[1],pos->mCoordFrac[2]);
739 void CIFData::Fractional2CartesianCoord()
741 for(vector<CIFAtom>::iterator pos=mvAtom.begin();pos!=mvAtom.end();++pos)
743 pos->mCoordCart.resize(3);
744 pos->mCoordCart[0]=pos->mCoordFrac.at(0);
745 pos->mCoordCart[1]=pos->mCoordFrac.at(1);
746 pos->mCoordCart[2]=pos->mCoordFrac.at(2);
747 f2c(pos->mCoordCart[0],pos->mCoordCart[1],pos->mCoordCart[2]);
754 CIF::CIF(istream &is,
const bool interpret,
const bool verbose)
757 (*fpObjCrystInformUser)(
"CIF: Opening CIF");
763 while(is.get(c))in.put(c);
764 const float t0read=chrono.seconds();
765 s=(boost::format(
"CIF: Parsing CIF (reading dt=%5.3fs)")%t0read).str();
766 (*fpObjCrystInformUser)(s);
768 const float t1parse=chrono.seconds();
769 s=(boost::format(
"CIF: Finished Parsing, Extracting...(parsing dt=%5.3fs)") % (t1parse-t0read)).str();
770 (*fpObjCrystInformUser)(s);
773 for(map<string,CIFData>::iterator posd=mvData.begin();posd!=mvData.end();++posd)
774 posd->second.ExtractAll(verbose);
775 const float t2interpret=chrono.seconds();
776 s=(boost::format(
"CIF: Finished Import...(interpret dt=%5.3fs, total CIF import=%5.3fs)")%(t2interpret-t1parse)%t2interpret).str();
777 (*fpObjCrystInformUser)(s);
780 bool iseol(
const char c) {
return ((c==
'\n')||(c==
'\r'));}
782 std::string trimString(
const std::string &s)
784 const size_t i0 = s.find_first_not_of(
" \t\r\n");
785 if (i0 == std::string::npos)
return "";
786 const size_t i1 = s.find_last_not_of(
" \t\r\n");
787 return s.substr(i0, i1-i0+1);
795 while(!isgraph(in.peek())) in.get(lastc);
796 while(in.peek()==
'#')
801 while(!isgraph(in.peek())) in.get(lastc);
805 bool warning=!iseol(lastc);
807 cout<<
"WARNING: Trying to read a SemiColonTextField but last char is not an end-of-line char !"<<endl;
810 while(in.peek()!=
';')
817 if(vv) cout<<
"SemiColonTextField:"<<value<<endl;
818 if(warning && !vv) cout<<
"SemiColonTextField:"<<value<<endl;
819 return trimString(value);
821 if((in.peek()==
'\'') || (in.peek()==
'\"'))
826 while(!((lastc==delim)&&(!isgraph(in.peek()))) )
831 if(vv) cout<<
"QuotedString:"<<value<<endl;
832 return trimString(value.substr(0,value.size()-1));
836 if(vv) cout<<
"NormalValue:"<<value<<endl;
840 void CIF::Parse(stringstream &in)
848 mess<<
"CIF: Parsing:"<<in.tellg();
849 (*fpObjCrystInformUser)(mess.str());
850 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
857 if(block==
"") mvComment.push_back(tmp);
858 else mvData[block].mvComment.push_back(tmp);
860 if(vv)cout<<
"Comment:"<<tmp<<endl;
868 for (string::size_type pos = tag.find(
'.'); pos != string::npos; pos = tag.find(
'.', ++ pos))
869 tag.replace(pos, 1, 1,
'_');
871 if(value==
string(
"?"))
continue;
872 mvData[block].mvItem[ci_string(tag.c_str())]=value;
873 if(vv)cout<<
"New Tag:"<<tag<<
" ("<<value.size()<<
"):"<<value<<endl;
876 if((in.peek()==
'd') || (in.peek()==
'D'))
881 if(vv) cout<<endl<<endl<<
"NEW BLOCK DATA: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ->"<<block<<endl<<endl<<endl;
885 if((in.peek()==
'l') || (in.peek()==
'L'))
887 vector<ci_string> tit;
890 if(vv) cout<<
"LOOP : "<<tmp;
893 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
897 if(block==
"") mvComment.push_back(tmp);
898 else mvData[block].mvComment.push_back(tmp);
903 if(vv) cout<<endl<<
"End of loop titles:"<<(char)in.peek()<<endl;
908 for (string::size_type pos = tmp.find(
'.'); pos != string::npos; pos = tmp.find(
'.', ++ pos))
909 tmp.replace(pos, 1, 1,
'_');
910 tit.push_back(ci_string(tmp.c_str()));
911 if(vv) cout<<
" , "<<tmp;
914 map<ci_string,vector<string> > lp;
917 while(!isgraph(in.peek()) && !in.eof()) in.get(lastc);
919 if(vv) cout<<
"LOOP VALUES...: "<<(char)in.peek()<<
" "<<endl;
920 if(in.peek()==
'_')
break;
925 if(block==
"") mvComment.push_back(tmp);
926 else mvData[block].mvComment.push_back(tmp);
928 if(vv) cout<<
"Comment in a loop (?):"<<tmp<<endl;
931 const std::ios::pos_type pos=in.tellg();
933 if(vv) cout<<
"WHATNEXT? "<<tmp;
934 if(ci_string(tmp.c_str())==
"loop_")
936 if(vv) cout<<endl<<
"END OF LOOP :"<<tmp<<endl;
941 if(ci_string(tmp.substr(0,5).c_str())==
"data_")
943 if(vv) cout<<endl<<
"END OF LOOP :"<<tmp<<endl;
949 for(
unsigned int i=0;i<tit.size();++i)
952 lp[tit[i]].push_back(value);
953 if(vv) cout<<
" #"<<i<<
" : "<<value<<endl;
958 for(
unsigned int i=0;i<tit.size();++i) stit.insert(tit[i]);
959 mvData[block].mvLoop[stit]=lp;
965 cout<<
"WARNING: did not understand : "<<junk<<endl;
969 REAL CIFNumeric2REAL(
const string &s)
971 if((s==
".") || (s==
"?"))
return 0.0;
975 ss.imbue(std::locale::classic());
980 int CIFNumeric2Int(
const string &s)
982 if((s==
".") || (s==
"?"))
return 0;
986 ss.imbue(std::locale::classic());
999 (*fpObjCrystInformUser)(
"CIF: Opening CIF");
1004 std::map<ScatteringPower*,std::pair<REAL,unsigned int> > vElementBiso;
1007 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1008 if(pos->second.mvLatticePar.size()==6)
1013 if((pos->second.mvAtom.size()==0) && (
gCrystalRegistry.GetNb()>0))
continue;
1016 if(pos->second.mSpacegroupSymbolHall!=
"")
try
1019 cctbx::sgtbx::space_group cctbxspg(pos->second.mSpacegroupSymbolHall);
1024 cctbxspg.type().number();
1025 cctbxspg.type().hall_symbol();
1026 cctbxspg.type().lookup_symbol();
1027 cctbxspg.match_tabulated_settings().extension();
1028 cctbxspg.match_tabulated_settings().hermann_mauguin();
1029 cctbxspg.type().universal_hermann_mauguin_symbol();
1030 cctbx::sgtbx::brick b(cctbxspg.type());
1031 spg=pos->second.mSpacegroupSymbolHall;
1035 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret Hall symbol:"<<pos->second.mSpacegroupSymbolHall, 10)
1037 if((spg==
"") && (pos->second.mSpacegroupHermannMauguin!=
""))
try
1040 cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupHermannMauguin));
1045 cctbxspg.type().number();
1046 cctbxspg.type().hall_symbol();
1047 cctbxspg.type().lookup_symbol();
1048 cctbxspg.type().universal_hermann_mauguin_symbol();
1049 cctbxspg.match_tabulated_settings().extension();
1050 cctbxspg.match_tabulated_settings().hermann_mauguin();
1051 cctbx::sgtbx::brick b(cctbxspg.type());
1052 spg=pos->second.mSpacegroupHermannMauguin;
1056 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret Hermann-Mauguin symbol:"<<pos->second.mSpacegroupHermannMauguin, 10)
1058 if((spg==
"") && (pos->second.mSpacegroupNumberIT!=
""))
1062 cctbx::sgtbx::space_group cctbxspg(cctbx::sgtbx::space_group_symbols(pos->second.mSpacegroupNumberIT));
1067 cctbxspg.type().number();
1068 cctbxspg.type().hall_symbol();
1069 cctbxspg.type().lookup_symbol();
1070 cctbxspg.type().universal_hermann_mauguin_symbol();
1071 cctbxspg.match_tabulated_settings().extension();
1072 cctbxspg.match_tabulated_settings().hermann_mauguin();
1073 cctbx::sgtbx::brick b(cctbxspg.type());
1074 spg=pos->second.mSpacegroupNumberIT;
1078 VFN_DEBUG_MESSAGE(
"CreateCrystalFromCIF(): could not interpret spacegroup number (!) :"<<pos->second.mSpacegroupNumberIT, 10)
1080 if(spg==
"") spg=
"P1";
1081 if(verbose) cout<<
"Create crystal with spacegroup: "<<spg
1082 <<
" / "<<pos->second.mSpacegroupHermannMauguin
1083 <<
" / "<<pos->second.mSpacegroupSymbolHall
1084 <<
" / "<<pos->second.mSpacegroupNumberIT
1087 (*fpObjCrystInformUser)(
"CIF: Create Crystal=");
1088 pCryst=
new Crystal(pos->second.mvLatticePar[0],pos->second.mvLatticePar[1],pos->second.mvLatticePar[2],
1089 pos->second.mvLatticePar[3],pos->second.mvLatticePar[4],pos->second.mvLatticePar[5],spg);
1090 if( (pos->second.mSpacegroupSymbolHall==
"")
1091 &&(pos->second.mvSymmetry_equiv_pos_as_xyz.size()>0)
1092 &&(pos->second.mSpacegroupHermannMauguin!=
"")
1097 static vector<string> origin_list;
1098 if(origin_list.size()==0)
1100 origin_list.resize(5);
1102 origin_list[1]=
":1";
1103 origin_list[2]=
":2";
1104 origin_list[3]=
":R";
1105 origin_list[4]=
":H";
1108 string hmorig=pos->second.mSpacegroupHermannMauguin;
1109 if(hmorig==
"") hmorig=pCryst->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
1111 if(verbose) cout<<
" Symmetry checking using symmetry_equiv_pos_as_xyz:"<<endl;
1112 string bestsymbol=hmorig;
1113 unsigned int bestscore=0;
1114 for(vector<string>::const_iterator posOrig=origin_list.begin();posOrig!=origin_list.end();++posOrig)
1117 pCryst->GetSpaceGroup().ChangeSpaceGroup(hmorig+*posOrig);
1120 if((posOrig!=origin_list.begin())&&(pCryst->GetSpaceGroup().GetName()==bestsymbol))
continue;
1122 unsigned int nbSymSpg=pCryst->GetSpaceGroup().GetCCTbxSpg().all_ops().size();
1123 unsigned int nbSymCommon=0;
1126 for(
unsigned int i=0;i<nbSymSpg;i++)
1128 for(set<string>::const_iterator posSymCIF=pos->second.mvSymmetry_equiv_pos_as_xyz.begin();
1129 posSymCIF!=pos->second.mvSymmetry_equiv_pos_as_xyz.end();++posSymCIF)
1131 cctbx::sgtbx::rt_mx mx1(*posSymCIF);
1132 cctbx::sgtbx::rt_mx mx2(pCryst->GetSpaceGroup().GetCCTbxSpg().all_ops()[i]);
1133 mx1.mod_positive_in_place();
1134 mx2.mod_positive_in_place();
1142 if(verbose) cout<<
" Trying: "<<pCryst->GetSpaceGroup().GetName()
1143 <<
" nbsym:"<<nbSymSpg<<
"(cctbx), "
1144 <<pos->second.mvSymmetry_equiv_pos_as_xyz.size()<<
"(CIF)"
1145 <<
",common:"<<nbSymCommon<<endl;
1146 if(bestscore<((nbSymSpg==pos->second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon))
1148 bestscore=(nbSymSpg==pos->second.mvSymmetry_equiv_pos_as_xyz.size())*nbSymCommon;
1149 bestsymbol=pCryst->GetSpaceGroup().GetName();
1154 cout<<
"WOOPS: cctbx error ! Wrong symmetry_equiv_pos_as_xyz strings ?"<<endl;
1157 if(verbose) cout<<endl<<
"Finally using spacegroup name:"<<bestsymbol<<endl;
1158 pCryst->GetSpaceGroup().ChangeSpaceGroup(bestsymbol);
1160 if(pos->second.mName!=
"") pCryst->SetName(pos->second.mName);
1161 else if(pos->second.mFormula!=
"") pCryst->SetName(pos->second.mFormula);
1162 const float t1=chrono.seconds();
1163 (*fpObjCrystInformUser)((boost::format(
"CIF: Create Crystal:%s(%s)(dt=%6.3fs)")%pCryst->GetName() % pCryst->GetSpaceGroup().GetName() % t1).str());
1165 for(vector<CIFData::CIFAtom>::const_iterator posat=pos->second.mvAtom.begin();posat!=pos->second.mvAtom.end();++posat)
1167 if( (posat->mLabel==
".") || (posat->mSymbol==
".") || (posat->mLabel.find(
"dummy")!=std::string::npos) || (posat->mSymbol.find(
"dummy")!=std::string::npos) )
1169 (*fpObjCrystInformUser)(
"CIF: Ignoring DUMMY Atom:"+posat->mLabel+
"(symbol="+posat->mSymbol+
")");
1173 const float t20=chrono.seconds();
1176 if(oneScatteringPowerPerElement)
1178 for(
unsigned int i=0;i<pCryst->GetScatteringPowerRegistry().GetNb();++i)
1180 if(pCryst->GetScatteringPowerRegistry().GetObj(i).GetSymbol()!=posat->mSymbol)
continue;
1181 vElementBiso[&(pCryst->GetScatteringPowerRegistry().GetObj(i))].first+=posat->
mBiso;
1182 vElementBiso[&(pCryst->GetScatteringPowerRegistry().GetObj(i))].second+=1;
1183 sp=&(pCryst->GetScatteringPowerRegistry().GetObj(i));
1188 if(verbose) cout<<
"Scattering power "<<posat->mSymbol<<
" not found, creating it..."<<endl;
1192 vElementBiso[sp].first+=posat->mBiso;
1193 vElementBiso[sp].second=1;
1194 pCryst->AddScatteringPower(sp);
1195 const float t21=chrono.seconds();
1196 (*fpObjCrystInformUser)((boost::format(
"CIF: Add scattering power: %s (dt=%6.3fsCrystal creation=%6.3fs total)")% posat->mSymbol % (t21-t20) % t21).str());
1201 for(
unsigned int i=0;i<pCryst->GetScatteringPowerRegistry().GetNb();++i)
1203 if(pCryst->GetScatteringPowerRegistry().GetObj(i).GetSymbol()!=posat->mSymbol)
continue;
1204 if(posat->mBeta.size() == 6)
1206 if( (pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(0)!=posat->mBeta[0])
1207 ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(1)!=posat->mBeta[1])
1208 ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(2)!=posat->mBeta[2])
1209 ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(3)!=posat->mBeta[3])
1210 ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(4)!=posat->mBeta[4])
1211 ||(pCryst->GetScatteringPowerRegistry().GetObj(i).GetBij(5)!=posat->mBeta[5]))
continue;
1213 else if(posat->mBiso!=pCryst->GetScatteringPowerRegistry().GetObj(i).GetBiso())
continue;
1214 sp=&(pCryst->GetScatteringPowerRegistry().GetObj(i));
1219 if(verbose) cout<<
"Scattering power "<<posat->mLabel<<
" not found, creating it..."<<endl;
1225 if(posat->mBeta.size() == 6)
1227 for (
int idx=0; idx<6; ++idx) sp->
SetBij(idx, posat->mBeta[idx]);
1229 pCryst->AddScatteringPower(sp);
1230 const float t21=chrono.seconds();
1231 (*fpObjCrystInformUser)((boost::format(
"CIF: Add scattering power: %s (dt=%6.3fsCrystal creation=%6.3fs total)") % posat->mLabel % (t21-t20) % t21).str());
1234 (*fpObjCrystInformUser)(
"CIF: Add Atom:"+posat->mLabel+
"("+sp->
GetName()+
")");
1235 pCryst->AddScatterer(
new Atom(posat->mCoordFrac[0],posat->mCoordFrac[1],posat->mCoordFrac[2],
1236 posat->mLabel,sp,posat->mOccupancy));
1237 const float t22=chrono.seconds();
1238 (*fpObjCrystInformUser)((boost::format(
"CIF: new Atom: %s (%s) (dt=%6.3fs, Crystal creation=%6.3fs total)") % posat->mLabel % sp->
GetName() % (t22-t20) % t22).str());
1240 if(oneScatteringPowerPerElement)
1242 for(std::map<
ScatteringPower*,std::pair<REAL,unsigned int> >::iterator pos=vElementBiso.begin();pos!=vElementBiso.end();++pos)
1243 pos->first->SetBiso(pos->second.first/pos->second.second);
1245 if(connectAtoms) pCryst->ConnectAtoms();
1255 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1257 if(pos->second.mPowderPatternObs.size()>10)
1269 for(map<string,CIFData>::iterator pos=cif.
mvData.begin();pos!=cif.
mvData.end();++pos)
1271 if(pos->second.mH.numElements()>0)
1286 pData->
SetHklIobs(pos->second.mH,pos->second.mK,pos->second.mL,pos->second.mIobs,pos->second.mSigma);
This class only serves to temporarilly set the LC_NUMERIC C locale to "C", in order to use '...
The CIFData class holds all the information from a single data_ block from a cif file.
Crystal * CreateCrystalFromCIF(CIF &cif, bool verbose, bool checkSymAsXYZ)
Extract Crystal object(s) from a CIF, if possible.
Simple chronometer class, with microsecond precision.
PowderPattern * CreatePowderPatternFromCIF(CIF &cif)
Create PowderPattern 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...
ObjRegistry< Crystal > gCrystalRegistry("List of all Crystals")
Global registry for all Crystal objects.
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 basic atom scatterer, in a crystal.
void ImportPowderPatternCIF(const CIF &cif)
Import CIF powder pattern data.
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
Powder pattern class, with an observed pattern and several calculated components to modelize the patt...
virtual void SetBiso(const REAL newB)
Sets the isotropic temperature B factor.
Main CIF class - parses the stream and separates data blocks, comments, items, loops.
string CIFReadValue(stringstream &in, char &lastc)
Read one value, whether it is numeric, string or text.
DiffractionDataSingleCrystal * CreateSingleCrystalDataFromCIF(CIF &cif, Crystal *pcryst)
Create DiffractionDataSingleCrystal object(s) from a CIF, if possible.
std::map< std::string, CIFData > mvData
The data blocks, after parsing. The key is the name of the data block.
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
The Scattering Power for an Atom.
virtual const string & GetName() const
Name of the object.
Crystal class: Unit cell, spacegroup, scatterers.
virtual void SetName(const string &name)
Name of the object.
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal...